Module: Legion::TTY::DaemonClient
- Extended by:
- Logging::Helper
- Defined in:
- lib/legion/tty/daemon_client.rb
Constant Summary collapse
- SUCCESS_CODES =
[200, 201, 202].freeze
Class Method Summary collapse
- .available? ⇒ Boolean
- .cached_manifest ⇒ Object
- .chat(message:, model: nil, provider: nil) ⇒ Object
- .configure(daemon_url: 'http://127.0.0.1:4567', cache_file: nil, timeout: 5) ⇒ Object
- .fetch_manifest ⇒ Object
- .inference(messages:, tools: [], model: nil, provider: nil, timeout: 120) ⇒ Object
- .manifest ⇒ Object
- .match_intent(intent_text) ⇒ Object
- .reset! ⇒ Object
- .run_tool(name:, args: {}) ⇒ Object
Class Method Details
.available? ⇒ Boolean
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/legion/tty/daemon_client.rb', line 26 def available? uri = URI("#{daemon_url}/api/health") response = Net::HTTP.start(uri.hostname, uri.port, open_timeout: @timeout, read_timeout: @timeout) do |http| http.get(uri.path) end response.code.to_i == 200 rescue StandardError => e handle_exception(e, level: :debug, operation: 'tty.daemon_client.available?', daemon_url: daemon_url) false end |
.cached_manifest ⇒ Object
50 51 52 53 54 55 56 57 58 59 |
# File 'lib/legion/tty/daemon_client.rb', line 50 def cached_manifest return @manifest if @manifest return nil unless @cache_file && File.exist?(@cache_file) @manifest = Legion::JSON.load(File.read(@cache_file)) rescue StandardError => e handle_exception(e, level: :warn, operation: 'tty.daemon_client.cached_manifest', cache_file: @cache_file) nil end |
.chat(message:, model: nil, provider: nil) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/legion/tty/daemon_client.rb', line 79 def chat(message:, model: nil, provider: nil) return nil unless available? uri = URI("#{daemon_url}/api/llm/chat") payload = Legion::JSON.dump({ message: , model: model, provider: provider }) log.debug { "TTY chat request model=#{model} provider=#{provider} message_length=#{.to_s.length}" } response = post_json(uri, payload) return nil unless response && SUCCESS_CODES.include?(response.code.to_i) Legion::JSON.load(response.body) rescue StandardError => e handle_exception(e, level: :warn, operation: 'tty.daemon_client.chat', daemon_url: daemon_url, model: model, provider: provider) nil end |
.configure(daemon_url: 'http://127.0.0.1:4567', cache_file: nil, timeout: 5) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/legion/tty/daemon_client.rb', line 18 def configure(daemon_url: 'http://127.0.0.1:4567', cache_file: nil, timeout: 5) @daemon_url = daemon_url @cache_file = cache_file || File.('~/.legionio/catalog.json') @timeout = timeout @manifest = nil log.info { "TTY daemon client configured daemon_url=#{@daemon_url} timeout=#{@timeout}" } end |
.fetch_manifest ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/legion/tty/daemon_client.rb', line 37 def fetch_manifest uri = URI("#{daemon_url}/api/catalog") response = Net::HTTP.start(uri.hostname, uri.port, open_timeout: @timeout, read_timeout: @timeout) do |http| http.get(uri.path) end return nil unless response.code.to_i == 200 store_manifest(Legion::JSON.load(response.body)[:data]) rescue StandardError => e handle_exception(e, level: :warn, operation: 'tty.daemon_client.fetch_manifest', daemon_url: daemon_url) nil end |
.inference(messages:, tools: [], model: nil, provider: nil, timeout: 120) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/legion/tty/daemon_client.rb', line 96 def inference(messages:, tools: [], model: nil, provider: nil, timeout: 120) log.debug { "TTY inference model=#{model} provider=#{provider} msgs=#{Array().size}" } response = post_inference(messages: , tools: tools, model: model, provider: provider, timeout: timeout) return inference_error_result(response) unless SUCCESS_CODES.include?(response.code.to_i) parse_inference_response(response) rescue StandardError => e handle_exception(e, level: :warn, operation: 'tty.daemon_client.inference', daemon_url: daemon_url, model: model, provider: provider, timeout: timeout) { status: :unavailable, error: { message: e. } } end |
.manifest ⇒ Object
61 62 63 |
# File 'lib/legion/tty/daemon_client.rb', line 61 def manifest @manifest || cached_manifest end |
.match_intent(intent_text) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/legion/tty/daemon_client.rb', line 65 def match_intent(intent_text) return nil unless manifest normalized = intent_text.downcase.strip manifest.each do |ext| next unless ext[:known_intents] ext[:known_intents].each do |ki| return ki if ki[:intent]&.downcase&.strip == normalized && ki[:confidence] >= 0.8 end end nil end |
.reset! ⇒ Object
125 126 127 128 129 130 |
# File 'lib/legion/tty/daemon_client.rb', line 125 def reset! @daemon_url = nil @cache_file = nil @timeout = nil @manifest = nil end |
.run_tool(name:, args: {}) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/legion/tty/daemon_client.rb', line 109 def run_tool(name:, args: {}) uri = URI("#{daemon_url}/api/tools/run") payload = Legion::JSON.dump({ name: name, args: args }) response = post_json(uri, payload) if SUCCESS_CODES.include?(response.code.to_i) body = Legion::JSON.load(response.body) { status: :ok, data: body[:data] || body } else { status: :error, error: "HTTP #{response.code}" } end rescue StandardError => e handle_exception(e, level: :warn, operation: 'tty.daemon_client.run_tool', daemon_url: daemon_url, name: name) { status: :unavailable } end |