add remote server launcher flow

This commit is contained in:
Shantur Rathore
2026-04-02 16:08:54 +01:00
parent 893d5f9296
commit 69d9e95bee
19 changed files with 1150 additions and 111 deletions

View File

@@ -11,6 +11,8 @@ import type {
SpeechSynthesisResponse,
SpeechTranscriptionResponse,
ServerMeta,
RemoteServerProbeRequest,
RemoteServerProbeResponse,
VoiceModeStateResponse,
WorkspaceCreateRequest,
WorkspaceDescriptor,
@@ -194,6 +196,12 @@ export const serverApi = {
fetchServerMeta(): Promise<ServerMeta> {
return request<ServerMeta>("/api/meta")
},
probeRemoteServer(payload: RemoteServerProbeRequest): Promise<RemoteServerProbeResponse> {
return request<RemoteServerProbeResponse>("/api/remote-servers/probe", {
method: "POST",
body: JSON.stringify(payload),
})
},
fetchAuthStatus(): Promise<{ authenticated: boolean; username?: string; passwordUserProvided?: boolean }> {
return request<{ authenticated: boolean; username?: string; passwordUserProvided?: boolean }>("/api/auth/status")
},

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "Select any folder on your computer",
"folderSelection.browse.button": "Browse Folders",
"folderSelection.browse.buttonOpening": "Opening...",
"folderSelection.actions.title": "Open Folder or Connect Server",
"folderSelection.actions.subtitle": "Open local folder or connect to a CodeNomad server",
"folderSelection.actions.connectButton": "Connect CodeNomad Server",
"folderSelection.advancedSettings": "Advanced Settings",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "Select Workspace",
"folderSelection.dialog.description": "Select workspace to start coding.",
"folderSelection.tabs.local": "Local Folders",
"folderSelection.tabs.servers": "Servers",
"folderSelection.servers.title": "Saved Servers",
"folderSelection.servers.subtitle": "Open a saved remote CodeNomad server in a new window",
"folderSelection.servers.count": "{count} Servers",
"folderSelection.servers.empty.title": "No Saved Servers",
"folderSelection.servers.empty.description": "Add a remote server to reconnect quickly from this device",
"folderSelection.servers.connectTitle": "Connect to Server",
"folderSelection.servers.connectSubtitle": "Save a remote CodeNomad server and open it in a new window",
"folderSelection.servers.connectButton": "Connect to Server",
"folderSelection.servers.remove": "Remove saved server",
"folderSelection.servers.skipTls": "Self-signed TLS",
"folderSelection.servers.errorTitle": "Remote Connection Failed",
"folderSelection.servers.dialog.title": "Connect to Server",
"folderSelection.servers.dialog.description": "Add a remote CodeNomad server and optionally open it right away.",
"folderSelection.servers.dialog.name": "Server name",
"folderSelection.servers.dialog.namePlaceholder": "Production Server",
"folderSelection.servers.dialog.url": "Server URL",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "Skip TLS verification for self-signed certificates.",
"folderSelection.servers.dialog.cancel": "Cancel",
"folderSelection.servers.dialog.save": "Save",
"folderSelection.servers.dialog.connect": "Connect",
"folderSelection.servers.dialog.connecting": "Connecting...",
"folderSelection.servers.dialog.errorRequired": "Server name and URL are required.",
"folderSelection.servers.dialog.errorConnect": "Could not connect to the remote server.",
} as const

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "Selecciona cualquier carpeta en tu ordenador",
"folderSelection.browse.button": "Explorar carpetas",
"folderSelection.browse.buttonOpening": "Abriendo...",
"folderSelection.actions.title": "Abrir carpeta o conectar servidor",
"folderSelection.actions.subtitle": "Abre una carpeta local o conéctate a un servidor de CodeNomad",
"folderSelection.actions.connectButton": "Conectar servidor CodeNomad",
"folderSelection.advancedSettings": "Configuración avanzada",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "Seleccionar workspace",
"folderSelection.dialog.description": "Selecciona un workspace para empezar a programar.",
"folderSelection.tabs.local": "Carpetas locales",
"folderSelection.tabs.servers": "Servidores",
"folderSelection.servers.title": "Servidores guardados",
"folderSelection.servers.subtitle": "Abre un servidor remoto de CodeNomad guardado en una ventana nueva",
"folderSelection.servers.count": "{count} servidores",
"folderSelection.servers.empty.title": "No hay servidores guardados",
"folderSelection.servers.empty.description": "Añade un servidor remoto para volver a conectarte rápidamente desde este dispositivo",
"folderSelection.servers.connectTitle": "Conectar a un servidor",
"folderSelection.servers.connectSubtitle": "Guarda un servidor remoto de CodeNomad y ábrelo en una ventana nueva",
"folderSelection.servers.connectButton": "Conectar a un servidor",
"folderSelection.servers.remove": "Eliminar servidor guardado",
"folderSelection.servers.skipTls": "TLS autofirmado",
"folderSelection.servers.errorTitle": "Falló la conexión remota",
"folderSelection.servers.dialog.title": "Conectar a un servidor",
"folderSelection.servers.dialog.description": "Añade un servidor remoto de CodeNomad y ábrelo ahora si quieres.",
"folderSelection.servers.dialog.name": "Nombre del servidor",
"folderSelection.servers.dialog.namePlaceholder": "Servidor de producción",
"folderSelection.servers.dialog.url": "URL del servidor",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "Omitir la verificación TLS para certificados autofirmados.",
"folderSelection.servers.dialog.cancel": "Cancelar",
"folderSelection.servers.dialog.save": "Guardar",
"folderSelection.servers.dialog.connect": "Conectar",
"folderSelection.servers.dialog.connecting": "Conectando...",
"folderSelection.servers.dialog.errorRequired": "El nombre y la URL del servidor son obligatorios.",
"folderSelection.servers.dialog.errorConnect": "No se pudo conectar al servidor remoto.",
} as const

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "Sélectionnez n'importe quel dossier sur votre ordinateur",
"folderSelection.browse.button": "Parcourir les dossiers",
"folderSelection.browse.buttonOpening": "Ouverture...",
"folderSelection.actions.title": "Ouvrir un dossier ou connecter un serveur",
"folderSelection.actions.subtitle": "Ouvrez un dossier local ou connectez-vous à un serveur CodeNomad",
"folderSelection.actions.connectButton": "Connecter un serveur CodeNomad",
"folderSelection.advancedSettings": "Paramètres avancés",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "Sélectionner l'espace de travail",
"folderSelection.dialog.description": "Sélectionnez un espace de travail pour commencer à coder.",
"folderSelection.tabs.local": "Dossiers locaux",
"folderSelection.tabs.servers": "Serveurs",
"folderSelection.servers.title": "Serveurs enregistrés",
"folderSelection.servers.subtitle": "Ouvrez un serveur CodeNomad distant enregistré dans une nouvelle fenêtre",
"folderSelection.servers.count": "{count} serveurs",
"folderSelection.servers.empty.title": "Aucun serveur enregistré",
"folderSelection.servers.empty.description": "Ajoutez un serveur distant pour vous reconnecter rapidement depuis cet appareil",
"folderSelection.servers.connectTitle": "Se connecter à un serveur",
"folderSelection.servers.connectSubtitle": "Enregistrez un serveur CodeNomad distant et ouvrez-le dans une nouvelle fenêtre",
"folderSelection.servers.connectButton": "Se connecter à un serveur",
"folderSelection.servers.remove": "Supprimer le serveur enregistré",
"folderSelection.servers.skipTls": "TLS auto-signé",
"folderSelection.servers.errorTitle": "Échec de la connexion distante",
"folderSelection.servers.dialog.title": "Se connecter à un serveur",
"folderSelection.servers.dialog.description": "Ajoutez un serveur CodeNomad distant et ouvrez-le immédiatement si vous le souhaitez.",
"folderSelection.servers.dialog.name": "Nom du serveur",
"folderSelection.servers.dialog.namePlaceholder": "Serveur de production",
"folderSelection.servers.dialog.url": "URL du serveur",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "Ignorer la vérification TLS pour les certificats auto-signés.",
"folderSelection.servers.dialog.cancel": "Annuler",
"folderSelection.servers.dialog.save": "Enregistrer",
"folderSelection.servers.dialog.connect": "Se connecter",
"folderSelection.servers.dialog.connecting": "Connexion...",
"folderSelection.servers.dialog.errorRequired": "Le nom du serveur et l'URL sont requis.",
"folderSelection.servers.dialog.errorConnect": "Impossible de se connecter au serveur distant.",
} as const

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "בחר כל תיקייה במחשב שלך",
"folderSelection.browse.button": "עיון בתיקיות",
"folderSelection.browse.buttonOpening": "פותח...",
"folderSelection.actions.title": "פתח תיקייה או התחבר לשרת",
"folderSelection.actions.subtitle": "פתח תיקייה מקומית או התחבר לשרת CodeNomad",
"folderSelection.actions.connectButton": "התחבר לשרת CodeNomad",
"folderSelection.advancedSettings": "הגדרות מתקדמות",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "בחר סביבת עבודה",
"folderSelection.dialog.description": "בחר סביבת עבודה כדי להתחיל לתכנת.",
"folderSelection.tabs.local": "תיקיות מקומיות",
"folderSelection.tabs.servers": "שרתים",
"folderSelection.servers.title": "שרתים שמורים",
"folderSelection.servers.subtitle": "פתח שרת CodeNomad מרוחק שמור בחלון חדש",
"folderSelection.servers.count": "{count} שרתים",
"folderSelection.servers.empty.title": "אין שרתים שמורים",
"folderSelection.servers.empty.description": "הוסף שרת מרוחק כדי להתחבר אליו במהירות מהמכשיר הזה",
"folderSelection.servers.connectTitle": "התחבר לשרת",
"folderSelection.servers.connectSubtitle": "שמור שרת CodeNomad מרוחק ופתח אותו בחלון חדש",
"folderSelection.servers.connectButton": "התחבר לשרת",
"folderSelection.servers.remove": "הסר שרת שמור",
"folderSelection.servers.skipTls": "TLS בחתימה עצמית",
"folderSelection.servers.errorTitle": "החיבור המרוחק נכשל",
"folderSelection.servers.dialog.title": "התחבר לשרת",
"folderSelection.servers.dialog.description": "הוסף שרת CodeNomad מרוחק ופתח אותו מיד אם תרצה.",
"folderSelection.servers.dialog.name": "שם השרת",
"folderSelection.servers.dialog.namePlaceholder": "שרת ייצור",
"folderSelection.servers.dialog.url": "כתובת השרת",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "דלג על אימות TLS עבור תעודות בחתימה עצמית.",
"folderSelection.servers.dialog.cancel": "ביטול",
"folderSelection.servers.dialog.save": "שמור",
"folderSelection.servers.dialog.connect": "התחבר",
"folderSelection.servers.dialog.connecting": "מתחבר...",
"folderSelection.servers.dialog.errorRequired": "שם השרת והכתובת הם שדות חובה.",
"folderSelection.servers.dialog.errorConnect": "לא ניתן היה להתחבר לשרת המרוחק.",
} as const

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "コンピュータ上の任意のフォルダを選択",
"folderSelection.browse.button": "フォルダを参照",
"folderSelection.browse.buttonOpening": "開いています...",
"folderSelection.actions.title": "フォルダを開くかサーバーに接続",
"folderSelection.actions.subtitle": "ローカルフォルダを開くか CodeNomad サーバーに接続します",
"folderSelection.actions.connectButton": "CodeNomad サーバーに接続",
"folderSelection.advancedSettings": "詳細設定",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "ワークスペースを選択",
"folderSelection.dialog.description": "コーディングを開始するワークスペースを選択してください。",
"folderSelection.tabs.local": "ローカルフォルダ",
"folderSelection.tabs.servers": "サーバー",
"folderSelection.servers.title": "保存済みサーバー",
"folderSelection.servers.subtitle": "保存したリモート CodeNomad サーバーを新しいウィンドウで開きます",
"folderSelection.servers.count": "{count} サーバー",
"folderSelection.servers.empty.title": "保存済みサーバーはありません",
"folderSelection.servers.empty.description": "この端末からすばやく再接続できるように、リモートサーバーを追加してください",
"folderSelection.servers.connectTitle": "サーバーに接続",
"folderSelection.servers.connectSubtitle": "リモート CodeNomad サーバーを保存して新しいウィンドウで開きます",
"folderSelection.servers.connectButton": "サーバーに接続",
"folderSelection.servers.remove": "保存したサーバーを削除",
"folderSelection.servers.skipTls": "自己署名 TLS",
"folderSelection.servers.errorTitle": "リモート接続に失敗しました",
"folderSelection.servers.dialog.title": "サーバーに接続",
"folderSelection.servers.dialog.description": "リモート CodeNomad サーバーを追加し、必要に応じてすぐに開きます。",
"folderSelection.servers.dialog.name": "サーバー名",
"folderSelection.servers.dialog.namePlaceholder": "本番サーバー",
"folderSelection.servers.dialog.url": "サーバー URL",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "自己署名証明書の TLS 検証をスキップします。",
"folderSelection.servers.dialog.cancel": "キャンセル",
"folderSelection.servers.dialog.save": "保存",
"folderSelection.servers.dialog.connect": "接続",
"folderSelection.servers.dialog.connecting": "接続中...",
"folderSelection.servers.dialog.errorRequired": "サーバー名と URL は必須です。",
"folderSelection.servers.dialog.errorConnect": "リモートサーバーに接続できませんでした。",
} as const

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "Выберите любую папку на компьютере",
"folderSelection.browse.button": "Обзор папок",
"folderSelection.browse.buttonOpening": "Открытие…",
"folderSelection.actions.title": "Открыть папку или подключить сервер",
"folderSelection.actions.subtitle": "Откройте локальную папку или подключитесь к серверу CodeNomad",
"folderSelection.actions.connectButton": "Подключить сервер CodeNomad",
"folderSelection.advancedSettings": "Расширенные настройки",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "Выберите рабочее пространство",
"folderSelection.dialog.description": "Выберите рабочее пространство, чтобы начать писать код.",
"folderSelection.tabs.local": "Локальные папки",
"folderSelection.tabs.servers": "Серверы",
"folderSelection.servers.title": "Сохраненные серверы",
"folderSelection.servers.subtitle": "Откройте сохраненный удаленный сервер CodeNomad в новом окне",
"folderSelection.servers.count": "{count} серверов",
"folderSelection.servers.empty.title": "Нет сохраненных серверов",
"folderSelection.servers.empty.description": "Добавьте удаленный сервер, чтобы быстро подключаться к нему с этого устройства",
"folderSelection.servers.connectTitle": "Подключиться к серверу",
"folderSelection.servers.connectSubtitle": "Сохраните удаленный сервер CodeNomad и откройте его в новом окне",
"folderSelection.servers.connectButton": "Подключиться к серверу",
"folderSelection.servers.remove": "Удалить сохраненный сервер",
"folderSelection.servers.skipTls": "Самоподписанный TLS",
"folderSelection.servers.errorTitle": "Ошибка удаленного подключения",
"folderSelection.servers.dialog.title": "Подключиться к серверу",
"folderSelection.servers.dialog.description": "Добавьте удаленный сервер CodeNomad и при желании сразу откройте его.",
"folderSelection.servers.dialog.name": "Имя сервера",
"folderSelection.servers.dialog.namePlaceholder": "Продакшн сервер",
"folderSelection.servers.dialog.url": "URL сервера",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "Пропустить проверку TLS для самоподписанных сертификатов.",
"folderSelection.servers.dialog.cancel": "Отмена",
"folderSelection.servers.dialog.save": "Сохранить",
"folderSelection.servers.dialog.connect": "Подключиться",
"folderSelection.servers.dialog.connecting": "Подключение...",
"folderSelection.servers.dialog.errorRequired": "Имя сервера и URL обязательны.",
"folderSelection.servers.dialog.errorConnect": "Не удалось подключиться к удаленному серверу.",
} as const

