legionio 1.6.42 → 1.6.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57f30aa272e7d11d9d59754a4092686c31b8224438c3e754db778ec6bed46b89
4
- data.tar.gz: 169950365e0ddc408ae7f497d05870b416502dc069fef6dc7843da1fa049049e
3
+ metadata.gz: 17578bcb7fd7292eb90672503f016fbc426e771bec3ca6a4d822aa20019b8979
4
+ data.tar.gz: f31d286761b71e11338608c17a24ae051b9d0a3aab6aec61ae0ecb655c8b01c8
5
5
  SHA512:
6
- metadata.gz: 7ae7156ccfac8ef9eed39b528bf455008a220874903d74364a4fe79095a8a74ed3e4ab74ab8f4345c448ad76df8fa59ead5e7fd6e42b5493eb7eb34f56bf4fde
7
- data.tar.gz: 3d4bbec7574202d679b7dabe9470f31de350580d917d9c31f264d7fb29c46524726fc52279750a64c16ee40c1ba1f4c9543ac0df5d720d3512abd769e9bf9b06
6
+ metadata.gz: 811ec04a329c5d791fbcbaecdcec3880bbedccc085016f573634e457998b3e625dfe4bcff3d9ebd37a08251ce671aea15765626b559b2990e28d1dbc938ccecf
7
+ data.tar.gz: 0fba42942c96a2add0b454edd4f5be563f93dd182ac7f8b10f7203062a2ab85aa6a07a9876587f04a16fcd16d22a6f4a4b0aa62a101bd29efc849693d56283c3
data/.rubocop.yml CHANGED
@@ -59,6 +59,7 @@ Metrics/BlockLength:
59
59
  - 'lib/legion/cli/setup_command.rb'
60
60
  - 'lib/legion/cli/trace_command.rb'
61
61
  - 'lib/legion/cli/features_command.rb'
62
+ - 'lib/legion/cli/absorb_command.rb'
62
63
 
63
64
  Metrics/AbcSize:
64
65
  Max: 60
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.6.43] - 2026-03-31
6
+
7
+ ### Added
8
+ - `POST /api/absorbers/dispatch` API endpoint for async absorber dispatch — CLI no longer loads extension classes directly
9
+ - Absorb dispatch runs in a background thread, returning job ID immediately
10
+
11
+ ### Changed
12
+ - `legionio absorb url` now routes through the local API instead of loading extension classes in-process (fixes `NameError` when extensions not loaded in CLI context)
13
+ - CLI absorb output updated to show async dispatch status with job ID
14
+
5
15
  ## [1.6.42] - 2026-03-31
6
16
 
7
17
  ### Fixed
@@ -19,6 +19,26 @@ module Legion
19
19
  json_response(items)
20
20
  end
21
21
 
22
+ app.post '/api/absorbers/dispatch' do
23
+ body = parse_request_body
24
+ input = body[:url] || body[:input]
25
+ halt 400, json_error('missing_param', 'url parameter is required') unless input
26
+
27
+ require 'legion/extensions/actors/absorber_dispatch'
28
+ context = body[:context] || {}
29
+ job_id = SecureRandom.hex(8)
30
+
31
+ Thread.new do
32
+ Legion::Extensions::Actors::AbsorberDispatch.dispatch(
33
+ input: input, job_id: job_id, context: context
34
+ )
35
+ rescue StandardError => e
36
+ Legion::Logging.error("Async absorb #{job_id} failed: #{e.message}") if defined?(Legion::Logging)
37
+ end
38
+
39
+ json_response({ success: true, job_id: job_id, absorber: PatternMatcher.resolve(input)&.name, status: :accepted })
40
+ end
41
+
22
42
  app.get '/api/absorbers/resolve' do
23
43
  input = params[:url] || params[:input]
24
44
  halt 400, json_error('missing_param', 'url parameter is required') unless input
@@ -17,22 +17,16 @@ module Legion
17
17
  desc 'url URL', 'Absorb content from a URL'
18
18
  option :scope, type: :string, default: 'global', desc: 'Knowledge scope (global/local/all)'
19
19
  def url(input_url)
20
- Connection.ensure_settings
21
- require 'legion/extensions/absorbers'
22
- require 'legion/extensions/absorbers/pattern_matcher'
23
- require 'legion/extensions/actors/absorber_dispatch'
24
-
25
20
  out = formatter
26
- result = Legion::Extensions::Actors::AbsorberDispatch.dispatch(
27
- input: input_url,
28
- context: { scope: options[:scope]&.to_sym }
29
- )
21
+ result = api_post('/api/absorbers/dispatch', url: input_url, context: { scope: options[:scope] })
30
22
 
31
23
  if options[:json]
32
24
  out.json(result)
33
25
  elsif result[:success]
34
- out.success("Absorbed: #{input_url}")
35
- out.detail(absorber: result[:absorber], job_id: result[:job_id])
26
+ out.success("Dispatched: #{input_url}")
27
+ puts " absorber: #{result[:absorber]}"
28
+ puts " job_id: #{result[:job_id]}"
29
+ puts ' Processing in background. Check daemon logs for progress.'
36
30
  else
37
31
  out.warn("Failed: #{result[:error]}")
38
32
  end
@@ -84,6 +78,29 @@ module Legion
84
78
  4567
85
79
  end
86
80
 
81
+ def api_post(path, **payload)
82
+ uri = URI("http://127.0.0.1:#{api_port}#{path}")
83
+ http = Net::HTTP.new(uri.host, uri.port)
84
+ http.read_timeout = 300
85
+ request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
86
+ request.body = ::JSON.generate(payload)
87
+ response = http.request(request)
88
+ unless response.is_a?(Net::HTTPSuccess)
89
+ formatter.error("API returned #{response.code} for #{path}")
90
+ raise SystemExit, 1
91
+ end
92
+ body = ::JSON.parse(response.body, symbolize_names: true)
93
+ body[:data]
94
+ rescue Errno::ECONNREFUSED
95
+ formatter.error('Daemon not running. Start with: legionio start')
96
+ raise SystemExit, 1
97
+ rescue SystemExit
98
+ raise
99
+ rescue StandardError => e
100
+ formatter.error("API request failed: #{e.message}")
101
+ raise SystemExit, 1
102
+ end
103
+
87
104
  def api_get(path)
88
105
  uri = URI("http://127.0.0.1:#{api_port}#{path}")
89
106
  response = Net::HTTP.get_response(uri)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Legion
4
- VERSION = '1.6.42'
4
+ VERSION = '1.6.43'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legionio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.42
4
+ version: 1.6.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity