Files
NetMesh/types/global/netcatty-bridge-session.d.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

621 lines
22 KiB
TypeScript

declare global {
interface NetcattyKittyKeyboardModeState {
mainFlags: number;
alternateFlags: number;
mainStack: number[];
alternateStack: number[];
alternateScreenActive: boolean;
}
interface NetcattyTerminalInterruptTrace {
debug?: boolean;
traceId?: string;
source?: string;
sessionId?: string;
rendererKeyAt?: number;
rendererSendAt?: number;
rendererStatus?: string;
rendererHasSelection?: boolean;
rendererPriority?: {
sessionId: string | null;
backlogBytes: number;
writeQueueDepth: number;
deferredAckBytes: number;
ackAfterInputBytes: number;
scheduledBackendResume: boolean;
skippedReason?: string;
};
}
interface NetcattyTerminalOutputPerfMeta {
id: string;
emittedAt: number;
sessionId?: string;
chars: number;
lineFeeds: number;
}
interface NetcattyBridge {
getWindowsPtyInfo?(): NetcattyWindowsPtyInfo | null;
startSSHSession(options: NetcattySSHOptions): Promise<string>;
startTelnetSession?(options: {
sessionId?: string;
hostname: string;
port?: number;
username?: string;
password?: string;
cols?: number;
rows?: number;
charset?: string;
env?: Record<string, string>;
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
}): Promise<string>;
startMoshSession?(options: {
sessionId?: string;
hostname: string;
username?: string;
password?: string;
privateKey?: string;
certificate?: string;
keyId?: string;
passphrase?: string;
authMethod?: import("../../domain/models").HostAuthMethod;
requiresMfa?: boolean;
identityFilePaths?: string[];
useSshAgent?: boolean;
agentPublicKeys?: string[];
identityAgent?: string;
identitiesOnly?: boolean;
addKeysToAgent?: string;
useKeychain?: boolean;
port?: number;
moshServerPath?: string;
moshClientPath?: string;
agentForwarding?: boolean;
sudoAutofillPassword?: string;
// Algorithm settings, forwarded so the host-info stats companion SSH
// connection (issue #1198) negotiates the same KEX / cipher / host-key
// set the interactive session would.
legacyAlgorithms?: boolean;
skipEcdsaHostKey?: boolean;
algorithmOverrides?: import("../../domain/models").HostAlgorithmOverrides;
// Known hosts, used to verify the host key before the stats companion
// connection (issue #1198) sends a saved password.
knownHosts?: import("../../domain/models").KnownHost[];
verifyHostKeys?: boolean;
cols?: number;
rows?: number;
charset?: string;
env?: Record<string, string>;
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
}): Promise<string>;
startEtSession?(options: {
sessionId?: string;
hostname: string;
hostId?: string;
username?: string;
password?: string;
privateKey?: string;
certificate?: string;
keyId?: string;
passphrase?: string;
authMethod?: import("../../domain/models").HostAuthMethod;
requiresMfa?: boolean;
identityFilePaths?: string[];
useSshAgent?: boolean;
agentPublicKeys?: string[];
identityAgent?: string;
identitiesOnly?: boolean;
addKeysToAgent?: string;
useKeychain?: boolean;
port?: number;
etPort?: number;
legacyAlgorithms?: boolean;
skipEcdsaHostKey?: boolean;
algorithmOverrides?: import("../../domain/models").HostAlgorithmOverrides;
knownHosts?: import("../../domain/models").KnownHost[];
verifyHostKeys?: boolean;
jumpHosts?: NetcattyJumpHost[];
agentForwarding?: boolean;
sudoAutofillPassword?: string;
cols?: number;
rows?: number;
charset?: string;
env?: Record<string, string>;
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
}): Promise<string>;
startLocalSession?(options: {
sessionId?: string;
cols?: number;
rows?: number;
shell?: string;
shellArgs?: string[];
cwd?: string;
env?: Record<string, string>;
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
bootEpoch?: number;
}): Promise<string>;
startSerialSession?(options: {
sessionId?: string;
path: string;
baudRate?: number;
dataBits?: 5 | 6 | 7 | 8;
stopBits?: 1 | 1.5 | 2;
parity?: 'none' | 'even' | 'odd' | 'mark' | 'space';
flowControl?: 'none' | 'xon/xoff' | 'rts/cts';
charset?: string;
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
}): Promise<string>;
listSerialPorts?(): Promise<Array<{
path: string;
manufacturer: string;
serialNumber: string;
vendorId: string;
productId: string;
pnpId: string;
}>>;
sendSerialYmodem?(sessionId: string, filePath: string): Promise<{
success: boolean;
fileName?: string;
totalBytes?: number;
writtenBytes?: number;
error?: string;
code?: string;
}>;
receiveSerialYmodem?(sessionId: string, destinationDir: string): Promise<{
success: boolean;
files?: Array<{
fileName: string;
filePath: string;
totalBytes: number;
writtenBytes: number;
}>;
fileCount?: number;
fileName?: string;
filePath?: string;
totalBytes?: number;
writtenBytes?: number;
error?: string;
code?: string;
}>;
getDefaultShell?(): Promise<string>;
discoverShells?(): Promise<DiscoveredShell[]>;
validatePath?(path: string, type?: 'file' | 'directory' | 'any'): Promise<{ exists: boolean; isFile: boolean; isDirectory: boolean; isExecutable: boolean }>;
generateKeyPair?(options: {
type: 'RSA' | 'ECDSA' | 'ED25519';
bits?: number;
comment?: string;
}): Promise<{ success: boolean; privateKey?: string; publicKey?: string; error?: string }>;
checkSshAgent?(options?: {
identityAgent?: string;
agentForwarding?: boolean;
hostname?: string;
port?: number;
username?: string;
}): Promise<{ running: boolean; startupType: string | null; error: string | null }>;
getDefaultKeys?(): Promise<Array<{ name: string; path: string }>>;
execCommand(options: {
hostname: string;
hostId?: string;
username: string;
port?: number;
authMethod?: import("../../domain/models").HostAuthMethod;
requiresMfa?: boolean;
password?: string;
privateKey?: string;
certificate?: string;
publicKey?: string;
keyId?: string;
keySource?: 'generated' | 'imported' | 'reference';
identityFilePaths?: string[];
useSshAgent?: boolean;
agentPublicKeys?: string[];
identityAgent?: string;
identitiesOnly?: boolean;
addKeysToAgent?: string;
useKeychain?: boolean;
passphrase?: string;
command: string;
timeout?: number;
sshTcpConnectTimeoutMs?: number;
sshAuthReadyTimeoutMs?: number;
enableKeyboardInteractive?: boolean;
sessionId?: string;
legacyAlgorithms?: boolean;
skipEcdsaHostKey?: boolean;
algorithmOverrides?: import("../../domain/models").HostAlgorithmOverrides;
}): Promise<{ stdout: string; stderr: string; code: number | null }>;
/** Get current working directory from an active SSH session */
getSessionPwd?(
sessionId: string,
options?: {
allowHomeFallback?: boolean;
allowLoginShellFallback?: boolean;
timeoutMs?: number;
},
): Promise<{ success: boolean; cwd?: string; error?: string }>;
/**
* Get metadata about an already-connected SSH session — currently the
* SSH server identification string (the `software` part of the
* SSH-2.0 banner). Used to classify network-device vendors from the
* banner without opening any additional exec channel.
*/
getSessionRemoteInfo?(sessionId: string): Promise<{
success: boolean;
remoteSshVersion?: string;
error?: string;
}>;
/**
* Probe the remote distro by running
* `cat /etc/os-release 2>/dev/null || uname -a` on the existing SSH
* connection's exec channel (not a brand-new connection). Used as a
* fallback when banner classification could not identify a network
* device vendor and we still want a distro-specific icon.
*/
getSessionDistroInfo?(sessionId: string): Promise<{
success: boolean;
stdout?: string;
stderr?: string;
error?: string;
}>;
/** Read the remote host's shell history file via an exec channel. */
readRemoteHistory?(sessionId: string, limit?: number): Promise<{
success: boolean;
pending?: boolean;
error?: string;
shell?: string;
bash?: string;
zsh?: string;
fish?: string;
}>;
/** Get server stats (CPU, Memory, Disk, Network) from an active SSH session */
getServerStats?(sessionId: string): Promise<{
success: boolean;
// Transient "not ready yet" (e.g. a Mosh session whose SSH handshake is
// still in progress, #1198). Callers should keep polling and NOT count
// this toward any consecutive-failure give-up.
pending?: boolean;
error?: string;
stats?: {
cpu: number | null; // CPU usage percentage (0-100)
cpuCores: number | null; // Number of CPU cores
cpuPerCore: number[]; // Per-core CPU usage array
memTotal: number | null; // Total memory in MB
memUsed: number | null; // Used memory in MB (excluding buffers/cache)
memFree: number | null; // Free memory in MB
memBuffers: number | null; // Buffers in MB
memCached: number | null; // Cached in MB
swapTotal: number | null; // Total swap in MB
swapUsed: number | null; // Used swap in MB
topProcesses: Array<{ // Top 10 processes by memory
pid: string;
memPercent: number;
command: string;
}>;
diskPercent: number | null; // Disk usage percentage for root partition
diskUsed: number | null; // Disk used in GB
diskTotal: number | null; // Total disk in GB
disks: Array<{ // All mounted disks
capacityKey?: string; // Filesystem or shared-pool identity
mountPoint: string;
used: number; // Used in GB
total: number; // Total in GB
percent: number; // Usage percentage
filesystemType?: string; // Filesystem type reported by df
}>;
netRxSpeed: number; // Total network receive speed (bytes/sec)
netTxSpeed: number; // Total network transmit speed (bytes/sec)
latencyMs: number | null; // TCP connection establishment latency to the SSH endpoint
netInterfaces: Array<{ // Per-interface network stats
name: string; // Interface name (e.g., eth0, ens33)
rxBytes: number; // Total received bytes
txBytes: number; // Total transmitted bytes
rxSpeed: number; // Receive speed (bytes/sec)
txSpeed: number; // Transmit speed (bytes/sec)
}>;
hostname?: string; // Hostname reported by the server
osName?: string; // Friendly OS name when available
kernelRelease?: string; // Kernel release from uname
uptimeSeconds?: number | null; // Server uptime in seconds
loadAverage?: number[]; // 1/5/15-minute load average
};
}>;
setSessionEncoding?(sessionId: string, encoding: string): Promise<{ ok: boolean; encoding: string }>;
writeToSession(
sessionId: string,
data: string,
options?: {
automated?: boolean;
/** Host-classified secret/no-echo input; always bypasses plugin observers and interceptors. */
sensitive?: boolean;
lineDelayMs?: number;
logRewrite?: { sentCommand: string; displayCommand: string };
},
): void;
interruptSession?(sessionId: string, trace?: NetcattyTerminalInterruptTrace): void;
resizeSession(sessionId: string, cols: number, rows: number): void;
/**
* Sync Windows ConPTY after the renderer clears the xterm viewport.
* No-op for SSH and non-ConPTY sessions.
*/
clearSessionPtyBuffer?(sessionId: string): void;
setSessionFlowPaused(sessionId: string, paused: boolean): void;
setSessionFlowPausedAndWait?(sessionId: string, paused: boolean): Promise<{ success: boolean; error?: string }>;
acquireSessionFlowPauseLease?(sessionId: string): Promise<{
success: boolean;
leaseId?: string;
error?: string;
}>;
waitSessionFlowPauseLease?(sessionId: string, leaseId: string): Promise<{
success: boolean;
error?: string;
}>;
releaseSessionFlowPauseLease?(
sessionId: string,
leaseId: string,
options?: { keepPaused?: boolean },
): Promise<{ success: boolean; error?: string }>;
onTerminalOutputDrainRequest?(
sessionId: string,
cb: (payload: { sessionId: string; requestId: string }) => void | Promise<void>,
): () => void;
respondTerminalOutputDrain?(requestId: string): void;
notifyTerminalSessionDisplayReady?(sessionId: string): void;
ackSessionFlow(sessionId: string, bytes: number): void;
closeSession(sessionId: string, options?: { bootEpoch?: number; retainOwnership?: boolean }): void | Promise<void>;
/** Move a live session's output port to this renderer (same PTY). */
rebindTerminalSessionOutput?(sessionId: string, authorization: string): Promise<{
success: boolean;
previousWebContentsId?: number | null;
webContentsId?: number;
error?: string;
}>;
/** Restore output after an attach popup closes. */
restoreTerminalSessionOutput?(
sessionId: string,
webContentsId?: number | null,
authorization?: string,
): Promise<{ success: boolean; restored?: boolean; webContentsId?: number; error?: string }>;
/** Ask the home renderer to serialize current terminal scrollback. */
requestTerminalSessionSnapshot?(sessionId: string, authorization: string): Promise<{
success: boolean;
snapshot?: string;
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState;
kittyKeyboardProtocolEnabled?: boolean;
passwordPromptActive?: boolean;
cwd?: string | null;
title?: string | null;
error?: string;
}>;
/** Home renderer: listen for snapshot requests. */
onTerminalSessionSnapshotRequest?(
cb: (payload: { sessionId: string; requestId: string }) => void,
): () => void;
/** Home renderer: reply with serialized scrollback. */
respondTerminalSessionSnapshot?(
requestId: string,
snapshot: string,
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState,
kittyKeyboardProtocolEnabled?: boolean,
passwordPromptActive?: boolean,
cwd?: string | null,
title?: string | null,
): void;
/** Observe popup: push current state back to the home renderer before restore. */
applyTerminalSessionSnapshot?(
sessionId: string,
snapshot: string,
context: {
contextSnapshot: string;
contextViewportSnapshot: string;
contextScrollbackSnapshot: string;
alternateScreen: boolean;
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState;
kittyKeyboardProtocolEnabled?: boolean;
passwordPromptActive?: boolean;
cwd?: string | null;
title?: string | null;
},
authorization: string,
): Promise<{
success: boolean;
error?: string;
}>;
markAttachPopupClosePrepared?(sessionId: string, authorization: string): Promise<{ success: boolean; error?: string }>;
onTerminalPopupPrepareClose?(cb: (payload: { sessionId: string; authorization: string }) => void): () => void;
/** Home renderer: apply a pushed snapshot from an observe popup. */
onTerminalSessionApplySnapshot?(
cb: (payload: {
sessionId: string;
snapshot: string;
contextSnapshot: string;
contextViewportSnapshot: string;
contextScrollbackSnapshot: string;
alternateScreen: boolean;
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState;
kittyKeyboardProtocolEnabled?: boolean;
passwordPromptActive?: boolean;
cwd?: string | null;
title?: string | null;
requestId: string;
}) => boolean | Promise<boolean>,
): () => void;
// ZMODEM file transfer
onZmodemEvent?(
sessionId: string,
cb: (event: {
type: 'detect' | 'progress' | 'complete' | 'error';
sessionId: string;
transferType?: 'upload' | 'download';
filename?: string;
transferred?: number;
total?: number;
fileIndex?: number;
fileCount?: number;
finalizing?: boolean;
error?: string;
}) => void
): () => void;
cancelZmodem?(sessionId: string, options?: { interrupt?: boolean }): void;
startZmodemDragDropUpload?(
sessionId: string,
files: Array<{
path?: string;
name: string;
remoteName: string;
data?: ArrayBuffer;
}>,
uploadCommand?: string,
): Promise<{ success: boolean; error?: string }>;
onZmodemOverwriteRequest?(
sessionId: string,
cb: (payload: { sessionId: string; requestId: string; filename: string }) => void
): () => void;
respondZmodemOverwrite?(payload: {
requestId: string;
action: "overwrite" | "skip" | "cancel";
applyToRest: boolean;
}): void;
onSessionData(
sessionId: string,
cb: (
data: string,
meta?: {
droppedOutputMayAffectTerminalState?: boolean;
droppedOutputAlternateScreenAction?: "enter" | "leave";
/** True while Mosh is still on the ephemeral SSH handshake PTY. */
moshHandshake?: boolean;
/** The Mosh SSH bootstrap is blocked on input that Netcatty cannot answer automatically. */
moshHandshakeRequiresUserInput?: boolean;
terminalPerf?: NetcattyTerminalOutputPerfMeta;
/** Original host output units acknowledged even when an interceptor changes display length. */
pluginPipelineIngressBytes?: number;
/** Host-owned provenance marker for output already processed by an interceptor. */
pluginPipelineProcessed?: boolean;
/** Host-classified authentication prompt state for protecting subsequent input. */
pluginPipelineSensitiveInput?: boolean;
/** Host-owned marker that a Plugin connection Provider has explicitly reached connected status. */
pluginConnectionReady?: boolean;
},
) => void,
options?: { replayBacklog?: boolean },
): () => void;
onSessionExit(
sessionId: string,
cb: (evt: { exitCode?: number; signal?: number; error?: string; reason?: "exited" | "error" | "timeout" | "closed" }) => void
): () => void;
onTelnetAutoLoginComplete?(
sessionId: string,
cb: (evt: { sessionId: string; bootEpoch?: number }) => void
): () => void;
onTelnetAutoLoginCancelled?(
sessionId: string,
cb: (evt: { sessionId: string; bootEpoch?: number }) => void
): () => void;
/** Fires after Mosh swaps from the SSH handshake PTY to mosh-client. */
onMoshSessionReady?(
sessionId: string,
cb: (evt: { sessionId: string; bootEpoch?: number }) => void
): () => void;
onTelnetEchoMode?(
sessionId: string,
cb: (evt: { sessionId: string; remoteEcho: boolean; localEcho: boolean }) => void
): () => void;
getTelnetEchoMode?(sessionId: string): Promise<{
success: boolean;
sessionId?: string;
remoteEcho?: boolean;
localEcho?: boolean;
error?: string;
}>;
onAuthFailed?(
sessionId: string,
cb: (evt: { sessionId: string; error: string; hostname: string }) => void
): () => void;
// Keyboard-interactive authentication (2FA/MFA)
onKeyboardInteractive?(
cb: (request: {
requestId: string;
sessionId: string;
hostId?: string;
name: string;
instructions: string;
prompts: Array<{ prompt: string; echo: boolean }>;
hostname: string;
savedPassword?: string | null;
/** When false, UI must not offer saving the response as the host password. */
allowSavePassword?: boolean;
scope?: "terminal" | "external";
bootEpoch?: number;
}) => void
): () => void;
onKeyboardInteractiveCancelled?(
cb: (event: {
requestId: string;
sessionId?: string;
reason?: string;
}) => void
): () => void;
respondKeyboardInteractive?(
requestId: string,
responses: string[],
cancelled?: boolean
): Promise<{ success: boolean; error?: string }>;
onHostKeyVerification?(
cb: (request: {
requestId: string;
sessionId: string;
hostname: string;
port: number;
status: 'unknown' | 'changed';
keyType: string;
fingerprint: string;
publicKey?: string;
knownHostId?: string;
knownFingerprint?: string;
bootEpoch?: number;
}) => void
): () => void;
respondHostKeyVerification?(
requestId: string,
accept: boolean,
addToKnownHosts?: boolean
): Promise<{ success: boolean; error?: string }>;
// Passphrase request for encrypted SSH keys
onPassphraseRequest?(
cb: (request: {
requestId: string;
keyPath: string;
keyName: string;
hostname?: string;
passphraseInvalid?: boolean;
sessionId?: string;
bootEpoch?: number;
}) => void
): () => void;
respondPassphrase?(
requestId: string,
passphrase: string,
cancelled?: boolean
): Promise<{ success: boolean; error?: string }>;
respondPassphraseSkip?(
requestId: string
): Promise<{ success: boolean; error?: string }>;
onPassphraseTimeout?(
cb: (event: { requestId: string }) => void
): () => void;
onPassphraseCancelled?(
cb: (event: { requestId: string; reason?: string }) => void
): () => void;
onPassphraseAuthFailed?(
cb: (event: { keyPaths: string[]; keyIds?: string[] }) => void
): () => void;
}
}
export {};