feat: Enhance AI Agent and Channel Management
- Updated labels in the AI Agents dashboard for clarity, changing "流程状态" to "Playbook 状态" and "未发布流程" to "未发布 Playbook". - Introduced AI Agent rollout percentage management in channel editing, allowing users to set and rollback rollout percentages. - Added new API endpoints for rolling back AI Agent rollout and fetching agent run metrics. - Implemented new UI components for displaying agent run details, including status, duration, and input/output tokens. - Enhanced type definitions for AdminChannel and AIAgent to include rollout percentages and runtime modes. - Updated navigation to include a section for agent runs. - Added new translations for agent run features in both English and Chinese.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"agent-desk/internal/models"
|
||||
"agent-desk/internal/repositories"
|
||||
|
||||
"github.com/mlogclub/simple/sqls"
|
||||
)
|
||||
|
||||
const (
|
||||
agentToolInvocationStatusRunning = "running"
|
||||
agentToolInvocationStatusCompleted = "completed"
|
||||
agentToolInvocationStatusFailed = "failed"
|
||||
)
|
||||
|
||||
var AgentToolInvocationService = newAgentToolInvocationService()
|
||||
|
||||
type AgentToolInvocationClaim struct {
|
||||
Item *models.AgentToolInvocation
|
||||
Completed bool
|
||||
Acquired bool
|
||||
}
|
||||
|
||||
type agentToolInvocationService struct{}
|
||||
|
||||
func newAgentToolInvocationService() *agentToolInvocationService {
|
||||
return &agentToolInvocationService{}
|
||||
}
|
||||
|
||||
// Claim obtains the persistent idempotency boundary. A completed invocation
|
||||
// can be returned to callers; an in-flight invocation is never executed again.
|
||||
func (s *agentToolInvocationService) Claim(conversationID, aiAgentID int64, toolCode, idempotencyKey string) (*AgentToolInvocationClaim, error) {
|
||||
toolCode = strings.TrimSpace(toolCode)
|
||||
idempotencyKey = strings.TrimSpace(idempotencyKey)
|
||||
if conversationID <= 0 || toolCode == "" || idempotencyKey == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if item := repositories.AgentToolInvocationRepository.GetByIdempotencyKey(sqls.DB(), conversationID, toolCode, idempotencyKey); item != nil {
|
||||
if item.Status == agentToolInvocationStatusCompleted {
|
||||
return &AgentToolInvocationClaim{Item: item, Completed: true}, nil
|
||||
}
|
||||
if item.Status == agentToolInvocationStatusRunning {
|
||||
return &AgentToolInvocationClaim{Item: item}, nil
|
||||
}
|
||||
if err := repositories.AgentToolInvocationRepository.Updates(sqls.DB(), item.ID, map[string]any{"status": agentToolInvocationStatusRunning, "error_message": "", "updated_at": time.Now()}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.Status, item.ErrorMessage = agentToolInvocationStatusRunning, ""
|
||||
return &AgentToolInvocationClaim{Item: item, Acquired: true}, nil
|
||||
}
|
||||
item := &models.AgentToolInvocation{ConversationID: conversationID, AIAgentID: aiAgentID, ToolCode: toolCode, IdempotencyKey: idempotencyKey, Status: agentToolInvocationStatusRunning}
|
||||
if err := repositories.AgentToolInvocationRepository.Create(sqls.DB(), item); err != nil {
|
||||
// A concurrent caller may have created the unique invocation first.
|
||||
if existing := repositories.AgentToolInvocationRepository.GetByIdempotencyKey(sqls.DB(), conversationID, toolCode, idempotencyKey); existing != nil {
|
||||
return &AgentToolInvocationClaim{Item: existing, Completed: existing.Status == agentToolInvocationStatusCompleted}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &AgentToolInvocationClaim{Item: item, Acquired: true}, nil
|
||||
}
|
||||
|
||||
func (s *agentToolInvocationService) Complete(item *models.AgentToolInvocation, resultData string) error {
|
||||
if item == nil || item.ID <= 0 {
|
||||
return nil
|
||||
}
|
||||
return repositories.AgentToolInvocationRepository.Updates(sqls.DB(), item.ID, map[string]any{"status": agentToolInvocationStatusCompleted, "result_data": resultData, "error_message": "", "updated_at": time.Now()})
|
||||
}
|
||||
|
||||
func (s *agentToolInvocationService) Fail(item *models.AgentToolInvocation, cause error) error {
|
||||
if item == nil || item.ID <= 0 {
|
||||
return nil
|
||||
}
|
||||
message := ""
|
||||
if cause != nil {
|
||||
message = cause.Error()
|
||||
}
|
||||
return repositories.AgentToolInvocationRepository.Updates(sqls.DB(), item.ID, map[string]any{"status": agentToolInvocationStatusFailed, "error_message": message, "updated_at": time.Now()})
|
||||
}
|
||||
Reference in New Issue
Block a user