feat(proxy): 网关随机 API Key + 启动失败提示

- SettingsViewModel 每次进程生成随机本机 Key,start 失败时暴露错误信息
- Settings 页显示 API Key 与错误提示
This commit is contained in:
Liuxinyu176 2026-10-09 00:04:55 +08:00
parent f5162bbf74
commit 67e1f060c5
3 changed files with 37 additions and 3 deletions

View File

@ -91,6 +91,8 @@ fun SettingsScreen(
val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val proxyRunning by viewModel.proxyRunning.collectAsStateWithLifecycle() val proxyRunning by viewModel.proxyRunning.collectAsStateWithLifecycle()
val proxyApiKey by viewModel.proxyApiKey.collectAsStateWithLifecycle()
val proxyError by viewModel.proxyError.collectAsStateWithLifecycle()
var showLanguageDialog by remember { mutableStateOf(false) } var showLanguageDialog by remember { mutableStateOf(false) }
Scaffold( Scaffold(
@ -164,6 +166,8 @@ fun SettingsScreen(
item { item {
ProxyGatewayCard( ProxyGatewayCard(
running = proxyRunning, running = proxyRunning,
apiKey = proxyApiKey,
error = proxyError,
onToggle = viewModel::setProxyEnabled onToggle = viewModel::setProxyEnabled
) )
} }
@ -192,6 +196,8 @@ fun SettingsScreen(
@Composable @Composable
private fun ProxyGatewayCard( private fun ProxyGatewayCard(
running: Boolean, running: Boolean,
apiKey: String,
error: String?,
onToggle: (Boolean) -> Unit onToggle: (Boolean) -> Unit
) { ) {
Card( Card(
@ -221,6 +227,20 @@ private fun ProxyGatewayCard(
color = InkMuted, color = InkMuted,
modifier = Modifier.padding(top = 2.dp) modifier = Modifier.padding(top = 2.dp)
) )
Text(
text = "API Key:$apiKey",
style = MaterialTheme.typography.bodySmall,
color = InkMuted,
modifier = Modifier.padding(top = 2.dp)
)
if (error != null) {
Text(
text = error,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(top = 2.dp)
)
}
} }
Switch( Switch(
checked = running, checked = running,

View File

@ -8,6 +8,7 @@ import com.rainy.token.data.repository.CredentialRepository
import com.rainy.token.domain.model.CredentialStatus import com.rainy.token.domain.model.CredentialStatus
import com.rainy.token.domain.service.ServiceType import com.rainy.token.domain.service.ServiceType
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import java.util.UUID
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -31,15 +32,28 @@ class SettingsViewModel @Inject constructor(
/** 本地反代服务运行状态。 */ /** 本地反代服务运行状态。 */
val proxyRunning: StateFlow<Boolean> = localProxyServer.isRunning val proxyRunning: StateFlow<Boolean> = localProxyServer.isRunning
/** 启动/停止本地反代服务。M1b 使用固定本地 Key,后续改为可配置。 */ /** 当前本机 API Key(每次进程随机生成,仅提示用)。 */
val proxyApiKey: StateFlow<String> = MutableStateFlow(generateProxyKey())
/** 启动失败时的错误信息。 */
private val _proxyError = MutableStateFlow<String?>(null)
val proxyError: StateFlow<String?> = _proxyError.asStateFlow()
/** 启动/停止本地反代服务。 */
fun setProxyEnabled(enabled: Boolean) { fun setProxyEnabled(enabled: Boolean) {
if (enabled) { if (enabled) {
localProxyServer.start(ProxyServerConfig(apiKey = "rainytoken")) localProxyServer.start(ProxyServerConfig(apiKey = proxyApiKey.value))
.onSuccess { _proxyError.value = null }
.onFailure { e -> _proxyError.value = e.message ?: "代理网关启动失败" }
} else { } else {
localProxyServer.stop() localProxyServer.stop()
_proxyError.value = null
} }
} }
private fun generateProxyKey(): String =
"rainy-" + UUID.randomUUID().toString().replace("-", "").take(16)
init { init {
refresh() refresh()
} }

View File

@ -72,7 +72,7 @@ WBAdpt TraeAdpt QoderAdpt RaccoonAdpt OfficialPassthrough
- WorkBuddy INTL / Trae SOLO/Work 实际协议归一化 - WorkBuddy INTL / Trae SOLO/Work 实际协议归一化
- M3 agent2api 全家桶(Qoder / 小浣熊 / CatPaw / AutoClaw / Cline / Accio / ZCode / CodeArts / Loomy) - M3 agent2api 全家桶(Qoder / 小浣熊 / CatPaw / AutoClaw / Cline / Accio / ZCode / CodeArts / Loomy)
- Qoder 需 COSY 请求签名/编码(ed25519 类原语),已列为攻坚项 - Qoder 需 COSY 请求签名/编码(ed25519 类原语),已列为攻坚项
- M4 长尾 + 官方透传 + 网关配置 UI 完善 - M4 长尾 + 官方透传 + 网关配置 UI 完善(已做:随机 API Key / 启动失败提示;待做:端口配置 / 状态持久化)
## 4. 里程碑 ## 4. 里程碑