Decouple bundled UI from runtime API and add remote instance tooling (#1228)
Add a packaged-client runtime boundary so the shared UI can talk to local, desktop, remote, and VS Code runtimes through the right transport instead of assuming one same-origin web server. Centralize OpenChamber-owned API access behind RuntimeAPIs, runtimeFetch, and runtime URL helpers, while keeping official OpenCode traffic on the SDK path. Support runtime switching, remote host selection, desktop client credentials, and headless connection links for pairing packaged clients with remote OpenChamber servers. Harden the new auth model by moving long-lived client tokens out of browser URLs, introducing short-lived scoped URL tokens for browser-owned transports, restricting URL-token access to explicit readable/realtime routes, and making client-token management session-scoped or self-scoped as appropriate. Update browser-owned assets and preview proxy flows to work with the split runtime model, including authenticated project icons, preview token propagation, CSP-safe preview bridge injection, and preview proxy auth that survives short-lived URL-token expiry. Tighten Electron security boundaries for packaged clients by gating privileged preload state to trusted origins and requiring explicit confirmation before connect deep-links import or switch remote runtimes. Also refresh agent guidance and project skills so future runtime/API, auth, preview, UI, CLI, settings, locale, and drag-to-reorder work follows the new architecture.
This commit is contained in:
committed by
GitHub
parent
a4314c189b
commit
2031e3b4a8
@@ -198,19 +198,50 @@ export const settingsDict = {
|
||||
"settings.magicPrompts.sidebar.item.sessionFusion": "Fusion",
|
||||
"settings.remoteInstances.sidebar.title": "Instancias remotas",
|
||||
"settings.remoteInstances.sidebar.total": "Total {count}",
|
||||
"settings.remoteInstances.sidebar.newSshInstanceName": "Nueva instancia SSH",
|
||||
"settings.remoteInstances.sidebar.actions.addSshInstance": "Añadir instancia SSH",
|
||||
"settings.remoteInstances.sidebar.newSshInstanceName": "Nueva conexión SSH",
|
||||
"settings.remoteInstances.sidebar.actions.addSshInstance": "Añadir conexión SSH",
|
||||
"settings.remoteInstances.sidebar.actions.connect": "Conectar",
|
||||
"settings.remoteInstances.sidebar.actions.disconnect": "Desconectar",
|
||||
"settings.remoteInstances.sidebar.actions.retry": "Reintentar",
|
||||
"settings.remoteInstances.sidebar.actions.remove": "Eliminar",
|
||||
"settings.remoteInstances.sidebar.confirm.localPortInUseRetry": "El puerto local ya está en uso. ¿Elegir un puerto libre aleatorio y reintentar?",
|
||||
"settings.remoteInstances.sidebar.toast.createFailed": "No se pudo crear la instancia SSH",
|
||||
"settings.remoteInstances.sidebar.toast.createFailed": "No se pudo crear la conexión SSH",
|
||||
"settings.remoteInstances.sidebar.toast.retriedWithRandomPort": "Reintentado con un puerto local aleatorio",
|
||||
"settings.remoteInstances.sidebar.toast.connectFailed": "No se pudo conectar la instancia",
|
||||
"settings.remoteInstances.sidebar.toast.disconnectFailed": "No se pudo desconectar la instancia",
|
||||
"settings.remoteInstances.sidebar.toast.retryFailed": "No se pudo reintentar la conexión",
|
||||
"settings.remoteInstances.sidebar.toast.removeFailed": "No se pudo eliminar la instancia",
|
||||
"settings.remoteInstances.direct.sidebarTitle": "Enlaces a servidores",
|
||||
"settings.remoteInstances.direct.sidebarDescription": "Conecta con un enlace o token",
|
||||
"settings.remoteInstances.direct.title": "Otros servidores de OpenChamber",
|
||||
"settings.remoteInstances.direct.description": "Añade otro servidor de OpenChamber por URL. Úsalo cuando el servidor ya esté en marcha y tengas un token de conexión.",
|
||||
"settings.remoteInstances.direct.field.labelPlaceholder": "Etiqueta (opcional)",
|
||||
"settings.remoteInstances.direct.field.urlPlaceholder": "https://host:port",
|
||||
"settings.remoteInstances.direct.field.tokenPlaceholder": "Token de conexión (opcional para servidores locales de confianza)",
|
||||
"settings.remoteInstances.direct.note": "Los tokens de conexión se guardan en este dispositivo y solo se usan cuando esta app se conecta a ese servidor.",
|
||||
"settings.remoteInstances.direct.actions.add": "Añadir servidor",
|
||||
"settings.remoteInstances.direct.import.description": "Pega un enlace de conexión de otro servidor de OpenChamber.",
|
||||
"settings.remoteInstances.direct.import.placeholder": "openchamber://connect?...",
|
||||
"settings.remoteInstances.direct.import.action": "Importar enlace",
|
||||
"settings.remoteInstances.direct.error.invalidConnectLink": "Enlace de conexión de OpenChamber no válido.",
|
||||
"settings.remoteInstances.direct.state.loading": "Cargando servidores...",
|
||||
"settings.remoteInstances.direct.state.empty": "Todavía no se han añadido otros servidores.",
|
||||
"settings.remoteInstances.clientAuth.title": "Conectarse a este servidor",
|
||||
"settings.remoteInstances.clientAuth.description": "Crea un enlace o token seguro para que OpenChamber Desktop pueda conectarse a este servidor.",
|
||||
"settings.remoteInstances.clientAuth.field.labelPlaceholder": "Nombre del dispositivo (opcional)",
|
||||
"settings.remoteInstances.clientAuth.actions.create": "Crear token",
|
||||
"settings.remoteInstances.clientAuth.actions.pair": "Crear enlace",
|
||||
"settings.remoteInstances.clientAuth.actions.revoke": "Revocar",
|
||||
"settings.remoteInstances.clientAuth.actions.clearRevoked": "Borrar revocados",
|
||||
"settings.remoteInstances.clientAuth.qrAlt": "OpenChamber connection QR code",
|
||||
"settings.remoteInstances.clientAuth.pairingUrl": "Enlace de conexión",
|
||||
"settings.remoteInstances.clientAuth.createdToken": "Copia este token ahora. Por seguridad, no se volverá a mostrar.",
|
||||
"settings.remoteInstances.clientAuth.state.loading": "Cargando tokens...",
|
||||
"settings.remoteInstances.clientAuth.state.empty": "Todavía no hay dispositivos conectados.",
|
||||
"settings.remoteInstances.clientAuth.state.revoked": "Revocado",
|
||||
"settings.remoteInstances.clientAuth.state.thisDevice": "Este dispositivo",
|
||||
"settings.remoteInstances.clientAuth.lastUsed": "Último uso {date}",
|
||||
"settings.remoteInstances.clientAuth.neverUsed": "Nunca usado",
|
||||
"settings.remoteInstances.sidebar.phase.ready": "Listo",
|
||||
"settings.remoteInstances.sidebar.phase.error": "Error",
|
||||
"settings.remoteInstances.sidebar.phase.reconnect": "Reconectar",
|
||||
@@ -221,20 +252,20 @@ export const settingsDict = {
|
||||
"settings.remoteInstances.sidebar.phase.connecting": "Conectando",
|
||||
"settings.remoteInstances.sidebar.phase.idle": "Inactivo",
|
||||
"settings.remoteInstances.page.section.instance": "Instancia",
|
||||
"settings.remoteInstances.page.section.instanceDescription": "Configuración básica de SSH.",
|
||||
"settings.remoteInstances.page.section.instanceDescription": "Choose the SSH command and a display name for this connection.",
|
||||
"settings.remoteInstances.page.field.mode": "Modo",
|
||||
"settings.remoteInstances.page.field.modeHint": "Instalaciones/actualizaciones gestionadas y arranque remoto de OpenChamber. Externo asume que ya está en ejecución.",
|
||||
"settings.remoteInstances.page.field.modeHint": "Elige si OpenChamber debe iniciar el servidor por ti o conectarse a uno que ya está en marcha.",
|
||||
"settings.remoteInstances.page.field.modePlaceholder": "Seleccionar modo",
|
||||
"settings.remoteInstances.page.field.modeManaged": "Gestionado (arranque automático)",
|
||||
"settings.remoteInstances.page.field.modeExternal": "Externo (ya en ejecución)",
|
||||
"settings.remoteInstances.page.field.modeManaged": "Iniciarlo por mí",
|
||||
"settings.remoteInstances.page.field.modeExternal": "Ya está en marcha",
|
||||
"settings.remoteInstances.page.field.preferredRemotePort": "Puerto remoto preferido",
|
||||
"settings.remoteInstances.page.field.preferredRemotePortHint": "Puerto que debe usar OpenChamber en el host remoto. Dejar vacío para que el entorno lo elija.",
|
||||
"settings.remoteInstances.page.field.preferredRemotePortHint": "Port to use on the remote machine. Leave empty to choose one automatically.",
|
||||
"settings.remoteInstances.page.field.keepServerRunning": "Mantener servidor en ejecución",
|
||||
"settings.remoteInstances.page.field.keepServerRunningHint": "Si está habilitado, el demonio de OpenChamber permanece en ejecución remotamente al desconectar.",
|
||||
"settings.remoteInstances.page.field.keepServerRunningHint": "Keep OpenChamber running on the remote machine after you disconnect.",
|
||||
"settings.remoteInstances.page.field.bindHost": "Host de enlace",
|
||||
"settings.remoteInstances.page.field.bindHostHint": "Interfaz de red para la URL local principal. Usar 127.0.0.1/localhost para acceso local solamente.",
|
||||
"settings.remoteInstances.page.field.bindHostHint": "Where the local connection should listen. Use 127.0.0.1 or localhost unless you need LAN access.",
|
||||
"settings.remoteInstances.page.field.preferredLocalPort": "Puerto local preferido",
|
||||
"settings.remoteInstances.page.field.preferredLocalPortHint": "Puerto local preferido para el túnel de OpenChamber principal. Dejar vacío para selección automática.",
|
||||
"settings.remoteInstances.page.field.preferredLocalPortHint": "Local port to open for this connection. Leave empty to choose one automatically.",
|
||||
"settings.remoteInstances.page.field.forwardType": "Tipo de redirección",
|
||||
"settings.remoteInstances.page.field.localHostPlaceholder": "127.0.0.1",
|
||||
"settings.remoteInstances.page.field.remoteHostPlaceholder": "127.0.0.1",
|
||||
@@ -243,7 +274,7 @@ export const settingsDict = {
|
||||
"settings.remoteInstances.page.preview.localSocks5": "(local SOCKS5)",
|
||||
"settings.remoteInstances.page.preview.local": "(local)",
|
||||
"settings.remoteInstances.page.preview.remote": "(remoto)",
|
||||
"settings.remoteInstances.page.toast.openLocalEndpointFailed": "No se pudo abrir el endpoint local",
|
||||
"settings.remoteInstances.page.toast.openLocalEndpointFailed": "No se pudo abrir la dirección local",
|
||||
"settings.remoteInstances.page.toast.localUrlCopied": "URL local copiada",
|
||||
"settings.remoteInstances.page.actions.copyLocalUrl": "Copiar URL local",
|
||||
"settings.remoteInstances.page.actions.open": "Abrir",
|
||||
@@ -945,26 +976,26 @@ export const settingsDict = {
|
||||
"settings.usage.pace.waitSeparator": " · Esperar ",
|
||||
"settings.usage.pace.predictionLabel": "Pred.: ",
|
||||
"settings.remoteInstances.page.title": "Instancia remota",
|
||||
"settings.remoteInstances.page.description": "Configura la conexión SSH, el servidor remoto y la configuración de redirección.",
|
||||
"settings.remoteInstances.page.description": "Conéctate a otra máquina por SSH y abre OpenChamber allí.",
|
||||
"settings.remoteInstances.page.empty.selectInstance": "Selecciona una instancia para ver y editar sus configuraciones.",
|
||||
"settings.remoteInstances.page.empty.noExtraForwards": "No hay redirecciones adicionales de puerto configuradas.",
|
||||
"settings.remoteInstances.page.section.actions": "Acciones",
|
||||
"settings.remoteInstances.page.section.actionsDescription": "Conectar, reconectar, inspeccionar registros o eliminar esta instancia.",
|
||||
"settings.remoteInstances.page.section.remoteServer": "Servidor remoto",
|
||||
"settings.remoteInstances.page.section.remoteServerDescription": "Cómo OpenChamber se gestiona y inicia en el host remoto.",
|
||||
"settings.remoteInstances.page.section.mainTunnel": "Túnel principal",
|
||||
"settings.remoteInstances.page.section.mainTunnelDescription": "Punto de conexión local principal para esta instancia remota.",
|
||||
"settings.remoteInstances.page.section.actionsDescription": "Conecta, reconecta, revisa registros o elimina esta conexión.",
|
||||
"settings.remoteInstances.page.section.remoteServer": "OpenChamber en la máquina remota",
|
||||
"settings.remoteInstances.page.section.remoteServerDescription": "Elige cómo debe ejecutarse OpenChamber después de conectar por SSH.",
|
||||
"settings.remoteInstances.page.section.mainTunnel": "Acceso local",
|
||||
"settings.remoteInstances.page.section.mainTunnelDescription": "Elige la dirección local que se usará para abrir este servidor remoto de OpenChamber.",
|
||||
"settings.remoteInstances.page.section.authentication": "Autenticación",
|
||||
"settings.remoteInstances.page.section.authenticationDescription": "Credenciales opcionales para SSH y la interfaz de usuario de OpenChamber remoto.",
|
||||
"settings.remoteInstances.page.section.portForwards": "Redirecciones de puerto",
|
||||
"settings.remoteInstances.page.section.portForwardsDescription": "Redirecciones SSH adicionales más allá del túnel principal.",
|
||||
"settings.remoteInstances.page.section.portForwardsDescription": "Puertos adicionales opcionales que estarán disponibles a través de esta conexión SSH.",
|
||||
"settings.remoteInstances.page.field.sshCommand": "Comando SSH",
|
||||
"settings.remoteInstances.page.field.sshCommandPlaceholder": "ssh user@host",
|
||||
"settings.remoteInstances.page.field.nickname": "Apodo",
|
||||
"settings.remoteInstances.page.field.nicknamePlaceholder": "Mi host remoto",
|
||||
"settings.remoteInstances.page.field.nicknamePlaceholder": "Portátil de trabajo",
|
||||
"settings.remoteInstances.page.field.connectionTimeoutSeconds": "Tiempo de espera de conexión (segundos)",
|
||||
"settings.remoteInstances.page.field.installMethod": "Método de instalación",
|
||||
"settings.remoteInstances.page.field.installMethodHint": "Cómo se instala OpenChamber cuando se ejecuta en modo gestionado.",
|
||||
"settings.remoteInstances.page.field.installMethodHint": "Cómo debe colocarse OpenChamber en la máquina remota cuando esta app lo inicia por ti.",
|
||||
"settings.remoteInstances.page.field.selectInstallMethodPlaceholder": "Seleccionar método de instalación",
|
||||
"settings.remoteInstances.page.field.installMethodDownloadRelease": "Descargar versión",
|
||||
"settings.remoteInstances.page.field.installMethodUploadBundle": "Subir paquete",
|
||||
@@ -973,14 +1004,14 @@ export const settingsDict = {
|
||||
"settings.remoteInstances.page.field.sshPasswordPlaceholder": "Introducir contraseña SSH",
|
||||
"settings.remoteInstances.page.field.uiPasswordOptional": "Contraseña de interfaz de usuario (opcional)",
|
||||
"settings.remoteInstances.page.field.uiPasswordPlaceholder": "Introducir contraseña de interfaz de usuario",
|
||||
"settings.remoteInstances.page.field.forwardTypeHint": "Elige redirección local (-L), remota (-R) o dinámica (-D).",
|
||||
"settings.remoteInstances.page.field.forwardTypeHint": "Elige qué tipo de acceso a puertos debe ofrecer esta conexión SSH.",
|
||||
"settings.remoteInstances.page.field.typePlaceholder": "Tipo",
|
||||
"settings.remoteInstances.page.forwardType.local": "Local (-L)",
|
||||
"settings.remoteInstances.page.forwardType.remote": "Remota (-R)",
|
||||
"settings.remoteInstances.page.forwardType.dynamic": "Dinámica (-D)",
|
||||
"settings.remoteInstances.page.forwardTypeDescription.local": "Redirige el tráfico local a un destino remoto.",
|
||||
"settings.remoteInstances.page.forwardTypeDescription.remote": "Expón un endpoint remoto y redirígelo de vuelta a su máquina local.",
|
||||
"settings.remoteInstances.page.forwardTypeDescription.dynamic": "Expón un proxy SOCKS5 local sobre SSH.",
|
||||
"settings.remoteInstances.page.forwardTypeDescription.local": "Abre un puerto local que se conecta a un servicio en la máquina remota.",
|
||||
"settings.remoteInstances.page.forwardTypeDescription.remote": "Abre un puerto en la máquina remota que vuelve a conectarse a tu ordenador.",
|
||||
"settings.remoteInstances.page.forwardTypeDescription.dynamic": "Abre un proxy SOCKS local a través de la conexión SSH.",
|
||||
"settings.remoteInstances.page.actions.create": "Crear",
|
||||
"settings.remoteInstances.page.actions.cancel": "Cancelar",
|
||||
"settings.remoteInstances.page.actions.connecting": "Conectando...",
|
||||
@@ -991,7 +1022,7 @@ export const settingsDict = {
|
||||
"settings.remoteInstances.page.actions.enableForwardAria": "Habilitar redirección",
|
||||
"settings.remoteInstances.page.actions.openLocal": "Abrir local",
|
||||
"settings.remoteInstances.page.actions.addForward": "Añadir redirección",
|
||||
"settings.remoteInstances.page.import.sectionTitle": "Importar desde configuración SSH",
|
||||
"settings.remoteInstances.page.import.sectionTitle": "Hosts SSH guardados",
|
||||
"settings.remoteInstances.page.import.loading": "Cargando hosts SSH...",
|
||||
"settings.remoteInstances.page.import.noneFound": "No se encontraron hosts SSH.",
|
||||
"settings.remoteInstances.page.import.noneAvailable": "No hay hosts SSH disponibles para importar.",
|
||||
@@ -1006,7 +1037,7 @@ export const settingsDict = {
|
||||
"settings.remoteInstances.page.phase.resolvingConfiguration": "Resolviendo configuración",
|
||||
"settings.remoteInstances.page.phase.checkingAuth": "Verificando autenticación",
|
||||
"settings.remoteInstances.page.phase.establishingSsh": "Estableciendo conexión SSH",
|
||||
"settings.remoteInstances.page.phase.probingRemote": "Explorando host remoto",
|
||||
"settings.remoteInstances.page.phase.probingRemote": "Comprobando la máquina remota",
|
||||
"settings.remoteInstances.page.phase.installingOpenChamber": "Instalando OpenChamber",
|
||||
"settings.remoteInstances.page.phase.updatingOpenChamber": "Actualizando OpenChamber",
|
||||
"settings.remoteInstances.page.phase.detectingServer": "Detectando servidor",
|
||||
@@ -1471,6 +1502,9 @@ export const settingsDict = {
|
||||
"settings.voice.page.preview.voiceLine": "¡Hola! Soy {voiceName}. Así suena mi voz.",
|
||||
"settings.voice.page.preview.customServerLine": "¡Hola! Esta es una previsualización del servidor TTS personalizado.",
|
||||
"settings.openchamber.visual.section.colorMode": "Modo de color",
|
||||
"settings.openchamber.visual.section.mobileLayout": "Diseño móvil",
|
||||
"settings.openchamber.visual.option.mobileLayout.default": "Predeterminado",
|
||||
"settings.openchamber.visual.option.mobileLayout.new": "Nuevo",
|
||||
"settings.openchamber.visual.section.localization": "Localización",
|
||||
"settings.openchamber.visual.section.spacingAndLayout": "Espaciado y diseño",
|
||||
"settings.openchamber.visual.section.navigation": "Navegación",
|
||||
|
||||
Reference in New Issue
Block a user