robot_lab-a2a 0.1.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 -29
- data/CHANGELOG.md +13 -0
- data/CLAUDE.md +57 -0
- data/Rakefile +59 -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 +9 -6
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,29 +1 @@
|
|
|
1
|
-
|
|
2
|
-
NewCops: enable
|
|
3
|
-
SuggestExtensions: false
|
|
4
|
-
Exclude:
|
|
5
|
-
- 'examples/**/*'
|
|
6
|
-
|
|
7
|
-
Style/Documentation:
|
|
8
|
-
Enabled: false
|
|
9
|
-
|
|
10
|
-
Layout/ExtraSpacing:
|
|
11
|
-
Enabled: false
|
|
12
|
-
|
|
13
|
-
Metrics/MethodLength:
|
|
14
|
-
Max: 25
|
|
15
|
-
CountAsOne:
|
|
16
|
-
- heredoc
|
|
17
|
-
- array
|
|
18
|
-
- hash
|
|
19
|
-
|
|
20
|
-
Metrics/AbcSize:
|
|
21
|
-
Max: 25
|
|
22
|
-
|
|
23
|
-
Metrics/ClassLength:
|
|
24
|
-
Max: 150
|
|
25
|
-
|
|
26
|
-
Metrics/BlockLength:
|
|
27
|
-
Exclude:
|
|
28
|
-
- 'Rakefile'
|
|
29
|
-
- '*.gemspec'
|
|
1
|
+
inherit_from: ../.rubocop-base.yml
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
13
|
+
## [0.2.1] - 2026-05-19
|
|
14
|
+
|
|
3
15
|
### Added
|
|
4
16
|
|
|
5
17
|
- Demo examples infrastructure: `examples/run` lifecycle script, shared `examples/common_config.rb`, and three complete demos:
|
|
@@ -13,6 +25,7 @@
|
|
|
13
25
|
### Changed
|
|
14
26
|
|
|
15
27
|
- Interactive mode `:acp_tool` renamed to `:a2a_tool` across all source, tests, and documentation
|
|
28
|
+
- Version synchronized with robot_lab core 0.2.1
|
|
16
29
|
|
|
17
30
|
### Fixed
|
|
18
31
|
|
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
|
+
- `:a2a_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
|
|
@@ -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,34 +61,72 @@ task :flog_check do
|
|
|
71
61
|
end
|
|
72
62
|
end
|
|
73
63
|
|
|
74
|
-
desc '
|
|
64
|
+
desc 'Check for structural code duplication with Flay (mass >= 50)'
|
|
65
|
+
task :flay_check do
|
|
66
|
+
require 'flay'
|
|
67
|
+
|
|
68
|
+
mass_threshold = 50
|
|
69
|
+
|
|
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
|
|
73
|
+
|
|
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'
|
|
75
84
|
task :quality do
|
|
76
|
-
|
|
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
|
|
77
98
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
results[:tests] = system('bundle exec rake test') ? :pass : :fail
|
|
99
|
+
green = ->(s) { "\e[32m#{s}\e[0m" }
|
|
100
|
+
red = ->(s) { "\e[31m#{s}\e[0m" }
|
|
101
|
+
width = results.map { |label, _| label.length }.max
|
|
82
102
|
|
|
83
103
|
puts "\n#{'=' * 60}"
|
|
84
|
-
puts 'Quality Gate
|
|
104
|
+
puts 'Quality Gate Summary'
|
|
85
105
|
puts '=' * 60
|
|
86
|
-
results
|
|
106
|
+
results.each do |label, status|
|
|
107
|
+
badge = status == :pass ? green.call('PASS') : red.call('FAIL')
|
|
108
|
+
puts " [#{badge}] #{label.ljust(width)}"
|
|
109
|
+
end
|
|
110
|
+
puts '-' * 60
|
|
87
111
|
|
|
88
|
-
|
|
89
|
-
|
|
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)}"
|
|
90
116
|
puts '=' * 60
|
|
91
|
-
results[:flog] = system('bundle exec rake flog_check') ? :pass : :fail
|
|
92
117
|
|
|
93
|
-
|
|
94
|
-
puts '
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
118
|
+
abort "\n#{red.call('Quality gate failed.')}" unless failed.zero?
|
|
119
|
+
puts "\n#{green.call('All quality gates passed.')}"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
namespace :docs do
|
|
123
|
+
desc 'Build MkDocs documentation'
|
|
124
|
+
task :build do
|
|
125
|
+
sh 'mkdocs build'
|
|
99
126
|
end
|
|
100
|
-
puts '=' * 60
|
|
101
127
|
|
|
102
|
-
|
|
103
|
-
|
|
128
|
+
desc 'Serve MkDocs documentation locally on http://localhost:8000'
|
|
129
|
+
task :serve do
|
|
130
|
+
sh 'mkdocs serve'
|
|
131
|
+
end
|
|
104
132
|
end
|
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.
|
|
4
|
+
version: 0.2.6
|
|
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:
|
|
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:
|
|
39
|
+
version: 0.2.0
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: simple_a2a
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -63,8 +63,11 @@ 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
|
|
70
|
+
- CLAUDE.md
|
|
68
71
|
- COMMITS.md
|
|
69
72
|
- LICENSE.txt
|
|
70
73
|
- README.md
|
|
@@ -122,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
122
125
|
- !ruby/object:Gem::Version
|
|
123
126
|
version: '0'
|
|
124
127
|
requirements: []
|
|
125
|
-
rubygems_version: 4.0.
|
|
128
|
+
rubygems_version: 4.0.17
|
|
126
129
|
specification_version: 4
|
|
127
130
|
summary: Agent2Agent (A2A) protocol adapter for RobotLab
|
|
128
131
|
test_files: []
|