robot_lab-a2a 0.2.1 → 0.2.6
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 +4 -4
- data/.envrc +2 -0
- data/.loki +10 -0
- data/.quality/reek_baseline.txt +6 -0
- data/.rubocop.yml +1 -173
- data/CHANGELOG.md +10 -0
- data/CLAUDE.md +1 -1
- data/Rakefile +47 -31
- data/docs/examples.md +54 -0
- data/docs/interactive-modes.md +4 -0
- data/docs/server-api.md +4 -4
- data/lib/robot_lab/a2a/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 508cfed94ac09af2dc3aef1bdce245e1ec12e561dc1af58e1a11c37c362c3e9a
|
|
4
|
+
data.tar.gz: 7014425d58923f5cf00f74e96242f0f77890e4342ea1cd06022cbab8d13dbdad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3604a8078469267732f02a7bd7d5bd52d00e1980a2bac92c38c7c495947d11404fe1dc1614f166589e3be6a75afa98d5889485ad01121fc87e14e1107911ada1
|
|
7
|
+
data.tar.gz: c87c24bf66e2d1490d3e51b4d6155e753d5f1e24083fa2a3c93b1341506c8927f813b509c72d82224d319931fdea3c4b3026c5a1109343478645a9830fb3356a
|
data/.envrc
CHANGED
data/.loki
ADDED
data/.rubocop.yml
CHANGED
|
@@ -1,173 +1 @@
|
|
|
1
|
-
|
|
2
|
-
NewCops: enable
|
|
3
|
-
SuggestExtensions: false
|
|
4
|
-
TargetRubyVersion: 4.0
|
|
5
|
-
Exclude:
|
|
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
|
|
16
|
-
|
|
17
|
-
Style/Documentation:
|
|
18
|
-
Enabled: false
|
|
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
|
-
|
|
63
|
-
Layout/ExtraSpacing:
|
|
64
|
-
Enabled: false
|
|
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
|
-
|
|
131
|
-
Metrics/MethodLength:
|
|
132
|
-
Max: 35
|
|
133
|
-
CountAsOne:
|
|
134
|
-
- heredoc
|
|
135
|
-
- array
|
|
136
|
-
- hash
|
|
137
|
-
Exclude:
|
|
138
|
-
- 'test/**/*'
|
|
139
|
-
|
|
140
|
-
Metrics/AbcSize:
|
|
141
|
-
Max: 40
|
|
142
|
-
Exclude:
|
|
143
|
-
- 'test/**/*'
|
|
144
|
-
|
|
145
|
-
Metrics/ClassLength:
|
|
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
|
|
168
|
-
|
|
169
|
-
Metrics/BlockLength:
|
|
170
|
-
Exclude:
|
|
171
|
-
- 'Rakefile'
|
|
172
|
-
- '*.gemspec'
|
|
173
|
-
- 'test/**/*'
|
|
1
|
+
inherit_from: ../.rubocop-base.yml
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
### Added
|
|
4
|
+
- `.loki` Asgard task file: `test`, `rubocop`, `rubocop_fix`, `flog`, `flay`, `quality`, `build`, `install`, `release`, and `console` tasks via the Asgard task runner
|
|
5
|
+
- `flay_check` Rake task: structural code duplication gate (mass threshold 50); integrated into the `quality` Rake task
|
|
6
|
+
- `flay` and `minitest-reporters` gems added to development dependencies
|
|
7
|
+
- `test_output.txt`, `flay_output.txt`, `flog_output.txt`, and `rubocop_output.txt` added to `.gitignore`
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- `test/test_helper.rb`: test output redirected to `test_output.txt` via `$stdout` reassignment; `TerminalSummaryReporter` prints a single PASS/FAIL summary line to the terminal
|
|
11
|
+
- `Rakefile`: `rubocop` and `rubocop_fix` tasks removed (now owned by Asgard); `flay_check` integrated into the `quality` gate
|
|
12
|
+
|
|
3
13
|
## [0.2.1] - 2026-05-19
|
|
4
14
|
|
|
5
15
|
### Added
|
data/CLAUDE.md
CHANGED
|
@@ -33,7 +33,7 @@ All source lives under `lib/robot_lab/a2a/`. The gem uses an adapter pattern —
|
|
|
33
33
|
|
|
34
34
|
**RobotAdapter** (`robot_adapter.rb`) — Wraps a `RobotLab::Robot` as an executor. Supports three interactive modes:
|
|
35
35
|
- `:none` — Synchronous, robot runs to completion with no input prompts.
|
|
36
|
-
- `:
|
|
36
|
+
- `:a2a_tool` — Injects `AskUserTool` into the robot's `@local_tools`, converting terminal blocking to Queue signaling. Restores original tools on teardown.
|
|
37
37
|
- `:io_bridge` — Replaces the robot's I/O streams with an `IoBridge` instance; works with robots that use `puts`/`gets` directly.
|
|
38
38
|
|
|
39
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.
|
data/Rakefile
CHANGED
|
@@ -24,16 +24,6 @@ task :test_file, [:file] do |_t, args|
|
|
|
24
24
|
ruby "test/#{args[:file]}"
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
desc 'Check code style with RuboCop'
|
|
28
|
-
task :rubocop do
|
|
29
|
-
sh 'bundle exec rubocop'
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
desc 'Auto-correct RuboCop offenses'
|
|
33
|
-
task :rubocop_fix do
|
|
34
|
-
sh 'bundle exec rubocop -a'
|
|
35
|
-
end
|
|
36
|
-
|
|
37
27
|
desc 'Check code complexity with Flog (warn >=20, fail >=50)'
|
|
38
28
|
task :flog_check do
|
|
39
29
|
require 'flog'
|
|
@@ -71,36 +61,62 @@ task :flog_check do
|
|
|
71
61
|
end
|
|
72
62
|
end
|
|
73
63
|
|
|
74
|
-
desc '
|
|
75
|
-
task :
|
|
76
|
-
|
|
64
|
+
desc 'Check for structural code duplication with Flay (mass >= 50)'
|
|
65
|
+
task :flay_check do
|
|
66
|
+
require 'flay'
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
puts 'Quality Gate: Tests + Coverage'
|
|
80
|
-
puts '=' * 60
|
|
81
|
-
results[:tests] = system('bundle exec rake test') ? :pass : :fail
|
|
68
|
+
mass_threshold = 50
|
|
82
69
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
results[:rubocop] = system('bundle exec rubocop') ? :pass : :fail
|
|
70
|
+
flay = Flay.new({ mass: mass_threshold, diff: false, verbose: false, summary: false, timeout: 60 })
|
|
71
|
+
flay.process(*Dir.glob('lib/**/*.rb'))
|
|
72
|
+
flay.analyze
|
|
87
73
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
74
|
+
if flay.hashes.empty?
|
|
75
|
+
puts "\nFlay: no structural duplication detected (mass >= #{mass_threshold})"
|
|
76
|
+
else
|
|
77
|
+
puts "\nFlay found structural duplication (mass >= #{mass_threshold}):"
|
|
78
|
+
flay.report
|
|
79
|
+
abort "\nFlay quality gate failed: #{flay.hashes.length} pattern(s) detected"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
desc 'Run all quality checks: tests (with coverage), RuboCop, Flog, and Flay'
|
|
84
|
+
task :quality do
|
|
85
|
+
gates = [
|
|
86
|
+
['Tests + Coverage', 'bundle exec rake test'],
|
|
87
|
+
['RuboCop', 'bundle exec rubocop'],
|
|
88
|
+
['Flog Complexity', 'bundle exec rake flog_check'],
|
|
89
|
+
['Flay Duplication', 'bundle exec rake flay_check']
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
results = gates.map do |label, command|
|
|
93
|
+
puts "\n#{'=' * 60}"
|
|
94
|
+
puts "Quality Gate: #{label}"
|
|
95
|
+
puts '=' * 60
|
|
96
|
+
[label, system(command) ? :pass : :fail]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
green = ->(s) { "\e[32m#{s}\e[0m" }
|
|
100
|
+
red = ->(s) { "\e[31m#{s}\e[0m" }
|
|
101
|
+
width = results.map { |label, _| label.length }.max
|
|
92
102
|
|
|
93
103
|
puts "\n#{'=' * 60}"
|
|
94
|
-
puts 'Quality Summary'
|
|
104
|
+
puts 'Quality Gate Summary'
|
|
95
105
|
puts '=' * 60
|
|
96
|
-
results.each do |
|
|
97
|
-
|
|
98
|
-
puts " [#{
|
|
106
|
+
results.each do |label, status|
|
|
107
|
+
badge = status == :pass ? green.call('PASS') : red.call('FAIL')
|
|
108
|
+
puts " [#{badge}] #{label.ljust(width)}"
|
|
99
109
|
end
|
|
110
|
+
puts '-' * 60
|
|
111
|
+
|
|
112
|
+
passed = results.count { |_, s| s == :pass }
|
|
113
|
+
failed = results.count { |_, s| s == :fail }
|
|
114
|
+
tally = "#{passed} passed, #{failed} failed"
|
|
115
|
+
puts " #{failed.zero? ? green.call(tally) : red.call(tally)}"
|
|
100
116
|
puts '=' * 60
|
|
101
117
|
|
|
102
|
-
abort "\
|
|
103
|
-
puts "\
|
|
118
|
+
abort "\n#{red.call('Quality gate failed.')}" unless failed.zero?
|
|
119
|
+
puts "\n#{green.call('All quality gates passed.')}"
|
|
104
120
|
end
|
|
105
121
|
|
|
106
122
|
namespace :docs do
|
data/docs/examples.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
```
|
|
6
6
|
examples/
|
|
7
7
|
run # launcher script
|
|
8
|
+
common_config.rb # shared $LOAD_PATH + require, loaded by every example
|
|
8
9
|
01_sync_robot/
|
|
9
10
|
server.rb # starts the A2A server
|
|
10
11
|
client.rb # sends a task and prints the result
|
|
@@ -14,6 +15,16 @@ examples/
|
|
|
14
15
|
03_robot_network/
|
|
15
16
|
server.rb
|
|
16
17
|
client.rb
|
|
18
|
+
04_io_bridge/
|
|
19
|
+
server.rb
|
|
20
|
+
client.rb
|
|
21
|
+
05_multi_agent/
|
|
22
|
+
server.rb
|
|
23
|
+
client.rb
|
|
24
|
+
06_rack_mount/
|
|
25
|
+
server.rb
|
|
26
|
+
config.ru # standalone Rack/Rails mount reference (not used by run)
|
|
27
|
+
client.rb
|
|
17
28
|
```
|
|
18
29
|
|
|
19
30
|
## How to run
|
|
@@ -114,3 +125,46 @@ Sending task to network...
|
|
|
114
125
|
Reply: [synthesised answer from the final pipeline stage]
|
|
115
126
|
Done.
|
|
116
127
|
```
|
|
128
|
+
|
|
129
|
+
## 04_io_bridge
|
|
130
|
+
|
|
131
|
+
**Demonstrates:** `:io_bridge` interactive mode. `QuoteRobot` has no knowledge of A2A at all — it just calls `@output.puts` and `@input.gets` (falling back to `$stdout`/`$stdin` when not injected), so the same class also runs fine interactively in a terminal. The server injects an `IoBridge` as `robot.input`/`robot.output` before each run.
|
|
132
|
+
|
|
133
|
+
**Two-turn flow:**
|
|
134
|
+
|
|
135
|
+
1. Client sends a topic (`"stoicism"`) → `QuoteRobot` writes its question to the buffered output, then calls `gets` → `IoBridge` flushes the buffer as the `input_required` prompt and blocks.
|
|
136
|
+
2. Client resumes with the same `task_id` and an answer (`"Ada"`) → `IoBridge` unblocks `gets` → the robot completes and returns a quote addressed to that name.
|
|
137
|
+
|
|
138
|
+
**What it shows:**
|
|
139
|
+
|
|
140
|
+
- `interactive: :io_bridge` server setup
|
|
141
|
+
- A robot written against plain Ruby IO, with no A2A-specific code
|
|
142
|
+
- The same two-turn `task_id` resume pattern as `:a2a_tool`
|
|
143
|
+
|
|
144
|
+
**Note:** Turn 2 requires a `simple_a2a` build with `ResumeContext` support (>= 0.3.1). On older versions the client still demonstrates Turn 1's `input_required` suspension.
|
|
145
|
+
|
|
146
|
+
## 05_multi_agent
|
|
147
|
+
|
|
148
|
+
**Demonstrates:** Multiple independent A2A agents served from a single process via the fluent builder API with explicit `path:` overrides — `HeadlineRobot` at `/headline` and `TagRobot` at `/tags`.
|
|
149
|
+
|
|
150
|
+
**What it shows:**
|
|
151
|
+
|
|
152
|
+
- Chaining `add_robot` calls with explicit `path:` values on one `Server` instance
|
|
153
|
+
- Two separate `A2A.client` instances, one per agent path, each with its own agent card
|
|
154
|
+
- That co-located agents are indistinguishable from independently hosted ones at the protocol level
|
|
155
|
+
|
|
156
|
+
**Expected output (client):** both clients discover their agent card, send the same input text, and print each robot's distinct reply (a capitalised headline vs. a list of `#hashtag` keywords) alongside pass/fail assertions.
|
|
157
|
+
|
|
158
|
+
## 06_rack_mount
|
|
159
|
+
|
|
160
|
+
**Demonstrates:** `server.to_app`, which returns a `Rack::URLMap` instead of starting a dedicated server — for embedding A2A agents inside a larger Rack application (Rails, Sinatra, Puma, etc.) rather than running `server.run` standalone.
|
|
161
|
+
|
|
162
|
+
The demo composes the A2A agent (`EchoRobot`, mounted via `to_app`) with a plain `/health` JSON Rack endpoint on the same combined app, run via `A2A::Server::FalconRunner`. `config.ru` in this directory is a copy-paste reference for mounting the same `to_app` result under Rackup or a Rails `config/routes.rb` — it is not used by `examples/run`.
|
|
163
|
+
|
|
164
|
+
**What it shows:**
|
|
165
|
+
|
|
166
|
+
- `add_robot(...).to_app` returning a `Rack::URLMap`
|
|
167
|
+
- Composing that map with unrelated Rack routes
|
|
168
|
+
- That both A2A and non-A2A routes work correctly side by side on the composed app
|
|
169
|
+
|
|
170
|
+
**Expected output (client):** a passing health check against `/health` followed by a normal A2A `send_task` round trip against `/echo-robot`, each reported with a pass/fail assertion.
|
data/docs/interactive-modes.md
CHANGED
|
@@ -102,3 +102,7 @@ RobotLab::A2A::Server.new(interactive: :io_bridge)
|
|
|
102
102
|
| `:io_bridge` | `robot.run(text)` + settable `robot.input=` / `robot.output=` | Robots that interact via raw stdin/stdout streams |
|
|
103
103
|
|
|
104
104
|
When in doubt, start with `:none`. Upgrade to `:a2a_tool` if your robot uses `AskUser`, or `:io_bridge` if it uses raw IO.
|
|
105
|
+
|
|
106
|
+
## Cancelling an in-progress task
|
|
107
|
+
|
|
108
|
+
While a robot is suspended waiting on `answer_queue` (i.e. between an `input_required` event and the client's resume), the A2A client may send `tasks/cancel` instead of resuming. `RobotAdapter#cancel` looks the task up in `Registry` by task ID, kills the robot thread with `Thread#kill`, and removes the entry from `Registry` before delegating to the default `AgentExecutor#cancel` behaviour. If no entry is found (e.g. the task already completed or was never interactive), `cancel` is a no-op aside from the default behaviour.
|
data/docs/server-api.md
CHANGED
|
@@ -27,8 +27,8 @@ Valid `interactive` values: `:none`, `:a2a_tool`, `:io_bridge`. See [Interactive
|
|
|
27
27
|
```ruby
|
|
28
28
|
server.add_robot(
|
|
29
29
|
robot,
|
|
30
|
-
name:
|
|
31
|
-
description:
|
|
30
|
+
name: nil, # String — human-readable agent name; defaults to robot.name
|
|
31
|
+
description: nil, # String — agent capability description; defaults to robot.description
|
|
32
32
|
path: nil # String — URL path segment; derived from name if nil
|
|
33
33
|
) → self
|
|
34
34
|
```
|
|
@@ -51,12 +51,12 @@ Wraps `robot` in a `RobotAdapter` using the server's `interactive` setting and r
|
|
|
51
51
|
server.add_network(
|
|
52
52
|
network,
|
|
53
53
|
name: required, # String — human-readable agent name
|
|
54
|
-
description:
|
|
54
|
+
description: nil, # String — agent capability description; defaults to name
|
|
55
55
|
path: nil # String — URL path segment; derived from name if nil
|
|
56
56
|
) → self
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Wraps `network` in a `NetworkAdapter`.
|
|
59
|
+
Wraps `network` in a `NetworkAdapter`, always constructed with `interactive: :none`. If the server's own `interactive` setting is anything other than `:none`, `add_network` raises `ArgumentError` instead of silently ignoring it — networks do not support interactive modes. Wrap individual robots with `RobotAdapter` (via `add_robot`) for interactive flows.
|
|
60
60
|
|
|
61
61
|
**`network` must respond to:**
|
|
62
62
|
|
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.2.
|
|
4
|
+
version: 0.2.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dewayne VanHoozer
|
|
@@ -63,6 +63,8 @@ extra_rdoc_files: []
|
|
|
63
63
|
files:
|
|
64
64
|
- ".envrc"
|
|
65
65
|
- ".github/workflows/deploy-github-pages.yml"
|
|
66
|
+
- ".loki"
|
|
67
|
+
- ".quality/reek_baseline.txt"
|
|
66
68
|
- ".rubocop.yml"
|
|
67
69
|
- CHANGELOG.md
|
|
68
70
|
- CLAUDE.md
|
|
@@ -123,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
123
125
|
- !ruby/object:Gem::Version
|
|
124
126
|
version: '0'
|
|
125
127
|
requirements: []
|
|
126
|
-
rubygems_version: 4.0.
|
|
128
|
+
rubygems_version: 4.0.17
|
|
127
129
|
specification_version: 4
|
|
128
130
|
summary: Agent2Agent (A2A) protocol adapter for RobotLab
|
|
129
131
|
test_files: []
|