From 63e4af2db566ac988fe3a8ea29c49a25cf4cc68b Mon Sep 17 00:00:00 2001 From: WeiCHEN Date: Mon, 7 Sep 2026 18:23:55 +0800 Subject: [PATCH] feat(cli): upgrade bizdev-cli with dynamic inspection, step manipulation, and manifest display Co-authored-by: Cursor --- cmd/bizdev-cli/main.go | 111 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/cmd/bizdev-cli/main.go b/cmd/bizdev-cli/main.go index 18fde0f6..cab3826b 100644 --- a/cmd/bizdev-cli/main.go +++ b/cmd/bizdev-cli/main.go @@ -6,9 +6,11 @@ import ( "fmt" "os" "path/filepath" + "strings" "chat-agent-system/internal/bizdev" "chat-agent-system/internal/config" + "chat-agent-system/internal/squad" ) func main() { @@ -21,6 +23,10 @@ func main() { market := flag.String("market", "国内", "目标市场") materials := flag.String("materials", "", "输入补充材料内容") envPath := flag.String("env", ".env", "环境配置文件路径") + inspectDir := flag.String("inspect", "", "审查并查看指定工作区状态目录") + autoRepair := flag.Bool("auto-repair", true, "启用质量门禁自动闭环修正") + listTasks := flag.Bool("list-tasks", false, "列出所有受支持的商务对接任务清单") + addStep := flag.String("add-step", "", "动态向工作区追加任务步骤 (格式: role:title,配合 -inspect)") flag.Parse() cfg, err := config.Load(*envPath) @@ -29,6 +35,27 @@ func main() { os.Exit(1) } + svc := bizdev.NewService(cfg) + + // 1. 列出支持的任务 + if *listTasks { + fmt.Println("=== 商务对接小队支持的独立任务清单 ===") + for _, t := range svc.ListTasks() { + fmt.Printf("- %-18s: %s (交付: %s)\n", t.Key, t.Title, t.ArtifactTitle) + if t.Description != "" { + fmt.Printf(" 说明: %s\n", t.Description) + } + } + return + } + + // 2. 审查已有工作区 + if *inspectDir != "" { + handleInspect(context.Background(), svc, *inspectDir, *addStep, *backend) + return + } + + // 3. 执行常规任务 activeBackend := cfg.AgentBackend if *backend != "" { activeBackend = *backend @@ -45,7 +72,6 @@ func main() { } } - svc := bizdev.NewService(cfg) res, err := svc.ExecuteTask(context.Background(), bizdev.TaskRunRequest{ TaskKey: *taskKey, ProjectName: *project, @@ -55,6 +81,7 @@ func main() { TargetMarket: *market, Materials: materialsList, Backend: activeBackend, + AutoRepair: *autoRepair, }) if err != nil { fmt.Fprintf(os.Stderr, "任务执行失败: %v\n", err) @@ -67,12 +94,34 @@ func main() { fmt.Printf("=== 任务执行成功 [%s] ===\n", res.TaskKey) fmt.Printf("耗时: %v\n", res.Duration) - fmt.Printf("宿主机受控工作区: %s\n", res.WorkDir) + fmt.Printf("工作区沙箱: %s\n", res.WorkDir) fmt.Printf("交付文档产物: %s\n", filepath.Join(res.WorkDir, "output.md")) if _, err := os.Stat(filepath.Join(res.WorkDir, "execution.log")); err == nil { fmt.Printf("执行审计日志: %s\n", filepath.Join(res.WorkDir, "execution.log")) } fmt.Printf("使用的后端: %s\n", res.BackendUsed) + + // 打印质量门禁与指纹报告 + if res.QualityReport != nil { + fmt.Printf("质量门禁评分: %.1f / 100 (达标: %v)\n", res.QualityReport.Score, res.QualityReport.Passed) + if len(res.QualityReport.Violations) > 0 { + fmt.Printf("门禁检测项:\n") + for _, v := range res.QualityReport.Violations { + fmt.Printf(" - %s\n", v) + } + } + } + if res.Manifest != nil { + fmt.Printf("审计指纹清单: %s (追踪文件数: %d)\n", filepath.Join(res.WorkDir, "manifest.json"), len(res.Manifest.Files)) + } + + if len(res.ExtractedData) > 0 { + fmt.Printf("黑板抽取事实字段:\n") + for k, v := range res.ExtractedData { + fmt.Printf(" - %s: %s\n", k, v) + } + } + if len(res.Attachments) > 0 { fmt.Printf("附加产物:\n") for _, a := range res.Attachments { @@ -81,3 +130,61 @@ func main() { } } } + +func handleInspect(ctx context.Context, svc bizdev.BizdevService, workDir string, addStepFlag string, backend string) { + state, err := svc.InspectWorkspace(ctx, workDir) + if err != nil { + fmt.Fprintf(os.Stderr, "查看工作区失败: %v\n", err) + os.Exit(1) + } + + fmt.Printf("=== 工作区状态审查 [%s] ===\n", workDir) + fmt.Printf("项目: %s | 客户: %s | 阶段: %s | 状态: %s\n", + state.Metadata.ProjectName, state.Metadata.CustomerName, state.Metadata.TaskKey, state.Metadata.Status) + + fmt.Printf("\n小队角色编制 (%d 位):\n", len(state.Squad.Agents)) + for _, a := range state.Squad.Agents { + fmt.Printf(" - %-12s: %s (模型: %s, 工具: %v)\n", a.Role, a.Name, a.Model, a.Tools) + } + + fmt.Printf("\n工作流步骤清单 (%d 步):\n", len(state.Workflow.Steps)) + for _, s := range state.Workflow.Steps { + fmt.Printf(" - [%s] %-10s (%-8s) : %s -> %s\n", s.Status, s.ID, s.Role, s.Title, s.SubWorkspace) + } + + if len(state.Blackboard.Fields) > 0 { + fmt.Printf("\n黑板抽取字段:\n") + for k, v := range state.Blackboard.Fields { + fmt.Printf(" - %s: %s\n", k, v) + } + } + + // 若用户指定了动态追加步骤 + if addStepFlag != "" { + parts := strings.SplitN(addStepFlag, ":", 2) + if len(parts) == 2 { + role := strings.TrimSpace(parts[0]) + title := strings.TrimSpace(parts[1]) + fmt.Printf("\n动态追加步骤: [%s] %s\n", role, title) + modifyReq := squad.ModifyWorkflowRequest{ + WorkDir: workDir, + Backend: backend, + AddSteps: []squad.StepSpec{ + { + ID: fmt.Sprintf("step_dyn_%d", len(state.Workflow.Steps)+1), + Role: role, + Title: title, + SubWorkspace: fmt.Sprintf("tasks/dyn_%s", role), + Mode: "execute", + }, + }, + } + runRes, err := svc.ResumeOrModifyWorkspace(ctx, modifyReq) + if err != nil { + fmt.Fprintf(os.Stderr, "执行动态追加步骤失败: %v\n", err) + } else { + fmt.Printf("动态步骤执行成功! 耗时: %v\n", runRes.Duration) + } + } + } +}