herdr-remote-relay 0.3.24 → 0.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,10 +11,12 @@ Brokers WebSocket connections between browsers and workstation host connectors.
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- npm install -g herdr-remote-relay
14
+ npm install -g https://github.com/dibin666/herdr-remote/releases/latest/download/herdr-remote-relay.tgz
15
15
  herdr-remote-relay --public-url https://herdr.example.com --password <password>
16
16
  ```
17
17
 
18
+ From npm instead: `npm install -g herdr-remote-relay` (it can lag a new release by a while).
19
+
18
20
  Requirements: Node.js 22+, TLS reverse proxy (nginx, Caddy, Cloudflare Tunnel).
19
21
 
20
22
  ## Docker
package/README.zh-CN.md CHANGED
@@ -11,10 +11,12 @@
11
11
  ## 安装
12
12
 
13
13
  ```bash
14
- npm install -g herdr-remote-relay
14
+ npm install -g https://github.com/dibin666/herdr-remote/releases/latest/download/herdr-remote-relay.tgz
15
15
  herdr-remote-relay --public-url https://herdr.example.com --password <密码>
16
16
  ```
17
17
 
18
+ 也可从 npm 安装:`npm install -g herdr-remote-relay`(新版本上线后 npm 可能要过一段时间才同步)。
19
+
18
20
  前置要求:Node.js 22+、TLS 反向代理(nginx、Caddy、Cloudflare Tunnel 等)。
19
21
 
20
22
  ## Docker 运行
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Validates the Herdr prefix keys crossing the wire, or read from a config
3
+ * file, into one canonical list: lowercase, no whitespace, no duplicates, at
4
+ * most `MAX_HERDR_PREFIX_KEYS` short entries. Herdr ignores entries it cannot
5
+ * read and so does this. `undefined` when nothing usable is left, so a host
6
+ * that says nothing and one that says garbage look the same.
7
+ */
8
+ export declare function sanitizeHerdrPrefixKeys(value: unknown): string[] | undefined;
@@ -0,0 +1,34 @@
1
+ // The keys that put the workstation's Herdr into prefix mode, as a host reads
2
+ // them from Herdr's config and a browser receives them. Browser-safe: no Node
3
+ // APIs, so the web app imports it.
4
+ /** Herdr accepts any number of prefix keys; a window has no use for more than this. */
5
+ const MAX_HERDR_PREFIX_KEYS = 8;
6
+ /** Longest real combo is `ctrl+shift+double_quote`; this leaves room for spelling variants. */
7
+ const MAX_HERDR_PREFIX_KEY_LENGTH = 32;
8
+ /**
9
+ * What the browser can act on: a key combo is printable ASCII (modifiers and
10
+ * key names joined by `+`). Whitespace is removed before this is tested.
11
+ */
12
+ const PREFIX_KEY = /^[\x21-\x7e]+$/;
13
+ /**
14
+ * Validates the Herdr prefix keys crossing the wire, or read from a config
15
+ * file, into one canonical list: lowercase, no whitespace, no duplicates, at
16
+ * most `MAX_HERDR_PREFIX_KEYS` short entries. Herdr ignores entries it cannot
17
+ * read and so does this. `undefined` when nothing usable is left, so a host
18
+ * that says nothing and one that says garbage look the same.
19
+ */
20
+ export function sanitizeHerdrPrefixKeys(value) {
21
+ if (!Array.isArray(value))
22
+ return undefined;
23
+ const keys = new Set();
24
+ for (const entry of value) {
25
+ if (keys.size >= MAX_HERDR_PREFIX_KEYS)
26
+ break;
27
+ if (typeof entry !== 'string')
28
+ continue;
29
+ const key = entry.replace(/\s+/g, '').toLowerCase();
30
+ if (key.length <= MAX_HERDR_PREFIX_KEY_LENGTH && PREFIX_KEY.test(key))
31
+ keys.add(key);
32
+ }
33
+ return keys.size > 0 ? [...keys] : undefined;
34
+ }
@@ -1,5 +1,7 @@
1
1
  export * from './frames.js';
2
2
  export * from './terminal.js';
3
+ export * from './herdr-keys.js';
3
4
  export * from './messages.js';
4
5
  export * from './paste.js';
6
+ export * from './release.js';
5
7
  export type * from './http.js';
@@ -3,5 +3,7 @@
3
3
  // packages build against; nothing here may be copied into the CLI or the web.
4
4
  export * from './frames.js';
5
5
  export * from './terminal.js';
6
+ export * from './herdr-keys.js';
6
7
  export * from './messages.js';
7
8
  export * from './paste.js';
9
+ export * from './release.js';
@@ -94,6 +94,11 @@ export interface ServerReadyMessage {
94
94
  clientCount?: number;
95
95
  /** The workstation's herdr-remote release; null when it is too old to say. */
96
96
  hostVersion?: string | null;
97
+ /**
98
+ * The keys that put the workstation's Herdr into prefix mode, lowercase,
99
+ * like `ctrl+b`. Left out when the host is too old to say.
100
+ */
101
+ herdrPrefixKeys?: string[];
97
102
  }
98
103
  export interface ServerPairedMessage {
99
104
  type: 'paired';
@@ -133,6 +138,8 @@ export interface ServerSessionRestartedMessage {
133
138
  terminalFont?: HostTerminalFont | null;
134
139
  /** As in `ready`: the host may have come back on another release. */
135
140
  hostVersion?: string | null;
141
+ /** As in `ready`: the host may have come back with another Herdr config. */
142
+ herdrPrefixKeys?: string[];
136
143
  }
137
144
  export interface ServerExitMessage {
138
145
  type: 'exit';
@@ -239,6 +246,11 @@ export interface HostHelloMessage {
239
246
  version?: string;
240
247
  terminalPalette?: HostTerminalPalette | null;
241
248
  terminalFont?: HostTerminalFont | null;
249
+ /**
250
+ * The keys `keys.prefix` in the workstation's Herdr config names, as the
251
+ * host read them. The relay sanitizes them; older connectors leave them out.
252
+ */
253
+ herdrPrefixKeys?: string[];
242
254
  capabilities?: string[];
243
255
  }
244
256
  /** One PTY the host is running, as the relay's status page lists it. */
@@ -0,0 +1,8 @@
1
+ /** Also the name an update check reports as its source. */
2
+ export declare const GITHUB_RELEASES_URL = "https://github.com/dibin666/herdr-remote/releases";
3
+ /** `{ schema, version, tag, relayVersion, tarball }`, attached to every release. */
4
+ export declare const LATEST_RELEASE_MANIFEST_URL = "https://github.com/dibin666/herdr-remote/releases/latest/download/latest.json";
5
+ /** The newest self-contained CLI tarball, for a workstation that cannot say which it needs. */
6
+ export declare const LATEST_CLI_TARBALL_URL = "https://github.com/dibin666/herdr-remote/releases/latest/download/herdr-remote.tgz";
7
+ /** One CLI release's self-contained tarball; it bundles the relay it was released with. */
8
+ export declare function cliTarballUrl(version: string): string;
@@ -0,0 +1,17 @@
1
+ // Where herdr-remote is released. The CLI updates from here and the browser
2
+ // shows the same addresses in its manual steps, so there is one definition.
3
+ //
4
+ // GitHub Releases is the primary channel: a release is downloadable the moment
5
+ // it is created, whereas npm can take many minutes after `npm publish` before
6
+ // a new version installs. npm carries the same tarballs as a fallback.
7
+ const RELEASE_REPOSITORY = 'dibin666/herdr-remote';
8
+ /** Also the name an update check reports as its source. */
9
+ export const GITHUB_RELEASES_URL = `https://github.com/${RELEASE_REPOSITORY}/releases`;
10
+ /** `{ schema, version, tag, relayVersion, tarball }`, attached to every release. */
11
+ export const LATEST_RELEASE_MANIFEST_URL = `${GITHUB_RELEASES_URL}/latest/download/latest.json`;
12
+ /** The newest self-contained CLI tarball, for a workstation that cannot say which it needs. */
13
+ export const LATEST_CLI_TARBALL_URL = `${GITHUB_RELEASES_URL}/latest/download/herdr-remote.tgz`;
14
+ /** One CLI release's self-contained tarball; it bundles the relay it was released with. */
15
+ export function cliTarballUrl(version) {
16
+ return `${GITHUB_RELEASES_URL}/download/herdr-remote-v${version}/herdr-remote-${version}.tgz`;
17
+ }
@@ -148,6 +148,7 @@ export function handleClientConnection(relay, ws, req) {
148
148
  terminalFont: host.terminalFont || null,
149
149
  clientCount: host.clients.size,
150
150
  hostVersion: host.version,
151
+ ...(host.herdrPrefixKeys ? { herdrPrefixKeys: host.herdrPrefixKeys } : {}),
151
152
  });
