feat(skill): refactor RuntimeContext to use AIAgent and AIConfig directly, removing contextLoader

This commit is contained in:
mlogclub
2026-04-17 17:37:36 +08:00
parent d5d1956964
commit 3b062c327c
6 changed files with 35 additions and 53 deletions
@@ -22,7 +22,8 @@ func (s *prepareService) selectSkill(ctx context.Context, req Request) (*models.
return nil, "", "", nil return nil, "", "", nil
} }
result, err := skills.Select(ctx, skills.RuntimeContext{ result, err := skills.Select(ctx, skills.RuntimeContext{
AIAgentID: req.AIAgent.ID, AIAgent: req.AIAgent,
AIConfig: req.AIConfig,
UserMessage: strings.TrimSpace(req.UserMessage.Content), UserMessage: strings.TrimSpace(req.UserMessage.Content),
ConversationID: req.Conversation.ID, ConversationID: req.Conversation.ID,
ManualSkillCode: strings.TrimSpace(req.ManualSkillCode), ManualSkillCode: strings.TrimSpace(req.ManualSkillCode),
-30
View File
@@ -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
}
+4 -3
View File
@@ -11,8 +11,9 @@ import (
func TestBuildRunLogMatchedPlan(t *testing.T) { func TestBuildRunLogMatchedPlan(t *testing.T) {
log := BuildRunLog( log := BuildRunLog(
RuntimeContext{ RuntimeContext{
AIAgent: &models.AIAgent{ID: 22},
AIConfig: &models.AIConfig{ID: 33},
ConversationID: 11, ConversationID: 11,
AIAgentID: 22,
ManualSkillCode: "manual_refund", ManualSkillCode: "manual_refund",
IntentCode: "refund", IntentCode: "refund",
UserMessage: "我要退款", UserMessage: "我要退款",
@@ -54,7 +55,7 @@ func TestBuildRunLogMatchedPlan(t *testing.T) {
func TestBuildRunLogNotMatchedAndError(t *testing.T) { func TestBuildRunLogNotMatchedAndError(t *testing.T) {
log := BuildRunLog( log := BuildRunLog(
RuntimeContext{ RuntimeContext{
AIAgentID: 22, AIAgent: &models.AIAgent{ID: 22},
UserMessage: "随便问问", UserMessage: "随便问问",
}, },
nil, nil,
@@ -73,7 +74,7 @@ func TestBuildRunLogNotMatchedAndError(t *testing.T) {
} }
noMatchLog := BuildRunLog( noMatchLog := BuildRunLog(
RuntimeContext{AIAgentID: 22, UserMessage: "随便问问"}, RuntimeContext{AIAgent: &models.AIAgent{ID: 22}, UserMessage: "随便问问"},
&ExecutionPlan{MatchReason: ""}, &ExecutionPlan{MatchReason: ""},
&ExecutionTrace{Status: "not_matched"}, &ExecutionTrace{Status: "not_matched"},
nil, nil,
+12 -13
View File
@@ -3,33 +3,32 @@ package skills
import ( import (
"context" "context"
"strings" "strings"
"cs-agent/internal/pkg/errorsx"
) )
func newPlanService() *planService { func newPlanService() *planService {
return &planService{ return &planService{}
loader: newContextLoader(),
}
} }
type planService struct { type planService struct{}
loader *contextLoader
}
// BuildExecutionPlan 构建当前请求的 Skill 执行计划。 // BuildExecutionPlan 构建当前请求的 Skill 执行计划。
func (s *planService) BuildExecutionPlan(execCtx context.Context, ctx RuntimeContext) (*ExecutionPlan, error) { func (s *planService) BuildExecutionPlan(execCtx context.Context, ctx RuntimeContext) (*ExecutionPlan, error) {
if s.loader == nil { if ctx.AIAgent == nil {
s.loader = newContextLoader() return nil, errorsx.InvalidParam("AIAgent不能为空")
} }
aiAgent, aiConfig, err := s.loader.loadAIAgentWithConfig(ctx.AIAgentID) if ctx.AIConfig == nil {
return nil, errorsx.InvalidParam("AIConfig不能为空")
skill, matchReason, routeTrace, err := MatchSkill(execCtx, ctx, aiAgent, aiConfig) }
skill, matchReason, routeTrace, err := MatchSkill(execCtx, ctx, ctx.AIAgent, ctx.AIConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &ExecutionPlan{ return &ExecutionPlan{
AIAgent: aiAgent, AIAgent: ctx.AIAgent,
AIConfig: aiConfig, AIConfig: ctx.AIConfig,
Skill: skill, Skill: skill,
MatchReason: strings.TrimSpace(matchReason), MatchReason: strings.TrimSpace(matchReason),
RouteTrace: routeTrace, RouteTrace: routeTrace,
+11 -1
View File
@@ -20,7 +20,7 @@ type RunLogService struct{}
func (s *RunLogService) Build(ctx RuntimeContext, plan *ExecutionPlan, trace *ExecutionTrace, err error) *models.SkillRunLog { func (s *RunLogService) Build(ctx RuntimeContext, plan *ExecutionPlan, trace *ExecutionTrace, err error) *models.SkillRunLog {
log := &models.SkillRunLog{ log := &models.SkillRunLog{
ConversationID: ctx.ConversationID, ConversationID: ctx.ConversationID,
AIAgentID: ctx.AIAgentID, AIAgentID: resolveRuntimeAIAgentID(ctx, plan),
ManualSkillCode: ctx.ManualSkillCode, ManualSkillCode: ctx.ManualSkillCode,
IntentCode: ctx.IntentCode, IntentCode: ctx.IntentCode,
UserMessage: ctx.UserMessage, UserMessage: ctx.UserMessage,
@@ -53,6 +53,16 @@ func (s *RunLogService) Build(ctx RuntimeContext, plan *ExecutionPlan, trace *Ex
return log 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 路由日志。 // Write 写入 Skill 路由日志。
func (s *RunLogService) Write(log *models.SkillRunLog) error { func (s *RunLogService) Write(log *models.SkillRunLog) error {
if log == nil { if log == nil {
+6 -5
View File
@@ -4,11 +4,12 @@ import "cs-agent/internal/models"
// RuntimeContext 表示一次 Skill 运行的输入上下文。 // RuntimeContext 表示一次 Skill 运行的输入上下文。
type RuntimeContext struct { type RuntimeContext struct {
AIAgentID int64 // AIAgentID 为当前请求所属的 AI Agent ID,必填。 AIAgent *models.AIAgent // AIAgent 为当前请求所属的 AI Agent,必填。
UserMessage string // UserMessage 为当前用户输入 AIConfig *models.AIConfig // AIConfig 为当前请求实际使用的模型配置,必填
ConversationID int64 // ConversationID 为当前会话 ID,无会话上下文时为 0 UserMessage string // UserMessage 为当前用户输入
ManualSkillCode string // ManualSkillCode 为显式指定的 Skill 编码 ConversationID int64 // ConversationID 为当前会话 ID,无会话上下文时为 0
IntentCode string // IntentCode 为上游识别出的意图编码。 ManualSkillCode string // ManualSkillCode 为显式指定的 Skill 编码。
IntentCode string // IntentCode 为上游识别出的意图编码。
} }
// ExecutionPlan 表示 Skill Runtime 计算出的最终路由结果。 // ExecutionPlan 表示 Skill Runtime 计算出的最终路由结果。