From 3b062c327ca329fa42bc361b47772ffda66e04ce Mon Sep 17 00:00:00 2001 From: mlogclub Date: Fri, 17 Apr 2026 17:37:36 +0800 Subject: [PATCH] feat(skill): refactor RuntimeContext to use AIAgent and AIConfig directly, removing contextLoader --- .../ai/application/runtime/prepare_service.go | 3 +- internal/ai/skills/context_loader.go | 30 ------------------- internal/ai/skills/log_test.go | 7 +++-- internal/ai/skills/plan_service.go | 25 ++++++++-------- internal/ai/skills/runlog_service.go | 12 +++++++- internal/ai/skills/types.go | 11 +++---- 6 files changed, 35 insertions(+), 53 deletions(-) delete mode 100644 internal/ai/skills/context_loader.go diff --git a/internal/ai/application/runtime/prepare_service.go b/internal/ai/application/runtime/prepare_service.go index 07522c1..8a1b9f8 100644 --- a/internal/ai/application/runtime/prepare_service.go +++ b/internal/ai/application/runtime/prepare_service.go @@ -22,7 +22,8 @@ func (s *prepareService) selectSkill(ctx context.Context, req Request) (*models. return nil, "", "", nil } result, err := skills.Select(ctx, skills.RuntimeContext{ - AIAgentID: req.AIAgent.ID, + AIAgent: req.AIAgent, + AIConfig: req.AIConfig, UserMessage: strings.TrimSpace(req.UserMessage.Content), ConversationID: req.Conversation.ID, ManualSkillCode: strings.TrimSpace(req.ManualSkillCode), diff --git a/internal/ai/skills/context_loader.go b/internal/ai/skills/context_loader.go deleted file mode 100644 index accd6b4..0000000 --- a/internal/ai/skills/context_loader.go +++ /dev/null @@ -1,30 +0,0 @@ -package skills - -import ( - "cs-agent/internal/models" - "cs-agent/internal/pkg/errorsx" - "cs-agent/internal/repositories" - - "github.com/mlogclub/simple/sqls" -) - -func newContextLoader() *contextLoader { - return &contextLoader{} -} - -type contextLoader struct{} - -func (l *contextLoader) loadAIAgentWithConfig(aiAgentID int64) (*models.AIAgent, *models.AIConfig, error) { - if aiAgentID <= 0 { - return nil, nil, errorsx.InvalidParam("AIAgentID不能为空") - } - aiAgent := repositories.AIAgentRepository.Get(sqls.DB(), aiAgentID) - if aiAgent == nil { - return nil, nil, errorsx.InvalidParam("AI Agent不存在") - } - aiConfig := repositories.AIConfigRepository.Get(sqls.DB(), aiAgent.AIConfigID) - if aiConfig == nil { - return nil, nil, errorsx.InvalidParam("AI Agent关联的AI配置不存在") - } - return aiAgent, aiConfig, nil -} diff --git a/internal/ai/skills/log_test.go b/internal/ai/skills/log_test.go index bfa77f4..4db9261 100644 --- a/internal/ai/skills/log_test.go +++ b/internal/ai/skills/log_test.go @@ -11,8 +11,9 @@ import ( func TestBuildRunLogMatchedPlan(t *testing.T) { log := BuildRunLog( RuntimeContext{ + AIAgent: &models.AIAgent{ID: 22}, + AIConfig: &models.AIConfig{ID: 33}, ConversationID: 11, - AIAgentID: 22, ManualSkillCode: "manual_refund", IntentCode: "refund", UserMessage: "我要退款", @@ -54,7 +55,7 @@ func TestBuildRunLogMatchedPlan(t *testing.T) { func TestBuildRunLogNotMatchedAndError(t *testing.T) { log := BuildRunLog( RuntimeContext{ - AIAgentID: 22, + AIAgent: &models.AIAgent{ID: 22}, UserMessage: "随便问问", }, nil, @@ -73,7 +74,7 @@ func TestBuildRunLogNotMatchedAndError(t *testing.T) { } noMatchLog := BuildRunLog( - RuntimeContext{AIAgentID: 22, UserMessage: "随便问问"}, + RuntimeContext{AIAgent: &models.AIAgent{ID: 22}, UserMessage: "随便问问"}, &ExecutionPlan{MatchReason: ""}, &ExecutionTrace{Status: "not_matched"}, nil, diff --git a/internal/ai/skills/plan_service.go b/internal/ai/skills/plan_service.go index 9548a88..566df21 100644 --- a/internal/ai/skills/plan_service.go +++ b/internal/ai/skills/plan_service.go @@ -3,33 +3,32 @@ package skills import ( "context" "strings" + + "cs-agent/internal/pkg/errorsx" ) func newPlanService() *planService { - return &planService{ - loader: newContextLoader(), - } + return &planService{} } -type planService struct { - loader *contextLoader -} +type planService struct{} // BuildExecutionPlan 构建当前请求的 Skill 执行计划。 func (s *planService) BuildExecutionPlan(execCtx context.Context, ctx RuntimeContext) (*ExecutionPlan, error) { - if s.loader == nil { - s.loader = newContextLoader() + if ctx.AIAgent == nil { + return nil, errorsx.InvalidParam("AIAgent不能为空") } - aiAgent, aiConfig, err := s.loader.loadAIAgentWithConfig(ctx.AIAgentID) - - skill, matchReason, routeTrace, err := MatchSkill(execCtx, ctx, aiAgent, aiConfig) + if ctx.AIConfig == nil { + return nil, errorsx.InvalidParam("AIConfig不能为空") + } + skill, matchReason, routeTrace, err := MatchSkill(execCtx, ctx, ctx.AIAgent, ctx.AIConfig) if err != nil { return nil, err } return &ExecutionPlan{ - AIAgent: aiAgent, - AIConfig: aiConfig, + AIAgent: ctx.AIAgent, + AIConfig: ctx.AIConfig, Skill: skill, MatchReason: strings.TrimSpace(matchReason), RouteTrace: routeTrace, diff --git a/internal/ai/skills/runlog_service.go b/internal/ai/skills/runlog_service.go index 4a5fe45..ca4077a 100644 --- a/internal/ai/skills/runlog_service.go +++ b/internal/ai/skills/runlog_service.go @@ -20,7 +20,7 @@ type RunLogService struct{} func (s *RunLogService) Build(ctx RuntimeContext, plan *ExecutionPlan, trace *ExecutionTrace, err error) *models.SkillRunLog { log := &models.SkillRunLog{ ConversationID: ctx.ConversationID, - AIAgentID: ctx.AIAgentID, + AIAgentID: resolveRuntimeAIAgentID(ctx, plan), ManualSkillCode: ctx.ManualSkillCode, IntentCode: ctx.IntentCode, UserMessage: ctx.UserMessage, @@ -53,6 +53,16 @@ func (s *RunLogService) Build(ctx RuntimeContext, plan *ExecutionPlan, trace *Ex return log } +func resolveRuntimeAIAgentID(ctx RuntimeContext, plan *ExecutionPlan) int64 { + if ctx.AIAgent != nil { + return ctx.AIAgent.ID + } + if plan != nil && plan.AIAgent != nil { + return plan.AIAgent.ID + } + return 0 +} + // Write 写入 Skill 路由日志。 func (s *RunLogService) Write(log *models.SkillRunLog) error { if log == nil { diff --git a/internal/ai/skills/types.go b/internal/ai/skills/types.go index 1f9d247..3b71a9e 100644 --- a/internal/ai/skills/types.go +++ b/internal/ai/skills/types.go @@ -4,11 +4,12 @@ import "cs-agent/internal/models" // RuntimeContext 表示一次 Skill 运行的输入上下文。 type RuntimeContext struct { - AIAgentID int64 // AIAgentID 为当前请求所属的 AI Agent ID,必填。 - UserMessage string // UserMessage 为当前用户输入。 - ConversationID int64 // ConversationID 为当前会话 ID,无会话上下文时为 0。 - ManualSkillCode string // ManualSkillCode 为显式指定的 Skill 编码。 - IntentCode string // IntentCode 为上游识别出的意图编码。 + AIAgent *models.AIAgent // AIAgent 为当前请求所属的 AI Agent,必填。 + AIConfig *models.AIConfig // AIConfig 为当前请求实际使用的模型配置,必填。 + UserMessage string // UserMessage 为当前用户输入。 + ConversationID int64 // ConversationID 为当前会话 ID,无会话上下文时为 0。 + ManualSkillCode string // ManualSkillCode 为显式指定的 Skill 编码。 + IntentCode string // IntentCode 为上游识别出的意图编码。 } // ExecutionPlan 表示 Skill Runtime 计算出的最终路由结果。