Files
kandev/apps/web/lib/executor-icons.ts
T
José Almeida ce6d4e6e2a feat(web): add SSH executor settings UI
SSHConnectionCard: connection form (name, host_alias / host / port /
user, identity source = ssh-agent | file with optional file path,
optional ProxyJump) with a Test Connection button that runs the backend
probe, surfaces the observed host fingerprint, and only enables Save
when the user explicitly ticks "Trust this host". Editing the host /
port / user / identity fields resets both the test result and the trust
checkbox. On save, if the executor already has running sessions, a
confirm modal warns that those keep going on the old host and only new
sessions will use the new config.

SSHSessionsCard: 90s-polled table of active sessions for the executor,
mirroring SpritesInstancesCard / DockerContainersCard. Columns: task,
session, user@host, remote agentctl port, local forward port, uptime,
status badge. Backed by GET /api/v1/ssh/executors/:id/sessions.

Also registers the ssh entry in executor-icons.ts (label "SSH",
IconTerminal2) so it surfaces consistently in the rest of the settings
chrome.
2026-05-17 23:28:50 +01:00

72 lines
1.8 KiB
TypeScript

import {
IconBox,
IconBoxOff,
IconCloud,
IconCloudOff,
IconFolder,
IconFolders,
IconServer,
IconServerOff,
IconTerminal2,
} from "@tabler/icons-react";
export const EXECUTOR_ICON_MAP: Record<string, typeof IconFolder> = {
local: IconFolder,
worktree: IconFolders,
local_docker: IconBox,
remote_docker: IconBox,
sprites: IconCloud,
ssh: IconTerminal2,
};
export function getExecutorIcon(type: string): typeof IconFolder {
return EXECUTOR_ICON_MAP[type] ?? IconFolder;
}
const EXECUTOR_LABEL_MAP: Record<string, string> = {
local: "Local",
worktree: "Worktree",
local_docker: "Local Docker",
remote_docker: "Remote Docker",
sprites: "Sprites.dev",
ssh: "SSH",
};
export function getExecutorLabel(type: string): string {
return EXECUTOR_LABEL_MAP[type] ?? type;
}
/**
* Picks the status icon for the right-side executor popover button and the
* left-side cloud tooltip on cards/lists. The "Off" variants signal an error
* state (e.g. missing sandbox upstream) so the surface can swap glyph + color
* without each caller inventing its own mapping.
*/
export function getExecutorStatusIcon(
executorType: string | null | undefined,
hasError: boolean,
): { Icon: typeof IconFolder; testId: string } {
if (executorType === "local_docker" || executorType === "remote_docker") {
return {
Icon: hasError ? IconBoxOff : IconBox,
testId: "executor-status-container-icon",
};
}
if (executorType === "sprites") {
return {
Icon: hasError ? IconCloudOff : IconCloud,
testId: "executor-status-cloud-icon",
};
}
if (executorType === "ssh") {
return {
Icon: hasError ? IconServerOff : IconTerminal2,
testId: "executor-status-ssh-icon",
};
}
return {
Icon: hasError ? IconServerOff : IconServer,
testId: "executor-status-server-icon",
};
}