From 60d7ab9642efe895c55203b18fb05fa85086a569 Mon Sep 17 00:00:00 2001 From: huangmengxuan Date: Mon, 13 Apr 2026 18:23:48 +0800 Subject: [PATCH] fix(config): clarify init copy for TTY, preserve original for AI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The interactive `config init` flow showed a QR code and verification link without indicating their relationship, leaving users unsure which to act on first and whether the link was still needed after scanning. Split the message strings on TTY vs non-TTY: - TTY: header above QR ("使用飞书 / Lark 扫码配置应用"), "或打开链接" framing to mark the link as an alternative, and an active waiting indicator. - Non-TTY (AI / piped callers via --new): keep the original copy verbatim so existing parsers and prompts are unaffected. QR is still rendered in both branches. Change-Id: I9b753f044ebefaedbb4b095cabf7beff4669eb2e --- cmd/config/init_interactive.go | 29 +++++++++++++------- cmd/config/init_messages.go | 45 ++++++++++++++++++++------------ cmd/config/init_messages_test.go | 13 +++++---- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/cmd/config/init_interactive.go b/cmd/config/init_interactive.go index f138a215c..0a511cd0d 100644 --- a/cmd/config/init_interactive.go +++ b/cmd/config/init_interactive.go @@ -177,17 +177,26 @@ func runCreateAppFlow(ctx context.Context, f *cmdutil.Factory, brandOverride cor // Step 2: Build and display verification URL + QR code verificationURL := larkauth.BuildVerificationURL(authResp.VerificationUriComplete, build.Version) - // Show QR code in terminal - qr, qrErr := qrcode.New(verificationURL, qrcode.Medium) - if qrErr == nil { - fmt.Fprint(f.IOStreams.ErrOut, qr.ToSmallString(false)) + // Branch on TTY: human-friendly copy in interactive terminals, + // preserve original copy for AI / non-interactive callers. + if f.IOStreams.IsTerminal { + fmt.Fprintf(f.IOStreams.ErrOut, "%s", msg.ScanQRCode) + qr, qrErr := qrcode.New(verificationURL, qrcode.Medium) + if qrErr == nil { + fmt.Fprint(f.IOStreams.ErrOut, qr.ToSmallString(false)) + } + fmt.Fprintf(f.IOStreams.ErrOut, "%s", msg.ScanOrOpenLink) + fmt.Fprintf(f.IOStreams.ErrOut, " %s\n\n", verificationURL) + fmt.Fprintf(f.IOStreams.ErrOut, "%s\n", msg.WaitingForScan) + } else { + qr, qrErr := qrcode.New(verificationURL, qrcode.Medium) + if qrErr == nil { + fmt.Fprint(f.IOStreams.ErrOut, qr.ToSmallString(false)) + } + fmt.Fprintf(f.IOStreams.ErrOut, "%s", msg.OpenLinkNonTTY) + fmt.Fprintf(f.IOStreams.ErrOut, " %s\n\n", verificationURL) + fmt.Fprintf(f.IOStreams.ErrOut, "%s\n", msg.WaitingForScanNonTTY) } - - fmt.Fprintf(f.IOStreams.ErrOut, "%s", msg.ScanOrOpenLink) - fmt.Fprintf(f.IOStreams.ErrOut, " %s\n\n", verificationURL) - - // Step 3: Poll for result - fmt.Fprintf(f.IOStreams.ErrOut, "%s\n", msg.WaitingForScan) result, err := larkauth.PollAppRegistration(ctx, httpClient, core.BrandFeishu, authResp.DeviceCode, authResp.Interval, authResp.ExpiresIn, f.IOStreams.ErrOut) if err != nil { return nil, output.ErrAuth("%v", err) diff --git a/cmd/config/init_messages.go b/cmd/config/init_messages.go index 54e2dbbef..4bfb622ea 100644 --- a/cmd/config/init_messages.go +++ b/cmd/config/init_messages.go @@ -16,11 +16,16 @@ type initMsg struct { Platform string SelectPlatform string Feishu string - ScanOrOpenLink string - WaitingForScan string - DetectedLarkTenant string - AppCreated string - ConfigSaved string + // TTY (interactive) variants + ScanQRCode string // header shown above QR code + ScanOrOpenLink string // post-QR alt link prompt ("or open...") + WaitingForScan string // active polling indicator + // Non-TTY (AI / non-interactive) variants — preserve original copy + OpenLinkNonTTY string // primary link prompt + WaitingForScanNonTTY string // passive waiting indicator + DetectedLarkTenant string + AppCreated string + ConfigSaved string } var initMsgZh = &initMsg{ @@ -29,12 +34,15 @@ var initMsgZh = &initMsg{ ConfigExistingApp: "手动输入应用凭证", Platform: "平台", SelectPlatform: "选择平台", - Feishu: "飞书", - ScanOrOpenLink: "\n打开以下链接配置应用:\n\n", - WaitingForScan: "等待配置应用...", - DetectedLarkTenant: "[lark-cli] 检测到 Lark 租户,切换端点重试...", - AppCreated: "应用配置成功! App ID: %s", - ConfigSaved: "应用配置成功! App ID: %s", + Feishu: "飞书", + ScanQRCode: "\n使用飞书 / Lark 扫码配置应用:\n\n", + ScanOrOpenLink: "\n或打开以下链接完成配置:\n", + WaitingForScan: "正在获取你的应用配置结果...", + OpenLinkNonTTY: "\n打开以下链接配置应用:\n\n", + WaitingForScanNonTTY: "等待配置应用...", + DetectedLarkTenant: "[lark-cli] 检测到 Lark 租户,切换端点重试...", + AppCreated: "应用配置成功! App ID: %s", + ConfigSaved: "应用配置成功! App ID: %s", } var initMsgEn = &initMsg{ @@ -43,12 +51,15 @@ var initMsgEn = &initMsg{ ConfigExistingApp: "Enter app credentials yourself", Platform: "Platform", SelectPlatform: "Select platform", - Feishu: "Feishu", - ScanOrOpenLink: "\nOpen the link below to configure app:\n\n", - WaitingForScan: "Waiting for app configuration...", - DetectedLarkTenant: "[lark-cli] Detected Lark tenant, switching endpoint...", - AppCreated: "App configured! App ID: %s", - ConfigSaved: "App configured! App ID: %s", + Feishu: "Feishu", + ScanQRCode: "\nScan the QR code with Feishu/Lark:\n\n", + ScanOrOpenLink: "\nOr open the link below in your browser:\n", + WaitingForScan: "Fetching configuration results...", + OpenLinkNonTTY: "\nOpen the link below to configure app:\n\n", + WaitingForScanNonTTY: "Waiting for app configuration...", + DetectedLarkTenant: "[lark-cli] Detected Lark tenant, switching endpoint...", + AppCreated: "App configured! App ID: %s", + ConfigSaved: "App configured! App ID: %s", } func getInitMsg(lang string) *initMsg { diff --git a/cmd/config/init_messages_test.go b/cmd/config/init_messages_test.go index 0e2ebe56a..ecafb0ec2 100644 --- a/cmd/config/init_messages_test.go +++ b/cmd/config/init_messages_test.go @@ -54,11 +54,14 @@ func assertAllFieldsNonEmpty(t *testing.T, msg *initMsg, label string) { "Platform": msg.Platform, "SelectPlatform": msg.SelectPlatform, "Feishu": msg.Feishu, - "ScanOrOpenLink": msg.ScanOrOpenLink, - "WaitingForScan": msg.WaitingForScan, - "DetectedLarkTenant": msg.DetectedLarkTenant, - "AppCreated": msg.AppCreated, - "ConfigSaved": msg.ConfigSaved, + "ScanQRCode": msg.ScanQRCode, + "ScanOrOpenLink": msg.ScanOrOpenLink, + "WaitingForScan": msg.WaitingForScan, + "OpenLinkNonTTY": msg.OpenLinkNonTTY, + "WaitingForScanNonTTY": msg.WaitingForScanNonTTY, + "DetectedLarkTenant": msg.DetectedLarkTenant, + "AppCreated": msg.AppCreated, + "ConfigSaved": msg.ConfigSaved, } for name, val := range fields { if val == "" {