robot_lab-a2a 0.1.1 → 0.2.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: b79d098ef9b24711b48d41af7140e3bf331594f427b5518814e4ff58cde38a2d
4
- data.tar.gz: e38b9117d0b2d2dae5f3483ff7dd826ef25e0f7525738cf30941aead87214f77
3
+ metadata.gz: 06fea066d630fe600e2f5e4aeebb95ef5d36ce1003a7808cf5a2bb6d2abbe52a
4
+ data.tar.gz: a1825a21bb7ad7fda768df531f376cb877a7b668429ef97a164e168b6cabb599
5
5
  SHA512:
6
- metadata.gz: 13b98611d8ef81ce10a0bddb1010a932e4b52a032546beb44eb3791d94f82d02fb3691a40c42222e3931824278cf31511fa9ec2fa864243dcbacdcf7779a2895
7
- data.tar.gz: a284690e28a7967c3784bbeebee40fd4019ca9c0c1f712d48f6cf5c0e42b33cc41881ddb866e9f7f7ad77b399d52b35da2ee92d2e55d3bc059de77b20714e473
6
+ metadata.gz: 0c387fb5ab2a628f94327ca5d86b96d1f16413c9aa4d76dfd22ed587a467c2ce9af25f530858ab51de6c1a62b83854f800cd7901a7a8c6d5d87b3d186a2ce469
7
+ data.tar.gz: a8a70420bdb2702311677af2b7ff7e231d6d97013e15d94129b9e48b57038664864cc7c95ed0cfe4b2ba082dfdf640edb37dbf6d7d17ff82ebf6dcdb08f4a06f
data/.rubocop.yml CHANGED
@@ -1,29 +1,173 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
3
  SuggestExtensions: false
4
+ TargetRubyVersion: 4.0
4
5
  Exclude:
5
6
  - 'examples/**/*'
7
+ - 'vendor/**/*'
8
+ - 'dead_code/**/*'
9
+
10
+ # ── Style: disabled cops ───────────────────────────────────────────────────
11
+ Style/StringLiterals:
12
+ Enabled: false
13
+
14
+ Style/StringLiteralsInInterpolation:
15
+ Enabled: false
6
16
 
7
17
  Style/Documentation:
8
18
  Enabled: false
9
19
 
20
+ # Ruby 4.0 freezes string literals by default
21
+ Style/FrozenStringLiteralComment:
22
+ Enabled: false
23
+
24
+ Style/IfUnlessModifier:
25
+ Enabled: false
26
+
27
+ Style/RescueModifier:
28
+ Enabled: false
29
+
30
+ Style/TrivialAccessors:
31
+ Enabled: false
32
+
33
+ Style/MultilineTernaryOperator:
34
+ Enabled: false
35
+
36
+ Style/SafeNavigation:
37
+ Enabled: false
38
+
39
+ Style/EmptyClassDefinition:
40
+ Enabled: false
41
+
42
+ Style/ClassAndModuleChildren:
43
+ Enabled: false
44
+
45
+ Style/RescueStandardError:
46
+ Enabled: false
47
+
48
+ Style/OneClassPerFile:
49
+ Enabled: false
50
+
51
+ # Both % and format/sprintf are acceptable
52
+ Style/FormatString:
53
+ Enabled: false
54
+
55
+ # String concatenation and interpolation are both acceptable
56
+ Style/StringConcatenation:
57
+ Enabled: false
58
+
59
+ # ── Layout ─────────────────────────────────────────────────────────────────
60
+ Layout/LineLength:
61
+ Max: 140
62
+
10
63
  Layout/ExtraSpacing:
11
64
  Enabled: false
12
65
 
