herdr-remote 0.2.38 → 0.3.31

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 (203) hide show
  1. package/dist/chunks/353DMT35.js +3 -0
  2. package/dist/chunks/42KARAL4.js +31 -0
  3. package/dist/chunks/7AUQHB3O.js +10 -0
  4. package/dist/chunks/7SMZ43LI.js +9 -0
  5. package/dist/chunks/AM3OEMFK.js +16 -0
  6. package/dist/chunks/ANNJESOL.js +10 -0
  7. package/dist/chunks/AWB4A65P.js +63 -0
  8. package/dist/chunks/C2UUZY6J.js +2 -0
  9. package/dist/chunks/DGUZCGQN.js +3 -0
  10. package/dist/chunks/H24ZP5D5.js +16 -0
  11. package/dist/chunks/I6NRCYLI.js +3 -0
  12. package/dist/chunks/JJGEV4EZ.js +3 -0
  13. package/dist/chunks/KRSURB5L.js +5 -0
  14. package/dist/chunks/KRVF37OW.js +3 -0
  15. package/dist/chunks/KUDCC7ZO.js +6 -0
  16. package/dist/chunks/M3NRPJK2.js +77 -0
  17. package/dist/chunks/M4AFZHKH.js +3 -0
  18. package/dist/chunks/M52LJEES.js +6 -0
  19. package/dist/chunks/O2LNVFUT.js +3 -0
  20. package/dist/chunks/OJPBI7KB.js +3 -0
  21. package/dist/chunks/OMN6C7J6.js +3 -0
  22. package/dist/chunks/PBMBFWLQ.js +3 -0
  23. package/dist/chunks/PBRQ3HEG.js +3 -0
  24. package/dist/chunks/PFFVGFPL.js +45 -0
  25. package/dist/chunks/QRGNEKME.js +5 -0
  26. package/dist/chunks/TNLCNVA2.js +3 -0
  27. package/dist/chunks/U27JJKJ6.js +3 -0
  28. package/dist/chunks/U6QAYG3E.js +3 -0
  29. package/dist/chunks/UEOQE77N.js +4 -0
  30. package/dist/chunks/WSACSE45.js +4 -0
  31. package/dist/chunks/WY7WHEJ4.js +3 -0
  32. package/dist/chunks/XJKWLK43.js +4 -0
  33. package/dist/chunks/XN6D5S55.js +3 -0
  34. package/dist/chunks/YD3MIP7B.js +5 -0
  35. package/dist/chunks/YXDQ62BB.js +4 -0
  36. package/dist/cli.js +21 -294
  37. package/dist/connector/admin-broker.js +3 -302
  38. package/dist/connector/main.js +20 -18
  39. package/dist/harfbuzz-subset.wasm +0 -0
  40. package/dist/postinstall.js +17 -0
  41. package/herdr-plugin.toml +1 -1
  42. package/node_modules/herdr-remote-relay/bin/herdr-remote-relay.js +33 -92
  43. package/node_modules/herdr-remote-relay/package.json +3 -46
  44. package/package.json +8 -27
  45. package/dist/agent-status.js +0 -130
  46. package/dist/binary-plist.js +0 -157
  47. package/dist/config.js +0 -278
  48. package/dist/connector/admin-broker-setup.js +0 -40
  49. package/dist/connector/admin-shell.js +0 -67
  50. package/dist/connector/admin-tab.js +0 -90
  51. package/dist/connector/adminBrokerEndpoint.js +0 -68
  52. package/dist/connector/agent-watch.js +0 -123
  53. package/dist/connector/elevatedPty.js +0 -141
  54. package/dist/connector/font-server.js +0 -165
  55. package/dist/connector/herdr-prefix-keys.js +0 -28
  56. package/dist/connector/host-connector.js +0 -433
  57. package/dist/connector/host-hello.js +0 -32
  58. package/dist/connector/lock.js +0 -73
  59. package/dist/connector/sessions.js +0 -381
  60. package/dist/connector/update-report.js +0 -70
  61. package/dist/connector/wire.js +0 -42
  62. package/dist/exit-codes.js +0 -13
  63. package/dist/font-subset.js +0 -110
  64. package/dist/herdr-api.js +0 -254
  65. package/dist/herdr-command.js +0 -245
  66. package/dist/herdr-plugin.js +0 -120
  67. package/dist/herdr-server.js +0 -190
  68. package/dist/i18n/en.js +0 -257
  69. package/dist/i18n/index.js +0 -48
  70. package/dist/i18n/zh.js +0 -256
  71. package/dist/keepalive/detached.js +0 -97
  72. package/dist/keepalive/environment.js +0 -44
  73. package/dist/keepalive/index.js +0 -129
  74. package/dist/keepalive/launchd.js +0 -117
  75. package/dist/keepalive/systemd.js +0 -112
  76. package/dist/keepalive/types.js +0 -1
  77. package/dist/keepalive/windows-service-setup.js +0 -138
  78. package/dist/keepalive/windows-service.js +0 -272
  79. package/dist/keepalive/windows-task.js +0 -191
  80. package/dist/lib/process.js +0 -132
  81. package/dist/lifecycle.js +0 -79
  82. package/dist/net-interfaces.js +0 -82
  83. package/dist/node-pty-loader.js +0 -80
  84. package/dist/pasted-files.js +0 -115
  85. package/dist/paths.js +0 -74
  86. package/dist/pty-session.js +0 -133
  87. package/dist/relay-client.js +0 -106
  88. package/dist/relay-urls.js +0 -99
  89. package/dist/runtime.js +0 -107
  90. package/dist/service.js +0 -267
  91. package/dist/settings-model.js +0 -298
  92. package/dist/socket-discovery.js +0 -70
  93. package/dist/supervisor.js +0 -323
  94. package/dist/terminal-font/deps.js +0 -83
  95. package/dist/terminal-font/files.js +0 -357
  96. package/dist/terminal-font/formats.js +0 -355
  97. package/dist/terminal-font/index.js +0 -187
  98. package/dist/terminal-font/readers.js +0 -373
  99. package/dist/terminal-font/terminals.js +0 -147
  100. package/dist/terminal-palette.js +0 -399
  101. package/dist/tui/App.js +0 -199
  102. package/dist/tui/api.js +0 -91
  103. package/dist/tui/components/TextField.js +0 -50
  104. package/dist/tui/components/common.js +0 -80
  105. package/dist/tui/index.js +0 -36
  106. package/dist/tui/mouse/index.js +0 -164
  107. package/dist/tui/mouse/protocol.js +0 -96
  108. package/dist/tui/mouse/source.js +0 -79
  109. package/dist/tui/screens/About.js +0 -172
  110. package/dist/tui/screens/Herdr.js +0 -75
  111. package/dist/tui/screens/Keepalive.js +0 -141
  112. package/dist/tui/screens/Overview.js +0 -36
  113. package/dist/tui/screens/Pair.js +0 -74
  114. package/dist/tui/screens/Relay.js +0 -243
  115. package/dist/tui/screens/Services.js +0 -63
  116. package/dist/tui/screens/Wizard.js +0 -241
  117. package/dist/tui/terminal.js +0 -39
  118. package/dist/tui/theme.js +0 -33
  119. package/dist/update-command.js +0 -118
  120. package/dist/updater/in-place.js +0 -83
  121. package/dist/updater/npm.js +0 -62
  122. package/dist/updater.js +0 -401
  123. package/node_modules/herdr-remote-relay/README.md +0 -76
  124. package/node_modules/herdr-remote-relay/README.zh-CN.md +0 -76
  125. package/node_modules/herdr-remote-relay/config.example.json +0 -18
  126. package/node_modules/herdr-remote-relay/deploy/cloudflared/config.yml.example +0 -9
  127. package/node_modules/herdr-remote-relay/deploy/docker/compose.yaml +0 -23
  128. package/node_modules/herdr-remote-relay/deploy/nginx/herdr-remote-relay.conf.example +0 -49
  129. package/node_modules/herdr-remote-relay/deploy/systemd/herdr-remote-relay.service +0 -41
  130. package/node_modules/herdr-remote-relay/deploy/systemd/relay.env.example +0 -25
  131. package/node_modules/herdr-remote-relay/dist/auth-store.d.ts +0 -114
  132. package/node_modules/herdr-remote-relay/dist/auth-store.js +0 -289
  133. package/node_modules/herdr-remote-relay/dist/metrics.d.ts +0 -76
  134. package/node_modules/herdr-remote-relay/dist/metrics.js +0 -249
  135. package/node_modules/herdr-remote-relay/dist/protocol/frames.d.ts +0 -27
  136. package/node_modules/herdr-remote-relay/dist/protocol/frames.js +0 -110
  137. package/node_modules/herdr-remote-relay/dist/protocol/herdr-keys.d.ts +0 -8
  138. package/node_modules/herdr-remote-relay/dist/protocol/herdr-keys.js +0 -34
  139. package/node_modules/herdr-remote-relay/dist/protocol/http.d.ts +0 -165
  140. package/node_modules/herdr-remote-relay/dist/protocol/http.js +0 -3
  141. package/node_modules/herdr-remote-relay/dist/protocol/index.d.ts +0 -7
  142. package/node_modules/herdr-remote-relay/dist/protocol/index.js +0 -9
  143. package/node_modules/herdr-remote-relay/dist/protocol/messages.d.ts +0 -362
  144. package/node_modules/herdr-remote-relay/dist/protocol/messages.js +0 -20
  145. package/node_modules/herdr-remote-relay/dist/protocol/paste.d.ts +0 -14
  146. package/node_modules/herdr-remote-relay/dist/protocol/paste.js +0 -50
  147. package/node_modules/herdr-remote-relay/dist/protocol/release.d.ts +0 -8
  148. package/node_modules/herdr-remote-relay/dist/protocol/release.js +0 -17
  149. package/node_modules/herdr-remote-relay/dist/protocol/terminal.d.ts +0 -79
  150. package/node_modules/herdr-remote-relay/dist/protocol/terminal.js +0 -150
  151. package/node_modules/herdr-remote-relay/dist/relay-config.d.ts +0 -74
  152. package/node_modules/herdr-remote-relay/dist/relay-config.js +0 -316
  153. package/node_modules/herdr-remote-relay/dist/relay-server.d.ts +0 -67
  154. package/node_modules/herdr-remote-relay/dist/relay-server.js +0 -196
  155. package/node_modules/herdr-remote-relay/dist/scroll-input.d.ts +0 -17
  156. package/node_modules/herdr-remote-relay/dist/scroll-input.js +0 -124
  157. package/node_modules/herdr-remote-relay/dist/server/client-channel.d.ts +0 -3
  158. package/node_modules/herdr-remote-relay/dist/server/client-channel.js +0 -396
  159. package/node_modules/herdr-remote-relay/dist/server/font-proxy.d.ts +0 -19
  160. package/node_modules/herdr-remote-relay/dist/server/font-proxy.js +0 -155
  161. package/node_modules/herdr-remote-relay/dist/server/host-broadcasts.d.ts +0 -27
  162. package/node_modules/herdr-remote-relay/dist/server/host-broadcasts.js +0 -83
  163. package/node_modules/herdr-remote-relay/dist/server/host-channel.d.ts +0 -3
  164. package/node_modules/herdr-remote-relay/dist/server/host-channel.js +0 -271
  165. package/node_modules/herdr-remote-relay/dist/server/http-api.d.ts +0 -4
  166. package/node_modules/herdr-remote-relay/dist/server/http-api.js +0 -219
  167. package/node_modules/herdr-remote-relay/dist/server/maintenance.d.ts +0 -5
  168. package/node_modules/herdr-remote-relay/dist/server/maintenance.js +0 -64
  169. package/node_modules/herdr-remote-relay/dist/server/requests.d.ts +0 -34
  170. package/node_modules/herdr-remote-relay/dist/server/requests.js +0 -142
  171. package/node_modules/herdr-remote-relay/dist/server/sessions.d.ts +0 -36
  172. package/node_modules/herdr-remote-relay/dist/server/sessions.js +0 -230
  173. package/node_modules/herdr-remote-relay/dist/server/sockets.d.ts +0 -12
  174. package/node_modules/herdr-remote-relay/dist/server/sockets.js +0 -64
  175. package/node_modules/herdr-remote-relay/dist/server/status.d.ts +0 -11
  176. package/node_modules/herdr-remote-relay/dist/server/status.js +0 -99
  177. package/node_modules/herdr-remote-relay/dist/server/transport.d.ts +0 -16
  178. package/node_modules/herdr-remote-relay/dist/server/transport.js +0 -110
  179. package/node_modules/herdr-remote-relay/dist/server/types.d.ts +0 -133
  180. package/node_modules/herdr-remote-relay/dist/server/types.js +0 -3
  181. package/node_modules/herdr-remote-relay/dist/server/version.d.ts +0 -2
  182. package/node_modules/herdr-remote-relay/dist/server/version.js +0 -5
  183. package/node_modules/herdr-remote-relay/dist/state.d.ts +0 -6
  184. package/node_modules/herdr-remote-relay/dist/state.js +0 -47
  185. package/node_modules/ws/LICENSE +0 -20
  186. package/node_modules/ws/README.md +0 -548
  187. package/node_modules/ws/browser.js +0 -8
  188. package/node_modules/ws/index.js +0 -22
  189. package/node_modules/ws/lib/buffer-util.js +0 -131
  190. package/node_modules/ws/lib/constants.js +0 -19
  191. package/node_modules/ws/lib/event-target.js +0 -292
  192. package/node_modules/ws/lib/extension.js +0 -203
  193. package/node_modules/ws/lib/limiter.js +0 -55
  194. package/node_modules/ws/lib/permessage-deflate.js +0 -530
  195. package/node_modules/ws/lib/receiver.js +0 -743
  196. package/node_modules/ws/lib/sender.js +0 -607
  197. package/node_modules/ws/lib/stream.js +0 -161
  198. package/node_modules/ws/lib/subprotocol.js +0 -62
  199. package/node_modules/ws/lib/validation.js +0 -152
  200. package/node_modules/ws/lib/websocket-server.js +0 -562
  201. package/node_modules/ws/lib/websocket.js +0 -1407
  202. package/node_modules/ws/package.json +0 -74
  203. package/node_modules/ws/wrapper.mjs +0 -21