152
153
  if (host.agentStatus)
153
154
  jsonSend(ws, host.agentStatus);
@@ -1,7 +1,7 @@
1
1
  // The host side of the relay: a workstation's WebSocket, from its hello and
2
2
  // the hand-off from an older connection to every message it sends after.
3
3
  import os from 'node:os';
4
- import { CAPABILITY, PROTOCOL_VERSION, sanitizeTerminalFont, sanitizeTerminalPalette, unpackStreamFrame, } from '../protocol/index.js';
4
+ import { CAPABILITY, PROTOCOL_VERSION, sanitizeHerdrPrefixKeys, sanitizeTerminalFont, sanitizeTerminalPalette, unpackStreamFrame, } from '../protocol/index.js';
5
5
  import { forwardFontChunk, forwardFontSubset, settleFontChunk, settleFontSubset, } from './font-proxy.js';
6
6
  import { broadcastAgentStatus, broadcastTerminalFont, broadcastUpdateStatus, releaseVersion, } from './host-broadcasts.js';
7
7
  import { allowHostHandshake } from './requests.js';
@@ -10,6 +10,7 @@ import { closeSocket, isOpen, jsonSend, parseJson, randomId, rejectHandshake } f
10
10
  import { broadcastToClients, notifyHostClientCount, sendClientBinary } from './transport.js';
