query.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package tools
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/vektah/gqlparser/v2"
  7. "github.com/vektah/gqlparser/v2/ast"
  8. "gogs.dmsc.dev/arp/graph"
  9. )
  10. // Query executes a GraphQL query
  11. func Query(ctx context.Context, resolver *graph.Resolver, schema *ast.Schema, args map[string]interface{}) (CallToolResult, error) {
  12. queryStr, ok := args["query"].(string)
  13. if !ok {
  14. return CallToolResult{
  15. Content: []ContentBlock{
  16. {Type: "text", Text: "Missing required 'query' parameter"},
  17. },
  18. IsError: true,
  19. }, nil
  20. }
  21. // Parse variables
  22. variables := make(map[string]interface{})
  23. if v, ok := args["variables"].(map[string]interface{}); ok {
  24. variables = v
  25. }
  26. // Parse the query
  27. queryDoc, err := gqlparser.LoadQuery(schema, queryStr)
  28. if err != nil {
  29. return CallToolResult{
  30. Content: []ContentBlock{
  31. {Type: "text", Text: fmt.Sprintf("Query parse error: %v", err)},
  32. },
  33. IsError: true,
  34. }, nil
  35. }
  36. // Execute each operation
  37. var results []interface{}
  38. for _, op := range queryDoc.Operations {
  39. if op.Operation != ast.Query {
  40. continue
  41. }
  42. result, errMsg := executeQuery(ctx, resolver, schema, queryDoc, op, variables)
  43. if errMsg != "" {
  44. return CallToolResult{
  45. Content: []ContentBlock{
  46. {Type: "text", Text: errMsg},
  47. },
  48. IsError: true,
  49. }, nil
  50. }
  51. results = append(results, result)
  52. }
  53. // Format response
  54. var responseText string
  55. if len(results) == 1 {
  56. bytes, _ := json.MarshalIndent(results[0], "", " ")
  57. responseText = string(bytes)
  58. } else {
  59. bytes, _ := json.MarshalIndent(results, "", " ")
  60. responseText = string(bytes)
  61. }
  62. return CallToolResult{
  63. Content: []ContentBlock{
  64. {Type: "text", Text: responseText},
  65. },
  66. }, nil
  67. }
  68. 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) {
  69. result := make(map[string]interface{})
  70. for _, sel := range op.SelectionSet {
  71. field, ok := sel.(*ast.Field)
  72. if !ok {
  73. continue
  74. }
  75. value, errMsg := resolveQueryField(ctx, resolver, schema, field, variables)
  76. if errMsg != "" {
  77. return nil, errMsg
  78. }
  79. result[field.Alias] = value
  80. }
  81. return result, ""
  82. }
  83. func resolveQueryField(ctx context.Context, resolver *graph.Resolver, schema *ast.Schema, field *ast.Field, variables map[string]interface{}) (interface{}, string) {
  84. // Get field arguments
  85. args := make(map[string]interface{})
  86. for _, arg := range field.Arguments {
  87. value, err := arg.Value.Value(variables)
  88. if err != nil {
  89. return nil, fmt.Sprintf("failed to evaluate argument %s: %v", arg.Name, err)
  90. }
  91. args[arg.Name] = value
  92. }
  93. // Resolve based on field name
  94. switch field.Name {
  95. case "users":
  96. users, err := resolver.Query().Users(ctx)
  97. if err != nil {
  98. return nil, err.Error()
  99. }
  100. return users, ""
  101. case "user":
  102. id, _ := args["id"].(string)
  103. user, err := resolver.Query().User(ctx, id)
  104. if err != nil {
  105. return nil, err.Error()
  106. }
  107. return user, ""
  108. case "notes":
  109. notes, err := resolver.Query().Notes(ctx)
  110. if err != nil {
  111. return nil, err.Error()
  112. }
  113. return notes, ""
  114. case "note":
  115. id, _ := args["id"].(string)
  116. note, err := resolver.Query().Note(ctx, id)
  117. if err != nil {
  118. return nil, err.Error()
  119. }
  120. return note, ""
  121. case "roles":
  122. roles, err := resolver.Query().Roles(ctx)
  123. if err != nil {
  124. return nil, err.Error()
  125. }
  126. return roles, ""
  127. case "role":
  128. id, _ := args["id"].(string)
  129. role, err := resolver.Query().Role(ctx, id)
  130. if err != nil {
  131. return nil, err.Error()
  132. }
  133. return role, ""
  134. case "permissions":
  135. perms, err := resolver.Query().Permissions(ctx)
  136. if err != nil {
  137. return nil, err.Error()
  138. }
  139. return perms, ""
  140. case "permission":
  141. id, _ := args["id"].(string)
  142. perm, err := resolver.Query().Permission(ctx, id)
  143. if err != nil {
  144. return nil, err.Error()
  145. }
  146. return perm, ""
  147. case "services":
  148. services, err := resolver.Query().Services(ctx)
  149. if err != nil {
  150. return nil, err.Error()
  151. }
  152. return services, ""
  153. case "service":
  154. id, _ := args["id"].(string)
  155. service, err := resolver.Query().Service(ctx, id)
  156. if err != nil {
  157. return nil, err.Error()
  158. }
  159. return service, ""
  160. case "tasks":
  161. tasks, err := resolver.Query().Tasks(ctx)
  162. if err != nil {
  163. return nil, err.Error()
  164. }
  165. return tasks, ""
  166. case "task":
  167. id, _ := args["id"].(string)
  168. task, err := resolver.Query().Task(ctx, id)
  169. if err != nil {
  170. return nil, err.Error()
  171. }
  172. return task, ""
  173. case "taskStatuses":
  174. statuses, err := resolver.Query().TaskStatuses(ctx)
  175. if err != nil {
  176. return nil, err.Error()
  177. }
  178. return statuses, ""
  179. case "taskStatus":
  180. id, _ := args["id"].(string)
  181. status, err := resolver.Query().TaskStatus(ctx, id)
  182. if err != nil {
  183. return nil, err.Error()
  184. }
  185. return status, ""
  186. case "messages":
  187. messages, err := resolver.Query().Messages(ctx)
  188. if err != nil {
  189. return nil, err.Error()
  190. }
  191. return messages, ""
  192. case "message":
  193. id, _ := args["id"].(string)
  194. message, err := resolver.Query().Message(ctx, id)
  195. if err != nil {
  196. return nil, err.Error()
  197. }
  198. return message, ""
  199. default:
  200. return nil, fmt.Sprintf("unknown field: %s", field.Name)
  201. }
  202. }