feat: gate remote projects as a technical preview

Remote Host and managed SSH project entry points were always exposed while the signed artifact workflow remains preview-stage. Remote Projects now defaults off behind its own Platform Features tab, preserves saved Hosts, projects, and credentials, and returns active remote work to a local project when disabled.

Main IPC enforces the same setting while still allowing in-flight cancellation. Application settings migrate to version 9 with the preview disabled.

Release note: 新增“远程项目(技术预览)”独立页签和开关,默认关闭;启用后显示 SSH Host 与远程项目功能,关闭不会删除已有配置。
This commit is contained in:
mesalogo
2026-08-25 00:16:02 +08:00
parent 607bb33249
commit 6c74f057eb
23 changed files with 1267 additions and 115 deletions
+25 -6
View File
@@ -60,7 +60,7 @@ import {
SettingsWarningList
} from './SettingsPrimitives'
import {
settingsCategoryList,
getSettingsCategoryList,
type SettingsCategoryId
} from './settings-categories'
import type { AppearanceTheme } from './theme'
@@ -115,7 +115,6 @@ function toEmbeddingConnectionDrafts(
}))
}
const settingsTabs = settingsCategoryList.map(({ id }) => id)
const contextCompressionTokenScale = 1_000
const minimumContextCompressionTriggerThousands = 8
const maximumContextCompressionTriggerThousands = 1_000
@@ -218,7 +217,9 @@ type SettingsPanelProps = {
appearanceTheme?: AppearanceTheme
onAppearanceThemeChange?: (theme: AppearanceTheme) => void
magicNotesEnabled?: boolean
remoteProjectsEnabled?: boolean
onMagicNotesEnabledChange?: (enabled: boolean) => void
onRemoteProjectsEnabledChange?: (enabled: boolean) => void
onMagicNotesShowIncompleteTodoCountChange?: (
enabled: boolean
) => void
@@ -585,7 +586,9 @@ export function SettingsPanel({
appearanceTheme = 'system',
onAppearanceThemeChange = () => {},
magicNotesEnabled = false,
remoteProjectsEnabled = false,
onMagicNotesEnabledChange = () => {},
onRemoteProjectsEnabledChange = () => {},
onMagicNotesShowIncompleteTodoCountChange = () => {},
onShortcutSettingsChanged = () => {},
onLeaveRequestReady = () => {}
@@ -707,8 +710,16 @@ export function SettingsPanel({
const [clearingLocalData, setClearingLocalData] = useState(false)
const [detection, setDetection] = useState<AgentRuntimeDetection>()
const [detecting, setDetecting] = useState(false)
const [activeTab, setActiveTab] =
useState<SettingsCategoryId>(initialCategory ?? 'runtime')
const [selectedTab, setActiveTab] =
useState<SettingsCategoryId>(
initialCategory === 'ssh-hosts' && !remoteProjectsEnabled
? 'platform-features'
: initialCategory ?? 'runtime'
)
const activeTab =
selectedTab === 'ssh-hosts' && !remoteProjectsEnabled
? 'platform-features'
: selectedTab
const [modelType, setModelType] = useState<ModelType>('llm')
const [speechModelDraftId, setSpeechModelDraftId] = useState<
string | null | undefined
@@ -959,6 +970,11 @@ export function SettingsPanel({
return true
}
const visibleSettingsCategories = getSettingsCategoryList(
remoteProjectsEnabled
)
const settingsTabs = visibleSettingsCategories.map(({ id }) => id)
const handleTabKeyDown = (
event: React.KeyboardEvent<HTMLButtonElement>,
tab: SettingsCategoryId
@@ -1820,7 +1836,7 @@ export function SettingsPanel({
className="settings-tabs"
role="tablist"
>
{settingsCategoryList.map((category) => (
{visibleSettingsCategories.map((category) => (
<button
aria-controls={`settings-panel-${category.id}`}
aria-label={t(
@@ -2036,6 +2052,9 @@ export function SettingsPanel({
onMagicNotesShowIncompleteTodoCountChange={
onMagicNotesShowIncompleteTodoCountChange
}
onRemoteProjectsEnabledChange={
onRemoteProjectsEnabledChange
}
onNotify={onNotify}
onShortcutSettingsChanged={onShortcutSettingsChanged}
/>
@@ -3584,7 +3603,7 @@ export function SettingsPanel({
/>
)}
{activeTab === 'ssh-hosts' && (
{remoteProjectsEnabled && activeTab === 'ssh-hosts' && (
<SshHostsSettingsSection
onDirtyChange={setSshHostsDirty}
onHostUpdated={onSshHostUpdated}