From 2583ef6aa48de68740f844b2e49d522fc2bc603c Mon Sep 17 00:00:00 2001 From: shinchan-zhai Date: Mon, 23 Mar 2026 00:52:46 +0800 Subject: [PATCH] fix: setup flow doesn't hijack normal conversation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Detects when user sends Chinese text, short text, or text with spaces during key-input steps → auto-pauses setup and answers the question - API key masking fixed (no more garbled display) - User can resume setup with '开始配置' anytime --- agent/onboard.go | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/agent/onboard.go b/agent/onboard.go index a1948ac4..301d77e8 100644 --- a/agent/onboard.go +++ b/agent/onboard.go @@ -79,13 +79,38 @@ func setConfig(st *store.Store, uid int64, key, val string) { func (a *Agent) handleSetupFlow(userID int64, text string, L string) (string, bool) { state := a.getSetupState(userID) - // Cancel setup lower := strings.ToLower(text) + + // Cancel setup — explicit or implicit (user asking unrelated questions) if lower == "cancel" || lower == "取消" || lower == "/cancel" { a.clearSetupState(userID) return a.setupMsg(L, "cancelled"), true } + // If in a step that expects a key/secret, check if user is NOT sending a key + // Keys are typically long strings without spaces and Chinese characters + if state.Step == "await_api_key" || state.Step == "await_api_secret" || state.Step == "await_passphrase" || state.Step == "await_ai_key" { + trimmed := strings.TrimSpace(text) + hasChinese := false + for _, r := range trimmed { + if r >= 0x4e00 && r <= 0x9fff { + hasChinese = true + break + } + } + hasSpaces := strings.Contains(trimmed, " ") && !strings.HasPrefix(trimmed, "sk-") + tooShort := len(trimmed) < 8 + + if hasChinese || hasSpaces || tooShort { + // User is probably asking a question, not providing a key + a.clearSetupState(userID) + if L == "zh" { + return "👌 配置已暂停。我先回答你的问题——\n\n随时发送 *开始配置* 继续配置。", false + } + return "👌 Setup paused. Let me answer your question first—\n\nSend *setup* anytime to continue.", false + } + } + switch state.Step { case "await_exchange": return a.handleExchangeChoice(userID, text, state, L) @@ -220,12 +245,12 @@ func (a *Agent) finishSetup(userID int64, state *SetupState, L string) (string, a.clearSetupState(userID) result := "" + maskedKey := maskKey(state.APIKey) if L == "zh" { result = fmt.Sprintf("🎉 *配置完成!*\n\n"+ "• 交易所: %s\n"+ - "• API Key: %s...%s\n", - strings.Title(state.Exchange), - state.APIKey[:4], state.APIKey[len(state.APIKey)-4:]) + "• API Key: %s\n", + strings.Title(state.Exchange), maskedKey) if state.AIModel != "" { result += fmt.Sprintf("• AI 模型: %s\n", state.AIModel) } @@ -233,9 +258,8 @@ func (a *Agent) finishSetup(userID int64, state *SetupState, L string) (string, } else { result = fmt.Sprintf("🎉 *Setup Complete!*\n\n"+ "• Exchange: %s\n"+ - "• API Key: %s...%s\n", - strings.Title(state.Exchange), - state.APIKey[:4], state.APIKey[len(state.APIKey)-4:]) + "• API Key: %s\n", + strings.Title(state.Exchange), maskedKey) if state.AIModel != "" { result += fmt.Sprintf("• AI Model: %s\n", state.AIModel) } @@ -334,6 +358,13 @@ func (a *Agent) createTraderFromSetup(state *SetupState) error { return nil } +func maskKey(key string) string { + if len(key) <= 8 { + return "****" + } + return key[:4] + "****" + key[len(key)-4:] +} + func needsPassphrase(exchange string) bool { return exchange == "okx" || exchange == "bitget" || exchange == "kucoin" }