66
+ Layout/HashAlignment:
67
+ Enabled: false
68
+
69
+ Layout/FirstHashElementIndentation:
70
+ Enabled: false
71
+
72
+ Layout/EmptyLineAfterGuardClause:
73
+ Enabled: false
74
+
75
+ # ── Naming ─────────────────────────────────────────────────────────────────
76
+ # Single-char params (c, e, n) are acceptable throughout
77
+ Naming/MethodParameterName:
78
+ Enabled: false
79
+
80
+ Naming/VariableNumber:
81
+ Exclude:
82
+ - 'test/**/*'
83
+
84
+ Naming/RescuedExceptionsVariableName:
85
+ Enabled: false
86
+
87
+ # set_results and similar explicit setters are clear and conventional
88
+ Naming/AccessorMethodName:
89
+ Enabled: false
90
+
91
+
92
+ # has_tool_calls? and similar are clear and conventional
93
+ Naming/PredicatePrefix:
94
+ Enabled: false
95
+
96
+ # Test helper methods don't need to follow predicate naming rules
97
+ Naming/PredicateMethod:
98
+ Exclude:
99
+ - 'test/**/*'
100
+
101
+ # ── Lint: relax noisy cops on intentional patterns ─────────────────────────
102
+ # Library and framework methods commonly accept args for API/documentation purposes
103
+ Lint/UnusedMethodArgument:
104
+ Enabled: false
105
+
106
+
107
+ Lint/EmptyBlock:
108
+ Exclude:
109
+ - 'test/**/*'
110
+
111
+ Lint/ConstantDefinitionInBlock:
112
+ Exclude:
113
+ - 'Rakefile'
114
+ - 'test/**/*'
115
+
116
+ # ── Gemspec ────────────────────────────────────────────────────────────────
117
+ Gemspec/DevelopmentDependencies:
118
+ EnforcedStyle: Gemfile
119
+
120
+ Gemspec/RequiredRubyVersion:
121
+ Enabled: false
122
+
123
+ Gemspec/OrderedDependencies:
124
+ Enabled: false
125
+
126
+ # ── Metrics ────────────────────────────────────────────────────────────────
127
+ # Framework-level code (routers, parsers, orchestrators) is inherently complex.
128
+ # Flog is the primary complexity gate — these RuboCop thresholds catch only
129
+ # egregious outliers without false-positiving every dispatch method.
130
+
13
131
  Metrics/MethodLength:
14
- Max: 25
132
+ Max: 35
15
133
  CountAsOne:
16
134
  - heredoc
17
135
  - array
18
136
  - hash
137
+ Exclude:
138
+ - 'test/**/*'
19
139
 
20
140
  Metrics/AbcSize:
21
- Max: 25
141
+ Max: 40
142
+ Exclude:
143
+ - 'test/**/*'
22
144
 
23
145
  Metrics/ClassLength:
24
- Max: 150
146
+ Max: 600
147
+ Exclude:
148
+ - 'test/**/*'
149
+
150
+ Metrics/ModuleLength:
151
+ Max: 200
152
+ Exclude:
153
+ - 'test/**/*'
154
+
155
+ Metrics/CyclomaticComplexity:
156
+ Max: 20
157
+ Exclude:
158
+ - 'test/**/*'
159
+
160
+ Metrics/PerceivedComplexity:
161
+ Max: 20
162
+ Exclude:
163
+ - 'test/**/*'
164
+
165
+ # Long method signatures with keyword args are a Ruby framework idiom
166
+ Metrics/ParameterLists:
167
+ Enabled: false
25
168
 
26
169
  Metrics/BlockLength:
27
170
  Exclude:
28
171
  - 'Rakefile'
29
172
  - '*.gemspec'
173
+ - 'test/**/*'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.1] - 2026-05-19
4
+
3
5
  ### Added
4
6
 
5
7
  - Demo examples infrastructure: `examples/run` lifecycle script, shared `examples/common_config.rb`, and three complete demos:
@@ -13,6 +15,7 @@
13
15
  ### Changed
14
16
 
15
17
  - Interactive mode `:acp_tool` renamed to `:a2a_tool` across all source, tests, and documentation
18
+ - Version synchronized with robot_lab core 0.2.1
16
19
 
17
20
  ### Fixed
18
21
 