11
11
  function createHostRecord(message, ws, pending, clients = new Set()) {
12
12
  const capabilities = Array.isArray(message.capabilities) ? message.capabilities : [];
13
+ const herdrPrefixKeys = sanitizeHerdrPrefixKeys(message.herdrPrefixKeys);
13
14
  return {
14
15
  id: message.hostId,
15
16
  ws,
@@ -23,6 +24,7 @@ function createHostRecord(message, ws, pending, clients = new Set()) {
23
24
  terminalPalette: sanitizeTerminalPalette(message.terminalPalette),
24
25
  /** Family, size and fetchable files of the workstation's terminal font. */
25
26
  terminalFont: sanitizeTerminalFont(message.terminalFont),
27
+ ...(herdrPrefixKeys ? { herdrPrefixKeys } : {}),
26
28
  /** The latest workstation snapshot is replayed when a browser joins late. */
27
29
  agentStatus: null,
28
30
  /** Whether the workstation's herdr-remote is behind; replayed the same way. */
@@ -72,6 +72,7 @@ export function startSession(relay, host, client, { restarted = false } = {}) {
72
72
  terminalPalette: host.terminalPalette || null,
73
73
  terminalFont: host.terminalFont || null,
74
74
  hostVersion: host.version,
75
+ ...(host.herdrPrefixKeys ? { herdrPrefixKeys: host.herdrPrefixKeys } : {}),
75
76
  });
76
77
  }
77
78
  }
@@ -31,6 +31,8 @@ export interface RelayHost {
31
31
  connectedAtMs: number;
32
32
  terminalPalette: HostTerminalPalette | null;
33
33
  terminalFont: HostTerminalFont | null;
34
+ /** Sanitized `keys.prefix` of the host's Herdr; absent when the host did not say. */
35
+ herdrPrefixKeys?: string[];
34
36
  /** The latest agent summary, replayed to a window that joins late. */
35
37
  agentStatus: ServerAgentStatusMessage | null;
36
38
  /** Whether the workstation's herdr-remote is behind; replayed the same way. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "herdr-remote-relay",
3
- "version": "0.3.24",
3
+ "version": "0.3.26",
4
4
  "description": "Standalone relay server and web terminal for Herdr Remote",
5
5
  "license": "MIT",
6
6
  "type": "module",