feat: remove deprecated service and types, and refactor tool search request handling

This commit is contained in:
mlogclub
2026-04-14 11:07:26 +08:00
parent c12e75b6a1
commit 2211f29da7
10 changed files with 100 additions and 178 deletions
-31
View File
@@ -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)
}
-8
View File
@@ -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
+10 -16
View File
@@ -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)
}
}