ai-remote 0.4.2 → 0.4.3
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/index.js +1 -6
- package/dist/protocols/index.js +3 -34
- package/dist/protocols/ssh/session.js +17 -608
- package/dist/protocols/ssh/terminal.js +6 -190
- package/dist/shared/connection.js +1 -113
- package/dist/shared/hosts.js +1 -132
- package/dist/shared/icons.js +1 -41
- package/dist/shared/protocol.js +1 -39
- package/dist/shared/signals.js +1 -41
- package/package.json +1 -1
- package/dist/protocols/rdp/buffer.d.ts +0 -38
- package/dist/protocols/rdp/buffer.js +0 -169
- package/dist/protocols/rdp/caps.d.ts +0 -49
- package/dist/protocols/rdp/caps.js +0 -259
- package/dist/protocols/rdp/cert.d.ts +0 -18
- package/dist/protocols/rdp/cert.js +0 -134
- package/dist/protocols/rdp/client.d.ts +0 -56
- package/dist/protocols/rdp/client.js +0 -1069
- package/dist/protocols/rdp/cliprdr.d.ts +0 -27
- package/dist/protocols/rdp/cliprdr.js +0 -239
- package/dist/protocols/rdp/credssp.d.ts +0 -34
- package/dist/protocols/rdp/credssp.js +0 -253
- package/dist/protocols/rdp/crypto.d.ts +0 -63
- package/dist/protocols/rdp/crypto.js +0 -368
- package/dist/protocols/rdp/display.d.ts +0 -38
- package/dist/protocols/rdp/display.js +0 -588
- package/dist/protocols/rdp/gcc.d.ts +0 -23
- package/dist/protocols/rdp/gcc.js +0 -131
- package/dist/protocols/rdp/keymap.d.ts +0 -9
- package/dist/protocols/rdp/keymap.js +0 -131
- package/dist/protocols/rdp/mcs.d.ts +0 -40
- package/dist/protocols/rdp/mcs.js +0 -222
- package/dist/protocols/rdp/ntlm.d.ts +0 -61
- package/dist/protocols/rdp/ntlm.js +0 -304
- package/dist/protocols/rdp/pdu.d.ts +0 -155
- package/dist/protocols/rdp/pdu.js +0 -443
- package/dist/protocols/rdp/rail.d.ts +0 -119
- package/dist/protocols/rdp/rail.js +0 -382
- package/dist/protocols/rdp/rle.d.ts +0 -13
- package/dist/protocols/rdp/rle.js +0 -275
- package/dist/protocols/rdp/sec.d.ts +0 -59
- package/dist/protocols/rdp/sec.js +0 -155
- package/dist/protocols/rdp/session.d.ts +0 -62
- package/dist/protocols/rdp/session.js +0 -306
- package/dist/protocols/rdp/tls.d.ts +0 -18
- package/dist/protocols/rdp/tls.js +0 -353
- package/dist/protocols/rdp/vchannel.d.ts +0 -28
- package/dist/protocols/rdp/vchannel.js +0 -58
- package/dist/protocols/rdp/x224.d.ts +0 -40
- package/dist/protocols/rdp/x224.js +0 -109
- package/dist/protocols/ssh/kex.d.ts +0 -97
- package/dist/protocols/ssh/kex.js +0 -176
- package/dist/protocols/ssh/messages.d.ts +0 -50
- package/dist/protocols/ssh/messages.js +0 -54
- package/dist/protocols/ssh/transport.d.ts +0 -62
- package/dist/protocols/ssh/transport.js +0 -612
- package/dist/protocols/ssh/wire.d.ts +0 -52
- package/dist/protocols/ssh/wire.js +0 -188
- package/dist/protocols/vnc/input.d.ts +0 -5
- package/dist/protocols/vnc/input.js +0 -15
- package/dist/protocols/vnc/session.d.ts +0 -12
- package/dist/protocols/vnc/session.js +0 -258
|
@@ -1,190 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const MIN_FONT_SIZE = 7;
|
|
8
|
-
function installStyles() {
|
|
9
|
-
if (document.getElementById(STYLE_ELEMENT_ID)) return;
|
|
10
|
-
const style = document.createElement("style");
|
|
11
|
-
style.id = STYLE_ELEMENT_ID;
|
|
12
|
-
style.textContent = xtermStyles;
|
|
13
|
-
document.head.appendChild(style);
|
|
14
|
-
}
|
|
15
|
-
const THEME = {
|
|
16
|
-
background: "#0b0d12",
|
|
17
|
-
foreground: "#dfe4ec",
|
|
18
|
-
cursor: "#f38020",
|
|
19
|
-
cursorAccent: "#0b0d12",
|
|
20
|
-
selectionBackground: "rgba(243, 128, 32, 0.32)",
|
|
21
|
-
black: "#1b1f27",
|
|
22
|
-
red: "#ff6b6b",
|
|
23
|
-
green: "#4ade80",
|
|
24
|
-
yellow: "#fbbf24",
|
|
25
|
-
blue: "#60a5fa",
|
|
26
|
-
magenta: "#c084fc",
|
|
27
|
-
cyan: "#34d3ee",
|
|
28
|
-
white: "#cbd3e1",
|
|
29
|
-
brightBlack: "#63708a",
|
|
30
|
-
brightRed: "#ff8787",
|
|
31
|
-
brightGreen: "#86efac",
|
|
32
|
-
brightYellow: "#fcd34d",
|
|
33
|
-
brightBlue: "#93c5fd",
|
|
34
|
-
brightMagenta: "#d8b4fe",
|
|
35
|
-
brightCyan: "#67e8f9",
|
|
36
|
-
brightWhite: "#f5f7fa"
|
|
37
|
-
};
|
|
38
|
-
class SshTerminal {
|
|
39
|
-
constructor(container) {
|
|
40
|
-
installStyles();
|
|
41
|
-
this.container = container;
|
|
42
|
-
this.terminal = new Terminal({
|
|
43
|
-
allowProposedApi: true,
|
|
44
|
-
convertEol: false,
|
|
45
|
-
cursorBlink: true,
|
|
46
|
-
cursorStyle: "bar",
|
|
47
|
-
drawBoldTextInBrightColors: true,
|
|
48
|
-
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
|
|
49
|
-
fontSize: BASE_FONT_SIZE,
|
|
50
|
-
lineHeight: 1.25,
|
|
51
|
-
letterSpacing: 0,
|
|
52
|
-
macOptionIsMeta: true,
|
|
53
|
-
minimumContrastRatio: 1.5,
|
|
54
|
-
scrollback: 1e4,
|
|
55
|
-
theme: THEME
|
|
56
|
-
});
|
|
57
|
-
this.fitAddon = new FitAddon();
|
|
58
|
-
this.terminal.loadAddon(this.fitAddon);
|
|
59
|
-
this.terminal.open(container);
|
|
60
|
-
this.fit();
|
|
61
|
-
this.observer = new ResizeObserver(() => this.fit());
|
|
62
|
-
this.observer.observe(container);
|
|
63
|
-
this.dataHandler = null;
|
|
64
|
-
this.terminal.onData((data) => this.dataHandler?.(data));
|
|
65
|
-
}
|
|
66
|
-
get columns() {
|
|
67
|
-
return this.terminal.cols;
|
|
68
|
-
}
|
|
69
|
-
get rows() {
|
|
70
|
-
return this.terminal.rows;
|
|
71
|
-
}
|
|
72
|
-
onData(handler) {
|
|
73
|
-
this.dataHandler = handler;
|
|
74
|
-
}
|
|
75
|
-
onResize(handler) {
|
|
76
|
-
this.terminal.onResize(({ cols, rows }) => handler(cols, rows));
|
|
77
|
-
}
|
|
78
|
-
write(data) {
|
|
79
|
-
this.terminal.write(data);
|
|
80
|
-
}
|
|
81
|
-
/** Gateway-side notices, kept visually apart from what the host prints. */
|
|
82
|
-
notice(text, tone = "info") {
|
|
83
|
-
const color = { info: "\x1B[38;5;245m", good: "\x1B[38;5;114m", bad: "\x1B[38;5;203m" }[tone] || "";
|
|
84
|
-
this.terminal.write(`${color}${text}\x1B[0m\r
|
|
85
|
-
`);
|
|
86
|
-
}
|
|
87
|
-
clear() {
|
|
88
|
-
this.terminal.clear();
|
|
89
|
-
}
|
|
90
|
-
focus() {
|
|
91
|
-
this.terminal.focus();
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Size the terminal to the panel, choosing the font so MIN_COLUMNS fit.
|
|
95
|
-
*
|
|
96
|
-
* The columns matter more than the type size here: the commands people run in
|
|
97
|
-
* a side panel -- `ls -l`, `top`, anything in PowerShell that prints a table
|
|
98
|
-
* -- are laid out for 80 columns, and a narrower grid wraps every row into an
|
|
99
|
-
* unreadable stack.
|
|
100
|
-
*
|
|
101
|
-
* `proposeDimensions()` reports the grid the current font size yields, and a
|
|
102
|
-
* monospace cell's width scales with its font size, so `fontSize * cols /
|
|
103
|
-
* MIN_COLUMNS` lands close to the size that gives MIN_COLUMNS. It is measured
|
|
104
|
-
* rather than assumed because the cell-width-to-font-size ratio belongs to
|
|
105
|
-
* whichever font the platform picked. A second pass settles the rounding.
|
|
106
|
-
* Changing the font resizes the element, which the ResizeObserver sees, so
|
|
107
|
-
* the guard keeps that from recursing.
|
|
108
|
-
*/
|
|
109
|
-
fit() {
|
|
110
|
-
if (this.fitting) return;
|
|
111
|
-
if (this.container.clientWidth <= 0 || this.container.clientHeight <= 0) return;
|
|
112
|
-
this.fitting = true;
|
|
113
|
-
try {
|
|
114
|
-
for (let pass = 0; pass < 2; pass++) {
|
|
115
|
-
const proposed = this.fitAddon.proposeDimensions();
|
|
116
|
-
if (!proposed || !(proposed.cols > 0)) break;
|
|
117
|
-
const current = this.terminal.options.fontSize || BASE_FONT_SIZE;
|
|
118
|
-
const wanted = Math.min(
|
|
119
|
-
BASE_FONT_SIZE,
|
|
120
|
-
Math.max(MIN_FONT_SIZE, Math.floor(current * proposed.cols / MIN_COLUMNS))
|
|
121
|
-
);
|
|
122
|
-
if (wanted === current) break;
|
|
123
|
-
this.terminal.options.fontSize = wanted;
|
|
124
|
-
}
|
|
125
|
-
this.fitAddon.fit();
|
|
126
|
-
const short = this.terminal.cols < MIN_COLUMNS;
|
|
127
|
-
this.container.classList.toggle("is-narrow", short);
|
|
128
|
-
if (short) this.terminal.resize(MIN_COLUMNS, this.terminal.rows);
|
|
129
|
-
} catch {
|
|
130
|
-
} finally {
|
|
131
|
-
this.fitting = false;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
/** The grid the host is being told about, for a status line or a log. */
|
|
135
|
-
get geometry() {
|
|
136
|
-
return {
|
|
137
|
-
columns: this.terminal.cols,
|
|
138
|
-
rows: this.terminal.rows,
|
|
139
|
-
fontSize: this.terminal.options.fontSize
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
get selection() {
|
|
143
|
-
return this.terminal.getSelection();
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Read one line from the user, for a password or a one-time code the host
|
|
147
|
-
* asked for during authentication. The shell is not open yet, so the
|
|
148
|
-
* terminal is free to be a prompt.
|
|
149
|
-
*/
|
|
150
|
-
readLine({ prompt = "", echo = false } = {}) {
|
|
151
|
-
return new Promise((resolve) => {
|
|
152
|
-
const previous = this.dataHandler;
|
|
153
|
-
let answer = "";
|
|
154
|
-
this.terminal.write(prompt.replaceAll("\n", "\r\n"));
|
|
155
|
-
this.dataHandler = (data) => {
|
|
156
|
-
for (const character of data) {
|
|
157
|
-
const code = character.charCodeAt(0);
|
|
158
|
-
if (code === 13 || code === 10) {
|
|
159
|
-
this.terminal.write("\r\n");
|
|
160
|
-
this.dataHandler = previous;
|
|
161
|
-
resolve(answer);
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
if (code === 127 || code === 8) {
|
|
165
|
-
if (answer.length === 0) continue;
|
|
166
|
-
answer = answer.slice(0, -1);
|
|
167
|
-
if (echo) this.terminal.write("\b \b");
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
if (code === 3) {
|
|
171
|
-
this.terminal.write("^C\r\n");
|
|
172
|
-
this.dataHandler = previous;
|
|
173
|
-
resolve("");
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
if (code < 32) continue;
|
|
177
|
-
answer += character;
|
|
178
|
-
if (echo) this.terminal.write(character);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
destroy() {
|
|
184
|
-
this.observer?.disconnect();
|
|
185
|
-
this.terminal.dispose();
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
export {
|
|
189
|
-
SshTerminal
|
|
190
|
-
};
|
|
1
|
+
import{Terminal as m}from"@xterm/xterm";import{FitAddon as u}from"@xterm/addon-fit";import b from"@xterm/xterm/css/xterm.css";var h="xterm-styles",l=80,c=13,g=7;function w(){if(document.getElementById(h))return;let s=document.createElement("style");s.id=h,s.textContent=b,document.head.appendChild(s)}var p={background:"#0b0d12",foreground:"#dfe4ec",cursor:"#f38020",cursorAccent:"#0b0d12",selectionBackground:"rgba(243, 128, 32, 0.32)",black:"#1b1f27",red:"#ff6b6b",green:"#4ade80",yellow:"#fbbf24",blue:"#60a5fa",magenta:"#c084fc",cyan:"#34d3ee",white:"#cbd3e1",brightBlack:"#63708a",brightRed:"#ff8787",brightGreen:"#86efac",brightYellow:"#fcd34d",brightBlue:"#93c5fd",brightMagenta:"#d8b4fe",brightCyan:"#67e8f9",brightWhite:"#f5f7fa"},f=class{constructor(t){w(),this.container=t,this.terminal=new m({allowProposedApi:!0,convertEol:!1,cursorBlink:!0,cursorStyle:"bar",drawBoldTextInBrightColors:!0,fontFamily:'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',fontSize:c,lineHeight:1.25,letterSpacing:0,macOptionIsMeta:!0,minimumContrastRatio:1.5,scrollback:1e4,theme:p}),this.fitAddon=new u,this.terminal.loadAddon(this.fitAddon),this.terminal.open(t),this.fit(),this.observer=new ResizeObserver(()=>this.fit()),this.observer.observe(t),this.dataHandler=null,this.terminal.onData(e=>this.dataHandler?.(e))}get columns(){return this.terminal.cols}get rows(){return this.terminal.rows}onData(t){this.dataHandler=t}onResize(t){this.terminal.onResize(({cols:e,rows:i})=>t(e,i))}write(t){this.terminal.write(t)}notice(t,e="info"){let i={info:"\x1B[38;5;245m",good:"\x1B[38;5;114m",bad:"\x1B[38;5;203m"}[e]||"";this.terminal.write(`${i}${t}\x1B[0m\r
|
|
2
|
+
`)}clear(){this.terminal.clear()}focus(){this.terminal.focus()}fit(){if(!this.fitting&&!(this.container.clientWidth<=0||this.container.clientHeight<=0)){this.fitting=!0;try{for(let e=0;e<2;e++){let i=this.fitAddon.proposeDimensions();if(!i||!(i.cols>0))break;let o=this.terminal.options.fontSize||c,r=Math.min(c,Math.max(g,Math.floor(o*i.cols/l)));if(r===o)break;this.terminal.options.fontSize=r}this.fitAddon.fit();let t=this.terminal.cols<l;this.container.classList.toggle("is-narrow",t),t&&this.terminal.resize(l,this.terminal.rows)}catch{}finally{this.fitting=!1}}}get geometry(){return{columns:this.terminal.cols,rows:this.terminal.rows,fontSize:this.terminal.options.fontSize}}get selection(){return this.terminal.getSelection()}readLine({prompt:t="",echo:e=!1}={}){return new Promise(i=>{let o=this.dataHandler,r="";this.terminal.write(t.replaceAll(`
|
|
3
|
+
`,`\r
|
|
4
|
+
`)),this.dataHandler=d=>{for(let a of d){let n=a.charCodeAt(0);if(n===13||n===10){this.terminal.write(`\r
|
|
5
|
+
`),this.dataHandler=o,i(r);return}if(n===127||n===8){if(r.length===0)continue;r=r.slice(0,-1),e&&this.terminal.write("\b \b");continue}if(n===3){this.terminal.write(`^C\r
|
|
6
|
+
`),this.dataHandler=o,i("");return}n<32||(r+=a,e&&this.terminal.write(a))}}})}destroy(){this.observer?.disconnect(),this.terminal.dispose()}};export{f as SshTerminal};
|
|
@@ -1,113 +1 @@
|
|
|
1
|
-
|
|
2
|
-
DEFAULT_PORTS,
|
|
3
|
-
toPort,
|
|
4
|
-
toRdpSecurity,
|
|
5
|
-
toRemoteProtocol
|
|
6
|
-
} from "./protocol.js";
|
|
7
|
-
const DEFAULT_DISPLAY_SETTINGS = {
|
|
8
|
-
quality: 6,
|
|
9
|
-
compression: 2,
|
|
10
|
-
scaling: true,
|
|
11
|
-
viewOnly: false
|
|
12
|
-
};
|
|
13
|
-
function connectionId(input) {
|
|
14
|
-
const program = input.remoteApp?.program?.trim() ?? "";
|
|
15
|
-
const base = `${input.protocol || "vnc"}:${input.host.trim()}:${input.port || ""}`;
|
|
16
|
-
return (program ? `${base}:${program}` : base).toLowerCase().slice(0, 64);
|
|
17
|
-
}
|
|
18
|
-
function emptyConnection(protocol = "vnc") {
|
|
19
|
-
const port = DEFAULT_PORTS[protocol];
|
|
20
|
-
return {
|
|
21
|
-
id: "",
|
|
22
|
-
label: "",
|
|
23
|
-
protocol,
|
|
24
|
-
host: "",
|
|
25
|
-
port,
|
|
26
|
-
username: "",
|
|
27
|
-
password: "",
|
|
28
|
-
domain: "",
|
|
29
|
-
security: "auto",
|
|
30
|
-
remoteApp: null,
|
|
31
|
-
display: { ...DEFAULT_DISPLAY_SETTINGS },
|
|
32
|
-
ssh: { enabled: false, port: DEFAULT_PORTS.ssh, username: "" },
|
|
33
|
-
openSshOnConnect: false
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function clampLevel(value, fallback, min, max) {
|
|
37
|
-
const level = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
38
|
-
if (!Number.isInteger(level)) return fallback;
|
|
39
|
-
return Math.min(max, Math.max(min, level));
|
|
40
|
-
}
|
|
41
|
-
function normalizeDisplaySettings(value) {
|
|
42
|
-
const input = value ?? {};
|
|
43
|
-
return {
|
|
44
|
-
quality: clampLevel(input.quality, DEFAULT_DISPLAY_SETTINGS.quality, 1, 9),
|
|
45
|
-
compression: clampLevel(input.compression, DEFAULT_DISPLAY_SETTINGS.compression, 0, 9),
|
|
46
|
-
scaling: typeof input.scaling === "boolean" ? input.scaling : DEFAULT_DISPLAY_SETTINGS.scaling,
|
|
47
|
-
viewOnly: Boolean(input.viewOnly)
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function normalizeRemoteApp(value) {
|
|
51
|
-
if (typeof value === "string") {
|
|
52
|
-
const program2 = value.trim();
|
|
53
|
-
return program2 ? { program: program2 } : null;
|
|
54
|
-
}
|
|
55
|
-
if (!value || typeof value !== "object") return null;
|
|
56
|
-
const input = value;
|
|
57
|
-
const program = String(input.program ?? "").trim();
|
|
58
|
-
if (!program) return null;
|
|
59
|
-
const workingDir = String(input.workingDir ?? "").trim();
|
|
60
|
-
const args = String(input.arguments ?? "").trim();
|
|
61
|
-
return {
|
|
62
|
-
program,
|
|
63
|
-
...workingDir ? { workingDir } : {},
|
|
64
|
-
...args ? { arguments: args } : {}
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
function normalizeConnection(input) {
|
|
68
|
-
const protocol = toRemoteProtocol(input.protocol);
|
|
69
|
-
const host = String(input.host ?? "").trim();
|
|
70
|
-
const port = toPort(input.port, DEFAULT_PORTS[protocol]);
|
|
71
|
-
const remoteApp = normalizeRemoteApp(input.remoteApp ?? input.program);
|
|
72
|
-
const sshInput = input.ssh ?? {};
|
|
73
|
-
const ssh = {
|
|
74
|
-
enabled: Boolean(sshInput.enabled),
|
|
75
|
-
port: toPort(sshInput.port, DEFAULT_PORTS.ssh),
|
|
76
|
-
username: String(sshInput.username ?? "").trim()
|
|
77
|
-
};
|
|
78
|
-
const settings = {
|
|
79
|
-
id: "",
|
|
80
|
-
label: String(input.label ?? "").trim() || host,
|
|
81
|
-
protocol,
|
|
82
|
-
host,
|
|
83
|
-
port,
|
|
84
|
-
username: String(input.username ?? "").trim(),
|
|
85
|
-
password: String(input.password ?? ""),
|
|
86
|
-
domain: String(input.domain ?? "").trim(),
|
|
87
|
-
security: toRdpSecurity(input.security),
|
|
88
|
-
remoteApp,
|
|
89
|
-
display: normalizeDisplaySettings(input.display),
|
|
90
|
-
ssh,
|
|
91
|
-
openSshOnConnect: Boolean(input.openSshOnConnect)
|
|
92
|
-
};
|
|
93
|
-
settings.id = String(input.id ?? "").trim() || connectionId(settings);
|
|
94
|
-
return settings;
|
|
95
|
-
}
|
|
96
|
-
function withoutPassword(settings) {
|
|
97
|
-
const { password: _password, ...rest } = settings;
|
|
98
|
-
return rest;
|
|
99
|
-
}
|
|
100
|
-
function describeConnection(settings) {
|
|
101
|
-
const target = `${settings.host || "no address"}:${settings.port}`;
|
|
102
|
-
const app = settings.remoteApp ? ` \xB7 ${settings.remoteApp.program}` : "";
|
|
103
|
-
return `${settings.protocol.toUpperCase()} \xB7 ${target}${app}`;
|
|
104
|
-
}
|
|
105
|
-
export {
|
|
106
|
-
DEFAULT_DISPLAY_SETTINGS,
|
|
107
|
-
connectionId,
|
|
108
|
-
describeConnection,
|
|
109
|
-
emptyConnection,
|
|
110
|
-
normalizeConnection,
|
|
111
|
-
normalizeDisplaySettings,
|
|
112
|
-
withoutPassword
|
|
113
|
-
};
|
|
1
|
+
var S=["vnc","rdp"];var d=["auto","nla","tls","rdp"],i={vnc:5900,rdp:3389,ssh:22},h=i.ssh;function y(o){return S.includes(o)}function R(o){return d.includes(o)}function m(o,n="vnc"){let t=String(o??"").toLowerCase();return y(t)?t:n}function l(o,n="auto"){let t=String(o??"").toLowerCase();return R(t)?t:n}function a(o,n){let t=typeof o=="number"?o:Number.parseInt(String(o??""),10);return Number.isInteger(t)&&t>0&&t<65536?t:n}var c={quality:6,compression:2,scaling:!0,viewOnly:!1};function b(o){let n=o.remoteApp?.program?.trim()??"",t=`${o.protocol||"vnc"}:${o.host.trim()}:${o.port||""}`;return(n?`${t}:${n}`:t).toLowerCase().slice(0,64)}function O(o="vnc"){let n=i[o];return{id:"",label:"",protocol:o,host:"",port:n,username:"",password:"",domain:"",security:"auto",remoteApp:null,display:{...c},ssh:{enabled:!1,port:i.ssh,username:""},openSshOnConnect:!1}}function u(o,n,t,r){let e=typeof o=="number"?o:Number.parseInt(String(o??""),10);return Number.isInteger(e)?Math.min(r,Math.max(t,e)):n}function P(o){let n=o??{};return{quality:u(n.quality,c.quality,1,9),compression:u(n.compression,c.compression,0,9),scaling:typeof n.scaling=="boolean"?n.scaling:c.scaling,viewOnly:!!n.viewOnly}}function f(o){if(typeof o=="string"){let s=o.trim();return s?{program:s}:null}if(!o||typeof o!="object")return null;let n=o,t=String(n.program??"").trim();if(!t)return null;let r=String(n.workingDir??"").trim(),e=String(n.arguments??"").trim();return{program:t,...r?{workingDir:r}:{},...e?{arguments:e}:{}}}function x(o){let n=m(o.protocol),t=String(o.host??"").trim(),r=a(o.port,i[n]),e=f(o.remoteApp??o.program),s=o.ssh??{},g={enabled:!!s.enabled,port:a(s.port,i.ssh),username:String(s.username??"").trim()},p={id:"",label:String(o.label??"").trim()||t,protocol:n,host:t,port:r,username:String(o.username??"").trim(),password:String(o.password??""),domain:String(o.domain??"").trim(),security:l(o.security),remoteApp:e,display:P(o.display),ssh:g,openSshOnConnect:!!o.openSshOnConnect};return p.id=String(o.id??"").trim()||b(p),p}function T(o){let{password:n,...t}=o;return t}function A(o){let n=`${o.host||"no address"}:${o.port}`,t=o.remoteApp?` \xB7 ${o.remoteApp.program}`:"";return`${o.protocol.toUpperCase()} \xB7 ${n}${t}`}export{c as DEFAULT_DISPLAY_SETTINGS,b as connectionId,A as describeConnection,O as emptyConnection,x as normalizeConnection,P as normalizeDisplaySettings,T as withoutPassword};
|
package/dist/shared/hosts.js
CHANGED
|
@@ -1,132 +1 @@
|
|
|
1
|
-
|
|
2
|
-
DEFAULT_PORTS,
|
|
3
|
-
DEFAULT_SSH_PORT,
|
|
4
|
-
isRdpSecurity,
|
|
5
|
-
toPort,
|
|
6
|
-
toRemoteProtocol
|
|
7
|
-
} from "./protocol.js";
|
|
8
|
-
function normalizeRemoteApp(value) {
|
|
9
|
-
if (typeof value === "string" && value.trim()) return { program: value.trim() };
|
|
10
|
-
if (!value || typeof value !== "object") return void 0;
|
|
11
|
-
const candidate = value;
|
|
12
|
-
const program = String(candidate.program ?? "").trim();
|
|
13
|
-
if (!program) return void 0;
|
|
14
|
-
return {
|
|
15
|
-
program,
|
|
16
|
-
...candidate.workingDir ? { workingDir: String(candidate.workingDir) } : {},
|
|
17
|
-
...candidate.arguments ? { arguments: String(candidate.arguments) } : {}
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function normalizeSsh(value, fallbackUsername) {
|
|
21
|
-
const inherited = typeof fallbackUsername === "string" && fallbackUsername.trim() ? fallbackUsername.trim() : void 0;
|
|
22
|
-
if (value === true) {
|
|
23
|
-
return { port: DEFAULT_SSH_PORT, ...inherited ? { username: inherited } : {} };
|
|
24
|
-
}
|
|
25
|
-
if (typeof value === "number" || typeof value === "string" && /^\d+$/.test(value.trim())) {
|
|
26
|
-
const port = toPort(value, 0);
|
|
27
|
-
if (!port) return void 0;
|
|
28
|
-
return { port, ...inherited ? { username: inherited } : {} };
|
|
29
|
-
}
|
|
30
|
-
if (!value || typeof value !== "object") return void 0;
|
|
31
|
-
const candidate = value;
|
|
32
|
-
if (candidate.enabled === false) return void 0;
|
|
33
|
-
const username = typeof candidate.username === "string" && candidate.username.trim() ? candidate.username.trim() : inherited;
|
|
34
|
-
return {
|
|
35
|
-
port: toPort(candidate.port, DEFAULT_SSH_PORT),
|
|
36
|
-
...username ? { username } : {}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function parseHostList(hostsJson, defaultProtocol, defaultHost, defaultPort, idPrefix) {
|
|
40
|
-
if (!hostsJson) return [];
|
|
41
|
-
let parsed;
|
|
42
|
-
try {
|
|
43
|
-
parsed = JSON.parse(hostsJson);
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.warn(`Failed to parse ${idPrefix.toUpperCase()}_HOSTS JSON, ignoring it:`, error);
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
if (!Array.isArray(parsed) || parsed.length === 0) return [];
|
|
49
|
-
return parsed.map((raw, index) => {
|
|
50
|
-
const entry = raw ?? {};
|
|
51
|
-
const protocol = toRemoteProtocol(entry.protocol, defaultProtocol);
|
|
52
|
-
const remoteApp = protocol === "rdp" ? normalizeRemoteApp(entry.remoteApp) : void 0;
|
|
53
|
-
const ssh = normalizeSsh(entry.ssh ?? entry.sshPort, entry.sshUser ?? entry.sshUsername);
|
|
54
|
-
const host = String(entry.host ?? "") || defaultHost;
|
|
55
|
-
const name = String(entry.name ?? "").trim() || host;
|
|
56
|
-
return {
|
|
57
|
-
id: String(entry.id ?? "") || `${idPrefix}-${index + 1}`,
|
|
58
|
-
name,
|
|
59
|
-
host,
|
|
60
|
-
port: toPort(entry.port ?? defaultPort, DEFAULT_PORTS[protocol]),
|
|
61
|
-
protocol,
|
|
62
|
-
...entry.domain ? { domain: String(entry.domain) } : {},
|
|
63
|
-
...isRdpSecurity(entry.security) ? { security: entry.security } : {},
|
|
64
|
-
...remoteApp ? { remoteApp } : {},
|
|
65
|
-
...ssh ? { ssh } : {}
|
|
66
|
-
};
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
function parseConfiguredHosts(options) {
|
|
70
|
-
const defaultHost = options.defaultHost || "10.0.0.10";
|
|
71
|
-
const defaultPort = options.defaultPort || String(DEFAULT_PORTS.vnc);
|
|
72
|
-
const hosts = [
|
|
73
|
-
...parseHostList(options.vncHostsJson, "vnc", defaultHost, defaultPort, "vnc-host"),
|
|
74
|
-
...parseHostList(
|
|
75
|
-
options.rdpHostsJson,
|
|
76
|
-
"rdp",
|
|
77
|
-
options.defaultRdpHost || defaultHost,
|
|
78
|
-
options.defaultRdpPort || String(DEFAULT_PORTS.rdp),
|
|
79
|
-
"rdp-host"
|
|
80
|
-
)
|
|
81
|
-
];
|
|
82
|
-
if (hosts.length > 0) return hosts;
|
|
83
|
-
return [
|
|
84
|
-
{
|
|
85
|
-
id: "default-host",
|
|
86
|
-
name: "Primary Host",
|
|
87
|
-
host: defaultHost,
|
|
88
|
-
port: toPort(defaultPort, DEFAULT_PORTS.vnc),
|
|
89
|
-
protocol: "vnc"
|
|
90
|
-
}
|
|
91
|
-
];
|
|
92
|
-
}
|
|
93
|
-
function ipv4ToInt(value) {
|
|
94
|
-
const parts = String(value).trim().split(".");
|
|
95
|
-
if (parts.length !== 4) return null;
|
|
96
|
-
let result = 0;
|
|
97
|
-
for (const part of parts) {
|
|
98
|
-
if (!/^\d{1,3}$/.test(part)) return null;
|
|
99
|
-
const octet = Number.parseInt(part, 10);
|
|
100
|
-
if (octet > 255) return null;
|
|
101
|
-
result = result << 8 | octet;
|
|
102
|
-
}
|
|
103
|
-
return result >>> 0;
|
|
104
|
-
}
|
|
105
|
-
function parseAllowedSubnets(value) {
|
|
106
|
-
if (!value) return [];
|
|
107
|
-
const subnets = [];
|
|
108
|
-
for (const entry of value.split(",")) {
|
|
109
|
-
const text = entry.trim();
|
|
110
|
-
if (!text) continue;
|
|
111
|
-
const wildcard = text.split(".").findIndex((part) => part === "*");
|
|
112
|
-
const [address, bits] = wildcard >= 0 ? [text.replaceAll("*", "0"), String(wildcard * 8)] : text.split("/");
|
|
113
|
-
const base = ipv4ToInt(address ?? "");
|
|
114
|
-
if (base === null) continue;
|
|
115
|
-
const width = bits === void 0 ? 32 : Number.parseInt(bits, 10);
|
|
116
|
-
if (!Number.isInteger(width) || width < 0 || width > 32) continue;
|
|
117
|
-
const mask = width === 0 ? 0 : 4294967295 << 32 - width >>> 0;
|
|
118
|
-
subnets.push({ base: (base & mask) >>> 0, mask });
|
|
119
|
-
}
|
|
120
|
-
return subnets;
|
|
121
|
-
}
|
|
122
|
-
function hostInAllowedSubnets(host, value) {
|
|
123
|
-
const address = ipv4ToInt(host);
|
|
124
|
-
if (address === null) return false;
|
|
125
|
-
return parseAllowedSubnets(value).some(({ base, mask }) => (address & mask) >>> 0 === base);
|
|
126
|
-
}
|
|
127
|
-
export {
|
|
128
|
-
hostInAllowedSubnets,
|
|
129
|
-
ipv4ToInt,
|
|
130
|
-
parseAllowedSubnets,
|
|
131
|
-
parseConfiguredHosts
|
|
132
|
-
};
|
|
1
|
+
var b=["vnc","rdp"];var T=["auto","nla","tls","rdp"],p={vnc:5900,rdp:3389,ssh:22},m=p.ssh;function w(t){return b.includes(t)}function l(t){return T.includes(t)}function S(t,n="vnc"){let r=String(t??"").toLowerCase();return w(r)?r:n}function d(t,n){let r=typeof t=="number"?t:Number.parseInt(String(t??""),10);return Number.isInteger(r)&&r>0&&r<65536?r:n}function H(t){if(typeof t=="string"&&t.trim())return{program:t.trim()};if(!t||typeof t!="object")return;let n=t,r=String(n.program??"").trim();if(r)return{program:r,...n.workingDir?{workingDir:String(n.workingDir)}:{},...n.arguments?{arguments:String(n.arguments)}:{}}}function O(t,n){let r=typeof n=="string"&&n.trim()?n.trim():void 0;if(t===!0)return{port:m,...r?{username:r}:{}};if(typeof t=="number"||typeof t=="string"&&/^\d+$/.test(t.trim())){let i=d(t,0);return i?{port:i,...r?{username:r}:{}}:void 0}if(!t||typeof t!="object")return;let e=t;if(e.enabled===!1)return;let s=typeof e.username=="string"&&e.username.trim()?e.username.trim():r;return{port:d(e.port,m),...s?{username:s}:{}}}function y(t,n,r,e,s){if(!t)return[];let i;try{i=JSON.parse(t)}catch(u){return console.warn(`Failed to parse ${s.toUpperCase()}_HOSTS JSON, ignoring it:`,u),[]}return!Array.isArray(i)||i.length===0?[]:i.map((u,a)=>{let o=u??{},c=S(o.protocol,n),f=c==="rdp"?H(o.remoteApp):void 0,g=O(o.ssh??o.sshPort,o.sshUser??o.sshUsername),R=String(o.host??"")||r,h=String(o.name??"").trim()||R;return{id:String(o.id??"")||`${s}-${a+1}`,name:h,host:R,port:d(o.port??e,p[c]),protocol:c,...o.domain?{domain:String(o.domain)}:{},...l(o.security)?{security:o.security}:{},...f?{remoteApp:f}:{},...g?{ssh:g}:{}}})}function _(t){let n=t.defaultHost||"10.0.0.10",r=t.defaultPort||String(p.vnc),e=[...y(t.vncHostsJson,"vnc",n,r,"vnc-host"),...y(t.rdpHostsJson,"rdp",t.defaultRdpHost||n,t.defaultRdpPort||String(p.rdp),"rdp-host")];return e.length>0?e:[{id:"default-host",name:"Primary Host",host:n,port:d(r,p.vnc),protocol:"vnc"}]}function P(t){let n=String(t).trim().split(".");if(n.length!==4)return null;let r=0;for(let e of n){if(!/^\d{1,3}$/.test(e))return null;let s=Number.parseInt(e,10);if(s>255)return null;r=r<<8|s}return r>>>0}function x(t){if(!t)return[];let n=[];for(let r of t.split(",")){let e=r.trim();if(!e)continue;let s=e.split(".").findIndex(f=>f==="*"),[i,u]=s>=0?[e.replaceAll("*","0"),String(s*8)]:e.split("/"),a=P(i??"");if(a===null)continue;let o=u===void 0?32:Number.parseInt(u,10);if(!Number.isInteger(o)||o<0||o>32)continue;let c=o===0?0:4294967295<<32-o>>>0;n.push({base:(a&c)>>>0,mask:c})}return n}function k(t,n){let r=P(t);return r===null?!1:x(n).some(({base:e,mask:s})=>(r&s)>>>0===e)}export{k as hostInAllowedSubnets,P as ipv4ToInt,x as parseAllowedSubnets,_ as parseConfiguredHosts};
|
package/dist/shared/icons.js
CHANGED
|
@@ -1,41 +1 @@
|
|
|
1
|
-
|
|
2
|
-
monitor: '<rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>',
|
|
3
|
-
link: '<path d="M9 17H7A5 5 0 0 1 7 7h2M15 7h2a5 5 0 1 1 0 10h-2M8 12h8"/>',
|
|
4
|
-
power: '<path d="M12 2v10"/><path d="M18.4 6.6a9 9 0 1 1-12.8 0"/>',
|
|
5
|
-
maximize: '<path d="M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3"/>',
|
|
6
|
-
minimize: '<path d="M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3"/>',
|
|
7
|
-
keyboard: '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="M6 8h.01M10 8h.01M14 8h.01M18 8h.01M8 12h.01M12 12h.01M16 12h.01M7 16h10"/>',
|
|
8
|
-
clipboard: '<rect x="8" y="2" width="8" height="4" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/>',
|
|
9
|
-
check: '<path d="m5 13 4 4 10-10"/>',
|
|
10
|
-
camera: '<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>',
|
|
11
|
-
eye: '<path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12z"/><circle cx="12" cy="12" r="3"/>',
|
|
12
|
-
sliders: '<path d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M2 14h4M10 8h4M18 16h4"/>',
|
|
13
|
-
expand: '<path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/>',
|
|
14
|
-
shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',
|
|
15
|
-
chevron: '<path d="m6 9 6 6 6-6"/>',
|
|
16
|
-
back: '<path d="m15 18-6-6 6-6"/>',
|
|
17
|
-
zap: '<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>',
|
|
18
|
-
cube: '<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="m3.3 7 8.7 5 8.7-5M12 22V12"/>',
|
|
19
|
-
logout: '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>',
|
|
20
|
-
clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/>',
|
|
21
|
-
activity: '<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>',
|
|
22
|
-
transfer: '<path d="m3 16 4 4 4-4M7 20V4M21 8l-4-4-4 4M17 4v16"/>',
|
|
23
|
-
screen: '<rect x="2" y="5" width="20" height="13" rx="2"/><path d="M7 21h10"/>',
|
|
24
|
-
command: '<path d="M15 6a3 3 0 1 1 3 3h-3zm0 0v12m0 0a3 3 0 1 0 3-3h-3zM9 6a3 3 0 1 0-3 3h3zm0 0v12m0 0a3 3 0 1 1-3-3h3z"/>',
|
|
25
|
-
apps: '<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>',
|
|
26
|
-
terminal: '<path d="m4 17 6-6-6-6M12 19h8"/>',
|
|
27
|
-
folder: '<path d="M3 7h6l2 2h10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M3 7V6a2 2 0 0 1 2-2h4l2 3"/>',
|
|
28
|
-
close: '<path d="M18 6 6 18M6 6l12 12"/>',
|
|
29
|
-
sparkles: '<path d="m12 3 1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9L12 3z"/><path d="m19 15 .8 2.2 2.2.8-2.2.8L19 21l-.8-2.2-2.2-.8 2.2-.8z"/>',
|
|
30
|
-
broom: '<path d="M10 10V4a2 2 0 0 1 4 0v6"/><path d="M6 10h12a2 2 0 0 1 2 2v2H4v-2a2 2 0 0 1 2-2Z"/><path d="m5 14-2 7h18l-2-7M9 18l-1 3M15 18l1 3"/>',
|
|
31
|
-
panel: '<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M14 4v16"/>',
|
|
32
|
-
menu: '<path d="M4 7h16M4 12h16M4 17h16"/>',
|
|
33
|
-
plus: '<path d="M12 5v14M5 12h14"/>',
|
|
34
|
-
star: '<path d="m12 3 2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 17.8 6.2 20.9l1.1-6.5L2.6 9.8l6.5-.9L12 3z"/>',
|
|
35
|
-
trash: '<path d="M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>'
|
|
36
|
-
};
|
|
37
|
-
const FAVICON_DATA_URI = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f38020' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='3' width='20' height='14' rx='2'/%3E%3Cpath d='M8 21h8M12 17v4'/%3E%3C/svg%3E";
|
|
38
|
-
export {
|
|
39
|
-
FAVICON_DATA_URI,
|
|
40
|
-
ICON_PATHS
|
|
41
|
-
};
|
|
1
|
+
var h={monitor:'<rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>',link:'<path d="M9 17H7A5 5 0 0 1 7 7h2M15 7h2a5 5 0 1 1 0 10h-2M8 12h8"/>',power:'<path d="M12 2v10"/><path d="M18.4 6.6a9 9 0 1 1-12.8 0"/>',maximize:'<path d="M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3"/>',minimize:'<path d="M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3"/>',keyboard:'<rect x="2" y="4" width="20" height="16" rx="2"/><path d="M6 8h.01M10 8h.01M14 8h.01M18 8h.01M8 12h.01M12 12h.01M16 12h.01M7 16h10"/>',clipboard:'<rect x="8" y="2" width="8" height="4" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/>',check:'<path d="m5 13 4 4 10-10"/>',camera:'<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>',eye:'<path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12z"/><circle cx="12" cy="12" r="3"/>',sliders:'<path d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M2 14h4M10 8h4M18 16h4"/>',expand:'<path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/>',shield:'<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',chevron:'<path d="m6 9 6 6 6-6"/>',back:'<path d="m15 18-6-6 6-6"/>',zap:'<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>',cube:'<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="m3.3 7 8.7 5 8.7-5M12 22V12"/>',logout:'<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/>',activity:'<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>',transfer:'<path d="m3 16 4 4 4-4M7 20V4M21 8l-4-4-4 4M17 4v16"/>',screen:'<rect x="2" y="5" width="20" height="13" rx="2"/><path d="M7 21h10"/>',command:'<path d="M15 6a3 3 0 1 1 3 3h-3zm0 0v12m0 0a3 3 0 1 0 3-3h-3zM9 6a3 3 0 1 0-3 3h3zm0 0v12m0 0a3 3 0 1 1-3-3h3z"/>',apps:'<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>',terminal:'<path d="m4 17 6-6-6-6M12 19h8"/>',folder:'<path d="M3 7h6l2 2h10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M3 7V6a2 2 0 0 1 2-2h4l2 3"/>',close:'<path d="M18 6 6 18M6 6l12 12"/>',sparkles:'<path d="m12 3 1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9L12 3z"/><path d="m19 15 .8 2.2 2.2.8-2.2.8L19 21l-.8-2.2-2.2-.8 2.2-.8z"/>',broom:'<path d="M10 10V4a2 2 0 0 1 4 0v6"/><path d="M6 10h12a2 2 0 0 1 2 2v2H4v-2a2 2 0 0 1 2-2Z"/><path d="m5 14-2 7h18l-2-7M9 18l-1 3M15 18l1 3"/>',panel:'<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M14 4v16"/>',menu:'<path d="M4 7h16M4 12h16M4 17h16"/>',plus:'<path d="M12 5v14M5 12h14"/>',star:'<path d="m12 3 2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 17.8 6.2 20.9l1.1-6.5L2.6 9.8l6.5-.9L12 3z"/>',trash:'<path d="M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>'},a="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f38020' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='3' width='20' height='14' rx='2'/%3E%3Cpath d='M8 21h8M12 17v4'/%3E%3C/svg%3E";export{a as FAVICON_DATA_URI,h as ICON_PATHS};
|
package/dist/shared/protocol.js
CHANGED
|
@@ -1,39 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const TRANSPORT_PROTOCOLS = ["vnc", "rdp", "ssh"];
|
|
3
|
-
const RDP_SECURITY_MODES = ["auto", "nla", "tls", "rdp"];
|
|
4
|
-
const DEFAULT_PORTS = {
|
|
5
|
-
vnc: 5900,
|
|
6
|
-
rdp: 3389,
|
|
7
|
-
ssh: 22
|
|
8
|
-
};
|
|
9
|
-
const DEFAULT_SSH_PORT = DEFAULT_PORTS.ssh;
|
|
10
|
-
function isRemoteProtocol(value) {
|
|
11
|
-
return REMOTE_PROTOCOLS.includes(value);
|
|
12
|
-
}
|
|
13
|
-
function isRdpSecurity(value) {
|
|
14
|
-
return RDP_SECURITY_MODES.includes(value);
|
|
15
|
-
}
|
|
16
|
-
function toRemoteProtocol(value, fallback = "vnc") {
|
|
17
|
-
const wanted = String(value ?? "").toLowerCase();
|
|
18
|
-
return isRemoteProtocol(wanted) ? wanted : fallback;
|
|
19
|
-
}
|
|
20
|
-
function toRdpSecurity(value, fallback = "auto") {
|
|
21
|
-
const wanted = String(value ?? "").toLowerCase();
|
|
22
|
-
return isRdpSecurity(wanted) ? wanted : fallback;
|
|
23
|
-
}
|
|
24
|
-
function toPort(value, fallback) {
|
|
25
|
-
const port = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
26
|
-
return Number.isInteger(port) && port > 0 && port < 65536 ? port : fallback;
|
|
27
|
-
}
|
|
28
|
-
export {
|
|
29
|
-
DEFAULT_PORTS,
|
|
30
|
-
DEFAULT_SSH_PORT,
|
|
31
|
-
RDP_SECURITY_MODES,
|
|
32
|
-
REMOTE_PROTOCOLS,
|
|
33
|
-
TRANSPORT_PROTOCOLS,
|
|
34
|
-
isRdpSecurity,
|
|
35
|
-
isRemoteProtocol,
|
|
36
|
-
toPort,
|
|
37
|
-
toRdpSecurity,
|
|
38
|
-
toRemoteProtocol
|
|
39
|
-
};
|
|
1
|
+
var r=["vnc","rdp"],u=["vnc","rdp","ssh"],n=["auto","nla","tls","rdp"],c={vnc:5900,rdp:3389,ssh:22},R=c.ssh;function p(o){return r.includes(o)}function s(o){return n.includes(o)}function S(o,e="vnc"){let t=String(o??"").toLowerCase();return p(t)?t:e}function i(o,e="auto"){let t=String(o??"").toLowerCase();return s(t)?t:e}function O(o,e){let t=typeof o=="number"?o:Number.parseInt(String(o??""),10);return Number.isInteger(t)&&t>0&&t<65536?t:e}export{c as DEFAULT_PORTS,R as DEFAULT_SSH_PORT,n as RDP_SECURITY_MODES,r as REMOTE_PROTOCOLS,u as TRANSPORT_PROTOCOLS,s as isRdpSecurity,p as isRemoteProtocol,O as toPort,i as toRdpSecurity,S as toRemoteProtocol};
|
package/dist/shared/signals.js
CHANGED
|
@@ -1,41 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const GATEWAY_KEEPALIVE_SIGNAL = "VNC_GATEWAY_KEEPALIVE_v1";
|
|
3
|
-
const KEEPALIVE_INTERVAL_MS = 25e3;
|
|
4
|
-
const MAX_CLOSE_REASON_BYTES = 123;
|
|
5
|
-
function isRetryableDisconnect(diagnostic) {
|
|
6
|
-
if (!diagnostic.established || !diagnostic.close) return false;
|
|
7
|
-
if (diagnostic.close.code === 1006) return true;
|
|
8
|
-
return diagnostic.close.code === 1011 && /tcp|socket|network|host closed/i.test(diagnostic.close.reason);
|
|
9
|
-
}
|
|
10
|
-
function websocketCloseReason(reason) {
|
|
11
|
-
const encoder = new TextEncoder();
|
|
12
|
-
if (encoder.encode(reason).byteLength <= MAX_CLOSE_REASON_BYTES) return reason;
|
|
13
|
-
let shortened = "";
|
|
14
|
-
for (const character of reason) {
|
|
15
|
-
if (encoder.encode(`${shortened}${character}\u2026`).byteLength > MAX_CLOSE_REASON_BYTES) break;
|
|
16
|
-
shortened += character;
|
|
17
|
-
}
|
|
18
|
-
return `${shortened}\u2026`;
|
|
19
|
-
}
|
|
20
|
-
function sendableCloseCode(code) {
|
|
21
|
-
return code === 1005 || code === 1006 || code === 1015 ? 1011 : code;
|
|
22
|
-
}
|
|
23
|
-
async function messageToBytes(data) {
|
|
24
|
-
if (typeof data === "string") return new TextEncoder().encode(data);
|
|
25
|
-
if (data instanceof ArrayBuffer) return new Uint8Array(data);
|
|
26
|
-
if (data instanceof Blob) return new Uint8Array(await data.arrayBuffer());
|
|
27
|
-
if (ArrayBuffer.isView(data)) {
|
|
28
|
-
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
29
|
-
}
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
export {
|
|
33
|
-
GATEWAY_KEEPALIVE_SIGNAL,
|
|
34
|
-
GATEWAY_READY_SIGNAL,
|
|
35
|
-
KEEPALIVE_INTERVAL_MS,
|
|
36
|
-
MAX_CLOSE_REASON_BYTES,
|
|
37
|
-
isRetryableDisconnect,
|
|
38
|
-
messageToBytes,
|
|
39
|
-
sendableCloseCode,
|
|
40
|
-
websocketCloseReason
|
|
41
|
-
};
|
|
1
|
+
var o="VNC_GATEWAY_READY_v1",s="VNC_GATEWAY_KEEPALIVE_v1",c=25e3,f=123;function A(e){return!e.established||!e.close?!1:e.close.code===1006?!0:e.close.code===1011&&/tcp|socket|network|host closed/i.test(e.close.reason)}function u(e){let n=new TextEncoder;if(n.encode(e).byteLength<=123)return e;let r="";for(let t of e){if(n.encode(`${r}${t}\u2026`).byteLength>123)break;r+=t}return`${r}\u2026`}function E(e){return e===1005||e===1006||e===1015?1011:e}async function i(e){return typeof e=="string"?new TextEncoder().encode(e):e instanceof ArrayBuffer?new Uint8Array(e):e instanceof Blob?new Uint8Array(await e.arrayBuffer()):ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):null}export{s as GATEWAY_KEEPALIVE_SIGNAL,o as GATEWAY_READY_SIGNAL,c as KEEPALIVE_INTERVAL_MS,f as MAX_CLOSE_REASON_BYTES,A as isRetryableDisconnect,i as messageToBytes,E as sendableCloseCode,u as websocketCloseReason};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-remote",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
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": {
|
|
@@ -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;
|