Files
Agent-System/internal/chat/session.go
T

127 lines
4.3 KiB
Go

package chat
import (
"context"
"fmt"
"time"
"chat-agent-system/internal/coordinator"
"chat-agent-system/internal/intent"
"chat-agent-system/internal/squad"
)
// Message 历史消息结构
type Message struct {
ID string `json:"id"`
Role string `json:"role"` // "user" | "assistant"
Content string `json:"content"`
Intent intent.IntentType `json:"intent,omitempty"`
Branch intent.ResolutionBranch `json:"branch,omitempty"`
AdvisorBrief *squad.AdvisorBriefing `json:"advisor_brief,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
// ChatResponse 会话单轮响应
type ChatResponse struct {
ReplyText string `json:"reply_text"`
Branch intent.ResolutionBranch `json:"branch"`
IntentResult *intent.IntentRecognitionResult `json:"intent_result"`
CoordinationResult *coordinator.CoordinationResult `json:"coordination_result"`
AdvisorBrief *squad.AdvisorBriefing `json:"advisor_brief,omitempty"`
PendingExpectation *intent.PendingExpectation `json:"pending_expectation,omitempty"`
}
// Session 多轮对话与协同会话管理器
type Session struct {
ID string `json:"id"`
UserCtx *coordinator.UserProjectContext `json:"user_ctx"`
Recognizer intent.Recognizer `json:"-"`
Coordinator *coordinator.CoordinatorEngine `json:"-"`
Messages []Message `json:"messages"`
CreatedAt time.Time `json:"created_at"`
}
// NewSession 创建新对话会话
func NewSession(id string, userCtx *coordinator.UserProjectContext, rec intent.Recognizer, coord *coordinator.CoordinatorEngine) *Session {
if rec == nil {
rec = intent.NewRecognizer()
}
if id == "" {
id = fmt.Sprintf("sess_%d", time.Now().Unix())
}
// 若上下文尚未挂起预期且当前已具有阶段,则初始化默认选项草稿
if userCtx != nil && userCtx.PendingExpectation == nil && userCtx.Project.CurrentStage != "" {
userCtx.PendingExpectation = coordinator.BuildNextExpectation(userCtx.Project.CurrentStage, userCtx.Project.Name)
}
return &Session{
ID: id,
UserCtx: userCtx,
Recognizer: rec,
Coordinator: coord,
Messages: make([]Message, 0),
CreatedAt: time.Now(),
}
}
// SendMessage 处理一轮用户输入
func (s *Session) SendMessage(ctx context.Context, userInput string) (*ChatResponse, error) {
userMsg := Message{
ID: fmt.Sprintf("msg_%d_u", time.Now().UnixNano()),
Role: "user",
Content: userInput,
Timestamp: time.Now(),
}
s.Messages = append(s.Messages, userMsg)
// 1. 意图识别 (L1 对话层,带非阻塞桌角备忘快照)
var snap *intent.ContextSnapshot
if s.UserCtx != nil {
snap = s.UserCtx.ToSnapshot()
}
recRes, err := s.Recognizer.Recognize(ctx, userInput, snap)
if err != nil {
return nil, fmt.Errorf("intent recognition failed: %w", err)
}
// 2. 协调调度与校验 (L2 协调层)
coordRes, err := s.Coordinator.ProcessIntent(ctx, recRes, s.UserCtx)
if err != nil {
return nil, fmt.Errorf("coordination execution failed: %w", err)
}
// 3. 更新上下文与挂起预期生命周期
if coordRes.UpdatedContext != nil {
s.UserCtx = coordRes.UpdatedContext
}
if coordRes.ClearExpectation {
s.UserCtx.PendingExpectation = nil
} else if coordRes.NextExpectation != nil {
s.UserCtx.PendingExpectation = coordRes.NextExpectation
} else if recRes.Branch == intent.BranchExpectationHit {
s.UserCtx.PendingExpectation = nil
}
// 若为 BranchNewIntentPreempt 且未产生新预期,原挂起预期在焦点底静默保留,不阻拦用户
asstMsg := Message{
ID: fmt.Sprintf("msg_%d_a", time.Now().UnixNano()),
Role: "assistant",
Content: coordRes.NaturalReply,
Intent: coordRes.Intent,
Branch: recRes.Branch,
AdvisorBrief: coordRes.AdvisorBrief,
Timestamp: time.Now(),
}
s.Messages = append(s.Messages, asstMsg)
return &ChatResponse{
ReplyText: coordRes.NaturalReply,
Branch: recRes.Branch,
IntentResult: recRes,
CoordinationResult: coordRes,
AdvisorBrief: coordRes.AdvisorBrief,
PendingExpectation: s.UserCtx.PendingExpectation,
}, nil
}