diff --git a/cmd/bizdev-cli/main.go b/cmd/bizdev-cli/main.go index 017ad9f8..3a54ab1c 100644 --- a/cmd/bizdev-cli/main.go +++ b/cmd/bizdev-cli/main.go @@ -16,6 +16,7 @@ import ( "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" "chat-agent-system/internal/squad" + "chat-agent-system/internal/stream" ) func main() { @@ -42,6 +43,8 @@ func main() { workDirFlag := flag.String("work-dir", "", "关联现有工作区目录 (如 sandbox/intake_xxx)") userName := flag.String("user", "张工", "用户姓名") userRole := flag.String("role", "engineer", "用户角色") + streamMode := flag.Bool("stream", true, "启用实时流式阶段状态指示 (默认开启)") + verboseMode := flag.Bool("verbose", false, "展开打印底层专员详细推演草稿与思考链 (默认隐藏)") flag.Parse() cfg, err := config.Load(*envPath) @@ -99,6 +102,8 @@ func main() { *market, *userName, *userRole, + *streamMode, + *verboseMode, ) return } @@ -343,6 +348,64 @@ func handleInspect(ctx context.Context, svc bizdev.BizdevService, workDir string } } +func createCLIStreamListener(verbose bool) stream.Listener { + return func(ev stream.StreamEvent) { + switch ev.Type { + case stream.EventPhase: + if ev.Phase != nil { + icon := "⏳" + switch ev.Phase.PhaseID { + case "squad_assembly": + icon = "👥" + case "knowledge_retrieval", "knowledge_retrieved": + icon = "📚" + case "step_executing": + icon = "⚙️ " + case "step_completed": + icon = "✅" + case "quality_gate": + icon = "🛡️ " + case "advisor_briefing": + icon = "💡" + case "stage_transition", "stage_started": + icon = "🚀" + case "stage_completed": + icon = "🎉" + } + fmt.Printf("%s [%s] %s\n", icon, ev.Phase.PhaseID, ev.Phase.Message) + } + case stream.EventStatus: + if ev.Status != nil && ev.Status.Message != "" { + fmt.Printf("🎯 [意图状态] %s\n", ev.Status.Message) + } + case stream.EventSummary: + if ev.Summary != nil { + fmt.Println("\n------------------------------------------------------------------") + fmt.Println("📌【核心进展与诊断摘要】") + fmt.Printf("标 题: %s\n", ev.Summary.Title) + fmt.Printf("诊 断: %s\n", ev.Summary.Content) + if ev.Summary.MaturityScore > 0 { + fmt.Printf("成熟度: %s (%d / 100)\n", ev.Summary.MaturityLevel, ev.Summary.MaturityScore) + } + fmt.Println("------------------------------------------------------------------") + } + case stream.EventDeliverable: + if ev.Deliverable != nil { + fmt.Printf("📄【A轨合规文档生成】%s (评分: %.1f) -> %s\n", ev.Deliverable.Title, ev.Deliverable.QualityScore, ev.Deliverable.FilePath) + if !verbose { + fmt.Println("💡 [提示: 底层专员思考过程与推演草稿已在沙箱归档,可使用 --verbose 参数在控制台展开查看]") + } + } + case stream.EventDetail: + if verbose && ev.Detail != nil { + fmt.Printf("\n--- 🔍 [底层推演详情: %s - %s] ---\n%s\n------------------------------------------------------------------\n", ev.Detail.Role, ev.Detail.Title, ev.Detail.Content) + } + case stream.EventError: + fmt.Printf("⚠️ [执行告警] %s\n", ev.Error) + } + } +} + func handleChatMode( ctx context.Context, svc bizdev.BizdevService, @@ -355,6 +418,8 @@ func handleChatMode( market string, userName string, userRole string, + streamMode bool, + verboseMode bool, ) { u := coordinator.UserInfo{ ID: "u_local", @@ -405,13 +470,18 @@ func handleChatMode( // 单次提问模式 (支持脚本与自动化测试) if chatQuery != "" { - resp, err := session.SendMessage(ctx, chatQuery) + var resp *chat.ChatResponse + if streamMode { + resp, err = session.SendMessageStream(ctx, chatQuery, createCLIStreamListener(verboseMode), verboseMode) + } else { + resp, err = session.SendMessage(ctx, chatQuery) + } if err != nil { fmt.Fprintf(os.Stderr, "对话处理失败: %v\n", err) os.Exit(1) } top := resp.IntentResult.TopIntent - fmt.Printf("[意图识别: %s (置信度: %.0f%%) | 消解分支: %s] - %s\n", top.Intent, top.Confidence*100, resp.Branch, top.Reasoning) + fmt.Printf("\n[意图识别: %s (置信度: %.0f%%) | 消解分支: %s] - %s\n", top.Intent, top.Confidence*100, resp.Branch, top.Reasoning) fmt.Printf("\n%s\n", resp.ReplyText) if resp.AdvisorBrief != nil && (top.Intent == intent.IntentAdvanceStage || top.Intent == intent.IntentQueryProgress) { printAdvisorBrief(resp.AdvisorBrief) @@ -426,6 +496,7 @@ func handleChatMode( fmt.Printf("项目名称: %s | 客户单位: %s\n", userCtx.Project.Name, userCtx.Project.CustomerName) fmt.Printf("当前阶段: %s | 用户身份: %s (%s)\n", userCtx.Project.CurrentStage, userCtx.User.Name, userCtx.User.Role) fmt.Printf("可用动作: %v\n", userCtx.AvailableActions) + fmt.Printf("流式反馈: %v | 详细推演模式: %v\n", streamMode, verboseMode) fmt.Println("------------------------------------------------------------------") fmt.Println("💡 参谋互动小贴士(三分支柔性消解):") fmt.Println(" • 极速兑现(分支 1):当参谋给出下一步建议时,回复“好”、“行”或“1”直接推进") @@ -451,7 +522,12 @@ func handleChatMode( break } - resp, err := session.SendMessage(ctx, input) + var resp *chat.ChatResponse + if streamMode { + resp, err = session.SendMessageStream(ctx, input, createCLIStreamListener(verboseMode), verboseMode) + } else { + resp, err = session.SendMessage(ctx, input) + } if err != nil { fmt.Fprintf(os.Stderr, "处理异常: %v\n", err) continue