lex-lex 0.2.1 → 0.3.1

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: 3777b77e3f3d3225f3f6460b7657da500864831adbd5968508f5680f0a0db8ba
4
- data.tar.gz: afcb223bac1af680e38c6efc4923c9d5211a6ab9e15d4ee8d52d0e3a72ec2f27
3
+ metadata.gz: 93780b160c34e525aba1595937595ccf5313d4cb0542a2d419dc676b0fd02831
4
+ data.tar.gz: b0b53037503181537ad91f9588fc0849e58a6211f5ef1669e294e957daf88006
5
5
  SHA512:
6
- metadata.gz: 6e8cbd38ec2f50c1a32fae430338865aeb871441036ca68ae02db68aaa4c9c981dedefef1c97a710c5738af37361a34a250f929d63cd764e594624faba8de756
7
- data.tar.gz: 7521e32b17b077f98ca453228ea797fcdc16a1982e90931b8ca5e83c1b855f4a30340bb7e31b4c825389dd27041dd8dff5fa0ef740804422df70edd53c75ca86
6
+ metadata.gz: a40d14b40f89d72785bbe9a2343f5059812ec1058f75f89b842a1ec9be2d5603f2e3741f20b1d88ff7e4749e88f66fe14b1f48596cde276a3cce69a41c3187f8
7
+ data.tar.gz: a4296c1dcff4f3d7000844b5f9ffc7aade39b9a26ee69987f44bedfe92143ead0b4789e8d8c63df5e8d400728069ae9d78610bbf34423caf4b537732861baada
data/.gitignore CHANGED
@@ -7,5 +7,7 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ Gemfile.lock
11
+
10
12
  # rspec failure tracking
11
13
  .rspec_status
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.1] - 2026-03-20
4
+
5
+ ### Added
6
+ - `Actor::AgentWatcher` — interval actor (every 30s) that detects file modifications to loaded YAML agent definitions and triggers hot-reload via `Legion::Extensions.load_yaml_agents`
7
+ - Conditional require of `AgentWatcher` in entry point (only when `Legion::Extensions::Actors::Every` is available)
8
+
9
+ ## [0.3.0] - 2026-03-18
10
+
11
+ ### Fixed
12
+ - `data_required?` now correctly overrides Core default (was instance method, framework ignored it)
13
+ - Sync runner only increments update counter on actual DB writes
14
+ - Sync runner no longer re-enables intentionally disabled extensions
15
+ - Register.save guards against nil extension_id after creation failure
16
+
17
+ ### Changed
18
+ - Renamed shadowed `update` local variables to `changes` in Extension, Runner, Function modules
19
+
3
20
  ## [0.2.1] - 2026-03-17
4
21
 
5
22
  ### Fixed
data/CLAUDE.md CHANGED
@@ -12,7 +12,7 @@ Without lex-lex, the extensions/runners/functions DB tables remain empty, and th
12
12
 
13
13
  **GitHub**: https://github.com/LegionIO/lex-lex
14
14
  **License**: MIT
15
- **Version**: 0.2.0
15
+ **Version**: 0.3.0
16
16
 
17
17
  ## Architecture
18
18
 
@@ -55,7 +55,7 @@ Startup (after all extensions load):
55
55
  | Path | Purpose |
56
56
  |------|---------|
57
57
  | `lib/legion/extensions/lex.rb` | Entry point, requires all runners |
58
- | `lib/legion/extensions/lex/version.rb` | VERSION constant (0.2.0) |
58
+ | `lib/legion/extensions/lex/version.rb` | VERSION constant (0.3.0) |
59
59
  | `lib/legion/extensions/lex/runners/extension.rb` | Extension CRUD |
60
60
  | `lib/legion/extensions/lex/runners/runner.rb` | Runner CRUD |
61
61
  | `lib/legion/extensions/lex/runners/function.rb` | Function CRUD + build_args |
@@ -67,7 +67,7 @@ Startup (after all extensions load):
67
67
 
68
68
  ```bash
69
69
  bundle install
70
- bundle exec rspec # 55 specs
70
+ bundle exec rspec # 71 specs, 0 failures
71
71
  bundle exec rubocop # 0 offenses
72
72
  ```
