| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- package tools
- import (
- "context"
- "encoding/json"
- "fmt"
- "github.com/vektah/gqlparser/v2"
- "github.com/vektah/gqlparser/v2/ast"
- "gogs.dmsc.dev/arp/graph"
- )
- // Query executes a GraphQL query
- func Query(ctx context.Context, resolver *graph.Resolver, schema *ast.Schema, args map[string]interface{}) (CallToolResult, error) {
- queryStr, ok := args["query"].(string)
- if !ok {
- return CallToolResult{
- Content: []ContentBlock{
- {Type: "text", Text: "Missing required 'query' parameter"},
- },
- IsError: true,
- }, nil
- }
- // Parse variables
- variables := make(map[string]interface{})
- if v, ok := args["variables"].(map[string]interface{}); ok {
- variables = v
- }
- // Parse the query
- queryDoc, err := gqlparser.LoadQuery(schema, queryStr)
- if err != nil {
- return CallToolResult{
- Content: []ContentBlock{
- {Type: "text", Text: fmt.Sprintf("Query parse error: %v", err)},
- },
- IsError: true,
- }, nil
- }
- // Execute each operation
- var results []interface{}
- for _, op := range queryDoc.Operations {
- if op.Operation != ast.Query {
- continue
- }
- result, errMsg := executeQuery(ctx, resolver, schema, queryDoc, op, variables)
- if errMsg != "" {
- return CallToolResult{
- Content: []ContentBlock{
- {Type: "text", Text: errMsg},
- },
- IsError: true,
- }, nil
- }
- results = append(results, result)
- }
- // Format response
- var responseText string
- if len(results) == 1 {
- bytes, _ := json.MarshalIndent(results[0], "", " ")
- responseText = string(bytes)
- } else {
- bytes, _ := json.MarshalIndent(results, "", " ")
- responseText = string(bytes)
- }
- return CallToolResult{
- Content: []ContentBlock{
- {Type: "text", Text: responseText},
- },
- }, nil
- }
- func executeQuery(ctx context.Context, resolver *graph.Resolver, schema *ast.Schema, doc *ast.QueryDocument, op *ast.OperationDefinition, variables map[string]interface{}) (map[string]interface{}, string) {
- result := make(map[string]interface{})
- for _, sel := range op.SelectionSet {
- field, ok := sel.(*ast.Field)
- if !ok {
- continue
- }
- value, errMsg := resolveQueryField(ctx, resolver, schema, field, variables)
- if errMsg != "" {
- return nil, errMsg
- }
- result[field.Alias] = value
- }
- return result, ""
- }
- func resolveQueryField(ctx context.Context, resolver *graph.Resolver, schema *ast.Schema, field *ast.Field, variables map[string]interface{}) (interface{}, string) {
- // Get field arguments
- args := make(map[string]interface{})
- for _, arg := range field.Arguments {
- value, err := arg.Value.Value(variables)
- if err != nil {
- return nil, fmt.Sprintf("failed to evaluate argument %s: %v", arg.Name, err)
- }
- args[arg.Name] = value
- }
- // Resolve based on field name
- switch field.Name {
- case "users":
- users, err := resolver.Query().Users(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return users, ""
- case "user":
- id, _ := args["id"].(string)
- user, err := resolver.Query().User(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return user, ""
- case "notes":
- notes, err := resolver.Query().Notes(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return notes, ""
- case "note":
- id, _ := args["id"].(string)
- note, err := resolver.Query().Note(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return note, ""
- case "roles":
- roles, err := resolver.Query().Roles(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return roles, ""
- case "role":
- id, _ := args["id"].(string)
- role, err := resolver.Query().Role(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return role, ""
- case "permissions":
- perms, err := resolver.Query().Permissions(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return perms, ""
- case "permission":
- id, _ := args["id"].(string)
- perm, err := resolver.Query().Permission(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return perm, ""
- case "services":
- services, err := resolver.Query().Services(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return services, ""
- case "service":
- id, _ := args["id"].(string)
- service, err := resolver.Query().Service(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return service, ""
- case "tasks":
- tasks, err := resolver.Query().Tasks(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return tasks, ""
- case "task":
- id, _ := args["id"].(string)
- task, err := resolver.Query().Task(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return task, ""
- case "taskStatuses":
- statuses, err := resolver.Query().TaskStatuses(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return statuses, ""
- case "taskStatus":
- id, _ := args["id"].(string)
- status, err := resolver.Query().TaskStatus(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return status, ""
- case "messages":
- messages, err := resolver.Query().Messages(ctx)
- if err != nil {
- return nil, err.Error()
- }
- return messages, ""
- case "message":
- id, _ := args["id"].(string)
- message, err := resolver.Query().Message(ctx, id)
- if err != nil {
- return nil, err.Error()
- }
- return message, ""
- default:
- return nil, fmt.Sprintf("unknown field: %s", field.Name)
- }
- }
|