169 lines
6.1 KiB
Go
169 lines
6.1 KiB
Go
package coordinator
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"chat-agent-system/internal/bizdev"
|
|
"chat-agent-system/internal/intent"
|
|
"chat-agent-system/internal/squad"
|
|
)
|
|
|
|
// UserInfo 用户在系统与项目内的身份
|
|
type UserInfo struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Role string `json:"role"` // 系统角色 (如 engineer, pm, director)
|
|
ProjectRole string `json:"project_role"` // 项目内角色 (如 编制人 composer, 审核人 reviewer, 批准人 approver)
|
|
}
|
|
|
|
// ProjectInfo 项目与工作流当前基准
|
|
type ProjectInfo struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
CustomerName string `json:"customer_name"`
|
|
DeviceType string `json:"device_type"`
|
|
IntendedUse string `json:"intended_use"`
|
|
TargetMarket string `json:"target_market"`
|
|
CurrentWorkflow string `json:"current_workflow"`
|
|
CurrentStage bizdev.MaturityStage `json:"current_stage"`
|
|
StageRules []string `json:"stage_rules,omitempty"`
|
|
}
|
|
|
|
// UserDocsInfo 用户相关文档清单与认领状态
|
|
type UserDocsInfo struct {
|
|
Composed []string `json:"composed"` // 负责编制的文档
|
|
Reviewed []string `json:"reviewed"` // 负责审核的文档
|
|
Approved []string `json:"approved"` // 负责批准的文档
|
|
Claimed []string `json:"claimed"` // 已认领/已打开查阅的文档
|
|
}
|
|
|
|
// PendingItems 待用户处理或决策的待办项
|
|
type PendingItems struct {
|
|
ConfirmModifications []string `json:"confirm_modifications,omitempty"`
|
|
PendingReviews []string `json:"pending_reviews,omitempty"`
|
|
PendingApprovals []string `json:"pending_approvals,omitempty"`
|
|
MyDraftsInProgress []string `json:"my_drafts_in_progress,omitempty"`
|
|
UnreadSupplements []string `json:"unread_supplements,omitempty"`
|
|
}
|
|
|
|
// UserProjectContext 用户项目级全量统一上下文 (对话系统与执行系统共同消费)
|
|
type UserProjectContext struct {
|
|
SnapshotID string `json:"snapshot_id"`
|
|
AssembledAt time.Time `json:"assembled_at"`
|
|
User UserInfo `json:"user"`
|
|
Project ProjectInfo `json:"project"`
|
|
UserDocs UserDocsInfo `json:"user_docs"`
|
|
Pending PendingItems `json:"pending"`
|
|
BlackboardFacts map[string]string `json:"blackboard_facts"`
|
|
LatestAdvisorBrief *squad.AdvisorBriefing `json:"latest_advisor_brief,omitempty"`
|
|
AvailableActions []string `json:"available_actions"`
|
|
RecentEvents []string `json:"recent_events,omitempty"`
|
|
WorkDir string `json:"work_dir,omitempty"`
|
|
}
|
|
|
|
// ContextAssembler 上下文组装服务
|
|
type ContextAssembler struct{}
|
|
|
|
func NewContextAssembler() *ContextAssembler {
|
|
return &ContextAssembler{}
|
|
}
|
|
|
|
// ComputeAvailableActions 根据当前成熟度阶段与角色计算允许执行的操作集合
|
|
func ComputeAvailableActions(stage bizdev.MaturityStage, pRole string) []string {
|
|
actions := []string{"QUERY_PROGRESS", "SUPPLEMENT_INFO", "VIEW_DOC"}
|
|
|
|
switch stage {
|
|
case bizdev.StageV01_Triage:
|
|
actions = append(actions, "TRIGGER_TASK:intake", "ADVANCE_STAGE:V0.5_feasibility")
|
|
case bizdev.StageV05_Feasibility:
|
|
actions = append(actions,
|
|
"TRIGGER_TASK:research",
|
|
"TRIGGER_TASK:feasibility_reg",
|
|
"TRIGGER_TASK:prelim_design",
|
|
"ADVANCE_STAGE:V1.0_quoting",
|
|
)
|
|
case bizdev.StageV10_Quoting:
|
|
actions = append(actions, "TRIGGER_TASK:cdo_quote", "LOCK_COMMERCIAL")
|
|
default:
|
|
actions = append(actions, "ADVANCE_STAGE:V0.1_triage")
|
|
}
|
|
|
|
return actions
|
|
}
|
|
|
|
// ToSnapshot 转换为 L1 意图识别器所需的轻量上下文快照
|
|
func (ctx *UserProjectContext) ToSnapshot() *intent.ContextSnapshot {
|
|
if ctx == nil {
|
|
return nil
|
|
}
|
|
return &intent.ContextSnapshot{
|
|
SnapshotID: ctx.SnapshotID,
|
|
ProjectName: ctx.Project.Name,
|
|
CurrentStage: string(ctx.Project.CurrentStage),
|
|
AvailableActions: ctx.AvailableActions,
|
|
}
|
|
}
|
|
|
|
// AssembleFromWorkspace 基于现有工作区快速组装 UserProjectContext
|
|
func (a *ContextAssembler) AssembleFromWorkspace(workDir string, user UserInfo) (*UserProjectContext, error) {
|
|
snapID := fmt.Sprintf("ctx_%d", time.Now().UnixNano())
|
|
|
|
ctx := &UserProjectContext{
|
|
SnapshotID: snapID,
|
|
AssembledAt: time.Now(),
|
|
User: user,
|
|
WorkDir: workDir,
|
|
BlackboardFacts: make(map[string]string),
|
|
AvailableActions: []string{"QUERY_PROGRESS", "SUPPLEMENT_INFO", "VIEW_DOC"},
|
|
}
|
|
|
|
// 1. 尝试读取 workspace.json
|
|
wsMetaPath := filepath.Join(workDir, "workspace.json")
|
|
if data, err := os.ReadFile(wsMetaPath); err == nil {
|
|
var wsMeta squad.WorkspaceMetadata
|
|
if json.Unmarshal(data, &wsMeta) == nil {
|
|
ctx.Project.Name = wsMeta.ProjectName
|
|
ctx.Project.CustomerName = wsMeta.CustomerName
|
|
ctx.Project.DeviceType = wsMeta.DeviceType
|
|
ctx.Project.IntendedUse = wsMeta.IntendedUse
|
|
ctx.Project.TargetMarket = wsMeta.TargetMarket
|
|
ctx.Project.CurrentWorkflow = wsMeta.TaskKey
|
|
}
|
|
}
|
|
|
|
// 2. 尝试读取 blackboard.json
|
|
bbPath := filepath.Join(workDir, "blackboard.json")
|
|
if data, err := os.ReadFile(bbPath); err == nil {
|
|
var bb squad.BlackboardState
|
|
if json.Unmarshal(data, &bb) == nil {
|
|
for k, v := range bb.Fields {
|
|
ctx.BlackboardFacts[k] = v
|
|
}
|
|
for _, g := range bb.Gaps {
|
|
if g.Blocking && !g.Resolved {
|
|
ctx.Pending.ConfirmModifications = append(ctx.Pending.ConfirmModifications, g.Item)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 尝试提取阶段与文档
|
|
if ctx.Project.CurrentStage == "" {
|
|
ctx.Project.CurrentStage = bizdev.StageV01_Triage
|
|
}
|
|
ctx.AvailableActions = ComputeAvailableActions(ctx.Project.CurrentStage, user.ProjectRole)
|
|
|
|
// 4. 若有 output.md,尝试提取最新的参谋简报
|
|
outPath := filepath.Join(workDir, "output.md")
|
|
if outBytes, err := os.ReadFile(outPath); err == nil && len(outBytes) > 0 {
|
|
ctx.LatestAdvisorBrief = squad.ExtractAdvisorBriefing(ctx.Project.CurrentWorkflow, string(outBytes), ctx.BlackboardFacts)
|
|
ctx.UserDocs.Composed = append(ctx.UserDocs.Composed, ctx.Project.CurrentWorkflow)
|
|
}
|
|
|
|
return ctx, nil
|
|
}
|