package/dist/cli.js CHANGED
@@ -1,19 +1,6 @@
1
- // herdr-remote command line: argument parsing and the subcommands.
2
- //
3
- // With no arguments (and a real terminal) this opens the configuration TUI;
4
- // the subcommands exist for scripting and for the actions declared in
5
- // herdr-plugin.toml, which Herdr runs without a terminal attached.
6
- import fs from 'node:fs';
7
- import os from 'node:os';
8
- import path from 'node:path';
9
- import { LANGUAGES, loadConfig, migrateLegacyConfig } from './config.js';
10
- import { PACKAGE_ROOT, configPath, stateDir } from './paths.js';
11
- import { extractPairingCode } from './relay-client.js';
12
- import { resolvePublicUrl } from './relay-urls.js';
13
- import { createTranslator, detectLocale } from './i18n/index.js';
14
- import { preferredLanAddress } from './net-interfaces.js';
15
- const VERSION = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8')).version;
16
- const USAGE = `herdr-remote ${VERSION} — browser access to Herdr workspaces
1
+ import { createRequire as __herdrCreateRequire } from 'node:module';
2
+ const require = __herdrCreateRequire(import.meta.url);
3
+ import{a as y,b as A}from"./chunks/XN6D5S55.js";import{f as S,h as w}from"./chunks/DGUZCGQN.js";import"./chunks/U6QAYG3E.js";import{f as m,l as v,n as $,o as k}from"./chunks/M52LJEES.js";import"./chunks/KRVF37OW.js";import"./chunks/QRGNEKME.js";import"./chunks/PBMBFWLQ.js";import{a as d,c as h,d as g}from"./chunks/TNLCNVA2.js";import"./chunks/I6NRCYLI.js";import U from"node:fs";import P from"node:os";import u from"node:path";var j=JSON.parse(U.readFileSync(u.join(d,"package.json"),"utf8")).version,f=`herdr-remote ${j} \u2014 browser access to Herdr workspaces
17
4
 
