178 lines
5.0 KiB
Go
178 lines
5.0 KiB
Go
package runtime
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"cs-agent/internal/ai/runtime/internal/engine"
|
|
"cs-agent/internal/ai/runtime/registry"
|
|
"cs-agent/internal/ai/runtime/tools"
|
|
"cs-agent/internal/ai/skills"
|
|
)
|
|
|
|
var Service = newService()
|
|
|
|
func newService() *service {
|
|
return &service{
|
|
runtime: engine.NewService(),
|
|
registry: registry.NewRegistry(
|
|
tools.NewCreateTicketConfirmTool(),
|
|
),
|
|
}
|
|
}
|
|
|
|
type service struct {
|
|
runtime *engine.Service
|
|
registry *registry.Registry
|
|
}
|
|
|
|
func (s *service) Run(ctx context.Context, req Request) (*Summary, error) {
|
|
skillSummary, skillErr := s.tryRunSkill(ctx, req)
|
|
if skillSummary != nil && strings.TrimSpace(skillSummary.ReplyText) != "" {
|
|
return skillSummary, nil
|
|
}
|
|
if err := s.prepareToolsForRun(&req); err != nil {
|
|
return nil, err
|
|
}
|
|
summary, err := s.runtime.Run(ctx, engine.Request{
|
|
Conversation: req.Conversation,
|
|
UserMessage: req.UserMessage,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
CheckPointID: req.CheckPointID,
|
|
ExtraTools: req.ExtraTools,
|
|
ExtraToolCodes: req.ExtraToolCodes,
|
|
})
|
|
if err != nil {
|
|
ret := toSummary(summary)
|
|
if ret != nil && skillErr != nil && strings.TrimSpace(ret.PlanReason) == "" {
|
|
ret.PlanReason = "skill_failed_fallback_runtime"
|
|
}
|
|
return ret, err
|
|
}
|
|
ret := toSummary(summary)
|
|
if ret != nil && skillErr != nil && strings.TrimSpace(ret.PlanReason) == "" {
|
|
ret.PlanReason = "skill_failed_fallback_runtime"
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (s *service) Resume(ctx context.Context, req ResumeRequest) (*Summary, error) {
|
|
if err := s.prepareToolsForResume(&req); err != nil {
|
|
return nil, err
|
|
}
|
|
summary, err := s.runtime.Resume(ctx, engine.ResumeRequest{
|
|
Conversation: req.Conversation,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
CheckPointID: req.CheckPointID,
|
|
ResumeData: req.ResumeData,
|
|
ExtraTools: req.ExtraTools,
|
|
ExtraToolCodes: req.ExtraToolCodes,
|
|
})
|
|
if err != nil {
|
|
return toSummary(summary), err
|
|
}
|
|
return toSummary(summary), nil
|
|
}
|
|
|
|
func (s *service) prepareToolsForRun(req *Request) error {
|
|
if req == nil || len(req.ExtraTools) > 0 || len(req.ExtraToolCodes) > 0 || s.registry == nil {
|
|
return nil
|
|
}
|
|
toolSet, err := s.registry.Resolve(registry.Context{
|
|
Conversation: req.Conversation,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
UserMessage: req.UserMessage,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.ExtraTools = toolSet.Tools
|
|
req.ExtraToolCodes = toolSet.ToolCodes
|
|
return nil
|
|
}
|
|
|
|
func (s *service) prepareToolsForResume(req *ResumeRequest) error {
|
|
if req == nil || len(req.ExtraTools) > 0 || len(req.ExtraToolCodes) > 0 || s.registry == nil {
|
|
return nil
|
|
}
|
|
toolSet, err := s.registry.Resolve(registry.Context{
|
|
Conversation: req.Conversation,
|
|
AIAgent: req.AIAgent,
|
|
AIConfig: req.AIConfig,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.ExtraTools = toolSet.Tools
|
|
req.ExtraToolCodes = toolSet.ToolCodes
|
|
return nil
|
|
}
|
|
|
|
func toSummary(summary *engine.Summary) *Summary {
|
|
if summary == nil {
|
|
return nil
|
|
}
|
|
ret := &Summary{
|
|
RunID: summary.RunID,
|
|
Status: summary.Status,
|
|
ReplyText: summary.ReplyText,
|
|
PlannedSkillCode: "",
|
|
PlanReason: "",
|
|
ModelName: summary.ModelName,
|
|
PromptTokens: summary.PromptTokens,
|
|
CompletionTokens: summary.CompletionTokens,
|
|
HistoryMessageCount: summary.HistoryMessageCount,
|
|
RetrieverCount: summary.RetrieverCount,
|
|
ToolCallCount: summary.ToolCallCount,
|
|
ToolCodes: append([]string(nil), summary.ToolCodes...),
|
|
InvokedToolCodes: append([]string(nil), summary.InvokedToolCodes...),
|
|
CheckPointID: summary.CheckPointID,
|
|
Interrupted: summary.Interrupted,
|
|
TraceData: summary.TraceData,
|
|
ErrorMessage: summary.ErrorMessage,
|
|
}
|
|
if len(summary.Interrupts) > 0 {
|
|
ret.Interrupts = make([]InterruptContextSummary, 0, len(summary.Interrupts))
|
|
for _, item := range summary.Interrupts {
|
|
ret.Interrupts = append(ret.Interrupts, InterruptContextSummary{
|
|
Type: item.Type,
|
|
ID: item.ID,
|
|
InfoPreview: item.InfoPreview,
|
|
})
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (s *service) tryRunSkill(ctx context.Context, req Request) (*Summary, error) {
|
|
if req.AIAgent == nil || req.AIConfig == nil || req.UserMessage == nil || req.Conversation == nil {
|
|
return nil, nil
|
|
}
|
|
result, err := skills.Execute(ctx, skills.RuntimeContext{
|
|
AIAgentID: req.AIAgent.ID,
|
|
UserMessage: strings.TrimSpace(req.UserMessage.Content),
|
|
ConversationID: req.Conversation.ID,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if result == nil || result.Plan == nil || result.Plan.Skill == nil {
|
|
return nil, nil
|
|
}
|
|
traceData := ""
|
|
if result.RunLog != nil {
|
|
traceData = result.RunLog.TraceData
|
|
}
|
|
return &Summary{
|
|
Status: "completed",
|
|
ReplyText: strings.TrimSpace(result.ReplyText),
|
|
PlannedSkillCode: strings.TrimSpace(result.Plan.Skill.Code),
|
|
PlanReason: strings.TrimSpace(result.Plan.MatchReason),
|
|
ModelName: req.AIConfig.ModelName,
|
|
TraceData: traceData,
|
|
}, nil
|
|
}
|