View File

@@ -20,6 +20,9 @@ export const folderSelectionMessages = {
"folderSelection.browse.subtitle": "选择你电脑上的任意文件夹",
"folderSelection.browse.button": "浏览文件夹",
"folderSelection.browse.buttonOpening": "正在打开...",
"folderSelection.actions.title": "打开文件夹或连接服务器",
"folderSelection.actions.subtitle": "打开本地文件夹或连接到 CodeNomad 服务器",
"folderSelection.actions.connectButton": "连接 CodeNomad 服务器",
"folderSelection.advancedSettings": "高级设置",
"folderSelection.opencode": "OpenCode",
@@ -39,4 +42,31 @@ export const folderSelectionMessages = {
"folderSelection.dialog.title": "选择工作区",
"folderSelection.dialog.description": "选择工作区以开始编码。",
"folderSelection.tabs.local": "本地文件夹",
"folderSelection.tabs.servers": "服务器",
"folderSelection.servers.title": "已保存的服务器",
"folderSelection.servers.subtitle": "在新窗口中打开已保存的远程 CodeNomad 服务器",
"folderSelection.servers.count": "{count} 个服务器",
"folderSelection.servers.empty.title": "没有已保存的服务器",
"folderSelection.servers.empty.description": "添加远程服务器,以便在此设备上快速重新连接",
"folderSelection.servers.connectTitle": "连接到服务器",
"folderSelection.servers.connectSubtitle": "保存远程 CodeNomad 服务器并在新窗口中打开它",
"folderSelection.servers.connectButton": "连接到服务器",
"folderSelection.servers.remove": "删除已保存服务器",
"folderSelection.servers.skipTls": "自签名 TLS",
"folderSelection.servers.errorTitle": "远程连接失败",
"folderSelection.servers.dialog.title": "连接到服务器",
"folderSelection.servers.dialog.description": "添加远程 CodeNomad 服务器,并可选择立即打开。",
"folderSelection.servers.dialog.name": "服务器名称",
"folderSelection.servers.dialog.namePlaceholder": "生产服务器",
"folderSelection.servers.dialog.url": "服务器 URL",
"folderSelection.servers.dialog.urlPlaceholder": "https://server.example.com",
"folderSelection.servers.dialog.skipTls": "为自签名证书跳过 TLS 验证。",
"folderSelection.servers.dialog.cancel": "取消",
"folderSelection.servers.dialog.save": "保存",
"folderSelection.servers.dialog.connect": "连接",
"folderSelection.servers.dialog.connecting": "连接中...",
"folderSelection.servers.dialog.errorRequired": "服务器名称和 URL 为必填项。",
"folderSelection.servers.dialog.errorConnect": "无法连接到远程服务器。",
} as const

View File

@@ -0,0 +1,34 @@
import { invoke } from "@tauri-apps/api/core"
import type { RemoteServerProfile } from "../../../../server/src/api-types"
import { runtimeEnv } from "../runtime-env"
export interface RemoteWindowOpenPayload {
id: string
name: string
baseUrl: string
skipTlsVerify: boolean
}
export async function openRemoteServerWindow(profile: Pick<RemoteServerProfile, "id" | "name" | "baseUrl" | "skipTlsVerify">): Promise<void> {
const payload: RemoteWindowOpenPayload = {
id: profile.id,
name: profile.name,
baseUrl: profile.baseUrl,
skipTlsVerify: profile.skipTlsVerify,
}
if (runtimeEnv.host === "electron") {
const api = (window as Window & { electronAPI?: ElectronAPI }).electronAPI
if (typeof api?.openRemoteWindow === "function") {
await api.openRemoteWindow(payload)
return
}
}
if (runtimeEnv.host === "tauri") {
await invoke("open_remote_window", { payload })
return
}
window.open(profile.baseUrl, "_blank", "noopener,noreferrer")
}