hook up remotes into remote command flow

This commit is contained in:
sawka
2023-04-03 15:55:03 -07:00
parent 81f555adcd
commit fb9eaf23f9
3 changed files with 357 additions and 40 deletions
+76 -8
View File
@@ -5,7 +5,7 @@ import {debounce} from "throttle-debounce";
import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeDataMap, genMergeSimpleData, boundInt, isModKeyPress} from "./util";
import {TermWrap} from "./term";
import {v4 as uuidv4} from "uuid";
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType, HistoryTypeStrs, RendererPluginType, WindowSize, ClientMigrationInfo, WebShareOpts, TermContextUnion} from "./types";
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType, HistoryTypeStrs, RendererPluginType, WindowSize, ClientMigrationInfo, WebShareOpts, TermContextUnion, RemoteEditType, RemoteViewType} from "./types";
import {WSControl} from "./ws";
import {measureText, getMonoFontSize, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows} from "./textmeasure";
import dayjs from "dayjs";
@@ -2283,12 +2283,13 @@ class BookmarksModel {
}
class RemotesModalModel {
openState : OV<boolean> = mobx.observable.box(false, {name: "RemotesModalModel-isOpen"});
selectedRemoteId : OV<string> = mobx.observable.box(null, {name: "RemotesModalModel-selectedRemoteId"});
remoteTermWrap : TermWrap;
remoteTermWrapFocus : OV<boolean> = mobx.observable.box(false, {name: "RemotesModalModel-remoteTermWrapFocus"});
showNoInputMsg : OV<boolean> = mobx.observable.box(false, {name: "RemotesModel-showNoInputMg"});
showNoInputTimeoutId : any = null;
authEditMode : OV<boolean> = mobx.observable.box(false, {name: "RemotesModal-authEditMode"});
remoteEdit : OV<RemoteEditType> = mobx.observable.box(null, {name: "RemoteModal-remoteEdit"});
openModal(remoteId? : string) : void {
if (remoteId == null) {
@@ -2304,7 +2305,17 @@ class RemotesModalModel {
}
}
mobx.action(() => {
this.openState.set(true);
this.selectedRemoteId.set(remoteId);
this.remoteEdit.set(null);
})();
}
openModalForEdit(redit : RemoteEditType) : void {
mobx.action(() => {
this.openState.set(true);
this.selectedRemoteId.set(redit.remoteid);
this.remoteEdit.set(redit);
})();
}
@@ -2314,31 +2325,38 @@ class RemotesModalModel {
}
mobx.action(() => {
this.selectedRemoteId.set(remoteId);
this.authEditMode.set(false);
this.remoteEdit.set(null);
})();
}
@boundMethod
startEditAuth() : void {
mobx.action(() => {
this.authEditMode.set(true);
})();
let remoteId = this.selectedRemoteId.get();
if (remoteId != null) {
GlobalCommandRunner.openEditRemote(remoteId);
}
}
@boundMethod
cancelEditAuth() : void {
mobx.action(() => {
this.authEditMode.set(false);
this.remoteEdit.set(null);
})();
}
isOpen() : boolean {
return this.selectedRemoteId.get() != null;
return this.openState.get();
}
isAuthEditMode() : boolean {
return this.remoteEdit.get() != null;
}
closeModal() : void {
mobx.action(() => {
this.openState.set(false);
this.selectedRemoteId.set(null);
this.remoteEdit.set(null);
})();
}
@@ -2618,6 +2636,9 @@ class Model {
}
if (e.code == "Escape") {
e.preventDefault();
if (this.clearModals()) {
return;
}
let inputModel = this.inputModel;
inputModel.toggleInfoMsg();
if (inputModel.inputMode.get() != null) {
@@ -2631,6 +2652,41 @@ class Model {
}
}
clearModals() : boolean {
let didSomething = false;
mobx.action(() => {
if (GlobalModel.screenSettingsModal.get()) {
GlobalModel.screenSettingsModal.set(null);
didSomething = true;
}
if (GlobalModel.sessionSettingsModal.get()) {
GlobalModel.sessionSettingsModal.set(null);
didSomething = true;
}
if (GlobalModel.screenSettingsModal.get()) {
GlobalModel.screenSettingsModal.set(null);
didSomething = true;
}
if (GlobalModel.remotesModalModel.isOpen()) {
GlobalModel.remotesModalModel.closeModal();
didSomething = true;
}
if (GlobalModel.clientSettingsModal.get()) {
GlobalModel.clientSettingsModal.set(false);
didSomething = true;
}
if (GlobalModel.lineSettingsModal.get()) {
GlobalModel.lineSettingsModal.set(null);
didSomething = true;
}
if (GlobalModel.welcomeModalOpen.get()) {
GlobalModel.welcomeModalOpen.set(false);
didSomething = true;
}
})();
return didSomething;
}
restartLocalServer() : void {
getApi().restartLocalServer();
}
@@ -2913,6 +2969,18 @@ class Model {
let info : InfoType = update.info;
this.inputModel.flashInfoMsg(info, info.timeoutms);
}
if (interactive && "remoteview" in update) {
let rview : RemoteViewType = update.remoteview;
if (rview.remoteshowall) {
this.remotesModalModel.openModal();
}
else if (rview.remoteedit != null) {
this.remotesModalModel.openModalForEdit(rview.remoteedit);
}
else if (rview.ptyremoteid) {
this.remotesModalModel.openModal(rview.ptyremoteid);
}
}
if ("cmdline" in update) {
this.inputModel.updateCmdLine(update.cmdline);
}
+276 -31
View File
@@ -6,8 +6,8 @@ import {boundMethod} from "autobind-decorator";
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
import cn from "classnames";
import {GlobalModel, GlobalCommandRunner, getTermPtyData, RemotesModalModel} from "./model";
import {Toggle, RemoteStatusLight, InlineSettingsTextEdit} from "./elements";
import {RemoteType, RemoteInputPacketType} from "./types";
import {Toggle, RemoteStatusLight, InlineSettingsTextEdit, InfoMessage} from "./elements";
import {RemoteType, RemoteInputPacketType, RemoteEditType} from "./types";
import * as util from "./util";
import * as textmeasure from "./textmeasure";
import {TermWrap} from "./term";
@@ -18,6 +18,7 @@ type OMap<K,V> = mobx.ObservableMap<K,V>;
const RemotePtyRows = 8;
const RemotePtyCols = 80;
const PasswordUnchangedSentinel = "--unchanged--";
function getRemoteCNWithPort(remote : RemoteType) {
if (util.isBlank(remote.remotevars.port) || remote.remotevars.port == "22") {
@@ -34,18 +35,254 @@ function getRemoteTitle(remote : RemoteType) {
}
@mobxReact.observer
class RemoteAuthSettings extends React.Component<{model : RemotesModalModel, remote : RemoteType}, {}> {
render() {
let {model, remote} = this.props;
class RemoteAuthSettings extends React.Component<{model : RemotesModalModel, remote : RemoteType, remoteEdit : RemoteEditType}, {}> {
authModeDropdownActive : OV<boolean> = mobx.observable.box(false, {name: "RemoteAuthSettings-authModeDropdownActive"});
connectModeDropdownActive : OV<boolean> = mobx.observable.box(false, {name: "RemoteAuthSettings-connectModeDropdownActive"});
tempAuthMode : OV<string>;
tempConnectMode : OV<string>;
tempManualMode : OV<boolean>;
tempPassword : OV<string>;
tempKeyFile : OV<string>;
constructor(props : any) {
super(props);
let {remote, remoteEdit} = this.props;
this.tempAuthMode = mobx.observable.box(remote.authtype, {name: "RemoteAuthSettings-authMode"});
this.tempConnectMode = mobx.observable.box(remote.connectmode, {name: "RemoteAuthSettings-connectMode"});
this.tempKeyFile = mobx.observable.box(remoteEdit.keystr ?? "", {name: "RemoteAuthSettings-keystr"});
this.tempPassword = mobx.observable.box(remoteEdit.haspassword ? PasswordUnchangedSentinel : "", {name: "RemoteAuthSettings-password"});
console.log("tempkeyfile", this.tempKeyFile.get());
console.log("keystr", mobx.toJS(remoteEdit));
}
@boundMethod
handleChangeKeyFile(e : any) : void {
mobx.action(() => {
this.tempKeyFile.set(e.target.value);
})();
}
@boundMethod
handleChangePassword(e : any) : void {
mobx.action(() => {
this.tempPassword.set(e.target.value);
})();
}
@boundMethod
canResetPw() : boolean {
let {remoteEdit} = this.props;
if (remoteEdit == null) {
return false;
}
return remoteEdit.haspassword && this.tempPassword.get() != PasswordUnchangedSentinel;
}
@boundMethod
resetPw() : void {
mobx.action(() => {
this.tempPassword.set(PasswordUnchangedSentinel);
})();
}
@boundMethod
onFocusPassword(e : any) {
if (this.tempPassword.get() == PasswordUnchangedSentinel) {
e.target.select();
}
}
@boundMethod
clickSetAuthMode(authMode : string) : void {
mobx.action(() => {
this.tempAuthMode.set(authMode);
this.authModeDropdownActive.set(false);
})();
}
@boundMethod
toggleAuthModeDropdown() : void {
mobx.action(() => {
this.authModeDropdownActive.set(!this.authModeDropdownActive.get());
})();
}
@boundMethod
submitRemote() : void {
let {remote} = this.props;
let authMode = this.tempAuthMode.get();
let kwargs : Record<string, string> = {};
if (authMode == "key" || authMode == "key+pw") {
kwargs["key"] = this.tempKeyFile.get();
}
else {
kwargs["key"] = "";
}
if (authMode == "pw" || authMode == "key+pw") {
kwargs["password"] = this.tempPassword.get();
}
else {
kwargs["password"] = ""
}
kwargs["connectmode"] = this.tempConnectMode.get();
kwargs["visual"] = "1";
kwargs["submit"] = "1";
GlobalCommandRunner.editRemote(remote.remoteid, kwargs);
}
renderAuthModeDropdown() : any {
return (
<div className="remote-detail">
<div className={cn("dropdown", "authmode-dropdown", {"is-active": this.authModeDropdownActive.get()})}>
<div className="dropdown-trigger">
<button onClick={this.toggleAuthModeDropdown} className="button is-small is-dark">
<span>{this.tempAuthMode.get()}</span>
<div className="flex-spacer"/>
<span className="icon is-small">
<i className="fa-sharp fa-regular fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div className="dropdown-menu" role="menu">
<div className="dropdown-content has-background-black">
<div key="none" onClick={() => this.clickSetAuthMode("none") } className="dropdown-item">none</div>
<div key="key" onClick={() => this.clickSetAuthMode("key") } className="dropdown-item">key</div>
<div key="password" onClick={() => this.clickSetAuthMode("password") } className="dropdown-item">password</div>
<div key="key+password" onClick={() => this.clickSetAuthMode("key+password") } className="dropdown-item">key+password</div>
</div>
</div>
</div>
);
}
@boundMethod
clickSetConnectMode(connectMode : string) : void {
mobx.action(() => {
this.tempConnectMode.set(connectMode);
this.connectModeDropdownActive.set(false);
})();
}
@boundMethod
toggleConnectModeDropdown() : void {
mobx.action(() => {
this.connectModeDropdownActive.set(!this.connectModeDropdownActive.get());
})();
}
renderConnectModeDropdown() : any {
return (
<div className={cn("dropdown", "connectmode-dropdown", {"is-active": this.connectModeDropdownActive.get()})}>
<div className="dropdown-trigger">
<button onClick={this.toggleConnectModeDropdown} className="button is-small is-dark">
<span>{this.tempConnectMode.get()}</span>
<div className="flex-spacer"/>
<span className="icon is-small">
<i className="fa-sharp fa-regular fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div className="dropdown-menu" role="menu">
<div className="dropdown-content has-background-black">
<div key="startup" onClick={() => this.clickSetConnectMode("startup") } className="dropdown-item">startup</div>
<div key="auto" onClick={() => this.clickSetConnectMode("auto") } className="dropdown-item">auto</div>
<div key="manual" onClick={() => this.clickSetConnectMode("manual") } className="dropdown-item">manual</div>
</div>
</div>
</div>
);
}
renderAuthModeMessage() : any {
let authMode = this.tempAuthMode.get();
if (authMode == "none") {
return (<span>This connection requires no authentication.<br/>Or authentication is already configured in ssh_config.</span>);
}
if (authMode == "key") {
return (<span>Use a public/private keypair.</span>);
}
if (authMode == "password") {
return (<span>Use a password.</span>);
}
if (authMode == "key+password") {
return (<span>Use a public/private keypair with a passphrase.</span>);
}
return null;
}
render() {
let {model, remote, remoteEdit} = this.props;
let authMode = this.tempAuthMode.get();
return (
<div className="remote-detail auth-editing">
<div className="title is-5">{getRemoteTitle(remote)}</div>
<div>
<div className="detail-subtitle">
Editing Authentication Settings
</div>
<div>
<div className="settings-field align-top">
<div className="settings-label">
Auth Mode
</div>
<div className="settings-input">
<div className="raw-input">{this.renderAuthModeDropdown()}</div>
<InfoMessage width={350}>
<ul>
<li><b>none</b> - No authentication, or authentication is already configured in your ssh config.</li>
<li><b>key</b> - Use a private key.</li>
<li><b>password</b> - Use a password.</li>
<li><b>key+password</b> - Use a key with a passphrase.</li>
</ul>
</InfoMessage>
</div>
</div>
<If condition={authMode == "key" || authMode == "key+password"}>
<div className="settings-field" style={{marginTop: 10}}>
<div className="settings-label">
SSH Keyfile
</div>
<div className="settings-input">
<input type="text" placeholder="keyfile" onChange={this.handleChangeKeyFile} value={this.tempKeyFile.get()} maxLength={400}/>
</div>
</div>
</If>
<If condition={authMode == "password" || authMode == "key+password"}>
<div className="settings-field" style={{marginTop: 10}}>
<div className="settings-label">
{authMode == "password" ? "SSH Password" : "Key Passphrase"}
</div>
<div className="settings-input">
<input type="password" placeholder="password" onFocus={this.onFocusPassword} onChange={this.handleChangePassword} value={this.tempPassword.get()} maxLength={400}/>
<If condition={this.canResetPw()}>
<div className="undo-icon" title="restore to original password"><i onClick={this.resetPw} className="icon fa-sharp fa-solid fa-rotate-left"/></div>
</If>
</div>
</div>
</If>
<div className="settings-field align-top" style={{marginTop: 10}}>
<div className="settings-label">
Connect Mode
</div>
<div className="settings-input">
<div className="raw-input"><div className="raw-input">{this.renderConnectModeDropdown()}</div></div>
<InfoMessage width={350}>
<ul>
<li><b>startup</b> - connect when [prompt] starts.</li>
<li><b>auto</b> - connect when you first run a command using this connection.</li>
<li><b>manual</b> - connect manually. Note, if your connection requires manual input, like an OPT code, you must use this setting.</li>
</ul>
</InfoMessage>
</div>
</div>
<If condition={!util.isBlank(remoteEdit.errorstr)}>
<div className="remoteedit-error">
Error: {remoteEdit.errorstr ?? "An error occured"}
</div>
</If>
<div className="flex-spacer"/>
<div className="action-buttons">
<div className="flex-spacer"/>
<div onClick={model.cancelEditAuth} className="button is-plain is-outlined is-small">Cancel</div>
<div style={{marginLeft: 10}} onClick={null} className="button is-prompt-green is-outlined is-small">Submit</div>
<div style={{marginLeft: 10, marginRight: 20}} onClick={this.submitRemote} className="button is-prompt-green is-outlined is-small">Submit</div>
</div>
</div>
);
@@ -117,7 +354,7 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
if (!confirm) {
return;
}
console.log("archive remote", remoteId);
GlobalCommandRunner.archiveRemote(remoteId);
});
}
@@ -166,18 +403,22 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
<div key="connect" style={{marginLeft: 10}} onClick={() => this.connectRemote(remote.remoteid)} className="button is-prompt-green is-outlined is-small">Connect Now</div>
);
let tryReconnectButton = (
<div style={{marginLeft: 10}} onClick={() => this.connectRemote(remote.remoteid)} className="button is-prompt-green is-outlined is-small">Try Reconnect</div>
<div key="tryreconnect" style={{marginLeft: 10}} onClick={() => this.connectRemote(remote.remoteid)} className="button is-prompt-green is-outlined is-small">Try Reconnect</div>
);
let updateAuthButton = (
<div style={{marginLeft: 10}} onClick={() => this.editAuthSettings()} className="button is-plain is-outlined is-small">Update Auth Settings</div>
<div key="updateauth" style={{marginLeft: 10}} onClick={() => this.editAuthSettings()} className="button is-plain is-outlined is-small">Update Auth Settings</div>
);
let cancelInstallButton = (
<div style={{marginLeft: 10}} onClick={() => this.cancelInstall(remote.remoteid)} className="button is-prompt-danger is-outlined is-small">Cancel Install</div>
<div key="cancelinstall" style={{marginLeft: 10}} onClick={() => this.cancelInstall(remote.remoteid)} className="button is-prompt-danger is-outlined is-small">Cancel Install</div>
);
let installNowButton = (
<div style={{marginLeft: 10}} onClick={() => this.installRemote(remote.remoteid)} className="button is-prompt-green is-outlined is-small">Install Now</div>
<div key="installnow" style={{marginLeft: 10}} onClick={() => this.installRemote(remote.remoteid)} className="button is-prompt-green is-outlined is-small">Install Now</div>
);
if (remote.local) {
installNowButton = null;
updateAuthButton = null;
cancelInstallButton = null;
}
if (remote.status == "connected") {
message = "Connected and ready to run commands.";
buttons = [disconnectButton];
@@ -258,11 +499,16 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
<div className="settings-field">
<div className="settings-label">Auth Type</div>
<div className="settings-input">
{remote.authtype} <i style={{marginLeft: 12}} className="fa-sharp fa-solid fa-pen hide-hover"/>
<div onClick={() => this.editAuthSettings()} className="button is-plain is-outlined is-small is-inline-height ml-2 update-auth-button">
<span className="icon is-small"><i className="fa-sharp fa-solid fa-pen"/></span>
<span>Update Auth Settings</span>
</div>
<If condition={!remote.local}>
{remote.authtype} <i style={{marginLeft: 12}} className="fa-sharp fa-solid fa-pen hide-hover"/>
<div onClick={() => this.editAuthSettings()} className="button is-plain is-outlined is-small is-inline-height ml-2 update-auth-button">
<span className="icon is-small"><i className="fa-sharp fa-solid fa-pen"/></span>
<span>Update Auth Settings</span>
</div>
</If>
<If condition={remote.local}>
local
</If>
</div>
</div>
<div className="settings-field">
@@ -272,14 +518,16 @@ class RemoteDetailView extends React.Component<{model : RemotesModalModel, remot
</div>
</div>
{this.renderInstallStatus(remote)}
<div className="settings-field">
<div className="settings-label">Archive</div>
<div className="settings-input">
<div onClick={() => this.clickArchive(remote.remoteid)} className="button is-prompt-danger is-outlined is-small is-inline-height">
Archive This Connection
<If condition={!remote.local}>
<div className="settings-field">
<div className="settings-label">Archive</div>
<div className="settings-input">
<div onClick={() => this.clickArchive(remote.remoteid)} className="button is-prompt-danger is-outlined is-small is-inline-height">
Archive This Connection
</div>
</div>
</div>
</div>
</If>
<div className="flex-spacer" style={{minHeight: 20}}/>
<div style={{width: termWidth}}>
{remoteMessage}
@@ -359,7 +607,7 @@ class RemotesModal extends React.Component<{model : RemotesModalModel}, {}> {
let selectedRemoteId = model.selectedRemoteId.get();
let allRemotes = util.sortAndFilterRemotes(GlobalModel.remotes.slice());
let remote : RemoteType = null;
let isAuthEditMode = model.authEditMode.get();
let isAuthEditMode = model.isAuthEditMode();
let selectedRemote = GlobalModel.getRemote(selectedRemoteId);
return (
<div className={cn("modal remotes-modal settings-modal prompt-modal is-active")}>
@@ -386,13 +634,10 @@ class RemotesModal extends React.Component<{model : RemotesModalModel}, {}> {
<RemoteDetailView key={"remotedetail-" + selectedRemoteId} remote={selectedRemote} model={model}/>
</If>
<If condition={isAuthEditMode}>
<RemoteAuthSettings key={"remoteauth-" + selectedRemoteId} remote={selectedRemote} model={model}/>
<RemoteAuthSettings key={"remoteauth-" + selectedRemoteId} remote={selectedRemote} remoteEdit={model.remoteEdit.get()} model={model}/>
</If>
</If>
</div>
<footer>
<div onClick={this.closeModal} className="button is-plain is-outlined is-small">Close</div>
</footer>
</div>
</div>
);
+5 -1
View File
@@ -274,6 +274,7 @@ type ModelUpdateType = {
selectedbookmark? : string,
clientdata? : ClientDataType,
historyviewdata? : HistoryViewDataType,
remoteview? : RemoteViewType,
};
type HistoryViewDataType = {
@@ -330,6 +331,9 @@ type InfoType = {
infocomps? : string[],
infocompsmore? : boolean,
timeoutms? : number,
};
type RemoteViewType = {
ptyremoteid? : string,
remoteedit? : RemoteEditType,
remoteshowall? : boolean,
@@ -583,4 +587,4 @@ type RendererContainerType = {
type LineHeightChangeCallbackType = (lineNum : number, newHeight : number, oldHeight : number) => void;
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts, RemoteStatusTypeStrs, WebFullScreen, WebScreen, WebLine, WebCmd, RemoteTermContext, TermContextUnion, WebRemote, PtyDataUpdate, WebShareWSMessage, LineHeightChangeCallbackType, LineFactoryProps, LineInterface, RendererContainerType};
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts, RemoteStatusTypeStrs, WebFullScreen, WebScreen, WebLine, WebCmd, RemoteTermContext, TermContextUnion, WebRemote, PtyDataUpdate, WebShareWSMessage, LineHeightChangeCallbackType, LineFactoryProps, LineInterface, RendererContainerType, RemoteViewType};