|
| 1 | +@tool |
| 2 | +extends RefCounted |
| 3 | + |
| 4 | +## Read-only access to version-correct Godot class metadata. |
| 5 | + |
| 6 | +const ErrorCodes := preload("res://addons/godot_ai/utils/error_codes.gd") |
| 7 | +const ClassIntrospection := preload("res://addons/godot_ai/utils/class_introspection.gd") |
| 8 | +const FuzzySuggestions := preload("res://addons/godot_ai/utils/fuzzy_suggestions.gd") |
| 9 | + |
| 10 | +func get_class_info(params: Dictionary) -> Dictionary: |
| 11 | + var requested_class: String = params.get("class_name", "") |
| 12 | + if requested_class.is_empty(): |
| 13 | + return ErrorCodes.make( |
| 14 | + ErrorCodes.MISSING_REQUIRED_PARAM, |
| 15 | + "Missing required param: class_name" |
| 16 | + ) |
| 17 | + if not ClassDB.class_exists(requested_class): |
| 18 | + var script_class := _global_script_class(requested_class) |
| 19 | + if not script_class.is_empty(): |
| 20 | + return _script_class_error(requested_class, script_class) |
| 21 | + return _unknown_class_error(requested_class) |
| 22 | + if params.has("limit") and int(params.get("limit")) < 0: |
| 23 | + return ErrorCodes.make( |
| 24 | + ErrorCodes.INVALID_PARAMS, |
| 25 | + "limit must be >= 0; use limit=0 only when an unlimited section is needed" |
| 26 | + ) |
| 27 | + var section_check := ClassIntrospection.validate_sections( |
| 28 | + params.get("sections", ClassIntrospection.DEFAULT_SECTIONS) |
| 29 | + ) |
| 30 | + if not section_check.invalid.is_empty(): |
| 31 | + return _invalid_sections_error(section_check.invalid) |
| 32 | + return {"data": ClassIntrospection.build(requested_class, params)} |
| 33 | + |
| 34 | + |
| 35 | +static func _unknown_class_error(requested_class: String) -> Dictionary: |
| 36 | + var suggestions := _suggest_classes(requested_class) |
| 37 | + var message := "Unknown Godot class: %s" % requested_class |
| 38 | + if not suggestions.is_empty(): |
| 39 | + message += ". Did you mean: %s?" % ", ".join(suggestions) |
| 40 | + var result := ErrorCodes.make(ErrorCodes.VALUE_OUT_OF_RANGE, message) |
| 41 | + result["error"]["data"] = {"suggestions": suggestions} |
| 42 | + return result |
| 43 | + |
| 44 | + |
| 45 | +static func _suggest_classes(requested_class: String) -> Array[String]: |
| 46 | + return FuzzySuggestions.rank(requested_class, ClassDB.get_class_list()) |
| 47 | + |
| 48 | + |
| 49 | +static func _global_script_class(requested_class: String) -> Dictionary: |
| 50 | + for raw_info in ProjectSettings.get_global_class_list(): |
| 51 | + var info: Dictionary = raw_info |
| 52 | + if info.get("class", "") == requested_class: |
| 53 | + return info |
| 54 | + return {} |
| 55 | + |
| 56 | + |
| 57 | +static func _script_class_error(requested_class: String, script_class: Dictionary) -> Dictionary: |
| 58 | + var path := str(script_class.get("path", "")) |
| 59 | + var base := str(script_class.get("base", "")) |
| 60 | + var message := ( |
| 61 | + "%s is a project script class, not a ClassDB class. " |
| 62 | + + "Use script_manage(op=\"find_symbols\", params={\"path\": \"%s\"}) for script symbols." |
| 63 | + ) % [requested_class, path] |
| 64 | + var result := ErrorCodes.make(ErrorCodes.WRONG_TYPE, message) |
| 65 | + result["error"]["data"] = { |
| 66 | + "script_class": true, |
| 67 | + "class_name": requested_class, |
| 68 | + "base_class": base, |
| 69 | + "path": path, |
| 70 | + } |
| 71 | + return result |
| 72 | + |
| 73 | + |
| 74 | +static func _invalid_sections_error(invalid_sections: Array[String]) -> Dictionary: |
| 75 | + var suggestions := {} |
| 76 | + for section in invalid_sections: |
| 77 | + suggestions[section] = FuzzySuggestions.rank( |
| 78 | + section, |
| 79 | + ClassIntrospection.KNOWN_SECTIONS, |
| 80 | + 3, |
| 81 | + 0.3 |
| 82 | + ) |
| 83 | + var message := "Unknown class-info section(s): %s. Valid sections: %s" % [ |
| 84 | + ", ".join(invalid_sections), |
| 85 | + ", ".join(ClassIntrospection.KNOWN_SECTIONS), |
| 86 | + ] |
| 87 | + var result := ErrorCodes.make(ErrorCodes.INVALID_PARAMS, message) |
| 88 | + result["error"]["data"] = {"suggestions": suggestions} |
| 89 | + return result |
0 commit comments