herdr-remote-relay 0.3.19 → 0.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/protocol/messages.d.ts +17 -8
- package/dist/protocol/messages.js +2 -2
- package/dist/server/client-channel.js +27 -2
- package/dist/server/host-broadcasts.d.ts +1 -1
- package/dist/server/host-broadcasts.js +2 -1
- package/dist/server/host-channel.js +1 -1
- package/dist/server/sessions.js +1 -10
- package/dist/server/types.d.ts +3 -2
- package/package.json +1 -1
- package/web/dist/assets/index-C_RZHFCw.js +61 -0
- package/web/dist/index.html +1 -1
- package/web/dist/assets/index-CrQV6NpQ.js +0 -61
|
@@ -9,8 +9,8 @@ export declare const CAPABILITY: {
|
|
|
9
9
|
readonly idleHeartbeat: "idle_heartbeat";
|
|
10
10
|
/** The host routes output by 16-bit stream index (v2 frames). */
|
|
11
11
|
readonly binaryFrameV2: "binary_frame_v2";
|
|
12
|
-
/** The host can
|
|
13
|
-
readonly
|
|
12
|
+
/** The host can open an elevated PowerShell as a tab of its Windows Herdr. */
|
|
13
|
+
readonly adminTabs: "admin_tabs";
|
|
14
14
|
};
|
|
15
15
|
export type ClientRole = 'controller' | 'viewer';
|
|
16
16
|
export type HostShellProfile = 'posix' | 'cmd' | 'powershell' | 'git-bash';
|
|
@@ -19,8 +19,6 @@ export interface ClientHelloMessage {
|
|
|
19
19
|
protocol: 1;
|
|
20
20
|
token?: string;
|
|
21
21
|
pairCode?: string;
|
|
22
|
-
/** Open this window's PTY through the host's pre-authorized admin broker. */
|
|
23
|
-
adminTerminal?: boolean;
|
|
24
22
|
clientId: string;
|
|
25
23
|
cols: number;
|
|
26
24
|
rows: number;
|
|
@@ -54,6 +52,13 @@ export interface ClientPasteFileMessage {
|
|
|
54
52
|
export interface ClientHerdrStartMessage {
|
|
55
53
|
type: 'herdr_start';
|
|
56
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Open an elevated PowerShell as a new tab of the workstation's Herdr. Carries
|
|
57
|
+
* nothing: the host decides what runs, through its own pre-authorized broker.
|
|
58
|
+
*/
|
|
59
|
+
export interface ClientAdminTabOpenMessage {
|
|
60
|
+
type: 'admin_tab_open';
|
|
61
|
+
}
|
|
57
62
|
/** One slice of an announced font file, by the file's hash. */
|
|
58
63
|
export interface ClientHostFontChunkRequestMessage {
|
|
59
64
|
type: 'host_font_chunk_request';
|
|
@@ -71,7 +76,7 @@ export interface ClientHostFontSubsetRequestMessage {
|
|
|
71
76
|
export interface ClientHostFontRefreshMessage {
|
|
72
77
|
type: 'host_font_refresh';
|
|
73
78
|
}
|
|
74
|
-
export type ClientJsonMessage = ClientHelloMessage | ClientHostFontChunkRequestMessage | ClientHostFontSubsetRequestMessage | ClientHostFontRefreshMessage | ClientClaimControlMessage | ClientReleaseControlMessage | ClientResizeMessage | ClientPingMessage | ClientPasteFileMessage | ClientHerdrStartMessage;
|
|
79
|
+
export type ClientJsonMessage = ClientHelloMessage | ClientHostFontChunkRequestMessage | ClientHostFontSubsetRequestMessage | ClientHostFontRefreshMessage | ClientClaimControlMessage | ClientReleaseControlMessage | ClientResizeMessage | ClientPingMessage | ClientPasteFileMessage | ClientHerdrStartMessage | ClientAdminTabOpenMessage;
|
|
75
80
|
export interface ServerReadyMessage {
|
|
76
81
|
type: 'ready';
|
|
77
82
|
role: ClientRole;
|
|
@@ -80,7 +85,7 @@ export interface ServerReadyMessage {
|
|
|
80
85
|
hostname?: string;
|
|
81
86
|
platform?: string;
|
|
82
87
|
shellProfile?: HostShellProfile;
|
|
83
|
-
/** The relay and Windows host both
|
|
88
|
+
/** The relay and Windows host can both open an administrator terminal tab. */
|
|
84
89
|
adminTerminalSupported?: boolean;
|
|
85
90
|
clientId?: string;
|
|
86
91
|
terminalPalette?: HostTerminalPalette | null;
|
|
@@ -180,6 +185,8 @@ export interface ServerUpdateStatusMessage {
|
|
|
180
185
|
latest: string;
|
|
181
186
|
updateAvailable: boolean;
|
|
182
187
|
restartPending: boolean;
|
|
188
|
+
/** The workstation has `herdr-remote update`, which installs and restarts in one step. */
|
|
189
|
+
updateCommand: boolean;
|
|
183
190
|
}
|
|
184
191
|
/** The workstation re-read its terminal font; sent to every window. */
|
|
185
192
|
export interface ServerTerminalFontMessage {
|
|
@@ -291,7 +298,6 @@ export interface RelaySessionStartMessage extends StreamAddressed {
|
|
|
291
298
|
cols: number;
|
|
292
299
|
rows: number;
|
|
293
300
|
role: ClientRole;
|
|
294
|
-
adminTerminal?: boolean;
|
|
295
301
|
/** Present when the host negotiated v2 frames and an index was free. */
|
|
296
302
|
streamIndex?: number;
|
|
297
303
|
}
|
|
@@ -306,6 +312,9 @@ export interface RelayResizeMessage extends StreamAddressed {
|
|
|
306
312
|
export interface RelayHerdrStartMessage extends StreamAddressed {
|
|
307
313
|
type: 'herdr_start';
|
|
308
314
|
}
|
|
315
|
+
export interface RelayAdminTabOpenMessage extends StreamAddressed {
|
|
316
|
+
type: 'admin_tab_open';
|
|
317
|
+
}
|
|
309
318
|
export interface RelayHostFontRefreshMessage extends StreamAddressed {
|
|
310
319
|
type: 'host_font_refresh';
|
|
311
320
|
}
|
|
@@ -331,5 +340,5 @@ export interface RelayErrorMessage {
|
|
|
331
340
|
code: string;
|
|
332
341
|
message: string;
|
|
333
342
|
}
|
|
334
|
-
export type RelayToHostMessage = RelayHostReadyMessage | RelayClientCountMessage | RelaySessionStartMessage | RelaySessionStopMessage | RelayResizeMessage | RelayHerdrStartMessage | RelayHostFontRefreshMessage | RelayHostFontChunkRequestMessage | RelayHostFontSubsetRequestMessage | RelayPasteFileMessage | RelayErrorMessage;
|
|
343
|
+
export type RelayToHostMessage = RelayHostReadyMessage | RelayClientCountMessage | RelaySessionStartMessage | RelaySessionStopMessage | RelayResizeMessage | RelayHerdrStartMessage | RelayAdminTabOpenMessage | RelayHostFontRefreshMessage | RelayHostFontChunkRequestMessage | RelayHostFontSubsetRequestMessage | RelayPasteFileMessage | RelayErrorMessage;
|
|
335
344
|
export {};
|
|
@@ -15,6 +15,6 @@ export const CAPABILITY = {
|
|
|
15
15
|
idleHeartbeat: 'idle_heartbeat',
|
|
16
16
|
/** The host routes output by 16-bit stream index (v2 frames). */
|
|
17
17
|
binaryFrameV2: 'binary_frame_v2',
|
|
18
|
-
/** The host can
|
|
19
|
-
|
|
18
|
+
/** The host can open an elevated PowerShell as a tab of its Windows Herdr. */
|
|
19
|
+
adminTabs: 'admin_tabs',
|
|
20
20
|
};
|
|
@@ -10,6 +10,8 @@ import { enqueueDelayedSend, notifyHostClientCount } from './transport.js';
|
|
|
10
10
|
const HERDR_START_REPEAT_MS = 3_000;
|
|
11
11
|
/** A window asks its workstation to re-read the terminal font at most this often. */
|
|
12
12
|
const FONT_REFRESH_REPEAT_MS = 2_000;
|
|
13
|
+
/** A window opens an administrator tab at most this often. */
|
|
14
|
+
const ADMIN_TAB_REPEAT_MS = 1_000;
|
|
13
15
|
function verifyImageMagicBytes(mime, dataBase64) {
|
|
14
16
|
if (typeof dataBase64 !== 'string' || dataBase64.length === 0)
|
|
15
17
|
return false;
|
|
@@ -86,7 +88,6 @@ export function handleClientConnection(relay, ws, req) {
|
|
|
86
88
|
// Stable per browser profile; used to recognise a reconnect from the
|
|
87
89
|
// same browser rather than a genuinely separate viewer.
|
|
88
90
|
browserClientId: typeof message.clientId === 'string' ? message.clientId.slice(0, 128) : null,
|
|
89
|
-
adminTerminal: message.adminTerminal === true,
|
|
90
91
|
handoffCapable: Array.isArray(message.capabilities) &&
|
|
91
92
|
message.capabilities.includes(CAPABILITY.hostHandoff),
|
|
92
93
|
session: null,
|
|
@@ -139,7 +140,7 @@ export function handleClientConnection(relay, ws, req) {
|
|
|
139
140
|
hostname: host.hostname,
|
|
140
141
|
platform: host.platform,
|
|
141
142
|
...(host.shellProfile ? { shellProfile: host.shellProfile } : {}),
|
|
142
|
-
adminTerminalSupported: host.
|
|
143
|
+
adminTerminalSupported: host.adminTabsAvailable,
|
|
143
144
|
clientId: client.id,
|
|
144
145
|
// Delivered with `ready`, before the first PTY byte, so the terminal
|
|
145
146
|
// is painted in the host's colors from its very first frame.
|
|
@@ -259,6 +260,30 @@ function handleClientMessage(relay, client, raw, isBinary) {
|
|
|
259
260
|
});
|
|
260
261
|
}
|
|
261
262
|
}
|
|
263
|
+
else if (message.type === 'admin_tab_open') {
|
|
264
|
+
// Routed like herdr_start. The host runs the fixed elevated PowerShell of
|
|
265
|
+
// its own broker; nothing in this message chooses what starts.
|
|
266
|
+
if (!client.session || !isOpen(host.ws))
|
|
267
|
+
return;
|
|
268
|
+
if (!host.adminTabsAvailable) {
|
|
269
|
+
jsonSend(client.ws, {
|
|
270
|
+
type: 'error',
|
|
271
|
+
code: 'admin_terminal_unsupported',
|
|
272
|
+
message: 'Update the host connector to open administrator terminals.',
|
|
273
|
+
});
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// A double tap is one request; a second tab needs a second, later tap.
|
|
277
|
+
const now = Date.now();
|
|
278
|
+
if (client.adminTabAt && now - client.adminTabAt < ADMIN_TAB_REPEAT_MS)
|
|
279
|
+
return;
|
|
280
|
+
client.adminTabAt = now;
|
|
281
|
+
jsonSend(host.ws, {
|
|
282
|
+
type: 'admin_tab_open',
|
|
283
|
+
clientId: client.session.streamId,
|
|
284
|
+
streamId: client.session.streamId,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
262
287
|
else if (message.type === 'host_font_chunk_request') {
|
|
263
288
|
requestFontChunk(host, client, message);
|
|
264
289
|
}
|
|
@@ -16,7 +16,7 @@ type Unchecked<T> = {
|
|
|
16
16
|
export declare function broadcastAgentStatus(relay: RelayContext, host: RelayHost, message: Unchecked<HostAgentStatusMessage>): void;
|
|
17
17
|
/**
|
|
18
18
|
* Whether the workstation runs the newest herdr-remote, for every window on
|
|
19
|
-
* it. Only version strings and
|
|
19
|
+
* it. Only version strings and three flags pass: this ends up as text in the
|
|
20
20
|
* browser, and the host is not the relay's to trust.
|
|
21
21
|
*/
|
|
22
22
|
export declare function broadcastUpdateStatus(relay: RelayContext, host: RelayHost, message: Unchecked<HostUpdateStatusMessage>): void;
|
|
@@ -51,7 +51,7 @@ export function broadcastAgentStatus(relay, host, message) {
|
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
53
|
* Whether the workstation runs the newest herdr-remote, for every window on
|
|
54
|
-
* it. Only version strings and
|
|
54
|
+
* it. Only version strings and three flags pass: this ends up as text in the
|
|
55
55
|
* browser, and the host is not the relay's to trust.
|
|
56
56
|
*/
|
|
57
57
|
export function broadcastUpdateStatus(relay, host, message) {
|
|
@@ -67,6 +67,7 @@ export function broadcastUpdateStatus(relay, host, message) {
|
|
|
67
67
|
latest,
|
|
68
68
|
updateAvailable: message.updateAvailable === true,
|
|
69
69
|
restartPending: message.restartPending === true,
|
|
70
|
+
updateCommand: message.updateCommand === true,
|
|
70
71
|
};
|
|
71
72
|
host.updateStatus = payload;
|
|
72
73
|
broadcastToClients(relay, host, () => payload);
|
|
@@ -16,7 +16,7 @@ function createHostRecord(message, ws, pending, clients = new Set()) {
|
|
|
16
16
|
hostname: typeof message.hostname === 'string' ? message.hostname.slice(0, 128) : os.hostname(),
|
|
17
17
|
platform: typeof message.platform === 'string' ? message.platform.slice(0, 32) : process.platform,
|
|
18
18
|
...(message.shellProfile === 'git-bash' ? { shellProfile: message.shellProfile } : {}),
|
|
19
|
-
|
|
19
|
+
adminTabsAvailable: capabilities.includes(CAPABILITY.adminTabs),
|
|
20
20
|
arch: typeof message.arch === 'string' ? message.arch.slice(0, 32) : process.arch,
|
|
21
21
|
connectedAt: new Date(pending.connectedAt).toISOString(),
|
|
22
22
|
connectedAtMs: pending.connectedAt,
|
package/dist/server/sessions.js
CHANGED
|
@@ -34,14 +34,6 @@ export function releaseSession(relay, host, client) {
|
|
|
34
34
|
export function startSession(relay, host, client, { restarted = false } = {}) {
|
|
35
35
|
if (!client || !isOpen(host.ws))
|
|
36
36
|
return;
|
|
37
|
-
if (client.adminTerminal && !host.adminSessionsAvailable) {
|
|
38
|
-
jsonSend(client.ws, {
|
|
39
|
-
type: 'error',
|
|
40
|
-
code: 'admin_terminal_unsupported',
|
|
41
|
-
message: 'Update the host connector to support administrator terminals.',
|
|
42
|
-
});
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
37
|
const streamId = randomId('session');
|
|
46
38
|
let streamIndex = null;
|
|
47
39
|
if (host.binaryFrameV2) {
|
|
@@ -65,7 +57,6 @@ export function startSession(relay, host, client, { restarted = false } = {}) {
|
|
|
65
57
|
cols: Math.max(MIN_SESSION_COLS, client.cols),
|
|
66
58
|
rows: Math.max(MIN_SESSION_ROWS, client.rows),
|
|
67
59
|
role: 'controller',
|
|
68
|
-
...(client.adminTerminal ? { adminTerminal: true } : {}),
|
|
69
60
|
...(streamIndex !== null ? { streamIndex } : {}),
|
|
70
61
|
});
|
|
71
62
|
if (restarted) {
|
|
@@ -77,7 +68,7 @@ export function startSession(relay, host, client, { restarted = false } = {}) {
|
|
|
77
68
|
hostname: host.hostname,
|
|
78
69
|
platform: host.platform,
|
|
79
70
|
...(host.shellProfile ? { shellProfile: host.shellProfile } : {}),
|
|
80
|
-
adminTerminalSupported: host.
|
|
71
|
+
adminTerminalSupported: host.adminTabsAvailable,
|
|
81
72
|
terminalPalette: host.terminalPalette || null,
|
|
82
73
|
terminalFont: host.terminalFont || null,
|
|
83
74
|
});
|
package/dist/server/types.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ export interface RelayHost {
|
|
|
24
24
|
hostname: string;
|
|
25
25
|
platform: string;
|
|
26
26
|
shellProfile?: HostShellProfile;
|
|
27
|
-
|
|
27
|
+
/** The host can open an administrator terminal as a Herdr tab. */
|
|
28
|
+
adminTabsAvailable: boolean;
|
|
28
29
|
arch: string;
|
|
29
30
|
connectedAt: string;
|
|
30
31
|
connectedAtMs: number;
|
|
@@ -59,7 +60,6 @@ export interface RelayClient {
|
|
|
59
60
|
deviceId: string;
|
|
60
61
|
/** Stable per browser profile, supplied by the browser itself. */
|
|
61
62
|
browserClientId: string | null;
|
|
62
|
-
adminTerminal: boolean;
|
|
63
63
|
handoffCapable: boolean;
|
|
64
64
|
session: ClientSession | null;
|
|
65
65
|
role: ClientRole;
|
|
@@ -75,6 +75,7 @@ export interface RelayClient {
|
|
|
75
75
|
cols: number;
|
|
76
76
|
rows: number;
|
|
77
77
|
herdrStartAt?: number;
|
|
78
|
+
adminTabAt?: number;
|
|
78
79
|
fontRefreshAt?: number;
|
|
79
80
|
/** When each outstanding font chunk request was sent. */
|
|
80
81
|
fontChunkRequests?: number[];
|