From a1fa033af29deb7d34acf8ae1d9153b1b5ad3b8c Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" <70015+atomantic@users.noreply.github.com> Date: Sun, 30 Aug 2026 22:03:50 +0000 Subject: [PATCH] feat: add Eidoverse source selectors --- .../settings/InstanceFeaturesTab.jsx | 85 +++++++++++++++++-- .../settings/InstanceFeaturesTab.test.jsx | 35 ++++++++ server/routes/settings.test.js | 5 +- server/services/eidoverse.js | 45 +++++----- server/services/eidoverse.test.js | 30 +++++-- server/services/instanceFeatures.js | 18 +++- server/services/instanceFeatures.test.js | 29 +++++++ 7 files changed, 212 insertions(+), 35 deletions(-) diff --git a/client/src/components/settings/InstanceFeaturesTab.jsx b/client/src/components/settings/InstanceFeaturesTab.jsx index 15bcbe2a8..81971dcb8 100644 --- a/client/src/components/settings/InstanceFeaturesTab.jsx +++ b/client/src/components/settings/InstanceFeaturesTab.jsx @@ -19,10 +19,40 @@ const sourceHint = (feature) => { }; const normalizeGitHubRepo = (url) => { + const parsed = parseGitHubUrl(url); + if (!parsed) return null; + return /^git@github\.com:/i.test(String(url).trim()) + ? `git@github.com:${parsed.owner}/${parsed.repo}.git` + : `https://github.com/${parsed.owner}/${parsed.repo}`; +}; + +const buildEidoverseRepoUrl = (owner, transport) => ( + transport === 'ssh' + ? `git@github.com:${owner}/eidoverse-worlds.git` + : `https://github.com/${owner}/eidoverse-worlds` +); + +const eidoverseTransport = (url) => (/^git@github\.com:/i.test(String(url).trim()) ? 'ssh' : 'http'); + +const githubBrowseUrl = (url) => { const parsed = parseGitHubUrl(url); return parsed ? `https://github.com/${parsed.owner}/${parsed.repo}` : null; }; +const SourceChoiceButton = ({ active, children, disabled = false, onClick }) => ( + +); + export function InstanceFeaturesTab() { const { features, error, reload } = useInstanceFeatures(); const [savingId, setSavingId] = useState(null); @@ -126,6 +156,11 @@ export function InstanceFeaturesTab() { const needsInstall = isEidoverse && setup?.installed !== true; const installing = savingId === feature.id; const selectedRepoUrl = eidoverseRepoUrl ?? setup?.worldsRepoUrl ?? ''; + const selectedRepo = parseGitHubUrl(selectedRepoUrl); + const selectedTransport = eidoverseTransport(selectedRepoUrl); + const selfOwner = setup?.sourceOwners?.self || null; + const upstreamOwner = setup?.sourceOwners?.upstream || 'anima-research'; + const worldsBrowseUrl = githubBrowseUrl(setup?.worldsRepoUrl); const repoIsValid = isGitHubRepoUrl(selectedRepoUrl); const canInstall = repoIsValid && setup?.registryAvailable !== false; const canUpdateSource = repoIsValid @@ -155,11 +190,47 @@ export function InstanceFeaturesTab() { {needsInstall &&

PortOS will install Bun if needed, clone your selected Worlds repository and the upstream video runtime as separate AGPL-3.0 repositories, install their dependencies, and register Worlds under Apps. It will not start the server automatically.

} -