[Init] Initial commit - NetMesh terminal manager
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
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
This commit is contained in:
164
domain/terminalHostResolution.ts
Normal file
164
domain/terminalHostResolution.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import type { GroupConfig, Host, ProxyProfile, TerminalSession } from "./models";
|
||||
import { applyGroupDefaults, resolveGroupDefaults } from "./groupConfig";
|
||||
import { materializeHostProxyProfile } from "./proxyProfiles";
|
||||
import { sanitizePluginConnection } from "./pluginConnection";
|
||||
|
||||
type LocalOs = Host["os"];
|
||||
|
||||
interface ResolveEffectiveHostOptions {
|
||||
host: Host;
|
||||
groupConfigs: GroupConfig[];
|
||||
proxyProfiles: ProxyProfile[];
|
||||
validProxyProfileIds?: ReadonlySet<string>;
|
||||
}
|
||||
|
||||
interface ResolveTerminalSessionHostOptions {
|
||||
session: TerminalSession;
|
||||
hosts: Host[];
|
||||
groupConfigs: GroupConfig[];
|
||||
proxyProfiles: ProxyProfile[];
|
||||
localOs: LocalOs;
|
||||
}
|
||||
|
||||
interface ResolveTerminalChainHostsOptions {
|
||||
host: Host | null | undefined;
|
||||
hosts: Host[];
|
||||
groupConfigs: GroupConfig[];
|
||||
proxyProfiles: ProxyProfile[];
|
||||
validProxyProfileIds?: ReadonlySet<string>;
|
||||
}
|
||||
|
||||
const resolveSerialBackspaceBehavior = (
|
||||
serialConfig: Host["serialConfig"],
|
||||
): Host["backspaceBehavior"] | null => {
|
||||
if (serialConfig?.backspaceBehavior === "ctrl-h") return "ctrl-h";
|
||||
if (serialConfig?.backspaceBehavior === "default") return undefined;
|
||||
return null;
|
||||
};
|
||||
|
||||
export function resolveEffectiveTerminalHost({
|
||||
host,
|
||||
groupConfigs,
|
||||
proxyProfiles,
|
||||
validProxyProfileIds = new Set(proxyProfiles.map((profile) => profile.id)),
|
||||
}: ResolveEffectiveHostOptions): Host {
|
||||
const groupDefaults = host.group
|
||||
? resolveGroupDefaults(host.group, groupConfigs, { validProxyProfileIds })
|
||||
: {};
|
||||
return materializeHostProxyProfile(
|
||||
applyGroupDefaults(host, groupDefaults, { validProxyProfileIds }),
|
||||
proxyProfiles,
|
||||
);
|
||||
}
|
||||
|
||||
const suppressDeviceTypeForShellTransport = (host: Host): Host => {
|
||||
if (!host.moshEnabled && !host.etEnabled) return host;
|
||||
if (host.deviceType === undefined) return host;
|
||||
return { ...host, deviceType: undefined };
|
||||
};
|
||||
|
||||
function buildFallbackHostFromSession(
|
||||
session: TerminalSession,
|
||||
localOs: LocalOs,
|
||||
): Host {
|
||||
const fallbackProtocol = session.protocol ?? "ssh";
|
||||
return {
|
||||
id: session.hostId,
|
||||
label: session.hostLabel || "Local Terminal",
|
||||
hostname: session.hostname || "localhost",
|
||||
username: session.username || "local",
|
||||
port: session.port ?? 22,
|
||||
os: fallbackProtocol === "local" ? localOs : "linux",
|
||||
group: "",
|
||||
tags: [],
|
||||
protocol: fallbackProtocol,
|
||||
pluginConnection: sanitizePluginConnection(session.pluginConnection, fallbackProtocol),
|
||||
moshEnabled: session.moshEnabled,
|
||||
etEnabled: session.etEnabled,
|
||||
charset: session.charset,
|
||||
serialConfig: session.serialConfig,
|
||||
backspaceBehavior: session.serialConfig?.backspaceBehavior === "ctrl-h" ? "ctrl-h" : undefined,
|
||||
localShell: session.localShell,
|
||||
localShellArgs: session.localShellArgs,
|
||||
localShellName: session.localShellName,
|
||||
localShellIcon: session.localShellIcon,
|
||||
localStartDir: session.localStartDir,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveTerminalSessionHost({
|
||||
session,
|
||||
hosts,
|
||||
groupConfigs,
|
||||
proxyProfiles,
|
||||
localOs,
|
||||
}: ResolveTerminalSessionHostOptions): Host {
|
||||
const vaultHost = hosts.find((host) => host.id === session.hostId);
|
||||
if (!vaultHost) return buildFallbackHostFromSession(session, localOs);
|
||||
|
||||
const existingHost = resolveEffectiveTerminalHost({
|
||||
host: vaultHost,
|
||||
groupConfigs,
|
||||
proxyProfiles,
|
||||
});
|
||||
|
||||
const protocol = session.protocol ?? existingHost.protocol;
|
||||
const pluginConnection = sanitizePluginConnection(session.pluginConnection, protocol)
|
||||
?? sanitizePluginConnection(existingHost.pluginConnection, protocol);
|
||||
const port = session.port ?? existingHost.port;
|
||||
const moshEnabled = session.moshEnabled ?? existingHost.moshEnabled;
|
||||
const etEnabled = session.etEnabled ?? existingHost.etEnabled;
|
||||
const sessionSerialBackspace = resolveSerialBackspaceBehavior(session.serialConfig);
|
||||
const hostSerialBackspace = resolveSerialBackspaceBehavior(existingHost.serialConfig);
|
||||
const backspaceBehavior = protocol === "serial"
|
||||
? sessionSerialBackspace !== null
|
||||
? sessionSerialBackspace
|
||||
: hostSerialBackspace !== null
|
||||
? hostSerialBackspace
|
||||
: existingHost.backspaceBehavior
|
||||
: existingHost.backspaceBehavior;
|
||||
|
||||
if (
|
||||
protocol === existingHost.protocol &&
|
||||
port === existingHost.port &&
|
||||
moshEnabled === existingHost.moshEnabled &&
|
||||
etEnabled === existingHost.etEnabled &&
|
||||
JSON.stringify(pluginConnection) === JSON.stringify(existingHost.pluginConnection) &&
|
||||
backspaceBehavior === existingHost.backspaceBehavior
|
||||
) {
|
||||
return suppressDeviceTypeForShellTransport(existingHost);
|
||||
}
|
||||
|
||||
return suppressDeviceTypeForShellTransport({
|
||||
...existingHost,
|
||||
protocol,
|
||||
port,
|
||||
moshEnabled,
|
||||
etEnabled,
|
||||
pluginConnection,
|
||||
backspaceBehavior,
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveTerminalChainHosts({
|
||||
host,
|
||||
hosts,
|
||||
groupConfigs,
|
||||
proxyProfiles,
|
||||
validProxyProfileIds = new Set(proxyProfiles.map((profile) => profile.id)),
|
||||
}: ResolveTerminalChainHostsOptions): Host[] {
|
||||
if (!host?.hostChain?.hostIds?.length) return [];
|
||||
const hostMap = new Map(hosts.map((candidate) => [candidate.id, candidate]));
|
||||
return host.hostChain.hostIds
|
||||
.map((hostId) => {
|
||||
const chainHost = hostMap.get(hostId);
|
||||
if (!chainHost) return undefined;
|
||||
return resolveEffectiveTerminalHost({
|
||||
host: chainHost,
|
||||
groupConfigs,
|
||||
proxyProfiles,
|
||||
validProxyProfileIds,
|
||||
});
|
||||
})
|
||||
.filter((value): value is Host => Boolean(value));
|
||||
}
|
||||
Reference in New Issue
Block a user