feat: remove deprecated service and types, and refactor tool search request handling
This commit is contained in:
@@ -1,31 +0,0 @@
|
|||||||
package app
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
applicationruntime "cs-agent/internal/ai/application/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Service struct {
|
|
||||||
app *applicationruntime.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewService() *Service {
|
|
||||||
return &Service{
|
|
||||||
app: applicationruntime.NewService(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
|
|
||||||
if s == nil || s.app == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return s.app.Run(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, error) {
|
|
||||||
if s == nil || s.app == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return s.app.Resume(ctx, req)
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package app
|
|
||||||
|
|
||||||
import applicationruntime "cs-agent/internal/ai/application/runtime"
|
|
||||||
|
|
||||||
type Request = applicationruntime.Request
|
|
||||||
type ResumeRequest = applicationruntime.ResumeRequest
|
|
||||||
type InterruptContextSummary = applicationruntime.InterruptContextSummary
|
|
||||||
type Summary = applicationruntime.Summary
|
|
||||||
@@ -24,6 +24,13 @@ type CreateTicketGraphInterruptInfo struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type createTicketGraphArgs struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Priority int64 `json:"priority"`
|
||||||
|
Severity int `json:"severity"`
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
schema.RegisterName[CreateTicketGraphState]("cs_agent_create_ticket_graph_state")
|
schema.RegisterName[CreateTicketGraphState]("cs_agent_create_ticket_graph_state")
|
||||||
schema.RegisterName[CreateTicketGraphInterruptInfo]("cs_agent_create_ticket_graph_interrupt_info")
|
schema.RegisterName[CreateTicketGraphInterruptInfo]("cs_agent_create_ticket_graph_interrupt_info")
|
||||||
@@ -99,16 +106,16 @@ func (g *CreateTicketGraph) buildCreateRequest(argumentsInJSON string) (request.
|
|||||||
ConversationID: g.conversation.ID,
|
ConversationID: g.conversation.ID,
|
||||||
SyncToConversation: true,
|
SyncToConversation: true,
|
||||||
}
|
}
|
||||||
raw := make(map[string]any)
|
var args createTicketGraphArgs
|
||||||
if strings.TrimSpace(argumentsInJSON) != "" {
|
if strings.TrimSpace(argumentsInJSON) != "" {
|
||||||
if err := json.Unmarshal([]byte(argumentsInJSON), &raw); err != nil {
|
if err := json.Unmarshal([]byte(argumentsInJSON), &args); err != nil {
|
||||||
return req, fmt.Errorf("invalid create ticket arguments: %w", err)
|
return req, fmt.Errorf("invalid create ticket arguments: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req.Title = strings.TrimSpace(getStringValue(raw, "title"))
|
req.Title = strings.TrimSpace(args.Title)
|
||||||
req.Description = strings.TrimSpace(getStringValue(raw, "description"))
|
req.Description = strings.TrimSpace(args.Description)
|
||||||
req.Priority = getInt64Value(raw, "priority")
|
req.Priority = args.Priority
|
||||||
req.Severity = int(getInt64Value(raw, "severity"))
|
req.Severity = args.Severity
|
||||||
if req.Title == "" {
|
if req.Title == "" {
|
||||||
req.Title = strings.TrimSpace(g.conversation.Subject)
|
req.Title = strings.TrimSpace(g.conversation.Subject)
|
||||||
}
|
}
|
||||||
@@ -137,35 +144,3 @@ func (g *CreateTicketGraph) buildAIPrincipal() *dto.AuthPrincipal {
|
|||||||
Nickname: username,
|
Nickname: username,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStringValue(data map[string]any, key string) string {
|
|
||||||
if len(data) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
value, ok := data[key]
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
text, _ := value.(string)
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInt64Value(data map[string]any, key string) int64 {
|
|
||||||
if len(data) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
value, ok := data[key]
|
|
||||||
if !ok {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
switch v := value.(type) {
|
|
||||||
case float64:
|
|
||||||
return int64(v)
|
|
||||||
case int64:
|
|
||||||
return v
|
|
||||||
case int:
|
|
||||||
return int64(v)
|
|
||||||
default:
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package graphs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"cs-agent/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateTicketGraphBuildCreateRequest(t *testing.T) {
|
||||||
|
graph := NewCreateTicketGraph(&models.Conversation{
|
||||||
|
ID: 12,
|
||||||
|
Subject: "fallback-title",
|
||||||
|
LastMessageSummary: "fallback-description",
|
||||||
|
}, &models.AIAgent{Name: "AI"})
|
||||||
|
|
||||||
|
req, err := graph.buildCreateRequest(`{"title":" test title ","description":" desc ","priority":2,"severity":3}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("buildCreateRequest returned error: %v", err)
|
||||||
|
}
|
||||||
|
if req.Title != "test title" || req.Description != "desc" {
|
||||||
|
t.Fatalf("unexpected request text fields: %#v", req)
|
||||||
|
}
|
||||||
|
if req.Priority != 2 || req.Severity != 3 {
|
||||||
|
t.Fatalf("unexpected request numeric fields: %#v", req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateTicketGraphBuildCreateRequestFallbacks(t *testing.T) {
|
||||||
|
graph := NewCreateTicketGraph(&models.Conversation{
|
||||||
|
ID: 12,
|
||||||
|
Subject: "fallback-title",
|
||||||
|
LastMessageSummary: "fallback-description",
|
||||||
|
}, &models.AIAgent{Name: "AI"})
|
||||||
|
|
||||||
|
req, err := graph.buildCreateRequest(`{}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("buildCreateRequest returned error: %v", err)
|
||||||
|
}
|
||||||
|
if req.Title != "fallback-title" {
|
||||||
|
t.Fatalf("unexpected fallback title: %#v", req)
|
||||||
|
}
|
||||||
|
if req.Description != "fallback-description" {
|
||||||
|
t.Fatalf("unexpected fallback description: %#v", req)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package engine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
runtimeeino "cs-agent/internal/ai/infra/eino"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Service struct {
|
|
||||||
executor *runtimeeino.RuntimeExecutor
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewService() *Service {
|
|
||||||
return &Service{
|
|
||||||
executor: runtimeeino.NewRuntimeExecutor(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
|
|
||||||
return s.ExecuteRun(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ExecuteRun(ctx context.Context, req RunInput) (*RunResult, error) {
|
|
||||||
return s.executor.ExecuteRun(ctx, runtimeeino.RunInput(req))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, error) {
|
|
||||||
return s.ExecuteResume(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ExecuteResume(ctx context.Context, req ResumeInput) (*RunResult, error) {
|
|
||||||
return s.executor.ExecuteResume(ctx, runtimeeino.ResumeInput(req))
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package engine
|
|
||||||
|
|
||||||
import runtimeeino "cs-agent/internal/ai/infra/eino"
|
|
||||||
|
|
||||||
// TODO 这个地方为什么要定义类型别名,不能直接用吗?
|
|
||||||
type RunInput = runtimeeino.RunInput
|
|
||||||
type ResumeInput = runtimeeino.ResumeInput
|
|
||||||
type InterruptContextSummary = runtimeeino.InterruptContextSummary
|
|
||||||
type RunResult = runtimeeino.RunResult
|
|
||||||
|
|
||||||
type Request = RunInput
|
|
||||||
type ResumeRequest = ResumeInput
|
|
||||||
type Summary = RunResult
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package executor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
publicexecutor "cs-agent/internal/ai/runtime/executor"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Service struct {
|
|
||||||
inner *publicexecutor.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewService() *Service {
|
|
||||||
return &Service{
|
|
||||||
inner: publicexecutor.NewService(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ExecuteRun(ctx context.Context, req RunInput) (*RunResult, error) {
|
|
||||||
if s == nil || s.inner == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return s.inner.ExecuteRun(ctx, publicexecutor.RunInput(req))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) ExecuteResume(ctx context.Context, req ResumeInput) (*RunResult, error) {
|
|
||||||
if s == nil || s.inner == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return s.inner.ExecuteResume(ctx, publicexecutor.ResumeInput(req))
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package executor
|
|
||||||
|
|
||||||
import publicexecutor "cs-agent/internal/ai/runtime/executor"
|
|
||||||
|
|
||||||
type RunInput = publicexecutor.RunInput
|
|
||||||
type ResumeInput = publicexecutor.ResumeInput
|
|
||||||
type InterruptContextSummary = publicexecutor.InterruptContextSummary
|
|
||||||
type RunResult = publicexecutor.RunResult
|
|
||||||
@@ -104,9 +104,9 @@ func (t *ToolSearchTool) InvokableRun(ctx context.Context, argumentsInJSON strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
type toolSearchRequest struct {
|
type toolSearchRequest struct {
|
||||||
Query string
|
Query string `json:"query"`
|
||||||
ToolCode string
|
ToolCode string `json:"toolCode"`
|
||||||
Arguments map[string]any
|
Arguments map[string]any `json:"arguments"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type toolSearchCandidate struct {
|
type toolSearchCandidate struct {
|
||||||
@@ -122,22 +122,16 @@ func parseToolSearchRequest(argumentsInJSON string) (*toolSearchRequest, error)
|
|||||||
if argumentsInJSON == "" {
|
if argumentsInJSON == "" {
|
||||||
return &toolSearchRequest{}, nil
|
return &toolSearchRequest{}, nil
|
||||||
}
|
}
|
||||||
raw := make(map[string]any)
|
var req toolSearchRequest
|
||||||
if err := json.Unmarshal([]byte(argumentsInJSON), &raw); err != nil {
|
if err := json.Unmarshal([]byte(argumentsInJSON), &req); err != nil {
|
||||||
return nil, fmt.Errorf("invalid tool_search arguments: %w", err)
|
return nil, fmt.Errorf("invalid tool_search arguments: %w", err)
|
||||||
}
|
}
|
||||||
req := &toolSearchRequest{
|
req.Query = strings.TrimSpace(req.Query)
|
||||||
Query: strings.TrimSpace(getStringValue(raw, "query")),
|
req.ToolCode = strings.TrimSpace(req.ToolCode)
|
||||||
ToolCode: strings.TrimSpace(getStringValue(raw, "toolCode")),
|
if req.Arguments == nil {
|
||||||
|
req.Arguments = map[string]any{}
|
||||||
}
|
}
|
||||||
if value, ok := raw["arguments"]; ok {
|
return &req, nil
|
||||||
args, ok := value.(map[string]any)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("tool_search arguments must be an object")
|
|
||||||
}
|
|
||||||
req.Arguments = args
|
|
||||||
}
|
|
||||||
return req, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ToolSearchTool) searchCandidates(ctx context.Context, query string) (string, error) {
|
func (t *ToolSearchTool) searchCandidates(ctx context.Context, query string) (string, error) {
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestParseToolSearchRequest(t *testing.T) {
|
||||||
|
req, err := parseToolSearchRequest(`{"query":" search docs ","toolCode":" mcp_server/search ","arguments":{"q":"hello"}}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseToolSearchRequest returned error: %v", err)
|
||||||
|
}
|
||||||
|
if req.Query != "search docs" {
|
||||||
|
t.Fatalf("unexpected query: %q", req.Query)
|
||||||
|
}
|
||||||
|
if req.ToolCode != "mcp_server/search" {
|
||||||
|
t.Fatalf("unexpected toolCode: %q", req.ToolCode)
|
||||||
|
}
|
||||||
|
if req.Arguments["q"] != "hello" {
|
||||||
|
t.Fatalf("unexpected arguments: %#v", req.Arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseToolSearchRequestDefaultsArguments(t *testing.T) {
|
||||||
|
req, err := parseToolSearchRequest(`{"query":"list"}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parseToolSearchRequest returned error: %v", err)
|
||||||
|
}
|
||||||
|
if req.Arguments == nil {
|
||||||
|
t.Fatalf("expected non-nil arguments map")
|
||||||
|
}
|
||||||
|
if len(req.Arguments) != 0 {
|
||||||
|
t.Fatalf("expected empty arguments map, got %#v", req.Arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user