18
5
  Usage: herdr-remote [command] [options]
19
6
 
@@ -39,281 +26,21 @@ Options:
39
26
  -v, --version Show version
40
27
 
41
28
  Self-hosting: docs/self-hosted-relay.md
42
- `;
43
- function parseArgs(argv) {
44
- const positional = [];
45
- const flags = {};
46
- for (let index = 0; index < argv.length; index += 1) {
47
- const arg = argv[index];
48
- if (arg === '--json') {
49
- flags.json = true;
50
- continue;
51
- }
52
- if (arg === '--daemon') {
53
- flags.daemon = true;
54
- continue;
55
- }
56
- if (arg === '--elevated') {
57
- flags.elevated = true;
58
- continue;
59
- }
60
- if (arg === '--help' || arg === '-h') {
61
- flags.help = true;
62
- continue;
63
- }
64
- if (arg === '--version' || arg === '-v') {
65
- flags.version = true;
66
- continue;
67
- }
68
- if (arg === '--lang') {
69
- flags.lang = argv[index + 1];
70
- index += 1;
71
- continue;
72
- }
73
- if (arg.startsWith('--lang=')) {
74
- flags.lang = arg.slice('--lang='.length);
75
- continue;
76
- }
77
- if (arg.startsWith('-')) {
78
- flags.unknown = arg;
79
- continue;
80
- }
81
- positional.push(arg);
82
- }
83
- return { positional, flags };
84
- }
85
- function printJson(value) {
86
- process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
87
- }
88
- function describeStatus(status, t) {
89
- const lines = [];
90
- lines.push(`${t('overview.mode')}: ${t(`mode.${status.mode}`)}`);
91
- if (status.relay.local) {
92
- lines.push(`${t('overview.relay')}: ${status.relay.alive ? t('common.running') : t('common.stopped')} (${status.relay.bind}:${status.relay.port})`);
93
- }
94
- else {
95
- lines.push(`${t('overview.relay')}: ${status.relay.remoteUrl}`);
96
- }
97
- lines.push(`${t('overview.host')}: ${status.host.alive ? t('common.running') : t('common.stopped')}`);
98
- lines.push(`${t('overview.socket')}: ${status.host.socketPath}${status.host.socketExists ? '' : ` (${t('overview.socketMissing')})`}`);
99
- lines.push(`${t('overview.webUrl')}: ${status.publicUrl}`);
100
- if (status.keepalive) {
101
- const state = status.keepalive.active
102
- ? t('common.running')
103
- : status.keepalive.installed
104
- ? t('common.installed')
105
- : t('common.notInstalled');
106
- lines.push(`${t('overview.keepalive')}: ${status.keepalive.manager} — ${state}`);
107
- }
108
- if (status.relay.health && status.relay.health.ok === false) {
109
- lines.push(`${t('overview.relay')}: ${t('overview.unreachable', { message: status.relay.health.message ?? '' })}`);
110
- }
111
- return lines.join('\n');
112
- }
113
- async function runTui(options) {
114
- const { startTui } = await import('./tui/index.js');
115
- await startTui(options);
116
- }
117
- async function main(argv = process.argv.slice(2)) {
118
- const { positional, flags } = parseArgs(argv);
119
- if (process.platform === 'win32') {
120
- const relative = path.relative(PACKAGE_ROOT, process.cwd());
121
- const insidePackage = relative === '' ||
122
- (relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
123
- if (insidePackage) {
124
- // Herdr starts plugin panels in PACKAGE_ROOT; Windows locks the cwd,
125
- // preventing npm from replacing that directory.
126
- process.chdir(os.homedir());
127
- }
128
- }
129
- const command = positional[0] || null;
130
- // Answered before anything reads the config or queries the terminal.
131
- if (flags.help) {
132
- process.stdout.write(USAGE);
133
- return;
134
- }
135
- if (flags.version) {
136
- process.stdout.write(`${VERSION}\n`);
137
- return;
138
- }
139
- if (flags.unknown) {
140
- process.stderr.write(`herdr-remote: unknown option "${flags.unknown}"\n\n${USAGE}`);
141
- process.exitCode = 2;
142
- return;
143
- }
144
- migrateLegacyConfig();
145
- // Ask the terminal for its colors while it is still a plain terminal: the
146
- // TUI takes the screen a few lines below, and the services this command
147
- // starts usually run detached with nothing to ask. Everything downstream
148
- // inherits the answer through the environment.
149
- await (await import('./terminal-palette.js')).captureTerminalPalette();
150
- // The font, likewise, is read while this process still knows which terminal
151
- // it runs in: its variables and its parent process are gone once a service
152
- // manager or Herdr's detached server starts the connector.
153
- (await import('./terminal-font/index.js')).captureTerminalFont();
154
- const config = loadConfig();
155
- const preference = flags.lang && LANGUAGES.includes(flags.lang)
156
- ? flags.lang
157
- : config.ui.language;
158
- const t = createTranslator(detectLocale({ preference }));
159
- // Loaded lazily so that the TUI does not pay for loading the
160
- // service layer (which pulls in the relay package and node-pty).
161
- const lifecycle = await import('./lifecycle.js');
162
- const service = await import('./service.js');
163
- switch (command) {
164
- case null: {
165
- if (process.stdin.isTTY && process.stdout.isTTY) {
166
- await runTui({ language: flags.lang || null });
167
- return;
168
- }
169
- // Herdr runs plugin panes and actions without a TTY; emit status instead
170
- // of trying to paint an interface into a pipe.
171
- printJson(await lifecycle.fullStatus(config));
172
- return;
173
- }
174
- case 'start': {
175
- const result = lifecycle.startAll(config);
176
- if (flags.json)
177
- printJson(result);
178
- else
179
- process.stdout.write(`${t('services.started')}\n${describeStatus(await lifecycle.fullStatus(config), t)}\n`);
180
- return;
181
- }
182
- case 'stop': {
183
- const result = lifecycle.stopAll(config);
184
- if (flags.json)
185
- printJson(result);
186
- else
187
- process.stdout.write(`${t('services.stopped')}\n`);
188
- return;
189
- }
190
- case 'restart': {
191
- const result = lifecycle.restartAll(config);
192
- if (flags.json)
193
- printJson(result);
194
- else
195
- process.stdout.write(`${t('services.restarted')}\n`);
196
- return;
197
- }
198
- case 'status': {
199
- const status = await lifecycle.fullStatus(config);
200
- if (flags.json)
201
- printJson(status);
202
- else
203
- process.stdout.write(`${describeStatus(status, t)}\n`);
204
- return;
205
- }
206
- case 'pair': {
207
- const pairing = await service.pair();
208
- if (flags.json) {
209
- printJson(pairing);
210
- return;
211
- }
212
- const code = extractPairingCode(pairing);
213
- const url = pairing.pairUrl ||
214
- `${resolvePublicUrl(config, preferredLanAddress())}/?pairCode=${encodeURIComponent(code)}`;
215
- const minutes = `${Math.round((config.auth.pairingTtlMs || 600000) / 60000)}m`;
216
- process.stdout.write(`${t('pair.code')}: ${code}\n${t('pair.url')}: ${url}\n${t('pair.expires', { minutes, time: new Date(pairing.expiresAt).toLocaleTimeString() })}\n`);
217
- return;
218
- }
219
- case 'url': {
220
- process.stdout.write(`${resolvePublicUrl(config, preferredLanAddress())}\n`);
221
- return;
222
- }
223
- case 'update': {
224
- const { runUpdate } = await import('./update-command.js');
225
- const outcome = await runUpdate(t, {
226
- config,
227
- ...(flags.json ? { report: () => { } } : {}),
228
- });
229
- if (flags.json)
230
- printJson(outcome);
231
- if (!outcome.ok)
232
- process.exitCode = 1;
233
- return;
234
- }
235
- case 'run': {
236
- const { runForeground } = await import('./supervisor.js');
237
- await runForeground({ logToFiles: Boolean(flags.daemon) });
238
- return;
239
- }
240
- case 'admin-broker': {
241
- const broker = await import('./connector/admin-broker.js');
242
- const action = positional[1] || 'status';
243
- if (action === 'install') {
244
- broker.installAdminBroker(t);
245
- printJson({ installed: true, available: await broker.waitForAdminBroker() });
246
- }
247
- else if (action === 'uninstall') {
248
- broker.uninstallAdminBroker(t);
249
- printJson({ installed: false });
250
- }
251
- else if (action === 'restart') {
252
- if ((await broker.stopAdminBroker()) === 'busy')
253
- throw new Error(t('adminBroker.busy'));
254
- broker.startAdminBrokerTask(t);
255
- printJson({ available: await broker.waitForAdminBroker() });
256
- }
257
- else if (action === 'status') {
258
- printJson({ available: await broker.adminBrokerStatus() });
259
- }
260
- else {
261
- throw new Error(`unknown administrator broker action: ${action}`);
262
- }
263
- return;
264
- }
265
- case 'admin-shell': {
266
- const { runAdminShell } = await import('./connector/admin-shell.js');
267
- process.exitCode = await runAdminShell(t);
268
- return;
269
- }
270
- case 'keepalive': {
271
- const keepalive = await import('./keepalive/index.js');
272
- const action = positional[1] || 'status';
273
- if (action === 'install' && flags.elevated) {
274
- const { completeServiceInstall } = await import('./keepalive/windows-service-setup.js');
275
- process.exitCode = await completeServiceInstall(t);
276
- }
277
- else if (action === 'install')
278
- printJson(await keepalive.install(config));
279
- else if (action === 'uninstall')
280
- printJson(await keepalive.uninstall(config));
281
- else if (action === 'restart')
282
- printJson(keepalive.restart(config));
283
- else if (action === 'status')
284
- printJson(keepalive.status(config));
285
- else
286
- throw new Error(`unknown keepalive action: ${action}`);
287
- return;
288
- }
289
- case 'plugin': {
290
- const plugin = await import('./herdr-plugin.js');
291
- const action = positional[1] || 'status';
292
- if (action === 'link')
293
- printJson(plugin.register());
294
- else if (action === 'unlink')
295
- printJson(plugin.unregister());
296
- else if (action === 'status')
297
- printJson(plugin.registrationStatus());
298
- else
299
- throw new Error(`unknown plugin action: ${action}`);
300
- return;
301
- }
302
- case 'config': {
303
- // Handy when reporting a problem: where does this install read from?
304
- printJson({ configPath: configPath(), stateDir: stateDir(), config });
305
- return;
306
- }
307
- default:
308
- process.stderr.write(`herdr-remote: unknown command "${command}"\n\n${USAGE}`);
309
- process.exitCode = 2;
310
- }
311
- }
312
- /** Runs the command line and reports a failure as the exit code. */
313
- function run() {
314
- main().catch((error) => {
315
- process.stderr.write(`herdr-remote: ${error.message}\n`);
316
- process.exitCode = 1;
317
- });
318
- }
319
- export { run, parseArgs, describeStatus };
29
+ `;function E(n){let s=[],t={};for(let l=0;l<n.length;l+=1){let r=n[l];if(r==="--json"){t.json=!0;continue}if(r==="--daemon"){t.daemon=!0;continue}if(r==="--elevated"){t.elevated=!0;continue}if(r==="--help"||r==="-h"){t.help=!0;continue}if(r==="--version"||r==="-v"){t.version=!0;continue}if(r==="--lang"){t.lang=n[l+1],l+=1;continue}if(r.startsWith("--lang=")){t.lang=r.slice(7);continue}if(r.startsWith("-")){t.unknown=r;continue}s.push(r)}return{positional:s,flags:t}}function i(n){process.stdout.write(`${JSON.stringify(n,null,2)}
30
+ `)}function b(n,s){let t=[];if(t.push(`${s("overview.mode")}: ${s(`mode.${n.mode}`)}`),n.relay.local?t.push(`${s("overview.relay")}: ${n.relay.alive?s("common.running"):s("common.stopped")} (${n.relay.bind}:${n.relay.port})`):t.push(`${s("overview.relay")}: ${n.relay.remoteUrl}`),t.push(`${s("overview.host")}: ${n.host.alive?s("common.running"):s("common.stopped")}`),t.push(`${s("overview.socket")}: ${n.host.socketPath}${n.host.socketExists?"":` (${s("overview.socketMissing")})`}`),t.push(`${s("overview.webUrl")}: ${n.publicUrl}`),n.keepalive){let l=n.keepalive.active?s("common.running"):n.keepalive.installed?s("common.installed"):s("common.notInstalled");t.push(`${s("overview.keepalive")}: ${n.keepalive.manager} \u2014 ${l}`)}return n.relay.health&&n.relay.health.ok===!1&&t.push(`${s("overview.relay")}: ${s("overview.unreachable",{message:n.relay.health.message??""})}`),t.join(`
31
+ `)}async function B(n){let{startTui:s}=await import("./chunks/M3NRPJK2.js");await s(n)}async function O(n=process.argv.slice(2)){let{positional:s,flags:t}=E(n);if(process.platform==="win32"){let e=u.relative(d,process.cwd());(e===""||e!==".."&&!e.startsWith(`..${u.sep}`)&&!u.isAbsolute(e))&&process.chdir(P.homedir())}let l=s[0]||null;if(t.help){process.stdout.write(f);return}if(t.version){process.stdout.write(`${j}
32
+ `);return}if(t.unknown){process.stderr.write(`herdr-remote: unknown option "${t.unknown}"
33
+
34
+ ${f}`),process.exitCode=2;return}$(),await(await import("./chunks/O2LNVFUT.js")).captureTerminalPalette(),(await import("./chunks/WY7WHEJ4.js")).captureTerminalFont();let r=k(),T=t.lang&&v.includes(t.lang)?t.lang:r.ui.language,a=A(y({preference:T})),c=await import("./chunks/353DMT35.js"),C=await import("./chunks/OJPBI7KB.js");switch(l){case null:{if(process.stdin.isTTY&&process.stdout.isTTY){await B({language:t.lang||null});return}i(await c.fullStatus(r));return}case"start":{let e=c.startAll(r);t.json?i(e):process.stdout.write(`${a("services.started")}
35
+ ${b(await c.fullStatus(r),a)}
36
+ `);return}case"stop":{let e=c.stopAll(r);t.json?i(e):process.stdout.write(`${a("services.stopped")}
37
+ `);return}case"restart":{let e=c.restartAll(r);t.json?i(e):process.stdout.write(`${a("services.restarted")}
38
+ `);return}case"status":{let e=await c.fullStatus(r);t.json?i(e):process.stdout.write(`${b(e,a)}
39
+ `);return}case"pair":{let e=await C.pair();if(t.json){i(e);return}let o=S(e),p=e.pairUrl||`${m(r,w())}/?pairCode=${encodeURIComponent(o)}`,x=`${Math.round((r.auth.pairingTtlMs||6e5)/6e4)}m`;process.stdout.write(`${a("pair.code")}: ${o}
40
+ ${a("pair.url")}: ${p}
41
+ ${a("pair.expires",{minutes:x,time:new Date(e.expiresAt).toLocaleTimeString()})}
42
+ `);return}case"url":{process.stdout.write(`${m(r,w())}
43
+ `);return}case"update":{let{runUpdate:e}=await import("./chunks/WSACSE45.js"),o=await e(a,{config:r,...t.json?{report:()=>{}}:{}});t.json&&i(o),o.ok||(process.exitCode=1);return}case"run":{let{runForeground:e}=await import("./chunks/YD3MIP7B.js");await e({logToFiles:!!t.daemon});return}case"admin-broker":{let e=await import("./connector/admin-broker.js"),o=s[1]||"status";if(o==="install")e.installAdminBroker(a),i({installed:!0,available:await e.waitForAdminBroker()});else if(o==="uninstall")e.uninstallAdminBroker(a),i({installed:!1});else if(o==="restart"){if(await e.stopAdminBroker()==="busy")throw new Error(a("adminBroker.busy"));e.startAdminBrokerTask(a),i({available:await e.waitForAdminBroker()})}else if(o==="status")i({available:await e.adminBrokerStatus()});else throw new Error(`unknown administrator broker action: ${o}`);return}case"admin-shell":{let{runAdminShell:e}=await import("./chunks/YXDQ62BB.js");process.exitCode=await e(a);return}case"keepalive":{let e=await import("./chunks/OMN6C7J6.js"),o=s[1]||"status";if(o==="install"&&t.elevated){let{completeServiceInstall:p}=await import("./chunks/AM3OEMFK.js");process.exitCode=await p(a)}else if(o==="install")i(await e.install(r));else if(o==="uninstall")i(await e.uninstall(r));else if(o==="restart")i(e.restart(r));else if(o==="status")i(e.status(r));else throw new Error(`unknown keepalive action: ${o}`);return}case"plugin":{let e=await import("./chunks/XJKWLK43.js"),o=s[1]||"status";if(o==="link")i(e.register());else if(o==="unlink")i(e.unregister());else if(o==="status")i(e.registrationStatus());else throw new Error(`unknown plugin action: ${o}`);return}case"config":{i({configPath:g(),stateDir:h(),config:r});return}default:process.stderr.write(`herdr-remote: unknown command "${l}"
44
+
45
+ ${f}`),process.exitCode=2}}function M(){O().catch(n=>{process.stderr.write(`herdr-remote: ${n.message}
46
+ `),process.exitCode=1})}export{b as describeStatus,E as parseArgs,M as run};
@@ -1,302 +1,3 @@
1
- import { execFileSync } from 'node:child_process';
2
- import fs from 'node:fs';
3
- import net from 'node:net';
4
- import path from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { PtySession } from '../pty-session.js';
7
- import { stateDir } from '../paths.js';
8
- import { ADMIN_BROKER_MAX_MESSAGE_BYTES, adminBrokerTaskName, adminBrokerTokenMatches, connectAdminBroker, listenAdminBroker, publishAdminBrokerEndpoint, sendAdminBrokerMessage, } from './adminBrokerEndpoint.js';
9
- const BROKER_PING_TIMEOUT_MS = 1_000;
10
- const BROKER_START_TIMEOUT_MS = 5_000;
11
- const BROKER_START_POLL_MS = 250;
12
- const BROKER_TASK_END_TIMEOUT_MS = 10_000;
13
- /** Time for a stopping broker's goodbye to reach the caller before the process ends. */
14
- const BROKER_EXIT_GRACE_MS = 1_000;
15
- function powershellQuote(value) {
16
- return `'${value.replaceAll("'", "''")}'`;
17
- }
18
- function runPowerShell(script, t) {
19
- try {
20
- execFileSync('powershell.exe', [
21
- '-NoProfile',
22
- '-NonInteractive',
23
- '-EncodedCommand',
24
- Buffer.from(script, 'utf16le').toString('base64'),
25
- ], {
26
- stdio: 'pipe',
27
- windowsHide: true,
28
- timeout: 15_000,
29
- });
30
- }
31
- catch {
32
- throw new Error(t('adminBroker.needsElevation'));
33
- }
34
- }
35
- /** Registers and starts the broker's logon task; run elevated. */
36
- export function adminBrokerTaskScript() {
37
- const brokerPath = fileURLToPath(import.meta.url);
38
- // Pinned so the broker publishes its endpoint where this install's callers look.
39
- const brokerCommand = `$env:HERDR_REMOTE_STATE_DIR = ${powershellQuote(stateDir())}; & ${powershellQuote(process.execPath)} ${powershellQuote(brokerPath)}`;
40
- const encodedBrokerCommand = Buffer.from(brokerCommand, 'utf16le').toString('base64');
41
- const powershell = path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
42
- // Not PACKAGE_ROOT: npm updates the package by renaming its directory, and
43
- // Windows refuses while it is the working directory of this long-lived task.
44
- return `
45
- $ErrorActionPreference = 'Stop'
46
- $taskName = ${powershellQuote(adminBrokerTaskName())}
47
- $user = [Security.Principal.WindowsIdentity]::GetCurrent().Name
48
- $action = New-ScheduledTaskAction -Execute ${powershellQuote(powershell)} -Argument ${powershellQuote(`-NoProfile -NonInteractive -WindowStyle Hidden -EncodedCommand ${encodedBrokerCommand}`)} -WorkingDirectory ${powershellQuote(stateDir())}
49
- $trigger = New-ScheduledTaskTrigger -AtLogOn -User $user
50
- $principal = New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Highest
51
- $settings = New-ScheduledTaskSettingsSet -MultipleInstances IgnoreNew -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Seconds 0)
52
- Stop-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
53
- Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null
54
- Start-ScheduledTask -TaskName $taskName
55
- `;
56
- }
57
- export function installAdminBroker(t) {
58
- if (process.platform !== 'win32')
59
- throw new Error(t('adminBroker.windowsOnly'));
60
- // The task cannot start in a working directory that does not exist yet.
61
- fs.mkdirSync(stateDir(), { recursive: true });
62
- runPowerShell(adminBrokerTaskScript(), t);
63
- }
64
- export function uninstallAdminBroker(t) {
65
- if (process.platform !== 'win32')
66
- throw new Error(t('adminBroker.windowsOnly'));
67
- runPowerShell(`
68
- $ErrorActionPreference = 'Stop'
69
- $taskName = ${powershellQuote(adminBrokerTaskName())}
70
- Stop-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
71
- Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
72
- `, t);
73
- }
74
- /** Send the broker one request and read the type of its one reply, or null without one. */
75
- function requestAdminBroker(type) {
76
- let broker;
77
- try {
78
- broker = connectAdminBroker();
79
- }
80
- catch {
81
- return Promise.resolve(null);
82
- }
83
- const { socket, token } = broker;
84
- return new Promise((resolve) => {
85
- let settled = false;
86
- let response = '';
87
- const finish = (reply) => {
88
- if (settled)
89
- return;
90
- settled = true;
91
- socket.destroy();
92
- resolve(reply);
93
- };
94
- socket.setTimeout(BROKER_PING_TIMEOUT_MS, () => finish(null));
95
- socket.setEncoding('utf8');
96
- socket.on('connect', () => sendAdminBrokerMessage(socket, { type, token }));
97
- socket.on('data', (chunk) => {
98
- response += chunk;
99
- const newline = response.indexOf('\n');
100
- if (newline < 0)
101
- return;
102
- try {
103
- finish(String(JSON.parse(response.slice(0, newline)).type));
104
- }
105
- catch {
106
- finish(null);
107
- }
108
- });
109
- socket.on('error', () => finish(null));
110
- });
111
- }
112
- export async function adminBrokerStatus() {
113
- return (await requestAdminBroker('ping')) === 'pong';
114
- }
115
- /**
116
- * Ask the broker to exit so its task can start it on a new release. It stays
117
- * while an administrator terminal is open: that terminal may be the one asking.
118
- * A broker from before this request answers neither way.
119
- */
120
- export async function stopAdminBroker() {
121
- const reply = await requestAdminBroker('shutdown');
122
- return reply === 'bye' ? 'stopped' : reply === 'busy' ? 'busy' : 'unavailable';
123
- }
124
- /** Start the broker's task now, which the account that registered it may do unelevated. */
125
- export function startAdminBrokerTask(t) {
126
- if (process.platform !== 'win32')
127
- throw new Error(t('adminBroker.windowsOnly'));
128
- runPowerShell(`
129
- $ErrorActionPreference = 'Stop'
130
- $taskName = ${powershellQuote(adminBrokerTaskName())}
131
- # A broker that was just stopped may still be ending, and IgnoreNew drops a start until it has.
132
- $deadline = [DateTime]::UtcNow.AddMilliseconds(${BROKER_TASK_END_TIMEOUT_MS})
133
- while ((Get-ScheduledTask -TaskName $taskName).State -eq 'Running' -and [DateTime]::UtcNow -lt $deadline) { Start-Sleep -Milliseconds ${BROKER_START_POLL_MS} }
134
- Start-ScheduledTask -TaskName $taskName
135
- `, t);
136
- }
137
- /** The task starts the broker a moment after it is registered; wait for it to answer. */
138
- export async function waitForAdminBroker() {
139
- const deadline = Date.now() + BROKER_START_TIMEOUT_MS;
140
- while (!(await adminBrokerStatus())) {
141
- if (Date.now() >= deadline)
142
- return false;
143
- await new Promise((resolve) => setTimeout(resolve, BROKER_START_POLL_MS));
144
- }
145
- return true;
146
- }
147
- function writeError(socket, error) {
148
- const message = error instanceof Error ? error.message : String(error);
149
- sendAdminBrokerMessage(socket, { type: 'error', message });
150
- socket.end();
151
- }
152
- function startBrokerPty(socket, message, spawn) {
153
- if (typeof message.command !== 'string' || !message.command || message.command.length > 4096)
154
- throw new Error('Invalid administrator terminal command.');
155
- if (path.basename(message.command).toLowerCase() !== 'powershell.exe')
156
- throw new Error('The administrator broker only starts PowerShell.');
157
- if (!Array.isArray(message.args) ||
158
- message.args.length > 128 ||
159
- !message.args.every((arg) => typeof arg === 'string'))
160
- throw new Error('Invalid administrator terminal arguments.');
161
- if (message.args.length !== 2 ||
162
- message.args[0] !== '-NoLogo' ||
163
- message.args[1] !== '-NoProfile')
164
- throw new Error('The administrator broker only starts an interactive PowerShell prompt.');
165
- if (typeof message.cwd !== 'string' || message.cwd.length > 4096)
166
- throw new Error('Invalid administrator terminal working directory.');
167
- if (message.socketPath !== null && message.socketPath !== undefined)
168
- throw new Error('An administrator PowerShell session does not use a Herdr socket.');
169
- const pty = new PtySession({
170
- command: message.command,
171
- args: message.args,
172
- cwd: message.cwd,
173
- socketPath: message.socketPath,
174
- platform: 'win32',
175
- // A plain PowerShell prompt does not need the Herdr UI's Kitty or mouse modes.
176
- fastWindowsPty: true,
177
- spawn,
178
- });
179
- pty.start({
180
- cols: PtySession.clampDimension(message.cols, PtySession.DEFAULT_COLS),
181
- rows: PtySession.clampDimension(message.rows, PtySession.DEFAULT_ROWS),
182
- onData: (data) => {
183
- if (socket.writable)
184
- sendAdminBrokerMessage(socket, {
185
- type: 'data',
186
- dataBase64: Buffer.from(data).toString('base64'),
187
- });
188
- },
189
- onExit: ({ exitCode, signal }) => {
190
- if (socket.writable)
191
- sendAdminBrokerMessage(socket, { type: 'exit', exitCode, signal });
192
- socket.end();
193
- },
194
- });
195
- sendAdminBrokerMessage(socket, { type: 'started', pid: pty.terminal?.pid ?? 0 });
196
- return pty;
197
- }
198
- /** Listen on loopback and publish the endpoint; every request must carry its token. */
199
- export function serveAdminBroker({ spawn, onShutdown = () => { }, } = {}) {
200
- let token = '';
201
- const sessions = new Set();
202
- const server = net.createServer((socket) => {
203
- socket.setEncoding('utf8');
204
- let pending = '';
205
- let pty = null;
206
- let firstMessage = true;
207
- socket.on('data', (chunk) => {
208
- pending += chunk;
209
- if (Buffer.byteLength(pending, 'utf8') > ADMIN_BROKER_MAX_MESSAGE_BYTES) {
210
- socket.destroy(new Error('Administrator terminal message exceeded the limit.'));
211
- return;
212
- }
213
- while (true) {
214
- const newline = pending.indexOf('\n');
215
- if (newline < 0)
216
- return;
217
- const line = pending.slice(0, newline);
218
- pending = pending.slice(newline + 1);
219
- let message;
220
- try {
221
- message = JSON.parse(line);
222
- }
223
- catch {
224
- writeError(socket, new Error('Invalid administrator terminal message.'));
225
- return;
226
- }
227
- if (firstMessage) {
228
- firstMessage = false;
229
- if (!adminBrokerTokenMatches(token, message.token)) {
230
- writeError(socket, new Error('Administrator terminal request was not authorized.'));
231
- return;
232
- }
233
- if (message.type === 'ping') {
234
- sendAdminBrokerMessage(socket, { type: 'pong' });
235
- socket.end();
236
- return;
237
- }
238
- if (message.type === 'shutdown') {
239
- const busy = sessions.size > 0;
240
- sendAdminBrokerMessage(socket, { type: busy ? 'busy' : 'bye' });
241
- socket.end();
242
- if (!busy) {
243
- server.close();
244
- onShutdown();
245
- }
246
- return;
247
- }
248
- if (message.type !== 'start') {
249
- writeError(socket, new Error('Expected an administrator terminal start request.'));
250
- return;
251
- }
252
- try {
253
- pty = startBrokerPty(socket, message, spawn);
254
- sessions.add(pty);
255
- }
256
- catch (error) {
257
- writeError(socket, error);
258
- return;
259
- }
260
- continue;
261
- }
262
- if (!pty)
263
- return;
264
- if (message.type === 'input' && typeof message.dataBase64 === 'string') {
265
- if (message.dataBase64.length <= ADMIN_BROKER_MAX_MESSAGE_BYTES)
266
- pty.write(Buffer.from(message.dataBase64, 'base64'));
267
- }
268
- else if (message.type === 'resize') {
269
- pty.resize(message.cols, message.rows);
270
- }
271
- else if (message.type === 'kill') {
272
- pty.kill();
273
- socket.end();
274
- return;
275
- }
276
- }
277
- });
278
- const release = () => {
279
- if (!pty)
280
- return;
281
- pty.kill();
282
- sessions.delete(pty);
283
- };
284
- socket.on('close', release);
285
- socket.on('error', release);
286
- });
287
- listenAdminBroker(server, (port) => {
288
- token = publishAdminBrokerEndpoint(port);
289
- });
290
- return server;
291
- }
292
- function runAdminBroker() {
293
- if (process.platform !== 'win32')
294
- throw new Error('Administrator PTYs are only supported on Windows.');
295
- serveAdminBroker({
296
- onShutdown: () => setTimeout(() => process.exit(0), BROKER_EXIT_GRACE_MS).unref(),
297
- }).on('error', (error) => {
298
- process.stderr.write(`herdr-remote administrator broker: ${error.message}\n`);
299
- });
300
- }
301
- if (path.basename(process.argv[1] || '') === 'admin-broker.js')
302
- runAdminBroker();
1
+ import { createRequire as __herdrCreateRequire } from 'node:module';
2
+ const require = __herdrCreateRequire(import.meta.url);
3
+ import{e as a,f as b,g as c,h as d,i as e,j as f,k as g,l as h}from"../chunks/42KARAL4.js";import"../chunks/TNLCNVA2.js";import"../chunks/I6NRCYLI.js";export{d as adminBrokerStatus,a as adminBrokerTaskScript,b as installAdminBroker,h as serveAdminBroker,f as startAdminBrokerTask,e as stopAdminBroker,c as uninstallAdminBroker,g as waitForAdminBroker};