Merge branch 'develop' into release

This commit is contained in:
2026-08-13 17:38:49 +09:00
5 changed files with 27 additions and 17 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "autonomy-studio-launcher", "name": "autonomy-studio-launcher",
"version": "1.1.1", "version": "1.1.2",
"description": "Autonomy Studio v2 Frontend", "description": "Autonomy Studio v2 Frontend",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": { "author": {
+25 -3
View File
@@ -739,11 +739,33 @@ async function loginTailscale(
await waitForTailscaleConnected() await waitForTailscaleConnected()
return { ok: true, message: 'Tailscale 연결 완료' } return { ok: true, message: 'Tailscale 연결 완료' }
} catch (error) { } catch (error) {
if (isTailscalePermissionError(error)) {
try {
await runCommand('pkexec', ['/usr/bin/tailscale', ...tailscaleArgs], 60000, commandEnv)
await waitForTailscaleConnected()
// Persist unprivileged access after the one privileged recovery login.
const operator = await ensureTailscaleOperator()
return {
ok: true,
message: operator.ok
? 'Tailscale 연결 완료'
: 'Tailscale 연결 완료. 다음 연결을 위해 제어 권한을 다시 확인하세요.',
}
} catch (pkexecError) {
return { return {
ok: false, ok: false,
message: isTailscalePermissionError(error) message: commandErrorMessage(
? commandErrorMessage(error, 'Tailscale 제어 권한이 없습니다. 다시 연결해 주세요.') pkexecError,
: commandErrorMessage(error, 'Tailscale 연결 실패'), commandErrorMessage(error, 'Tailscale 제어 권한이 없습니다. 다시 연결해 주세요.'),
),
}
}
}
return {
ok: false,
message: commandErrorMessage(error, 'Tailscale 연결 실패'),
} }
} }
} }
+1 -1
View File
@@ -1689,7 +1689,7 @@ done`
const buildOnly = body.buildOnly === true const buildOnly = body.buildOnly === true
const configuredImage = typeof body.dockerImage === 'string' ? body.dockerImage.trim() : module.dockerImage?.trim() const configuredImage = typeof body.dockerImage === 'string' ? body.dockerImage.trim() : module.dockerImage?.trim()
const nav2Launch = nav2LaunchSpec(module.folderName) const nav2Launch = nav2LaunchSpec(module.folderName)
const runtimeImage = configuredImage || (nav2Launch ? 'nav2-dev:humble' : AUTOWARE_IMAGE) const runtimeImage = configuredImage || (nav2Launch ? 'future-nav2-gazebo:humble' : AUTOWARE_IMAGE)
if (!/^[A-Za-z0-9._/:@-]+$/.test(runtimeImage)) throw new Error('모듈 런타임 이미지가 올바르지 않습니다.') if (!/^[A-Za-z0-9._/:@-]+$/.test(runtimeImage)) throw new Error('모듈 런타임 이미지가 올바르지 않습니다.')
const nav2RunCommand = nav2Launch const nav2RunCommand = nav2Launch
? `set -e; source /opt/ros/humble/setup.bash; for setup in /modules/*/install/setup.bash; do [ -f "${'$'}setup" ] && source "${'$'}setup"; done; exec ros2 launch ${nav2Launch.packageName} ${nav2Launch.launchFile} ${'$'}1` ? `set -e; source /opt/ros/humble/setup.bash; for setup in /modules/*/install/setup.bash; do [ -f "${'$'}setup" ] && source "${'$'}setup"; done; exec ros2 launch ${nav2Launch.packageName} ${nav2Launch.launchFile} ${'$'}1`
-1
View File
@@ -61,7 +61,6 @@ function App(): React.JSX.Element {
blockLauncherSessionRefresh() blockLauncherSessionRefresh()
window.launcherSession?.endUserSession().catch(() => undefined) window.launcherSession?.endUserSession().catch(() => undefined)
requestLogout(authSession?.accessToken) requestLogout(authSession?.accessToken)
window.launcherTailscale?.logout().catch(() => undefined)
window.localStorage.removeItem(AUTH_SESSION_KEY) window.localStorage.removeItem(AUTH_SESSION_KEY)
window.sessionStorage.removeItem(AUTH_SESSION_KEY) window.sessionStorage.removeItem(AUTH_SESSION_KEY)
setAuthSession(null) setAuthSession(null)
-11
View File
@@ -288,17 +288,6 @@ function Dashboard({ authSession, onSessionUpdate, onLogout, onSessionExpired }:
const sshKey = await window.launcherSshKey?.ensure().catch(() => null) const sshKey = await window.launcherSshKey?.ensure().catch(() => null)
if (cancelled) return if (cancelled) return
const operator = await launcherTailscale.ensureOperator()
if (cancelled) return
if (!operator.ok) {
setTailscaleIssue({
state: 'warning',
title: '원격 연결 권한 필요',
message: operator.message || 'Tailscale 제어 권한을 설정하지 못했습니다.',
})
return
}
const response = await fetchWithAuthRefreshRef.current(`${LAUNCHER_API_BASE_URL}/api/provision/session`, { const response = await fetchWithAuthRefreshRef.current(`${LAUNCHER_API_BASE_URL}/api/provision/session`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },