ai-remote 0.4.8 → 0.4.10
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 +6 -0
- package/dist/cli.mjs +17 -6
- package/dist/index.d.ts +254 -12
- package/dist/protocols.d.ts +349 -0
- package/package.json +3 -3
- package/dist/protocols/index.d.ts +0 -33
- package/dist/protocols/rdp/buffer.d.ts +0 -38
- package/dist/protocols/rdp/caps.d.ts +0 -49
- package/dist/protocols/rdp/cert.d.ts +0 -18
- package/dist/protocols/rdp/client.d.ts +0 -56
- package/dist/protocols/rdp/cliprdr.d.ts +0 -27
- package/dist/protocols/rdp/credssp.d.ts +0 -34
- package/dist/protocols/rdp/crypto.d.ts +0 -63
- package/dist/protocols/rdp/display.d.ts +0 -38
- package/dist/protocols/rdp/gcc.d.ts +0 -23
- package/dist/protocols/rdp/keymap.d.ts +0 -9
- package/dist/protocols/rdp/mcs.d.ts +0 -40
- package/dist/protocols/rdp/ntlm.d.ts +0 -61
- package/dist/protocols/rdp/pdu.d.ts +0 -155
- package/dist/protocols/rdp/rail.d.ts +0 -119
- package/dist/protocols/rdp/rle.d.ts +0 -13
- package/dist/protocols/rdp/sec.d.ts +0 -59
- package/dist/protocols/rdp/session.d.ts +0 -62
- package/dist/protocols/rdp/tls.d.ts +0 -18
- package/dist/protocols/rdp/vchannel.d.ts +0 -28
- package/dist/protocols/rdp/x224.d.ts +0 -40
- package/dist/protocols/ssh/identity.d.ts +0 -39
- package/dist/protocols/ssh/kex.d.ts +0 -97
- package/dist/protocols/ssh/messages.d.ts +0 -52
- package/dist/protocols/ssh/session.d.ts +0 -67
- package/dist/protocols/ssh/terminal.d.ts +0 -46
- package/dist/protocols/ssh/transport.d.ts +0 -62
- package/dist/protocols/ssh/wire.d.ts +0 -52
- package/dist/protocols/types.d.ts +0 -127
- package/dist/protocols/vnc/des.d.ts +0 -25
- package/dist/protocols/vnc/input.d.ts +0 -5
- package/dist/protocols/vnc/keysyms.d.ts +0 -16
- package/dist/protocols/vnc/rfb.d.ts +0 -64
- package/dist/protocols/vnc/session.d.ts +0 -12
- package/dist/shared/connection.d.ts +0 -81
- package/dist/shared/device.d.ts +0 -26
- package/dist/shared/hosts.d.ts +0 -63
- package/dist/shared/icons.d.ts +0 -46
- package/dist/shared/protocol.d.ts +0 -32
- package/dist/shared/signals.d.ts +0 -37
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vocabulary both halves of the gateway share.
|
|
3
|
+
*
|
|
4
|
+
* The Worker and the browser have to agree on what a "protocol" is, what ports
|
|
5
|
+
* they default to and how an RDP security layer is named, so those live here
|
|
6
|
+
* rather than being re-declared on each side and drifting apart.
|
|
7
|
+
*/
|
|
8
|
+
/** A remote-desktop protocol the session workspace can display. */
|
|
9
|
+
declare const REMOTE_PROTOCOLS: readonly ['vnc', 'rdp'];
|
|
10
|
+
type RemoteProtocol = (typeof REMOTE_PROTOCOLS)[number];
|
|
11
|
+
/** Every protocol the gateway relays, including the terminal side panel. */
|
|
12
|
+
declare const TRANSPORT_PROTOCOLS: readonly ['vnc', 'rdp', 'ssh'];
|
|
13
|
+
type TransportProtocol = (typeof TRANSPORT_PROTOCOLS)[number];
|
|
14
|
+
/**
|
|
15
|
+
* The RDP security layer. `auto` negotiates with the host, which is right for
|
|
16
|
+
* anything that answers honestly; the rest are for hosts that do not.
|
|
17
|
+
*/
|
|
18
|
+
declare const RDP_SECURITY_MODES: readonly ['auto', 'nla', 'tls', 'rdp'];
|
|
19
|
+
type RdpSecurity = (typeof RDP_SECURITY_MODES)[number];
|
|
20
|
+
declare const DEFAULT_PORTS: Record<TransportProtocol, number>;
|
|
21
|
+
declare const DEFAULT_SSH_PORT: number;
|
|
22
|
+
/**
|
|
23
|
+
* How patient `runCommand` is, in three different senses.
|
|
24
|
+
*
|
|
25
|
+
* A single deadline cannot tell "the shell ignored me" apart from "the
|
|
26
|
+
* installer is three minutes into a download", and a short one turns every
|
|
27
|
+
* real piece of work -- a package install, a build, a large copy -- into a
|
|
28
|
+
* false failure that also leaves the command running on the far side.
|
|
29
|
+
*
|
|
30
|
+
* So the wait is judged by what the shell is doing. It has START_MS to
|
|
31
|
+
* acknowledge the command at all; after that it may take as long as it likes
|
|
32
|
+
* as long as it keeps printing, and only silence longer than IDLE_MS, or a run
|
|
33
|
+
* longer than MAX_MS, is treated as stuck.
|
|
34
|
+
*/
|
|
35
|
+
export declare const COMMAND_START_MS = 20000;
|
|
36
|
+
/** Max idle silence allowed during command execution. */
|
|
37
|
+
export declare const COMMAND_IDLE_MS: number;
|
|
38
|
+
declare function isRemoteProtocol(value: unknown): value is RemoteProtocol;
|
|
39
|
+
declare function isRdpSecurity(value: unknown): value is RdpSecurity;
|
|
40
|
+
/** Coerce anything to a protocol, falling back to what the caller opens on. */
|
|
41
|
+
declare function toRemoteProtocol(value: unknown, fallback?: RemoteProtocol): RemoteProtocol;
|
|
42
|
+
declare function toRdpSecurity(value: unknown, fallback?: RdpSecurity): RdpSecurity;
|
|
43
|
+
/** A port number, or the protocol's default when the value is not one. */
|
|
44
|
+
declare function toPort(value: unknown, fallback: number): number;
|
|
45
|
+
/** A published Windows application launched instead of the full desktop. */
|
|
46
|
+
interface RemoteAppLaunch {
|
|
47
|
+
/** Alias (`||notepad`) or an executable path. */
|
|
48
|
+
program: string;
|
|
49
|
+
workingDir?: string;
|
|
50
|
+
arguments?: string;
|
|
51
|
+
}
|
|
52
|
+
/** The companion terminal offered beside a desktop. */
|
|
53
|
+
interface SshCompanion {
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
port: number;
|
|
56
|
+
username: string;
|
|
57
|
+
}
|
|
58
|
+
/** Picture and input options. VNC negotiates them; RDP and SSH ignore what does not apply. */
|
|
59
|
+
interface DisplaySettings {
|
|
60
|
+
/** RFB quality level, 1 (smallest) to 9 (sharpest). */
|
|
61
|
+
quality: number;
|
|
62
|
+
/** RFB compression level, 0 (fastest) to 9 (smallest). */
|
|
63
|
+
compression: number;
|
|
64
|
+
/** Fit the remote desktop to the pane rather than scrolling it. */
|
|
65
|
+
scaling: boolean;
|
|
66
|
+
/** Watch without sending keyboard or pointer input. */
|
|
67
|
+
viewOnly: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Everything a session needs. `password` is the only field never persisted
|
|
71
|
+
* anywhere -- not in the device library on the gateway, not in localStorage.
|
|
72
|
+
*/
|
|
73
|
+
interface ConnectionSettings {
|
|
74
|
+
/** Stable identity: protocol, address, port and program. See {@link connectionId}. */
|
|
75
|
+
id: string;
|
|
76
|
+
label: string;
|
|
77
|
+
protocol: RemoteProtocol;
|
|
78
|
+
host: string;
|
|
79
|
+
port: number;
|
|
80
|
+
username: string;
|
|
81
|
+
password: string;
|
|
82
|
+
/** Windows domain or computer name. RDP only. */
|
|
83
|
+
domain: string;
|
|
84
|
+
security: RdpSecurity;
|
|
85
|
+
remoteApp: RemoteAppLaunch | null;
|
|
86
|
+
display: DisplaySettings;
|
|
87
|
+
ssh: SshCompanion;
|
|
88
|
+
/** Open the terminal panel as soon as the desktop appears. */
|
|
89
|
+
openSshOnConnect: boolean;
|
|
90
|
+
}
|
|
91
|
+
declare const DEFAULT_DISPLAY_SETTINGS: DisplaySettings;
|
|
92
|
+
/**
|
|
93
|
+
* A connection's identity is what it points at, not when it was made. Editing
|
|
94
|
+
* the address therefore makes a different connection rather than silently
|
|
95
|
+
* repointing an existing card, which is the behaviour people expect from a
|
|
96
|
+
* list of machines.
|
|
97
|
+
*/
|
|
98
|
+
declare function connectionId(input: Pick<ConnectionSettings, 'protocol' | 'host' | 'port'> & {
|
|
99
|
+
remoteApp?: RemoteAppLaunch | null;
|
|
100
|
+
}): string;
|
|
101
|
+
/** A blank connection, ready for the dialog to fill in. */
|
|
102
|
+
declare function emptyConnection(protocol?: RemoteProtocol): ConnectionSettings;
|
|
103
|
+
declare function normalizeDisplaySettings(value: unknown): DisplaySettings;
|
|
104
|
+
/**
|
|
105
|
+
* Build a complete, valid connection out of whatever a caller happens to have.
|
|
106
|
+
* Partial input from a saved card, a host list entry, a URL or localStorage all
|
|
107
|
+
* arrive here, so the dialog never has to reason about missing fields.
|
|
108
|
+
*/
|
|
109
|
+
declare function normalizeConnection(input: Partial<ConnectionSettings> & Record<string, unknown>): ConnectionSettings;
|
|
110
|
+
/** What a connection is worth remembering by -- never the password. */
|
|
111
|
+
type PersistedConnection = Omit<ConnectionSettings, 'password'>;
|
|
112
|
+
declare function withoutPassword(settings: ConnectionSettings): PersistedConnection;
|
|
113
|
+
/** A one-line description for the dialog's summary row and the status bar. */
|
|
114
|
+
declare function describeConnection(settings: ConnectionSettings): string;
|
|
115
|
+
/** Where the pointer may go, in framebuffer pixels. */
|
|
116
|
+
export interface ScreenGeometry {
|
|
117
|
+
width: number;
|
|
118
|
+
height: number;
|
|
119
|
+
viewport: {
|
|
120
|
+
x: number;
|
|
121
|
+
y: number;
|
|
122
|
+
width: number;
|
|
123
|
+
height: number;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Mouse buttons, as the UI names them. */
|
|
127
|
+
type PointerButton = 0 | 1 | 2;
|
|
128
|
+
/** Wheel movement in discrete remote-protocol notches. Positive is right/down. */
|
|
129
|
+
interface ScrollDelta {
|
|
130
|
+
x: number;
|
|
131
|
+
y: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A live session. Both drivers expose this, so the AI pane's screen tool and
|
|
135
|
+
* the toolbar never have to ask which protocol they are driving.
|
|
136
|
+
*/
|
|
137
|
+
export interface RemoteSession extends EventTarget {
|
|
138
|
+
readonly protocol: RemoteProtocol;
|
|
139
|
+
disconnect(): void;
|
|
140
|
+
/** True once the desktop has been reached. */
|
|
141
|
+
readonly connected: boolean;
|
|
142
|
+
/** Fit the remote desktop to the pane rather than scrolling it. */
|
|
143
|
+
scaleViewport: boolean;
|
|
144
|
+
/** Watch without sending keyboard or pointer input. */
|
|
145
|
+
viewOnly: boolean;
|
|
146
|
+
/** RFB quality level. RDP ignores it. */
|
|
147
|
+
qualityLevel?: number;
|
|
148
|
+
/** RFB compression level. RDP ignores it. */
|
|
149
|
+
compressionLevel?: number;
|
|
150
|
+
/** The transport the metrics rail instruments. Can appear a tick after construction. */
|
|
151
|
+
readonly socket?: WebSocket | null;
|
|
152
|
+
readonly screenGeometry: ScreenGeometry;
|
|
153
|
+
movePointer(x: number, y: number): boolean;
|
|
154
|
+
clickPointer(x: number, y: number, button?: PointerButton): boolean;
|
|
155
|
+
pointerButton(x: number, y: number, button?: PointerButton, pressed?: boolean): boolean;
|
|
156
|
+
scrollPointer(x: number, y: number, delta: ScrollDelta): boolean;
|
|
157
|
+
typeText(text: string): boolean;
|
|
158
|
+
/** Prefer the protocol clipboard for longer text when it can paste reliably. */
|
|
159
|
+
pasteText?(text: string): boolean | Promise<boolean>;
|
|
160
|
+
/** Press or release one key by keysym. */
|
|
161
|
+
sendKey(keysym: number, code: string | null, down?: boolean): void;
|
|
162
|
+
/** Send text to the host's clipboard, when the protocol carries one. */
|
|
163
|
+
sendClipboard?(text: string): void;
|
|
164
|
+
/**
|
|
165
|
+
* Stop taking keystrokes: the workspace has given the keyboard to something
|
|
166
|
+
* local, such as the terminal or the assistant's message box.
|
|
167
|
+
*
|
|
168
|
+
* Both protocols listen on the element they paint into, so a key only leaves
|
|
169
|
+
* for the host while that element holds focus. Handing focus back is the
|
|
170
|
+
* whole mechanism -- plus, for RDP, letting go of anything still held down,
|
|
171
|
+
* which would otherwise stay down on the far side.
|
|
172
|
+
*/
|
|
173
|
+
releaseKeyboard?(): void;
|
|
174
|
+
/** Ask the host for a different desktop size, when the protocol allows it. */
|
|
175
|
+
requestDesktopSize?(width: number, height: number): void;
|
|
176
|
+
/** The canvas the session paints into, for screenshots and thumbnails. */
|
|
177
|
+
readonly canvas?: HTMLCanvasElement | null;
|
|
178
|
+
}
|
|
179
|
+
/** What the workspace hands a driver to open a session. */
|
|
180
|
+
export interface SessionOptions {
|
|
181
|
+
credentials: {
|
|
182
|
+
username: string;
|
|
183
|
+
password: string;
|
|
184
|
+
};
|
|
185
|
+
domain: string;
|
|
186
|
+
security: RdpSecurity;
|
|
187
|
+
remoteApp: RemoteAppLaunch | null;
|
|
188
|
+
/** Desktop size to ask the host for. */
|
|
189
|
+
width: number;
|
|
190
|
+
height: number;
|
|
191
|
+
/** False on a phone, where resizing the host would make a portrait strip of it. */
|
|
192
|
+
allowRemoteResize: boolean;
|
|
193
|
+
scaleViewport: boolean;
|
|
194
|
+
viewOnly: boolean;
|
|
195
|
+
quality: number;
|
|
196
|
+
compression: number;
|
|
197
|
+
/** Shown in this driver's own log lines. */
|
|
198
|
+
hostLabel: string;
|
|
199
|
+
}
|
|
200
|
+
/** Wording for the one connect dialog, which is shared markup across protocols. */
|
|
201
|
+
interface DialogCopy {
|
|
202
|
+
usernameLabel: string;
|
|
203
|
+
usernamePlaceholder: string;
|
|
204
|
+
usernameHelp: string;
|
|
205
|
+
passwordLabel: string;
|
|
206
|
+
passwordPlaceholder: string;
|
|
207
|
+
passwordHelp: string;
|
|
208
|
+
/** A VNC session needs some secret; RDP can sign in on the host's own screen. */
|
|
209
|
+
requiresPassword: boolean;
|
|
210
|
+
}
|
|
211
|
+
/** Everything the UI knows about a close, before anyone tries to explain it. */
|
|
212
|
+
interface DisconnectContext {
|
|
213
|
+
code?: number;
|
|
214
|
+
reason: string;
|
|
215
|
+
/** Pre-rendered ` (WebSocket 1006: ...)` tail, so wording stays consistent. */
|
|
216
|
+
suffix: string;
|
|
217
|
+
}
|
|
218
|
+
/** One protocol implementation. */
|
|
219
|
+
export interface ProtocolDriver {
|
|
220
|
+
readonly protocol: RemoteProtocol;
|
|
221
|
+
/** Used as the prefix of this driver's console lines. */
|
|
222
|
+
readonly label: string;
|
|
223
|
+
readonly defaultPort: number;
|
|
224
|
+
readonly dialog: DialogCopy;
|
|
225
|
+
/** The gateway endpoint for this connection, including any query it needs. */
|
|
226
|
+
buildUrl(origin: string, settings: ConnectionSettings): string;
|
|
227
|
+
createSession(container: HTMLElement, url: string, options: SessionOptions): RemoteSession;
|
|
228
|
+
/** Extra detail worth logging once the first server frame has been parsed. */
|
|
229
|
+
describeState(session: RemoteSession): Record<string, unknown>;
|
|
230
|
+
/** Protocol-specific wording for a close, or null to fall back to the shared text. */
|
|
231
|
+
describeDisconnect(context: DisconnectContext): string | null;
|
|
232
|
+
}
|
|
233
|
+
export declare const DEFAULT_PORT = 22;
|
|
234
|
+
export declare const COMMAND_MAX_MS: number;
|
|
235
|
+
/**
|
|
236
|
+
* The one line that runs `command` and marks where its output starts and ends.
|
|
237
|
+
*
|
|
238
|
+
* Each shell gets its own, because none of the three agree on how to print a
|
|
239
|
+
* string, run a command and read back its exit status.
|
|
240
|
+
*/
|
|
241
|
+
export declare function frameCommand(family: any, command: string, id: any): string;
|
|
242
|
+
export declare class SshSession extends EventTarget {
|
|
243
|
+
#private;
|
|
244
|
+
/**
|
|
245
|
+
* @param {string} url gateway WebSocket URL
|
|
246
|
+
* @param {object} options
|
|
247
|
+
* @param {string} options.username
|
|
248
|
+
* @param {string} [options.password]
|
|
249
|
+
* @param {SshIdentity[] | (() => Promise<SshIdentity[]>)} [options.identities]
|
|
250
|
+
* @param {'powershell'} [options.preferredShell]
|
|
251
|
+
* @param {(info: object) => Promise<boolean>} [options.verifyHost]
|
|
252
|
+
* @param {(prompt: object) => Promise<string>} [options.requestInput]
|
|
253
|
+
*/
|
|
254
|
+
constructor(url: string, options?: {});
|
|
255
|
+
connect(): void;
|
|
256
|
+
disconnect(): void;
|
|
257
|
+
/** Send keystrokes, or anything else the terminal produces, to the shell. */
|
|
258
|
+
write(data: Uint8Array): void;
|
|
259
|
+
/**
|
|
260
|
+
* Run one command in this shell and return what it printed.
|
|
261
|
+
*
|
|
262
|
+
* Deliberately the *same* shell the user is looking at, not a second channel:
|
|
263
|
+
* a command the assistant runs inherits the working directory, the
|
|
264
|
+
* environment and the login the user already has, and it appears in their
|
|
265
|
+
* terminal as it happens. An agent acting on a machine invisibly is worse
|
|
266
|
+
* than an agent that is slower to read.
|
|
267
|
+
*
|
|
268
|
+
* The output is framed by markers rather than measured, because an
|
|
269
|
+
* interactive shell echoes its input and prints a prompt around it. The
|
|
270
|
+
* markers are assembled by the shell from two pieces, so the echoed command
|
|
271
|
+
* line -- which contains the pieces but not the joined marker -- never looks
|
|
272
|
+
* like the real boundary.
|
|
273
|
+
*
|
|
274
|
+
* A `command` event brackets the run so the terminal can label it, and the
|
|
275
|
+
* three deadlines above decide when a command is stuck rather than slow.
|
|
276
|
+
*/
|
|
277
|
+
runCommand(command: string, { startMs, idleMs, maxMs, }?: {
|
|
278
|
+
idleMs?: number;
|
|
279
|
+
maxMs?: number;
|
|
280
|
+
startMs?: number;
|
|
281
|
+
}): Promise<unknown>;
|
|
282
|
+
/** Tell the shell its window changed, so full-screen programs redraw. */
|
|
283
|
+
resize(columns: number, rows: number): void;
|
|
284
|
+
}
|
|
285
|
+
export declare class SshTerminal {
|
|
286
|
+
constructor(container: any);
|
|
287
|
+
get columns(): any;
|
|
288
|
+
get rows(): any;
|
|
289
|
+
onData(handler: any): void;
|
|
290
|
+
onResize(handler: any): void;
|
|
291
|
+
write(data: Uint8Array): void;
|
|
292
|
+
/** Gateway-side notices, kept visually apart from what the host prints. */
|
|
293
|
+
notice(text: string, tone?: string): void;
|
|
294
|
+
clear(): void;
|
|
295
|
+
focus(): void;
|
|
296
|
+
/**
|
|
297
|
+
* Size the terminal to the panel, choosing the font so MIN_COLUMNS fit.
|
|
298
|
+
*
|
|
299
|
+
* The columns matter more than the type size here: the commands people run in
|
|
300
|
+
* a side panel -- `ls -l`, `top`, anything in PowerShell that prints a table
|
|
301
|
+
* -- are laid out for 80 columns, and a narrower grid wraps every row into an
|
|
302
|
+
* unreadable stack.
|
|
303
|
+
*
|
|
304
|
+
* `proposeDimensions()` reports the grid the current font size yields, and a
|
|
305
|
+
* monospace cell's width scales with its font size, so `fontSize * cols /
|
|
306
|
+
* MIN_COLUMNS` lands close to the size that gives MIN_COLUMNS. It is measured
|
|
307
|
+
* rather than assumed because the cell-width-to-font-size ratio belongs to
|
|
308
|
+
* whichever font the platform picked. A second pass settles the rounding.
|
|
309
|
+
* Changing the font resizes the element, which the ResizeObserver sees, so
|
|
310
|
+
* the guard keeps that from recursing.
|
|
311
|
+
*/
|
|
312
|
+
fit(): void;
|
|
313
|
+
/** The grid the host is being told about, for a status line or a log. */
|
|
314
|
+
get geometry(): {
|
|
315
|
+
columns: any;
|
|
316
|
+
rows: any;
|
|
317
|
+
fontSize: any;
|
|
318
|
+
};
|
|
319
|
+
get selection(): any;
|
|
320
|
+
/**
|
|
321
|
+
* Read one line from the user, for a password or a one-time code the host
|
|
322
|
+
* asked for during authentication. The shell is not open yet, so the
|
|
323
|
+
* terminal is free to be a prompt.
|
|
324
|
+
*/
|
|
325
|
+
readLine({ prompt, echo }?: {
|
|
326
|
+
echo?: boolean;
|
|
327
|
+
prompt?: string;
|
|
328
|
+
}): Promise<unknown>;
|
|
329
|
+
destroy(): void;
|
|
330
|
+
}
|
|
331
|
+
export declare const DRIVERS: Record<RemoteProtocol, ProtocolDriver>;
|
|
332
|
+
/** Unknown names fall back to VNC, which is what the dialog opens on. */
|
|
333
|
+
export declare function driverFor(protocol: string | undefined): ProtocolDriver;
|
|
334
|
+
/** What the workspace knows about a session that has just ended. */
|
|
335
|
+
export interface DisconnectDiagnostic {
|
|
336
|
+
protocol: RemoteProtocol;
|
|
337
|
+
/** The transport close, when one arrived. A 1006 means it did not. */
|
|
338
|
+
close: {
|
|
339
|
+
code: number;
|
|
340
|
+
reason: string;
|
|
341
|
+
} | null;
|
|
342
|
+
/** True once the session had reached the desktop. */
|
|
343
|
+
established: boolean;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Explain a disconnect in terms someone can act on. The protocol gets first
|
|
347
|
+
* say, then the close codes that mean the same thing either way.
|
|
348
|
+
*/
|
|
349
|
+
export declare function explainDisconnect(diagnostic: DisconnectDiagnostic, clean: boolean, protocolMessage: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-remote",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"description": "RDP, VNC and SSH protocol engines that run in Node, a Worker or a browser -- plus `npx ai-remote`, a CLI that drives a machine and shows you what it is doing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -54,12 +54,12 @@
|
|
|
54
54
|
"default": "./dist/apple-dh.js"
|
|
55
55
|
},
|
|
56
56
|
"./protocols": {
|
|
57
|
-
"types": "./dist/protocols
|
|
57
|
+
"types": "./dist/protocols.d.ts",
|
|
58
58
|
"import": "./dist/protocols.js",
|
|
59
59
|
"default": "./dist/protocols.js"
|
|
60
60
|
},
|
|
61
61
|
"./protocols/*": {
|
|
62
|
-
"types": "./dist/protocols
|
|
62
|
+
"types": "./dist/protocols.d.ts",
|
|
63
63
|
"import": "./dist/protocols.js",
|
|
64
64
|
"default": "./dist/protocols.js"
|
|
65
65
|
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The protocol registry the workspace talks to.
|
|
3
|
-
*
|
|
4
|
-
* The UI owns the toolbar, the dialogs, the stats rail and the on-screen
|
|
5
|
-
* keyboard, none of which care whether a session is VNC or RDP. Everything that
|
|
6
|
-
* does differ -- the endpoint, how a client is constructed, the wording of a
|
|
7
|
-
* failure, the labels in the connect dialog -- is looked up here instead of
|
|
8
|
-
* branching at each site.
|
|
9
|
-
*/
|
|
10
|
-
import type { ProtocolDriver } from './types';
|
|
11
|
-
import type { RemoteProtocol } from '../shared/protocol';
|
|
12
|
-
export type { ProtocolDriver, RemoteSession, SessionOptions, ScreenGeometry } from './types';
|
|
13
|
-
export * from './ssh/session';
|
|
14
|
-
export * from './ssh/terminal';
|
|
15
|
-
export declare const DRIVERS: Record<RemoteProtocol, ProtocolDriver>;
|
|
16
|
-
/** Unknown names fall back to VNC, which is what the dialog opens on. */
|
|
17
|
-
export declare function driverFor(protocol: string | undefined): ProtocolDriver;
|
|
18
|
-
/** What the workspace knows about a session that has just ended. */
|
|
19
|
-
export interface DisconnectDiagnostic {
|
|
20
|
-
protocol: RemoteProtocol;
|
|
21
|
-
/** The transport close, when one arrived. A 1006 means it did not. */
|
|
22
|
-
close: {
|
|
23
|
-
code: number;
|
|
24
|
-
reason: string;
|
|
25
|
-
} | null;
|
|
26
|
-
/** True once the session had reached the desktop. */
|
|
27
|
-
established: boolean;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Explain a disconnect in terms someone can act on. The protocol gets first
|
|
31
|
-
* say, then the close codes that mean the same thing either way.
|
|
32
|
-
*/
|
|
33
|
-
export declare function explainDisconnect(diagnostic: DisconnectDiagnostic, clean: boolean, protocolMessage: string): string;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export declare class Writer {
|
|
2
|
-
#private;
|
|
3
|
-
private bytes;
|
|
4
|
-
private view;
|
|
5
|
-
private offset;
|
|
6
|
-
constructor(capacity?: number);
|
|
7
|
-
u8(value: number): this;
|
|
8
|
-
u16le(value: number): this;
|
|
9
|
-
u16be(value: number): this;
|
|
10
|
-
u32le(value: number): this;
|
|
11
|
-
u32be(value: number): this;
|
|
12
|
-
raw(bytes: Uint8Array): this;
|
|
13
|
-
zeros(count: number): this;
|
|
14
|
-
/** UTF-16LE, optionally padded or truncated to a fixed byte width. */
|
|
15
|
-
utf16le(text: string, fixedBytes?: number): this;
|
|
16
|
-
/** Overwrite an earlier 16-bit slot, for length fields known only later. */
|
|
17
|
-
patchU16le(position: number, value: number): this;
|
|
18
|
-
patchU16be(position: number, value: number): this;
|
|
19
|
-
get length(): number;
|
|
20
|
-
take(): Uint8Array;
|
|
21
|
-
}
|
|
22
|
-
export declare class Reader {
|
|
23
|
-
#private;
|
|
24
|
-
private readonly bytes;
|
|
25
|
-
private readonly view;
|
|
26
|
-
offset: number;
|
|
27
|
-
constructor(bytes: Uint8Array, offset?: number);
|
|
28
|
-
get remaining(): number;
|
|
29
|
-
u8(): number;
|
|
30
|
-
u16le(): number;
|
|
31
|
-
u16be(): number;
|
|
32
|
-
u32le(): number;
|
|
33
|
-
u32be(): number;
|
|
34
|
-
raw(count: number): Uint8Array;
|
|
35
|
-
skip(count: number): this;
|
|
36
|
-
rest(): Uint8Array;
|
|
37
|
-
}
|
|
38
|
-
export declare function concatBytes(...parts: readonly Uint8Array[]): Uint8Array;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
export declare const CAPSET: {
|
|
2
|
-
GENERAL: number;
|
|
3
|
-
BITMAP: number;
|
|
4
|
-
ORDER: number;
|
|
5
|
-
BITMAPCACHE: number;
|
|
6
|
-
CONTROL: number;
|
|
7
|
-
ACTIVATION: number;
|
|
8
|
-
POINTER: number;
|
|
9
|
-
SHARE: number;
|
|
10
|
-
COLORCACHE: number;
|
|
11
|
-
SOUND: number;
|
|
12
|
-
INPUT: number;
|
|
13
|
-
FONT: number;
|
|
14
|
-
BRUSH: number;
|
|
15
|
-
GLYPHCACHE: number;
|
|
16
|
-
OFFSCREENCACHE: number;
|
|
17
|
-
VIRTUALCHANNEL: number;
|
|
18
|
-
RAIL: number;
|
|
19
|
-
WINDOW: number;
|
|
20
|
-
MULTIFRAGMENTUPDATE: number;
|
|
21
|
-
LARGE_POINTER: number;
|
|
22
|
-
SURFACE_COMMANDS: number;
|
|
23
|
-
BITMAP_CODECS: number;
|
|
24
|
-
};
|
|
25
|
-
export declare function buildClientCapabilities({ width, height, keyboardLayout, remoteApp, remoteAppCaps }: {
|
|
26
|
-
height: any;
|
|
27
|
-
keyboardLayout: any;
|
|
28
|
-
remoteApp?: boolean;
|
|
29
|
-
remoteAppCaps?: any;
|
|
30
|
-
width: any;
|
|
31
|
-
}): {
|
|
32
|
-
bytes: Uint8Array<ArrayBufferLike>;
|
|
33
|
-
count: number;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* Read the host's Demand Active capabilities. The desktop size it reports wins
|
|
37
|
-
* over anything the client asked for.
|
|
38
|
-
*/
|
|
39
|
-
export declare function parseServerCapabilities(bytes: Uint8Array): {
|
|
40
|
-
desktopWidth: number;
|
|
41
|
-
desktopHeight: number;
|
|
42
|
-
preferredBitsPerPixel: number;
|
|
43
|
-
refreshRectSupport: boolean;
|
|
44
|
-
railSupportLevel: number;
|
|
45
|
-
windowSupportLevel: number;
|
|
46
|
-
numIconCaches: number;
|
|
47
|
-
numIconCacheEntries: number;
|
|
48
|
-
types: any[];
|
|
49
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pull the RSA public key out of a DER X.509 certificate, for the TLS layer.
|
|
3
|
-
*
|
|
4
|
-
* CredSSP needs the exact bytes of the certificate's subjectPublicKey BIT
|
|
5
|
-
* STRING contents -- the DER RSAPublicKey -- because that is what both ends
|
|
6
|
-
* hash to bind the authentication to this TLS channel (MS-CSSP 3.1.5).
|
|
7
|
-
*/
|
|
8
|
-
export declare function parseX509PublicKey(der: Uint8Array): {
|
|
9
|
-
modulus: Uint8Array<ArrayBufferLike>;
|
|
10
|
-
exponent: Uint8Array<ArrayBufferLike>;
|
|
11
|
-
subjectPublicKey: any;
|
|
12
|
-
};
|
|
13
|
-
/** Parse a server certificate blob into an RSA public key. */
|
|
14
|
-
export declare function parseServerCertificate(certificateBytes: Uint8Array): {
|
|
15
|
-
modulus: Uint8Array<ArrayBuffer>;
|
|
16
|
-
exponent: Uint8Array<ArrayBuffer>;
|
|
17
|
-
source: string;
|
|
18
|
-
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A single RDP connection. Emits:
|
|
3
|
-
* 'ready' { width, height } -- the desktop size is known
|
|
4
|
-
* 'bitmap' { rects } -- decoded rectangles to paint
|
|
5
|
-
* 'palette' Uint8Array -- 8bpp palette update
|
|
6
|
-
* 'pointer' pointer update -- shape, position or visibility
|
|
7
|
-
* 'error' { message } -- fatal, always followed by 'close'
|
|
8
|
-
* 'close' { clean, message }
|
|
9
|
-
*/
|
|
10
|
-
export declare class RdpClient extends EventTarget {
|
|
11
|
-
#private;
|
|
12
|
-
constructor(url: string, options?: {});
|
|
13
|
-
disconnect(): void;
|
|
14
|
-
/**
|
|
15
|
-
* The window the session exists to show: the largest top-level application
|
|
16
|
-
* window. Menus, tooltips and drag images are RAIL windows too, and fitting
|
|
17
|
-
* one of those to the browser instead of the application would be worse than
|
|
18
|
-
* doing nothing.
|
|
19
|
-
*/
|
|
20
|
-
get remoteAppPrimaryWindow(): any;
|
|
21
|
-
/**
|
|
22
|
-
* Size the remote application's window to the room the browser has for it.
|
|
23
|
-
*
|
|
24
|
-
* The RDP desktop is fixed for the life of a connection -- resizing it needs
|
|
25
|
-
* the dynamic virtual channel this client does not speak -- so the desktop is
|
|
26
|
-
* negotiated large at connect time and the application window is moved and
|
|
27
|
-
* resized inside it instead. The canvas then shows only that window.
|
|
28
|
-
*/
|
|
29
|
-
fitRemoteApp(width: number, height: number): boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Hand the host our clipboard text. Resolves once the host has acknowledged
|
|
32
|
-
* owning it, which is what makes it safe to send a paste keystroke next.
|
|
33
|
-
*/
|
|
34
|
-
setClipboardText(text: string): any;
|
|
35
|
-
get clipboardShared(): boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Deliver text into the session the way a person would: put it on the host's
|
|
38
|
-
* clipboard, wait for the host to acknowledge owning it, then press the paste
|
|
39
|
-
* shortcut. Waiting is what stops the keystroke from pasting the previous
|
|
40
|
-
* contents. A host with no clipboard channel gets the text typed instead.
|
|
41
|
-
*/
|
|
42
|
-
pasteToHost(text: string): any;
|
|
43
|
-
get connected(): boolean;
|
|
44
|
-
sendKeyByCode(code: number, pressed: boolean): boolean;
|
|
45
|
-
sendUnicode(text: string): void;
|
|
46
|
-
sendCtrlAltDel(): void;
|
|
47
|
-
sendMouseMove(x: number, y: number): void;
|
|
48
|
-
sendMouseButton(button: number, pressed: boolean, x: number, y: number): void;
|
|
49
|
-
sendWheel(delta: number, x: number, y: number, horizontal?: boolean): void;
|
|
50
|
-
/** Tell the host which lock keys are already on, so they do not drift. */
|
|
51
|
-
sendKeyboardSync(toggleFlags: number): void;
|
|
52
|
-
/** Ask the host to resend a region, used after the canvas is re-created. */
|
|
53
|
-
refresh(rect: any): void;
|
|
54
|
-
/** Pause or resume host output, e.g. while the tab is hidden. */
|
|
55
|
-
setOutputEnabled(enabled: boolean): void;
|
|
56
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One clipboard channel. Emits:
|
|
3
|
-
* 'text' { text } -- the host's clipboard now holds this text
|
|
4
|
-
*/
|
|
5
|
-
export declare class ClipboardChannel extends EventTarget {
|
|
6
|
-
#private;
|
|
7
|
-
private readonly send;
|
|
8
|
-
private readonly log;
|
|
9
|
-
private ready;
|
|
10
|
-
private longFormatNames;
|
|
11
|
-
private localText;
|
|
12
|
-
private pendingAck;
|
|
13
|
-
/**
|
|
14
|
-
* @param {(bytes: Uint8Array) => void} send delivers one complete channel message
|
|
15
|
-
* @param {(step: string, detail?: unknown) => void} [log]
|
|
16
|
-
*/
|
|
17
|
-
constructor({ send, log }: {
|
|
18
|
-
log: any;
|
|
19
|
-
send: any;
|
|
20
|
-
});
|
|
21
|
-
/**
|
|
22
|
-
* Announce that this side now owns the clipboard and holds `text`. Resolves
|
|
23
|
-
* once the host has acknowledged, so a paste keystroke can safely follow.
|
|
24
|
-
*/
|
|
25
|
-
setLocalText(text: string): Promise<unknown>;
|
|
26
|
-
receive(bytes: Uint8Array): void;
|
|
27
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export declare class CredSspClient {
|
|
2
|
-
#private;
|
|
3
|
-
private readonly username;
|
|
4
|
-
private readonly domain;
|
|
5
|
-
private readonly password;
|
|
6
|
-
private readonly serverPublicKey;
|
|
7
|
-
private readonly send;
|
|
8
|
-
private readonly log;
|
|
9
|
-
private inbound;
|
|
10
|
-
private waiters;
|
|
11
|
-
constructor({ username, domain, password, serverPublicKey, send, log }: {
|
|
12
|
-
domain: any;
|
|
13
|
-
log: any;
|
|
14
|
-
password: any;
|
|
15
|
-
send: any;
|
|
16
|
-
serverPublicKey: any;
|
|
17
|
-
username: any;
|
|
18
|
-
});
|
|
19
|
-
/** Feed decrypted TLS application data. */
|
|
20
|
-
receive(bytes: Uint8Array): void;
|
|
21
|
-
authenticate(): Promise<{
|
|
22
|
-
authenticated: boolean;
|
|
23
|
-
reachedChallenge: boolean;
|
|
24
|
-
hostVersion: any;
|
|
25
|
-
targetName: string;
|
|
26
|
-
note: string;
|
|
27
|
-
} | {
|
|
28
|
-
reachedChallenge?: undefined;
|
|
29
|
-
note?: undefined;
|
|
30
|
-
authenticated: boolean;
|
|
31
|
-
hostVersion: any;
|
|
32
|
-
targetName: string;
|
|
33
|
-
}>;
|
|
34
|
-
}
|