73
73
 
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Lex
6
+ module Actor
7
+ class AgentWatcher < Legion::Extensions::Actors::Every
8
+ def time = 30
9
+ def run_now? = false
10
+ def use_runner? = false
11
+ def check_subtask? = false
12
+ def generate_task? = false
13
+
14
+ def action(**_opts)
15
+ current = Legion::Extensions.instance_variable_get(:@load_yaml_agents) || []
16
+ reloaded = 0
17
+
18
+ current.each do |agent|
19
+ path = agent[:_source_path]
20
+ next unless path && File.exist?(path)
21
+ next unless File.mtime(path) > agent[:_source_mtime]
22
+
23
+ reloaded += 1
24
+ end
25
+
26
+ if reloaded.positive?
27
+ Legion::Extensions.instance_variable_set(:@load_yaml_agents, nil)
28
+ Legion::Extensions.load_yaml_agents
29
+ end
30
+
31
+ { reloaded: reloaded }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -22,18 +22,18 @@ module Legion
22
22
  extension = Legion::Data::Model::Extension[extension_id]
23
23
  return { success: false, reason: 'extension not found' } if extension.nil?
24
24
 
25
- update = {}
25
+ changes = {}
26
26
  %i[name namespace active exchange uri].each do |column|
27
27
  next unless opts.key?(column)
28
28
  next if extension.values[column] == opts[column]
29
29
 
30
- update[column] = opts[column]
30
+ changes[column] = opts[column]
31
31
  end
32
32
 
33
- return { success: true, changed: false, extension_id: extension_id } if update.empty?
33
+ return { success: true, changed: false, extension_id: extension_id } if changes.empty?
34
34
 
35
- extension.update(update)
36
- { success: true, changed: true, updates: update, extension_id: extension_id }
35
+ extension.update(changes)
36
+ { success: true, changed: true, updates: changes, extension_id: extension_id }
37
37
  end
38
38
 
39
39
  def get(extension_id: nil, name: nil, namespace: nil, **_opts)
@@ -22,18 +22,18 @@ module Legion
22
22
  function = Legion::Data::Model::Function[function_id]
23
23
  return { success: false, reason: 'function not found' } if function.nil?
24
24
 
25
- update = {}
26
- update[:active] = opts[:active] if opts.key?(:active) && function.values[:active] != opts[:active]
25
+ changes = {}
26
+ changes[:active] = opts[:active] if opts.key?(:active) && function.values[:active] != opts[:active]
27
27
 
28
28
  if opts.key?(:formatted_args)
29
29
  args = Legion::JSON.dump(opts[:formatted_args])
30
- update[:args] = args unless args == function.values[:args]
30
+ changes[:args] = args unless args == function.values[:args]
31
31
  end
32
32
 
33
- return { success: true, changed: false, function_id: function_id } if update.empty?
33
+ return { success: true, changed: false, function_id: function_id } if changes.empty?
34
34
 
35
- function.update(update)
36
- { success: true, changed: true, updates: update, function_id: function_id }
35
+ function.update(changes)
36
+ { success: true, changed: true, updates: changes, function_id: function_id }
37
37
  end
38
38
 
39
39
  def get(function_id:, **_opts)
@@ -22,6 +22,8 @@ module Legion
22
22
  name: runner_opts[:extension_name],
23
23
  namespace: runner_opts[:extension_class].to_s
24
24
  )
25
+ return { success: false, error: 'extension creation failed' } if ext_result[:extension_id].nil?
26
+
25
27
  extension_id = ext_result[:extension_id]
26
28
  end
27
29
 
@@ -27,18 +27,18 @@ module Legion
27
27
  runner = Legion::Data::Model::Runner[runner_id]
28
28
  return { success: false, reason: 'runner not found' } if runner.nil?
29
29
 
30
- update = {}
30
+ changes = {}
31
31
  %i[name namespace active queue uri].each do |column|
32
32
  next unless opts.key?(column)
33
33
  next if runner.values[column] == opts[column]
34
34
 
35
- update[column] = opts[column]
35
+ changes[column] = opts[column]
36
36
  end
37
37
 
38
- return { success: true, changed: false, runner_id: runner_id } if update.empty?
38
+ return { success: true, changed: false, runner_id: runner_id } if changes.empty?
39
39
 
40
- runner.update(update)
41
- { success: true, changed: true, updates: update, runner_id: runner_id }
40
+ runner.update(changes)
41
+ { success: true, changed: true, updates: changes, runner_id: runner_id }
42
42
  end
43
43
 
44
44
  def get(runner_id:, **_opts)
@@ -33,8 +33,10 @@ module Legion
33
33
  created += 1
34
34
  else
35
35
  ns = values[:extension_class].to_s
36
- existing.update(namespace: ns, active: true) if existing.values[:namespace] != ns
37
- updated += 1
36
+ if existing.values[:namespace] != ns
37
+ existing.update(namespace: ns)
38
+ updated += 1
39
+ end
38
40
  end
39
41
  synced += 1
40
42
  end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Lex
6
- VERSION = '0.2.1'
6
+ VERSION = '0.3.1'
7
7
  end
8
8
  end
9
9
  end
@@ -6,13 +6,14 @@ require_relative 'lex/runners/runner'
6
6
  require_relative 'lex/runners/function'