data/CLAUDE.md ADDED
@@ -0,0 +1,57 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What This Gem Does
6
+
7
+ `robot_lab-a2a` is an Agent2Agent (A2A) protocol adapter that exposes RobotLab robots and networks as A2A agents over HTTP+SSE. It bridges RobotLab's terminal-based `AskUser` tool to A2A's `input_required`/resume lifecycle, enabling multi-turn conversational flows without terminal dependency. It delegates HTTP serving to the `simple_a2a` gem.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ rake test # Run full test suite (default rake task)
13
+ rake build # Build the gem package
14
+ rake install # Install gem locally
15
+
16
+ bin/setup # Install dependencies
17
+ bin/console # IRB session with gem loaded
18
+
19
+ # Run a single test file
20
+ ruby -Ilib -Itest test/robot_lab/test_a2a.rb
21
+
22
+ # Run a single test by name
23
+ ruby -Ilib -Itest test/robot_lab/test_a2a.rb -n test_registry_stores_and_retrieves
24
+ ```
25
+
26
+ ## Architecture
27
+
28
+ All source lives under `lib/robot_lab/a2a/`. The gem uses an adapter pattern — the two adapters both implement the `A2A::Server::AgentExecutor` interface with a single `call(context)` method.
29
+
30
+ ### Key Abstractions
31
+
32
+ **Registry** (`registry.rb`) — Thread-safe singleton tracking active robot sessions across HTTP requests. Entries are `Data.define(:thread, :event_queue, :answer_queue)` stored by session ID. Required because A2A `tasks/send` resumes an in-flight robot thread.
33
+
34
+ **RobotAdapter** (`robot_adapter.rb`) — Wraps a `RobotLab::Robot` as an executor. Supports three interactive modes:
35
+ - `:none` — Synchronous, robot runs to completion with no input prompts.
36
+ - `:acp_tool` — Injects `AskUserTool` into the robot's `@local_tools`, converting terminal blocking to Queue signaling. Restores original tools on teardown.
37
+ - `:io_bridge` — Replaces the robot's I/O streams with an `IoBridge` instance; works with robots that use `puts`/`gets` directly.
38
+
39
+ **AskUserTool** (`ask_user_tool.rb`) — Drop-in replacement for `RobotLab::AskUser`. On `call`, pushes `{type: :ask, prompt:}` to the event_queue then blocks on answer_queue until the A2A client sends a resume.
40
+
41
+ **IoBridge** (`io_bridge.rb`) — IO-compatible object. Buffers all writes; on `gets`, flushes the buffer as the prompt event and blocks on answer_queue. Enables interactive mode for robots that don't use the AskUser tool directly.
42
+
43
+ **NetworkAdapter** (`network_adapter.rb`) — Wraps a `RobotLab::Network`. Currently supports only `:none` mode; interactive mode per network node is not yet implemented.
44
+
45
+ **Server** (`server.rb`) — Fluent builder. `add_robot` / `add_network` register adapters keyed by DNS-safe path labels (underscores→hyphens, RFC 1123). `run(port:)` starts the HTTP server; `to_app` returns a Rack app for embedding in Rails/Puma.
46
+
47
+ ### Thread Safety
48
+
49
+ Interactive modes run each robot on its own Ruby Thread. `Registry` uses a `Mutex`. `AskUserTool` and `IoBridge` use Ruby's `Queue` for producer/consumer coordination between the robot thread and the HTTP request handler.
50
+
51
+ ### Extension Registration
52
+
53
+ The gem hooks into RobotLab's extension system at require time (`a2a.rb`) and registers itself as the `:a2a` extension.
54
+
55
+ ## Tests
56
+
57
+ Tests live in `test/robot_lab/test_a2a.rb` using Minitest with autorun. The test helper is `test/test_helper.rb`. There is no `.rspec` or RuboCop config — no linter is configured.
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/testtask'
6
6
  Rake::TestTask.new(:test) do |t|
7
7
  t.libs << 'test'
8
8
  t.libs << 'lib'
9
- t.test_files = FileList['test/**/*_test.rb']
9
+ t.test_files = FileList['test/**/*_test.rb', 'test/**/test_*.rb'].exclude('**/*_helper.rb')
10
10
  t.verbose = true
11
11
  t.ruby_opts << '-rtest_helper'
12
12
  end
@@ -102,3 +102,15 @@ task :quality do
102
102
  abort "\nQuality gate failed" if results.values.any?(:fail)
103
103
  puts "\nAll quality gates passed."
104
104
  end
105
+
106
+ namespace :docs do
107
+ desc 'Build MkDocs documentation'
108
+ task :build do
109
+ sh 'mkdocs build'
110
+ end
111
+
112
+ desc 'Serve MkDocs documentation locally on http://localhost:8000'
113
+ task :serve do
114
+ sh 'mkdocs serve'
115
+ end
116
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RobotLab
4
4
  module A2A
5
- VERSION = '0.1.1'
5
+ VERSION = '0.2.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robot_lab-a2a
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
@@ -27,16 +27,16 @@ dependencies:
27
27
  name: robot_lab
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 0.2.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '0'
39
+ version: 0.2.0
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: simple_a2a
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -65,6 +65,7 @@ files:
65
65
  - ".github/workflows/deploy-github-pages.yml"
66
66
  - ".rubocop.yml"
67
67
  - CHANGELOG.md
68
+ - CLAUDE.md
68
69
  - COMMITS.md
69
70
  - LICENSE.txt
70
71
  - README.md