Class: NeuronAiChatbot::ApiIntentValidator

Inherits:
Object
  • Object
show all
Defined in:
app/services/neuron_ai_chatbot/api_intent_validator.rb

Class Method Summary collapse

Class Method Details

.find_catalog_row(catalog, request_path, method) ⇒ Object



35
36
37
38
39
# File 'app/services/neuron_ai_chatbot/api_intent_validator.rb', line 35

def self.find_catalog_row(catalog, request_path, method)
  catalog.find do |row|
    row[:method].to_s.upcase == method && path_matches_template?(request_path, row[:endpoint].to_s)
  end
end

.merge_path_params(template_path, request_path, params) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'app/services/neuron_ai_chatbot/api_intent_validator.rb', line 55

def self.merge_path_params(template_path, request_path, params)
  return params unless template_path.include?("{id}")

  out = params.dup
  return out if present_param?(out, "id")

  req_segments = request_path.split("/")
  tpl_segments = template_path.split("/")
  tpl_segments.each_with_index do |seg, i|
    if seg == "{id}" && req_segments[i].to_s.match?(/\A\d+\z/)
      out["id"] = req_segments[i]
      break
    end
  end
  out
end

.normalize_endpoint(ep) ⇒ Object



72
73
74
# File 'app/services/neuron_ai_chatbot/api_intent_validator.rb', line 72

def self.normalize_endpoint(ep)
  ep.to_s.sub(/\A(GET|POST|PUT|PATCH|DELETE)\s+/i, "").strip
end

.path_matches_template?(request_path, template_path) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/services/neuron_ai_chatbot/api_intent_validator.rb', line 41

def self.path_matches_template?(request_path, template_path)
  return true if request_path == template_path

  return false unless template_path.include?("{id}")

  req_segments = request_path.split("/")
  tpl_segments = template_path.split("/")
  return false unless req_segments.length == tpl_segments.length

  req_segments.zip(tpl_segments).all? do |req_seg, tpl_seg|
    tpl_seg == "{id}" ? req_seg.match?(/\A\d+\z/) : req_seg == tpl_seg
  end
end

.present_param?(params, key) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
79
80
81
82
# File 'app/services/neuron_ai_chatbot/api_intent_validator.rb', line 76

def self.present_param?(params, key)
  val = params[key]
  return false if val.nil?
  return false if val.is_a?(String) && val.strip.blank?

  true
end

.validate(ai_output, catalog = nil) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'app/services/neuron_ai_chatbot/api_intent_validator.rb', line 5

def self.validate(ai_output, catalog = nil)
  catalog ||= NeuronAiChatbot.api_knowledge_array
  return nil if catalog.blank?
  return nil if ai_output.is_a?(Hash) && ai_output["error"].present?

  endpoint = normalize_endpoint(ai_output["endpoint"])
  method   = ai_output["method"].to_s.upcase
  params   = (ai_output["params"] || {}).stringify_keys.dup

  match = find_catalog_row(catalog, endpoint, method)
  return nil if match.nil?

  template_path = match[:endpoint].to_s
  effective_params = merge_path_params(template_path, endpoint, params)

  required = Array(match[:required]).map(&:to_s)
  missing = required.reject { |k| present_param?(effective_params, k) }

  return nil if missing.empty?

  {
    status: 400,
    body:   {
      "error"            => "Missing required parameters for #{method} #{endpoint}.",
      "missing_required" => missing,
      "required_fields"  => required
    }
  }
end