7
7
  require_relative 'lex/runners/register'
8
8
  require_relative 'lex/runners/sync'
9
+ require_relative 'lex/actors/agent_watcher' if defined?(Legion::Extensions::Actors::Every)
9
10
 
10
11
  module Legion
11
12
  module Extensions
12
13
  module Lex
13
14
  extend Legion::Extensions::Core if Legion::Extensions.const_defined?(:Core)
14
15
 
15
- def data_required?
16
+ def self.data_required?
16
17
  true
17
18
  end
18
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-lex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -108,11 +108,11 @@ files:
108
108
  - CHANGELOG.md
109
109
  - CLAUDE.md
110
110
  - Gemfile
111
- - Gemfile.lock
112
111
  - LICENSE.txt
113
112
  - README.md
114
113
  - lex-lex.gemspec
115
114
  - lib/legion/extensions/lex.rb
115
+ - lib/legion/extensions/lex/actors/agent_watcher.rb
116
116
  - lib/legion/extensions/lex/actors/sync.rb
117
117
  - lib/legion/extensions/lex/runners/extension.rb
118
118
  - lib/legion/extensions/lex/runners/function.rb
data/Gemfile.lock DELETED
@@ -1,91 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- lex-lex (0.2.1)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- addressable (2.8.9)
10
- public_suffix (>= 2.0.2, < 8.0)
11
- ast (2.4.3)
12
- bigdecimal (4.0.1)
13
- diff-lcs (1.6.2)
14
- docile (1.4.1)
15
- json (2.19.1)
16
- json-schema (6.2.0)
17
- addressable (~> 2.8)
18
- bigdecimal (>= 3.1, < 5)
19
- language_server-protocol (3.17.0.5)
20
- lint_roller (1.1.0)
21
- mcp (0.8.0)
22
- json-schema (>= 4.1)
23
- parallel (1.27.0)
24
- parser (3.3.10.2)
25
- ast (~> 2.4.1)
26
- racc
27
- prism (1.9.0)
28
- public_suffix (7.0.5)
29
- racc (1.8.1)
30
- rainbow (3.1.1)
31
- rake (13.3.1)
32
- regexp_parser (2.11.3)
33
- rspec (3.13.2)
34
- rspec-core (~> 3.13.0)
35
- rspec-expectations (~> 3.13.0)
36
- rspec-mocks (~> 3.13.0)
37
- rspec-core (3.13.6)
38
- rspec-support (~> 3.13.0)
39
- rspec-expectations (3.13.5)
40
- diff-lcs (>= 1.2.0, < 2.0)
41
- rspec-support (~> 3.13.0)
42
- rspec-mocks (3.13.8)
43
- diff-lcs (>= 1.2.0, < 2.0)
44
- rspec-support (~> 3.13.0)
45
- rspec-support (3.13.7)
46
- rspec_junit_formatter (0.6.0)
47
- rspec-core (>= 2, < 4, != 2.12.0)
48
- rubocop (1.85.1)
49
- json (~> 2.3)
50
- language_server-protocol (~> 3.17.0.2)
51
- lint_roller (~> 1.1.0)
52
- mcp (~> 0.6)
53
- parallel (~> 1.10)
54
- parser (>= 3.3.0.2)
55
- rainbow (>= 2.2.2, < 4.0)
56
- regexp_parser (>= 2.9.3, < 3.0)
57
- rubocop-ast (>= 1.49.0, < 2.0)
58
- ruby-progressbar (~> 1.7)
59
- unicode-display_width (>= 2.4.0, < 4.0)
60
- rubocop-ast (1.49.1)
61
- parser (>= 3.3.7.2)
62
- prism (~> 1.7)
63
- rubocop-rspec (3.9.0)
64
- lint_roller (~> 1.1)
65
- rubocop (~> 1.81)
66
- ruby-progressbar (1.13.0)
67
- simplecov (0.22.0)
68
- docile (~> 1.1)
69
- simplecov-html (~> 0.11)
70
- simplecov_json_formatter (~> 0.1)
71
- simplecov-html (0.13.2)
72
- simplecov_json_formatter (0.1.4)
73
- unicode-display_width (3.2.0)
74
- unicode-emoji (~> 4.1)
75
- unicode-emoji (4.2.0)
76
-
77
- PLATFORMS
78
- arm64-darwin-25
79
- ruby
80
-
81
- DEPENDENCIES
82
- lex-lex!
83
- rake
84
- rspec (~> 3.13)
85
- rspec_junit_formatter
86
- rubocop (~> 1.75)
87
- rubocop-rspec
88
- simplecov
89
-
90
- BUNDLED WITH
91
- 2.6.9