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
@@ -231,19 +231,50 @@ export const settingsDict = {
|
||||
'settings.magicPrompts.sidebar.item.sessionFusion': 'Fusion',
|
||||
'settings.remoteInstances.sidebar.title': 'Remote Instances',
|
||||
'settings.remoteInstances.sidebar.total': 'Total {count}',
|
||||
'settings.remoteInstances.sidebar.newSshInstanceName': 'New SSH Instance',
|
||||
'settings.remoteInstances.sidebar.actions.addSshInstance': 'Add SSH instance',
|
||||
'settings.remoteInstances.sidebar.newSshInstanceName': 'New SSH connection',
|
||||
'settings.remoteInstances.sidebar.actions.addSshInstance': 'Add SSH connection',
|
||||
'settings.remoteInstances.sidebar.actions.connect': 'Connect',
|
||||
'settings.remoteInstances.sidebar.actions.disconnect': 'Disconnect',
|
||||
'settings.remoteInstances.sidebar.actions.retry': 'Retry',
|
||||
'settings.remoteInstances.sidebar.actions.remove': 'Remove',
|
||||
'settings.remoteInstances.sidebar.confirm.localPortInUseRetry': 'Local port is already in use. Pick a random free local port and retry?',
|
||||
'settings.remoteInstances.sidebar.toast.createFailed': 'Failed to create SSH instance',
|
||||
'settings.remoteInstances.sidebar.toast.createFailed': 'Failed to create SSH connection',
|
||||
'settings.remoteInstances.sidebar.toast.retriedWithRandomPort': 'Retried with a random local port',
|
||||
'settings.remoteInstances.sidebar.toast.connectFailed': 'Failed to connect instance',
|
||||
'settings.remoteInstances.sidebar.toast.disconnectFailed': 'Failed to disconnect instance',
|
||||
'settings.remoteInstances.sidebar.toast.retryFailed': 'Failed to retry connection',
|
||||
'settings.remoteInstances.sidebar.toast.removeFailed': 'Failed to remove instance',
|
||||
'settings.remoteInstances.direct.sidebarTitle': 'Server links',
|
||||
'settings.remoteInstances.direct.sidebarDescription': 'Connect with a link or token',
|
||||
'settings.remoteInstances.direct.title': 'Other OpenChamber servers',
|
||||
'settings.remoteInstances.direct.description': 'Add another OpenChamber server by URL. Use this when the server is already running and you have a connection token.',
|
||||
'settings.remoteInstances.direct.field.labelPlaceholder': 'Label (optional)',
|
||||
'settings.remoteInstances.direct.field.urlPlaceholder': 'https://host:port',
|
||||
'settings.remoteInstances.direct.field.tokenPlaceholder': 'Connection token (optional for trusted local servers)',
|
||||
'settings.remoteInstances.direct.note': 'Connection tokens are saved on this device and used only when this app connects to that server.',
|
||||
'settings.remoteInstances.direct.actions.add': 'Add Server',
|
||||
'settings.remoteInstances.direct.import.description': 'Paste a connection link from another OpenChamber server.',
|
||||
'settings.remoteInstances.direct.import.placeholder': 'openchamber://connect?...',
|
||||
'settings.remoteInstances.direct.import.action': 'Import Link',
|
||||
'settings.remoteInstances.direct.error.invalidConnectLink': 'Invalid OpenChamber connection link.',
|
||||
'settings.remoteInstances.direct.state.loading': 'Loading instances...',
|
||||
'settings.remoteInstances.direct.state.empty': 'No other servers added yet.',
|
||||
'settings.remoteInstances.clientAuth.title': 'Connect to this server',
|
||||
'settings.remoteInstances.clientAuth.description': 'Create a secure link or token so OpenChamber Desktop can connect to this server.',
|
||||
'settings.remoteInstances.clientAuth.field.labelPlaceholder': 'Device name (optional)',
|
||||
'settings.remoteInstances.clientAuth.actions.create': 'Create Token',
|
||||
'settings.remoteInstances.clientAuth.actions.pair': 'Create Link',
|
||||
'settings.remoteInstances.clientAuth.actions.revoke': 'Revoke',
|
||||
'settings.remoteInstances.clientAuth.actions.clearRevoked': 'Clear revoked',
|
||||
'settings.remoteInstances.clientAuth.qrAlt': 'OpenChamber connection QR code',
|
||||
'settings.remoteInstances.clientAuth.pairingUrl': 'Connection link',
|
||||
'settings.remoteInstances.clientAuth.createdToken': 'Copy this token now. For security, it will not be shown again.',
|
||||
'settings.remoteInstances.clientAuth.state.loading': 'Loading tokens...',
|
||||
'settings.remoteInstances.clientAuth.state.empty': 'No devices connected yet.',
|
||||
'settings.remoteInstances.clientAuth.state.revoked': 'Revoked',
|
||||
'settings.remoteInstances.clientAuth.state.thisDevice': 'This device',
|
||||
'settings.remoteInstances.clientAuth.lastUsed': 'Last used {date}',
|
||||
'settings.remoteInstances.clientAuth.neverUsed': 'Never used',
|
||||
'settings.remoteInstances.sidebar.phase.ready': 'Ready',
|
||||
'settings.remoteInstances.sidebar.phase.error': 'Error',
|
||||
'settings.remoteInstances.sidebar.phase.reconnect': 'Reconnect',
|
||||
@@ -254,20 +285,20 @@ export const settingsDict = {
|
||||
'settings.remoteInstances.sidebar.phase.connecting': 'Connecting',
|
||||
'settings.remoteInstances.sidebar.phase.idle': 'Idle',
|
||||
'settings.remoteInstances.page.section.instance': 'Instance',
|
||||
'settings.remoteInstances.page.section.instanceDescription': 'Core SSH settings.',
|
||||
'settings.remoteInstances.page.section.instanceDescription': 'Choose the SSH command and a display name for this connection.',
|
||||
'settings.remoteInstances.page.field.mode': 'Mode',
|
||||
'settings.remoteInstances.page.field.modeHint': 'Managed installs/updates and starts OpenChamber remotely. External assumes it is already running.',
|
||||
'settings.remoteInstances.page.field.modeHint': 'Choose whether OpenChamber should start the server for you, or connect to one that is already running.',
|
||||
'settings.remoteInstances.page.field.modePlaceholder': 'Select mode',
|
||||
'settings.remoteInstances.page.field.modeManaged': 'Managed (auto start)',
|
||||
'settings.remoteInstances.page.field.modeExternal': 'External (already running)',
|
||||
'settings.remoteInstances.page.field.modeManaged': 'Start it for me',
|
||||
'settings.remoteInstances.page.field.modeExternal': 'Already running',
|
||||
'settings.remoteInstances.page.field.preferredRemotePort': 'Preferred remote port',
|
||||
'settings.remoteInstances.page.field.preferredRemotePortHint': 'Port OpenChamber should use on the remote host. Leave empty to let the runtime choose.',
|
||||
'settings.remoteInstances.page.field.preferredRemotePortHint': 'Port to use on the remote machine. Leave empty to choose one automatically.',
|
||||
'settings.remoteInstances.page.field.keepServerRunning': 'Keep server running',
|
||||
'settings.remoteInstances.page.field.keepServerRunningHint': 'If enabled, OpenChamber daemon is left running remotely when you disconnect.',
|
||||
'settings.remoteInstances.page.field.keepServerRunningHint': 'Keep OpenChamber running on the remote machine after you disconnect.',
|
||||
'settings.remoteInstances.page.field.bindHost': 'Bind host',
|
||||
'settings.remoteInstances.page.field.bindHostHint': 'Network interface for the main local URL. Use 127.0.0.1/localhost for local-only access.',
|
||||
'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': 'Preferred local port',
|
||||
'settings.remoteInstances.page.field.preferredLocalPortHint': 'Preferred local port for the main OpenChamber tunnel. Leave empty for auto-select.',
|
||||
'settings.remoteInstances.page.field.preferredLocalPortHint': 'Local port to open for this connection. Leave empty to choose one automatically.',
|
||||
'settings.remoteInstances.page.field.forwardType': 'Forward type',
|
||||
'settings.remoteInstances.page.field.localHostPlaceholder': '127.0.0.1',
|
||||
'settings.remoteInstances.page.field.remoteHostPlaceholder': '127.0.0.1',
|
||||
@@ -276,7 +307,7 @@ export const settingsDict = {
|
||||
'settings.remoteInstances.page.preview.localSocks5': '(local SOCKS5)',
|
||||
'settings.remoteInstances.page.preview.local': '(local)',
|
||||
'settings.remoteInstances.page.preview.remote': '(remote)',
|
||||
'settings.remoteInstances.page.toast.openLocalEndpointFailed': 'Failed to open local endpoint',
|
||||
'settings.remoteInstances.page.toast.openLocalEndpointFailed': 'Failed to open local address',
|
||||
'settings.remoteInstances.page.toast.localUrlCopied': 'Local URL copied',
|
||||
'settings.remoteInstances.page.actions.copyLocalUrl': 'Copy local URL',
|
||||
'settings.remoteInstances.page.actions.open': 'Open',
|
||||
@@ -978,26 +1009,26 @@ export const settingsDict = {
|
||||
'settings.usage.pace.waitSeparator': ' · Wait ',
|
||||
'settings.usage.pace.predictionLabel': 'Pred: ',
|
||||
'settings.remoteInstances.page.title': 'Remote Instance',
|
||||
'settings.remoteInstances.page.description': 'Configure SSH connection, remote server, and forwarding settings.',
|
||||
'settings.remoteInstances.page.description': 'Connect to another machine over SSH and open OpenChamber there.',
|
||||
'settings.remoteInstances.page.empty.selectInstance': 'Select an instance to view and edit its settings.',
|
||||
'settings.remoteInstances.page.empty.noExtraForwards': 'No extra port forwards configured.',
|
||||
'settings.remoteInstances.page.section.actions': 'Actions',
|
||||
'settings.remoteInstances.page.section.actionsDescription': 'Connect, reconnect, inspect logs, or remove this instance.',
|
||||
'settings.remoteInstances.page.section.remoteServer': 'Remote Server',
|
||||
'settings.remoteInstances.page.section.remoteServerDescription': 'How OpenChamber is managed and started on the remote host.',
|
||||
'settings.remoteInstances.page.section.mainTunnel': 'Main Tunnel',
|
||||
'settings.remoteInstances.page.section.mainTunnelDescription': 'Primary local endpoint for this remote instance.',
|
||||
'settings.remoteInstances.page.section.actionsDescription': 'Connect, reconnect, view logs, or remove this connection.',
|
||||
'settings.remoteInstances.page.section.remoteServer': 'OpenChamber on the remote machine',
|
||||
'settings.remoteInstances.page.section.remoteServerDescription': 'Choose how OpenChamber should run after SSH connects.',
|
||||
'settings.remoteInstances.page.section.mainTunnel': 'Local access',
|
||||
'settings.remoteInstances.page.section.mainTunnelDescription': 'Choose the local address used to open this remote OpenChamber server.',
|
||||
'settings.remoteInstances.page.section.authentication': 'Authentication',
|
||||
'settings.remoteInstances.page.section.authenticationDescription': 'Optional credentials for SSH and the remote OpenChamber UI.',
|
||||
'settings.remoteInstances.page.section.portForwards': 'Port Forwards',
|
||||
'settings.remoteInstances.page.section.portForwardsDescription': 'Additional SSH forwards beyond the main tunnel.',
|
||||
'settings.remoteInstances.page.section.portForwardsDescription': 'Optional extra ports to make available through this SSH connection.',
|
||||
'settings.remoteInstances.page.field.sshCommand': 'SSH command',
|
||||
'settings.remoteInstances.page.field.sshCommandPlaceholder': 'ssh user@host',
|
||||
'settings.remoteInstances.page.field.nickname': 'Nickname',
|
||||
'settings.remoteInstances.page.field.nicknamePlaceholder': 'My remote host',
|
||||
'settings.remoteInstances.page.field.nicknamePlaceholder': 'Work laptop',
|
||||
'settings.remoteInstances.page.field.connectionTimeoutSeconds': 'Connection timeout (seconds)',
|
||||
'settings.remoteInstances.page.field.installMethod': 'Install method',
|
||||
'settings.remoteInstances.page.field.installMethodHint': 'How OpenChamber is installed when running in managed mode.',
|
||||
'settings.remoteInstances.page.field.installMethodHint': 'How OpenChamber should be placed on the remote machine when this app starts it for you.',
|
||||
'settings.remoteInstances.page.field.selectInstallMethodPlaceholder': 'Select install method',
|
||||
'settings.remoteInstances.page.field.installMethodDownloadRelease': 'Download release',
|
||||
'settings.remoteInstances.page.field.installMethodUploadBundle': 'Upload bundle',
|
||||
@@ -1006,14 +1037,14 @@ export const settingsDict = {
|
||||
'settings.remoteInstances.page.field.sshPasswordPlaceholder': 'Enter SSH password',
|
||||
'settings.remoteInstances.page.field.uiPasswordOptional': 'UI password (optional)',
|
||||
'settings.remoteInstances.page.field.uiPasswordPlaceholder': 'Enter UI password',
|
||||
'settings.remoteInstances.page.field.forwardTypeHint': 'Choose local (-L), remote (-R), or dynamic (-D) forwarding.',
|
||||
'settings.remoteInstances.page.field.forwardTypeHint': 'Choose what kind of port access this SSH connection should provide.',
|
||||
'settings.remoteInstances.page.field.typePlaceholder': 'Type',
|
||||
'settings.remoteInstances.page.forwardType.local': 'Local (-L)',
|
||||
'settings.remoteInstances.page.forwardType.remote': 'Remote (-R)',
|
||||
'settings.remoteInstances.page.forwardType.dynamic': 'Dynamic (-D)',
|
||||
'settings.remoteInstances.page.forwardTypeDescription.local': 'Forward local traffic to a remote destination.',
|
||||
'settings.remoteInstances.page.forwardTypeDescription.remote': 'Expose a remote endpoint and forward it back to your local machine.',
|
||||
'settings.remoteInstances.page.forwardTypeDescription.dynamic': 'Expose a local SOCKS5 proxy over SSH.',
|
||||
'settings.remoteInstances.page.forwardTypeDescription.local': 'Open a local port that connects to something on the remote machine.',
|
||||
'settings.remoteInstances.page.forwardTypeDescription.remote': 'Open a port on the remote machine that connects back to your computer.',
|
||||
'settings.remoteInstances.page.forwardTypeDescription.dynamic': 'Open a local SOCKS proxy through the SSH connection.',
|
||||
'settings.remoteInstances.page.actions.create': 'Create',
|
||||
'settings.remoteInstances.page.actions.cancel': 'Cancel',
|
||||
'settings.remoteInstances.page.actions.connecting': 'Connecting...',
|
||||
@@ -1024,7 +1055,7 @@ export const settingsDict = {
|
||||
'settings.remoteInstances.page.actions.enableForwardAria': 'Enable forward',
|
||||
'settings.remoteInstances.page.actions.openLocal': 'Open local',
|
||||
'settings.remoteInstances.page.actions.addForward': 'Add forward',
|
||||
'settings.remoteInstances.page.import.sectionTitle': 'Import from SSH config',
|
||||
'settings.remoteInstances.page.import.sectionTitle': 'Saved SSH hosts',
|
||||
'settings.remoteInstances.page.import.loading': 'Loading SSH hosts...',
|
||||
'settings.remoteInstances.page.import.noneFound': 'No SSH hosts found.',
|
||||
'settings.remoteInstances.page.import.noneAvailable': 'No SSH hosts available to import.',
|
||||
@@ -1034,12 +1065,12 @@ export const settingsDict = {
|
||||
'settings.remoteInstances.page.logsDialog.title': 'SSH Logs',
|
||||
'settings.remoteInstances.page.logsDialog.loading': 'Loading logs...',
|
||||
'settings.remoteInstances.page.logsDialog.empty': 'No SSH logs yet.',
|
||||
'settings.remoteInstances.page.patternDialog.title': 'Create from wildcard pattern',
|
||||
'settings.remoteInstances.page.patternDialog.title': 'Choose an SSH destination',
|
||||
'settings.remoteInstances.page.patternDialog.destinationPlaceholder': 'user@host',
|
||||
'settings.remoteInstances.page.phase.resolvingConfiguration': 'Resolving configuration',
|
||||
'settings.remoteInstances.page.phase.checkingAuth': 'Checking authentication',
|
||||
'settings.remoteInstances.page.phase.establishingSsh': 'Establishing SSH connection',
|
||||
'settings.remoteInstances.page.phase.probingRemote': 'Probing remote host',
|
||||
'settings.remoteInstances.page.phase.probingRemote': 'Checking remote machine',
|
||||
'settings.remoteInstances.page.phase.installingOpenChamber': 'Installing OpenChamber',
|
||||
'settings.remoteInstances.page.phase.updatingOpenChamber': 'Updating OpenChamber',
|
||||
'settings.remoteInstances.page.phase.detectingServer': 'Detecting server',
|
||||
@@ -1504,6 +1535,9 @@ export const settingsDict = {
|
||||
'settings.voice.page.preview.voiceLine': 'Hello! I\'m {voiceName}. This is how I sound.',
|
||||
'settings.voice.page.preview.customServerLine': 'Hello! This is a preview of the custom TTS server.',
|
||||
'settings.openchamber.visual.section.colorMode': 'Color Mode',
|
||||
'settings.openchamber.visual.section.mobileLayout': 'Mobile Layout',
|
||||
'settings.openchamber.visual.option.mobileLayout.default': 'Default',
|
||||
'settings.openchamber.visual.option.mobileLayout.new': 'New',
|
||||
'settings.openchamber.visual.section.localization': 'Localization',
|
||||
'settings.openchamber.visual.section.spacingAndLayout': 'Spacing & Layout',
|
||||
'settings.openchamber.visual.section.navigation': 'Navigation',
|
||||
|
||||
Reference in New Issue
Block a user