Module: Legion::LLM::API::Namespaces::Helpers

Includes:
ErrorTranslator, SharedHelpers
Defined in:
lib/legion/llm/api/namespaces/helpers.rb

Instance Method Summary collapse

Methods included from ErrorTranslator

#translate_escalation_exhausted, #translate_invalid_header, #translate_no_lane_available, #translate_routing_rejected

Methods included from SharedHelpers

#api_context_stats, #api_duration_ms, #api_hash_value, #api_provider_latency_ms, #api_stop_reason, #api_thinking_tokens, #api_token_value, #api_tool_execution_count, #build_client_tool_class, #build_response_metrics, #build_server_caller, #build_tool_definitions, #cache_available?, #caller_client_string, #detect_caller_client, #detect_modality, #emit_response_tool_call_events, #emit_sse_event, #emit_timeline_tool_events, #extract_text_content, #extract_tool_calls, #identity_caller_hash, #identity_canonical_name, #identity_request_from_env, #json_error, #json_response, #log_api_completion_summary, #log_native_inference_response, #openai_tool_call_arguments, #openai_tool_call_name, #parse_request_body, #require_llm!, #returned_client_tool_call_payload, #set_routing_response_headers, #token_value, #validate_messages!, #validate_required!, #validate_tools!

Instance Method Details

#anthropic_error(error_type, message, status_code: 500) ⇒ Object



25
26
27
28
29
# File 'lib/legion/llm/api/namespaces/helpers.rb', line 25

def anthropic_error(error_type, message, status_code: 500)
  content_type :json
  status status_code
  Legion::JSON.dump({ type: 'error', error: { type: error_type, message: message } })
end

#data_subsystem_available?Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
# File 'lib/legion/llm/api/namespaces/helpers.rb', line 73

def data_subsystem_available?
  defined?(Legion::Data) && Legion::Data.respond_to?(:connected?) && Legion::Data.connected?
rescue StandardError => e
  log.debug "[llm][api][namespaces][helpers] action=data_subsystem_check_fallback error=#{e.class} message=#{e.message}"
  false
end

#detect_client(rack_env) ⇒ Object



31
32
33
34
35
36
# File 'lib/legion/llm/api/namespaces/helpers.rb', line 31

def detect_client(rack_env)
  return :anthropic if rack_env['HTTP_ANTHROPIC_VERSION']
  return :anthropic if rack_env['HTTP_X_API_KEY'] && !rack_env['HTTP_AUTHORIZATION']

  :openai
end

#openai_error(message, type: 'server_error', code: nil, param: nil, status_code: 500) ⇒ Object

OpenAI error envelope — ALWAYS carries all four keys (message, type, param, code); param/code are null when not applicable.



18
19
20
21
22
23
# File 'lib/legion/llm/api/namespaces/helpers.rb', line 18

def openai_error(message, type: 'server_error', code: nil, param: nil, status_code: 500)
  content_type :json
  status status_code
  body = { error: { message: message, type: type, param: param, code: code } }
  Legion::JSON.dump(body)
end

#require_data!Object



38
39
40
41
42
43
44
45
# File 'lib/legion/llm/api/namespaces/helpers.rb', line 38

def require_data!
  return if data_subsystem_available?

  halt 503, { 'Content-Type' => 'application/json' },
       Legion::JSON.dump({ error: { code:    'data_required',
                                    message: 'Legion::Data is required for this operation',
                                    type:    'server_error' } })
end

#validate_legion_routing_headers!(rack_env) ⇒ Object

G31 / opus M7: validate x-legion-* routing headers against Taxonomies at ingress. Raises Errors::InvalidHeader if any header contains an unknown value. Called by inference routes before building the executor request.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/legion/llm/api/namespaces/helpers.rb', line 50

def validate_legion_routing_headers!(rack_env)
  http_headers = rack_env.select { |k, _| k.start_with?('HTTP_') }

  # Build a flat header map from Rack env (HTTP_X_LEGION_TIERS → x-legion-tiers)
  mapped = http_headers.each_with_object({}) do |(k, v), h|
    h[k.sub(/^HTTP_/, '').downcase.tr('_', '-')] = v
  end

  # Validate each x-legion taxonomy header
  {
    'x-legion-tiers' => Legion::Extensions::Llm::Taxonomies::TIERS
  }.each do |header_name, taxonomy|
    Legion::LLM::Inference::Executor::PayloadBuilder.parse_and_validate_header(
      headers: mapped, name: header_name, taxonomy: taxonomy
    )
  end
rescue Legion::LLM::Errors::InvalidHeader
  raise
rescue StandardError => e
  handle_exception(e, level: :warn, handled: true, operation: 'llm.api.validate_legion_routing_headers')
  nil
end