robot_lab 0.2.6 → 0.2.8
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 +4 -0
- data/.loki +5 -0
- data/Archspec.rb +44 -0
- data/CHANGELOG.md +17 -1
- data/README.md +124 -64
- data/Rakefile +6 -111
- data/_typos.toml +21 -0
- data/docs/api/core/index.md +41 -15
- data/docs/api/core/memory.md +247 -29
- data/docs/api/core/network.md +255 -33
- data/docs/api/core/result.md +120 -32
- data/docs/api/core/robot.md +551 -61
- data/docs/api/core/state.md +87 -197
- data/docs/api/core/tool.md +165 -20
- data/docs/api/errors.md +110 -17
- data/docs/api/hooks.md +469 -0
- data/docs/api/index.md +80 -7
- data/docs/api/mcp/client.md +129 -35
- data/docs/api/mcp/index.md +164 -23
- data/docs/api/mcp/server.md +27 -3
- data/docs/api/mcp/transports.md +94 -22
- data/docs/api/messages/index.md +26 -3
- data/docs/api/messages/text-message.md +33 -11
- data/docs/api/messages/tool-call-message.md +27 -4
- data/docs/api/messages/tool-result-message.md +23 -4
- data/docs/api/messages/user-message.md +45 -8
- data/docs/api/skills.md +423 -0
- data/docs/api/streaming/context.md +28 -5
- data/docs/api/streaming/index.md +57 -11
- data/docs/api/support.md +846 -0
- data/docs/architecture/core-concepts.md +79 -31
- data/docs/architecture/index.md +87 -11
- data/docs/architecture/message-flow.md +66 -29
- data/docs/architecture/network-orchestration.md +145 -38
- data/docs/architecture/robot-execution.md +172 -90
- data/docs/architecture/state-management.md +31 -12
- data/docs/concepts.md +176 -21
- data/docs/examples/basic-chat.md +72 -19
- data/docs/examples/index.md +117 -31
- data/docs/examples/mcp-server.md +154 -45
- data/docs/examples/multi-robot-network.md +91 -21
- data/docs/examples/tool-usage.md +104 -37
- data/docs/getting-started/configuration.md +288 -98
- data/docs/getting-started/installation.md +53 -41
- data/docs/getting-started/quick-start.md +51 -6
- data/docs/guides/building-robots.md +258 -50
- data/docs/guides/creating-networks.md +214 -30
- data/docs/guides/hooks.md +263 -54
- data/docs/guides/knowledge.md +35 -4
- data/docs/guides/mcp-integration.md +211 -44
- data/docs/guides/memory.md +103 -12
- data/docs/guides/observability.md +95 -47
- data/docs/guides/streaming.md +184 -125
- data/docs/guides/using-tools.md +247 -18
- data/docs/index.md +36 -4
- data/examples/01_simple_robot.rb +2 -2
- data/examples/02_tools.rb +14 -4
- data/examples/03_network.rb +12 -7
- data/examples/04_mcp.rb +11 -4
- data/examples/05_streaming.rb +8 -5
- data/examples/06_prompt_templates.rb +13 -9
- data/examples/07_network_memory.rb +5 -5
- data/examples/08_llm_config.rb +20 -15
- data/examples/09_chaining.rb +4 -4
- data/examples/11_network_introspection.rb +4 -4
- data/examples/12_message_bus.rb +2 -2
- data/examples/13_spawn.rb +2 -2
- data/examples/14_rusty_circuit/README.md +1 -0
- data/examples/14_rusty_circuit/comic.rb +7 -3
- data/examples/14_rusty_circuit/display.rb +14 -0
- data/examples/14_rusty_circuit/heckler.rb +8 -6
- data/examples/14_rusty_circuit/open_mic.rb +17 -6
- data/examples/14_rusty_circuit/scout.rb +17 -10
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +14 -10
- data/examples/15_memory_network_and_bus/linux_writer.rb +2 -2
- data/examples/15_memory_network_and_bus/os_editor.rb +3 -1
- data/examples/15_memory_network_and_bus/os_writer.rb +4 -1
- data/examples/16_writers_room/writer.rb +22 -22
- data/examples/16_writers_room/writers_room.rb +2 -0
- data/examples/17_skills.rb +14 -13
- data/examples/18_rails/README.md +20 -1
- data/examples/18_rails/app/controllers/chat_controller.rb +5 -1
- data/examples/18_rails/app/jobs/robot_run_job.rb +11 -5
- data/examples/18_rails/app/robots/chat_robot.rb +11 -0
- data/examples/18_rails/config/initializers/robot_lab.rb +8 -0
- data/examples/19_token_tracking.rb +25 -9
- data/examples/20_circuit_breaker.rb +10 -7
- data/examples/21_learning_loop.rb +42 -16
- data/examples/22_context_compression.rb +23 -23
- data/examples/23_convergence.rb +24 -17
- data/examples/24_structured_delegation.rb +13 -8
- data/examples/25_history_search.rb +12 -8
- data/examples/27_incident_response/incident_response.rb +31 -13
- data/examples/28_mcp_discovery.rb +17 -13
- data/examples/29_ractor_tools.rb +4 -2
- data/examples/30_ractor_network.rb +22 -17
- data/examples/31_launch_assessment.rb +20 -9
- data/examples/32_newsletter_reader.rb +7 -2
- data/examples/33_stock_predictor.rb +34 -13
- data/examples/34_agentskills.rb +7 -3
- data/examples/35_hooks.rb +18 -8
- data/examples/README.md +199 -45
- data/examples/common.rb +79 -11
- data/examples/xyzzy.rb +8 -1
- data/lib/robot_lab/agent_skill_catalog.rb +1 -0
- data/lib/robot_lab/ask_user.rb +2 -0
- data/lib/robot_lab/bus_poller.rb +2 -0
- data/lib/robot_lab/capabilities.rb +4 -0
- data/lib/robot_lab/config.rb +18 -5
- data/lib/robot_lab/doom_loop_detector.rb +6 -3
- data/lib/robot_lab/history_compressor.rb +5 -0
- data/lib/robot_lab/hook.rb +1 -0
- data/lib/robot_lab/hook_context.rb +4 -0
- data/lib/robot_lab/hook_registry.rb +1 -0
- data/lib/robot_lab/hooks.rb +6 -3
- data/lib/robot_lab/mcp/client.rb +2 -2
- data/lib/robot_lab/mcp/connection_poller.rb +16 -8
- data/lib/robot_lab/mcp/server_discovery.rb +1 -0
- data/lib/robot_lab/mcp/transports/sse.rb +3 -0
- data/lib/robot_lab/mcp/transports/stdio.rb +5 -0
- data/lib/robot_lab/mcp/transports/streamable_http.rb +4 -0
- data/lib/robot_lab/mcp/transports/websocket.rb +3 -0
- data/lib/robot_lab/memory.rb +23 -6
- data/lib/robot_lab/memory_change.rb +1 -0
- data/lib/robot_lab/message.rb +3 -0
- data/lib/robot_lab/names.rb +400 -0
- data/lib/robot_lab/network.rb +13 -6
- data/lib/robot_lab/robot/agent_skill_matching.rb +3 -3
- data/lib/robot_lab/robot/bus_messaging.rb +19 -8
- data/lib/robot_lab/robot/history_search.rb +2 -0
- data/lib/robot_lab/robot/hooking.rb +3 -0
- data/lib/robot_lab/robot/mcp_management.rb +11 -3
- data/lib/robot_lab/robot/template_rendering.rb +29 -7
- data/lib/robot_lab/robot.rb +81 -19
- data/lib/robot_lab/robot_result.rb +3 -0
- data/lib/robot_lab/run_config.rb +5 -0
- data/lib/robot_lab/script_tool.rb +20 -39
- data/lib/robot_lab/state_proxy.rb +1 -0
- data/lib/robot_lab/streaming/context.rb +1 -0
- data/lib/robot_lab/streaming/events.rb +1 -0
- data/lib/robot_lab/task.rb +2 -0
- data/lib/robot_lab/tool.rb +4 -0
- data/lib/robot_lab/user_message.rb +1 -0
- data/lib/robot_lab/utils.rb +2 -0
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab/waiter.rb +3 -0
- data/lib/robot_lab.rb +27 -18
- data/mkdocs.yml +6 -1
- metadata +12 -7
- data/lib/robot_lab/sandbox/null.rb +0 -13
- data/lib/robot_lab/sandbox/seatbelt.rb +0 -104
- data/lib/robot_lab/sandbox.rb +0 -52
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# lib/robot_lab/names.rb
|
|
2
|
+
|
|
3
|
+
# A large curated word list, not application logic — kept as one inline
|
|
4
|
+
# module for lookup speed, so the size/length cops below are false positives.
|
|
5
|
+
# rubocop:disable-next Metrics/ModuleLength
|
|
6
|
+
module RobotLab
|
|
7
|
+
# Fictional robot names
|
|
8
|
+
# rubocop:disable-next Metrics/CollectionLiteralLength
|
|
9
|
+
NAMES = %w[
|
|
10
|
+
R_7723
|
|
11
|
+
R_790
|
|
12
|
+
AXL
|
|
13
|
+
Adam
|
|
14
|
+
Adam_Link
|
|
15
|
+
Alfie
|
|
16
|
+
Alojzy_Kukuryk
|
|
17
|
+
Alpha_5
|
|
18
|
+
Alpha_6
|
|
19
|
+
Alsatia_Zevo
|
|
20
|
+
AMEE
|
|
21
|
+
Ancient_Ore_Crusher
|
|
22
|
+
Andrew
|
|
23
|
+
Andrew_Martin
|
|
24
|
+
Andromon
|
|
25
|
+
Aniel
|
|
26
|
+
Aqua
|
|
27
|
+
Arbeitsmaschine
|
|
28
|
+
Arthur
|
|
29
|
+
Artificial_Friend
|
|
30
|
+
Ash
|
|
31
|
+
Astor
|
|
32
|
+
Astro_Boy
|
|
33
|
+
Athena
|
|
34
|
+
Atmophytes
|
|
35
|
+
AUTO
|
|
36
|
+
Ava
|
|
37
|
+
B_4
|
|
38
|
+
BATs
|
|
39
|
+
BEN
|
|
40
|
+
BOB
|
|
41
|
+
B166ER
|
|
42
|
+
Baymax
|
|
43
|
+
BB
|
|
44
|
+
BB_8
|
|
45
|
+
Becker
|
|
46
|
+
Bender
|
|
47
|
+
Bénédict_Masson
|
|
48
|
+
Bennie
|
|
49
|
+
Beta
|
|
50
|
+
Beta_Machine
|
|
51
|
+
Billybot
|
|
52
|
+
Bishop
|
|
53
|
+
Black_Beauty
|
|
54
|
+
Blue_Senturion
|
|
55
|
+
Boilerplate
|
|
56
|
+
Boppers
|
|
57
|
+
Bors
|
|
58
|
+
Box
|
|
59
|
+
Brackenridge
|
|
60
|
+
Brainbots
|
|
61
|
+
BRL_A
|
|
62
|
+
Bruno
|
|
63
|
+
Bubo
|
|
64
|
+
Buffybot
|
|
65
|
+
BURN_E
|
|
66
|
+
Byron
|
|
67
|
+
C_3PO
|
|
68
|
+
CHOMPS
|
|
69
|
+
Calculon
|
|
70
|
+
Caliban
|
|
71
|
+
Call
|
|
72
|
+
Cambot
|
|
73
|
+
Candy_Droober
|
|
74
|
+
Carl
|
|
75
|
+
Casandra_Kresnov
|
|
76
|
+
CASE
|
|
77
|
+
Cassandra_One
|
|
78
|
+
Chani
|
|
79
|
+
CHAPPiE
|
|
80
|
+
Charlie
|
|
81
|
+
Cherry_2000
|
|
82
|
+
Chip
|
|
83
|
+
CHIP
|
|
84
|
+
Chitti
|
|
85
|
+
Chuck_the_Robot
|
|
86
|
+
Chucky
|
|
87
|
+
Chumblies
|
|
88
|
+
Claire
|
|
89
|
+
Clamps
|
|
90
|
+
Clunk
|
|
91
|
+
Coconuts
|
|
92
|
+
Coldfire
|
|
93
|
+
Coldstone
|
|
94
|
+
Colossus
|
|
95
|
+
Conky_2000
|
|
96
|
+
Coppélia
|
|
97
|
+
Coyote
|
|
98
|
+
Crimson
|
|
99
|
+
Crow_T_Robot
|
|
100
|
+
Cutie
|
|
101
|
+
Cybots
|
|
102
|
+
Cylons
|
|
103
|
+
D_FIB
|
|
104
|
+
DARYL
|
|
105
|
+
Damon
|
|
106
|
+
Data
|
|
107
|
+
David
|
|
108
|
+
David_8
|
|
109
|
+
Dee_Model
|
|
110
|
+
Dewey
|
|
111
|
+
DOR_15
|
|
112
|
+
Dorfl
|
|
113
|
+
Dot_Matrix
|
|
114
|
+
DV_8
|
|
115
|
+
ED_209
|
|
116
|
+
EDI
|
|
117
|
+
Elio
|
|
118
|
+
Elle
|
|
119
|
+
Emma_2
|
|
120
|
+
Enforcer_Drone
|
|
121
|
+
Engimals
|
|
122
|
+
EVAs
|
|
123
|
+
Eve
|
|
124
|
+
EVE
|
|
125
|
+
Evolver
|
|
126
|
+
Ez_27
|
|
127
|
+
false_Maria
|
|
128
|
+
Fembots
|
|
129
|
+
Flexo
|
|
130
|
+
Frank_Saunders
|
|
131
|
+
Franklin_Droober
|
|
132
|
+
Freya
|
|
133
|
+
Freysa
|
|
134
|
+
Frost
|
|
135
|
+
G2
|
|
136
|
+
Galaxina
|
|
137
|
+
GERTY_3000
|
|
138
|
+
Giant_Robot
|
|
139
|
+
Giddy
|
|
140
|
+
Gigantor
|
|
141
|
+
Gnut
|
|
142
|
+
GO_4
|
|
143
|
+
Goddard
|
|
144
|
+
Gog
|
|
145
|
+
Gort
|
|
146
|
+
Gort
|
|
147
|
+
Gris
|
|
148
|
+
Grounder
|
|
149
|
+
Guardromon
|
|
150
|
+
Gypsy
|
|
151
|
+
Hadaly
|
|
152
|
+
HAN_S
|
|
153
|
+
Haro
|
|
154
|
+
HCR_328
|
|
155
|
+
Hector
|
|
156
|
+
Helen_OLoy
|
|
157
|
+
Helena
|
|
158
|
+
Hermes
|
|
159
|
+
Huey
|
|
160
|
+
Hymie
|
|
161
|
+
Ilia
|
|
162
|
+
Intergalactic_Advocate_Bob
|
|
163
|
+
Jaegers
|
|
164
|
+
Janice_Em
|
|
165
|
+
Jay_Score
|
|
166
|
+
Jay_Dub
|
|
167
|
+
Jenkins
|
|
168
|
+
Jenny_Wakeman
|
|
169
|
+
Jessica
|
|
170
|
+
Jet
|
|
171
|
+
Jet_Jaguar
|
|
172
|
+
Jinx
|
|
173
|
+
Johnny_5
|
|
174
|
+
Johnny_Cab
|
|
175
|
+
Juliana_Tainer
|
|
176
|
+
K
|
|
177
|
+
K_2SO
|
|
178
|
+
K9
|
|
179
|
+
Kampfmaschin
|
|
180
|
+
KARR
|
|
181
|
+
Kay_Em_14
|
|
182
|
+
Kei
|
|
183
|
+
Kikaider
|
|
184
|
+
Killbots
|
|
185
|
+
Kirby
|
|
186
|
+
Kit
|
|
187
|
+
KITT
|
|
188
|
+
Klapaucius
|
|
189
|
+
Kronos
|
|
190
|
+
Kryten
|
|
191
|
+
Kwanzaa_Bot
|
|
192
|
+
Kyoko
|
|
193
|
+
L_76
|
|
194
|
+
L3_37
|
|
195
|
+
Lal
|
|
196
|
+
Lenny
|
|
197
|
+
Leon_Kowalski
|
|
198
|
+
Lomax
|
|
199
|
+
Lore
|
|
200
|
+
Louie
|
|
201
|
+
Luv
|
|
202
|
+
M_O
|
|
203
|
+
M3GAN
|
|
204
|
+
Mac
|
|
205
|
+
Magog
|
|
206
|
+
Mami
|
|
207
|
+
Manders
|
|
208
|
+
Mandroid
|
|
209
|
+
Marcus_Wright
|
|
210
|
+
Maria
|
|
211
|
+
Mariette
|
|
212
|
+
Marius
|
|
213
|
+
Mark_1
|
|
214
|
+
MARK13
|
|
215
|
+
Marvin
|
|
216
|
+
Mary_25
|
|
217
|
+
Maschinenmensch
|
|
218
|
+
Mata_Nui
|
|
219
|
+
Maureen_Droober
|
|
220
|
+
MAX
|
|
221
|
+
Max_404
|
|
222
|
+
Maximillian
|
|
223
|
+
May
|
|
224
|
+
MD_63
|
|
225
|
+
Mech_Eagles
|
|
226
|
+
Mecha_King_Ghidorah
|
|
227
|
+
Mechagodzilla
|
|
228
|
+
Mechagodzilla
|
|
229
|
+
Mechani_Kong
|
|
230
|
+
Mechano
|
|
231
|
+
Mechonoids
|
|
232
|
+
Mec_Willy
|
|
233
|
+
Melfina
|
|
234
|
+
Merlin_Athrawes
|
|
235
|
+
Micro_Managers
|
|
236
|
+
MM7
|
|
237
|
+
Moguera
|
|
238
|
+
MOOSE
|
|
239
|
+
Moravecs
|
|
240
|
+
Mordel
|
|
241
|
+
Morgan
|
|
242
|
+
Mr_Split
|
|
243
|
+
Mr_Static
|
|
244
|
+
Muranian
|
|
245
|
+
Necron_99
|
|
246
|
+
Neotnia
|
|
247
|
+
Newman
|
|
248
|
+
Nimani
|
|
249
|
+
Nimue_Alban
|
|
250
|
+
Norby
|
|
251
|
+
NS4
|
|
252
|
+
Okra
|
|
253
|
+
Olimpia
|
|
254
|
+
Oliver
|
|
255
|
+
Olympia
|
|
256
|
+
Omega
|
|
257
|
+
Omnidroid
|
|
258
|
+
Otis
|
|
259
|
+
POPS
|
|
260
|
+
Paws
|
|
261
|
+
Peace
|
|
262
|
+
Phatasaur
|
|
263
|
+
Phil
|
|
264
|
+
Pino_Petto
|
|
265
|
+
PR_T
|
|
266
|
+
Primus
|
|
267
|
+
Pris
|
|
268
|
+
Project_2501
|
|
269
|
+
Proteus_IV
|
|
270
|
+
Quinn
|
|
271
|
+
R_Daneel_Olivaw
|
|
272
|
+
R_Giskard_Reventlov
|
|
273
|
+
RALF
|
|
274
|
+
ROTOR
|
|
275
|
+
R2_D2
|
|
276
|
+
R4_P17
|
|
277
|
+
Rabbot
|
|
278
|
+
Rachael
|
|
279
|
+
Radius
|
|
280
|
+
Rena
|
|
281
|
+
Replicators
|
|
282
|
+
Rex
|
|
283
|
+
RIA
|
|
284
|
+
Richard_Daniel
|
|
285
|
+
Rick_Deckard
|
|
286
|
+
Ro_Man_Extension_XJ_2
|
|
287
|
+
Rob_Monkey
|
|
288
|
+
Robbie
|
|
289
|
+
Robby
|
|
290
|
+
Robo
|
|
291
|
+
Robo_Clowns
|
|
292
|
+
RoboDoc
|
|
293
|
+
RoboGadget
|
|
294
|
+
Robot_7
|
|
295
|
+
Robot_B_9
|
|
296
|
+
Robot_Devil
|
|
297
|
+
Robot_Santa
|
|
298
|
+
Robot_ZX29B
|
|
299
|
+
Robotoid
|
|
300
|
+
Roderick
|
|
301
|
+
Rosie
|
|
302
|
+
Roy_Batty
|
|
303
|
+
Roz
|
|
304
|
+
ROZZUM_unit_7134
|
|
305
|
+
SAR_003
|
|
306
|
+
S1MONE
|
|
307
|
+
Samantha
|
|
308
|
+
Sapper_Morton
|
|
309
|
+
Sara
|
|
310
|
+
Scratch
|
|
311
|
+
Sentinels
|
|
312
|
+
Setaur
|
|
313
|
+
Sheen
|
|
314
|
+
Sheriff_Not_a_Robot
|
|
315
|
+
SHROUD
|
|
316
|
+
SI_9
|
|
317
|
+
Sico
|
|
318
|
+
SID_67
|
|
319
|
+
SIMON
|
|
320
|
+
Skutters
|
|
321
|
+
Solo
|
|
322
|
+
Sonny
|
|
323
|
+
Sox
|
|
324
|
+
Sparks
|
|
325
|
+
Speedy
|
|
326
|
+
Spofforth
|
|
327
|
+
Spot
|
|
328
|
+
Stitchpunks
|
|
329
|
+
Sulla
|
|
330
|
+
T_1000
|
|
331
|
+
T_600
|
|
332
|
+
T_800
|
|
333
|
+
T_850
|
|
334
|
+
T_Bob
|
|
335
|
+
T_X
|
|
336
|
+
Talkie_Toaster
|
|
337
|
+
TARS
|
|
338
|
+
Terminus
|
|
339
|
+
Tet
|
|
340
|
+
The_Automaton
|
|
341
|
+
The_Cast_Iron_Man
|
|
342
|
+
The_Electric_Grandmother
|
|
343
|
+
The_Fury
|
|
344
|
+
The_Golden_Army
|
|
345
|
+
The_Gunslinger
|
|
346
|
+
The_Hangman
|
|
347
|
+
The_Iron_Giant
|
|
348
|
+
The_Iron_Man
|
|
349
|
+
The_Juggernaut
|
|
350
|
+
The_Mechanical_Cow
|
|
351
|
+
The_Mechanical_Dummy
|
|
352
|
+
The_Mechanical_Horse
|
|
353
|
+
The_Mechanical_Hound
|
|
354
|
+
The_One_Who_Waits
|
|
355
|
+
Tin_Man
|
|
356
|
+
Tik_Tok
|
|
357
|
+
Tilk
|
|
358
|
+
Tilly
|
|
359
|
+
Tima
|
|
360
|
+
Toaster
|
|
361
|
+
Tobor
|
|
362
|
+
Tom
|
|
363
|
+
Tom_Servo
|
|
364
|
+
Tony
|
|
365
|
+
Torg
|
|
366
|
+
Trace_Mayter
|
|
367
|
+
Trurl
|
|
368
|
+
Twonky
|
|
369
|
+
Ultron
|
|
370
|
+
Ulyssses
|
|
371
|
+
UniBlab
|
|
372
|
+
US_47
|
|
373
|
+
VINCENT
|
|
374
|
+
Vahki
|
|
375
|
+
Val
|
|
376
|
+
Valerie_23
|
|
377
|
+
Vanessa_Kensington
|
|
378
|
+
VAQ_M
|
|
379
|
+
Victor
|
|
380
|
+
Vision
|
|
381
|
+
VN_GO
|
|
382
|
+
Voltron
|
|
383
|
+
WALL_E
|
|
384
|
+
Walter_One
|
|
385
|
+
Weebo
|
|
386
|
+
Wilmer
|
|
387
|
+
XJ_9
|
|
388
|
+
Yod
|
|
389
|
+
Z_1
|
|
390
|
+
Z_2
|
|
391
|
+
Z_3
|
|
392
|
+
Zane_Gort
|
|
393
|
+
Zat
|
|
394
|
+
Zhora
|
|
395
|
+
Zoromes
|
|
396
|
+
].freeze
|
|
397
|
+
|
|
398
|
+
def self.name = names.first
|
|
399
|
+
def self.names(how_many = 1) = NAMES.sample(how_many).sort
|
|
400
|
+
end
|
data/lib/robot_lab/network.rb
CHANGED
|
@@ -87,6 +87,7 @@ module RobotLab
|
|
|
87
87
|
# task :billing, billing_robot, context: { dept: "billing" }, depends_on: :optional
|
|
88
88
|
# end
|
|
89
89
|
#
|
|
90
|
+
# :reek:ControlParameter -- `memory || ...` and `config || ...` are nil-safe defaults, not behavior selection.
|
|
90
91
|
def initialize(name:, concurrency: :auto, memory: nil, config: nil, parallel_mode: :async, &)
|
|
91
92
|
@name = name.to_s
|
|
92
93
|
@robots = {}
|
|
@@ -125,6 +126,7 @@ module RobotLab
|
|
|
125
126
|
# @example Task with dependencies
|
|
126
127
|
# task :writer, writer_robot, depends_on: [:analyst]
|
|
127
128
|
#
|
|
129
|
+
# :reek:LongParameterList -- one keyword per documented per-task option.
|
|
128
130
|
def task(name, robot, context: {}, mcp: :none, tools: :none, memory: nil, config: nil, depends_on: :none,
|
|
129
131
|
poller_group: :default)
|
|
130
132
|
task_wrapper = Task.new(
|
|
@@ -180,6 +182,7 @@ module RobotLab
|
|
|
180
182
|
# result.value # => RobotResult from last robot
|
|
181
183
|
# result.context[:classifier] # => RobotResult from classifier
|
|
182
184
|
#
|
|
185
|
+
# :reek:TooManyStatements -- linear assembly of run params and hook context before dispatch.
|
|
183
186
|
def run(message = nil, **run_context)
|
|
184
187
|
# Runnable protocol: accept a positional message like Robot#run does, so
|
|
185
188
|
# callers can `run(msg, ...)` uniformly. `run(message: msg)` still works.
|
|
@@ -200,12 +203,13 @@ module RobotLab
|
|
|
200
203
|
)
|
|
201
204
|
|
|
202
205
|
RobotLab::Hooks.run(:network_run, context, registries: [RobotLab.hooks, @hooks]) do
|
|
206
|
+
run_params = context.context
|
|
203
207
|
if @parallel_mode == :ractor
|
|
204
|
-
run_with_ractor_scheduler(
|
|
208
|
+
run_with_ractor_scheduler(run_params)
|
|
205
209
|
else
|
|
206
210
|
initial_result = SimpleFlow::Result.new(
|
|
207
|
-
|
|
208
|
-
context: { run_params:
|
|
211
|
+
run_params,
|
|
212
|
+
context: { run_params: run_params }
|
|
209
213
|
)
|
|
210
214
|
@pipeline.call_parallel(initial_result, max_concurrent: @config.max_concurrent_robots)
|
|
211
215
|
end
|
|
@@ -329,11 +333,12 @@ module RobotLab
|
|
|
329
333
|
# @raise [ArgumentError] if a robot with the same name already exists
|
|
330
334
|
#
|
|
331
335
|
def add_robot(robot)
|
|
332
|
-
|
|
333
|
-
|
|
336
|
+
name = robot.name
|
|
337
|
+
if @robots.key?(name)
|
|
338
|
+
raise ArgumentError, "Robot '#{name}' already exists in network '#{@name}'"
|
|
334
339
|
end
|
|
335
340
|
|
|
336
|
-
@robots[
|
|
341
|
+
@robots[name] = robot
|
|
337
342
|
self
|
|
338
343
|
end
|
|
339
344
|
|
|
@@ -398,6 +403,7 @@ module RobotLab
|
|
|
398
403
|
|
|
399
404
|
private
|
|
400
405
|
|
|
406
|
+
# :reek:TooManyStatements -- linear build-specs/run/shutdown sequence for the ractor scheduler.
|
|
401
407
|
def run_with_ractor_scheduler(run_context)
|
|
402
408
|
unless RobotLab.extension_loaded?(:ractor)
|
|
403
409
|
raise RobotLab::DependencyError,
|
|
@@ -419,6 +425,7 @@ module RobotLab
|
|
|
419
425
|
results
|
|
420
426
|
end
|
|
421
427
|
|
|
428
|
+
# :reek:FeatureEnvy -- snapshotting a robot's identity fields into a Ractor-shareable spec is this method's job.
|
|
422
429
|
def build_robot_spec(task_wrapper)
|
|
423
430
|
robot = task_wrapper.robot
|
|
424
431
|
RobotSpec.new(
|
|
@@ -40,6 +40,8 @@ module RobotLab
|
|
|
40
40
|
# @param message [String]
|
|
41
41
|
# @param threshold [Float] cosine similarity cutoff (default SIMILARITY_THRESHOLD)
|
|
42
42
|
# @return [Array<AgentSkill>]
|
|
43
|
+
# :reek:TooManyStatements -- linear search/filter with a best-effort rescue fallback.
|
|
44
|
+
# :reek:NestedIterators -- 2-deep filter_map/find joining search hits back to pending skills.
|
|
43
45
|
def match_agent_skills(message, threshold: SIMILARITY_THRESHOLD)
|
|
44
46
|
return [] if @pending_agent_skills.nil? || @pending_agent_skills.empty?
|
|
45
47
|
|
|
@@ -90,9 +92,7 @@ module RobotLab
|
|
|
90
92
|
#
|
|
91
93
|
# @return [String, nil]
|
|
92
94
|
def current_agent_skill_instructions
|
|
93
|
-
|
|
94
|
-
sys = messages&.find { |m| m.role.to_s == "system" }
|
|
95
|
-
sys&.content
|
|
95
|
+
current_system_instructions
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
end
|
|
@@ -12,9 +12,15 @@ module RobotLab
|
|
|
12
12
|
# == Delivery Serialization
|
|
13
13
|
#
|
|
14
14
|
# TypedBus delivers messages in concurrent Async fibers. Robots
|
|
15
|
-
# enqueue deliveries into a BusPoller rather than
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# enqueue deliveries into a shared BusPoller rather than dispatching
|
|
16
|
+
# them straight to the handler. Despite the name, BusPoller runs no
|
|
17
|
+
# background thread: `enqueue` processes the delivery inline in the
|
|
18
|
+
# caller's own execution context (Async fiber or OS thread) when the
|
|
19
|
+
# robot is idle, and otherwise queues it behind the delivery already
|
|
20
|
+
# in flight and drains it once that one returns. A mutex therefore
|
|
21
|
+
# serializes deliveries per robot, so a robot's run() calls never
|
|
22
|
+
# interleave — but nothing makes progress while the calling fiber is
|
|
23
|
+
# parked.
|
|
18
24
|
#
|
|
19
25
|
# Owns: @bus, @bus_poller, @private_bus_poller, @bus_poller_group, @bus_subscriber_id, @message_counter, @outbox, @message_handler
|
|
20
26
|
# Reads: @name
|
|
@@ -78,12 +84,14 @@ module RobotLab
|
|
|
78
84
|
# counterpart to how a Cyborg answers its human — one call makes any bus
|
|
79
85
|
# member a first-class responder instead of hand-wiring {#on_message}.
|
|
80
86
|
#
|
|
81
|
-
# The responder runs
|
|
82
|
-
#
|
|
87
|
+
# The responder runs inline in the caller's execution context (BusPoller has
|
|
88
|
+
# no drain thread), and deliveries to this member are serialized, so a long
|
|
89
|
+
# turn blocks both the sender and the next inbound message.
|
|
83
90
|
#
|
|
84
91
|
# @param auto_reply [Boolean] send the responder's result back to the sender
|
|
85
92
|
# @yield [message] the inbound task; return the reply content (nil => no reply)
|
|
86
93
|
# @return [self]
|
|
94
|
+
# :reek:BooleanParameter :reek:ControlParameter -- auto_reply is a documented public API toggle for reply behavior.
|
|
87
95
|
def respond_to_tasks(auto_reply: true, &responder)
|
|
88
96
|
on_message do |message|
|
|
89
97
|
next if message.reply?
|
|
@@ -100,6 +108,7 @@ module RobotLab
|
|
|
100
108
|
#
|
|
101
109
|
# @param auto_reply [Boolean]
|
|
102
110
|
# @return [self]
|
|
111
|
+
# :reek:BooleanParameter -- auto_reply is a documented public API toggle, forwarded to respond_to_tasks.
|
|
103
112
|
def serve(auto_reply: true)
|
|
104
113
|
respond_to_tasks(auto_reply: auto_reply) { |message| run(bus_task_content(message)).reply }
|
|
105
114
|
end
|
|
@@ -154,6 +163,7 @@ module RobotLab
|
|
|
154
163
|
# @param bus [TypedBus::MessageBus, nil] bus to join (creates one if nil)
|
|
155
164
|
# @return [self]
|
|
156
165
|
#
|
|
166
|
+
# :reek:ControlParameter -- `bus || @bus || new` implements the documented join-or-create semantics.
|
|
157
167
|
def with_bus(bus = nil)
|
|
158
168
|
return self if bus && @bus == bus
|
|
159
169
|
|
|
@@ -165,8 +175,9 @@ module RobotLab
|
|
|
165
175
|
|
|
166
176
|
# Assign a shared BusPoller from a Network.
|
|
167
177
|
#
|
|
168
|
-
#
|
|
169
|
-
# the network's shared poller for the given group.
|
|
178
|
+
# Drops any private poller this robot auto-created, then adopts
|
|
179
|
+
# the network's shared poller for the given group. Called by
|
|
180
|
+
# Network#task; groups are informational labels only.
|
|
170
181
|
#
|
|
171
182
|
# @param poller [BusPoller] the network's shared poller
|
|
172
183
|
# @param group [Symbol] poller group for this robot (default: :default)
|
|
@@ -223,7 +234,7 @@ module RobotLab
|
|
|
223
234
|
@bus_poller.enqueue(robot: self, delivery: delivery, group: @bus_poller_group)
|
|
224
235
|
end
|
|
225
236
|
|
|
226
|
-
# Process a single delivery (called by BusPoller drain
|
|
237
|
+
# Process a single delivery (called by BusPoller during its inline drain).
|
|
227
238
|
def process_delivery(delivery)
|
|
228
239
|
message = delivery.message
|
|
229
240
|
correlate_reply(message) if message.reply?
|
|
@@ -32,6 +32,8 @@ module RobotLab
|
|
|
32
32
|
# @param limit [Integer] maximum number of results to return (default 5)
|
|
33
33
|
# @return [Array<HistoryResult>] results sorted by score descending
|
|
34
34
|
# @raise [RobotLab::DependencyError] if the 'classifier' gem is not installed
|
|
35
|
+
# :reek:TooManyStatements -- linear vectorize/score/collect scan over the chat history.
|
|
36
|
+
# :reek:FeatureEnvy -- scoring each message's extracted text against the query is the search itself.
|
|
35
37
|
def search_history(query, limit: 5)
|
|
36
38
|
TextAnalysis.require_classifier!
|
|
37
39
|
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
module RobotLab
|
|
4
4
|
class Robot < RubyLLM::Agent
|
|
5
5
|
module Hooking
|
|
6
|
+
# :reek:LongParameterList -- the documented Robot#run public API: each keyword is a distinct run-scoped override.
|
|
7
|
+
# :reek:TooManyStatements -- the run lifecycle (memory writer swap, hook wrap, budget, cleanup) is one
|
|
8
|
+
# deliberate orchestrator; flog gates its complexity.
|
|
6
9
|
def run(message = nil, network: nil, task: nil, network_memory: nil, network_config: nil,
|
|
7
10
|
memory: nil, mcp: :none, tools: :none, hooks: nil, **kwargs, &block)
|
|
8
11
|
run_memory = resolve_run_memory(memory, network: network, network_memory: network_memory)
|
|
@@ -11,6 +11,7 @@ module RobotLab
|
|
|
11
11
|
private
|
|
12
12
|
|
|
13
13
|
# Resolve MCP hierarchy: runtime -> robot build -> network -> config
|
|
14
|
+
# :reek:ControlParameter -- `network_config&.mcp || ...` is the documented fallback cascade, not a mode switch.
|
|
14
15
|
def resolve_mcp_hierarchy(runtime_value, network: nil, network_config: nil)
|
|
15
16
|
parent_value = network_config&.mcp || network_parent_config(network)&.mcp || RobotLab.config.mcp
|
|
16
17
|
build_resolved = ToolConfig.resolve_mcp(@mcp_config, parent_value: parent_value)
|
|
@@ -18,6 +19,7 @@ module RobotLab
|
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
# Resolve tools hierarchy: runtime -> robot build -> network -> config
|
|
22
|
+
# :reek:ControlParameter -- `network_config&.tools || ...` is the documented fallback cascade, not a mode switch.
|
|
21
23
|
def resolve_tools_hierarchy(runtime_value, network: nil, network_config: nil)
|
|
22
24
|
parent_value = network_config&.tools || network_parent_config(network)&.tools || RobotLab.config.tools
|
|
23
25
|
build_resolved = ToolConfig.resolve_tools(@tools_config, parent_value: parent_value)
|
|
@@ -32,6 +34,7 @@ module RobotLab
|
|
|
32
34
|
|
|
33
35
|
# Ensure MCP clients are initialized for the given server configs.
|
|
34
36
|
# On subsequent calls, retries any servers that previously failed to connect.
|
|
37
|
+
# :reek:TooManyStatements -- first-run init vs retry paths share the needed-server list; linear either way.
|
|
35
38
|
def ensure_mcp_clients(mcp_servers)
|
|
36
39
|
return if mcp_servers.empty?
|
|
37
40
|
|
|
@@ -54,6 +57,7 @@ module RobotLab
|
|
|
54
57
|
@mcp_initialized = true
|
|
55
58
|
end
|
|
56
59
|
|
|
60
|
+
# :reek:TooManyStatements -- connect success/failure bookkeeping plus the rescue path for one server.
|
|
57
61
|
def init_mcp_client(server_config)
|
|
58
62
|
client = MCP::Client.new(server_config)
|
|
59
63
|
client.connect
|
|
@@ -78,6 +82,7 @@ module RobotLab
|
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
# Retry connecting to servers that previously failed
|
|
85
|
+
# :reek:TooManyStatements -- per-server retry with success bookkeeping and a best-effort rescue.
|
|
81
86
|
def retry_failed_servers(_mcp_servers, needed_servers)
|
|
82
87
|
return if @failed_mcp_configs.nil? || @failed_mcp_configs.empty?
|
|
83
88
|
|
|
@@ -85,8 +90,9 @@ module RobotLab
|
|
|
85
90
|
to_retry = @failed_mcp_configs.slice(*needed_servers)
|
|
86
91
|
return if to_retry.empty?
|
|
87
92
|
|
|
93
|
+
logger = RobotLab.config.logger
|
|
88
94
|
to_retry.each do |name, server_config|
|
|
89
|
-
|
|
95
|
+
logger.info(
|
|
90
96
|
"Robot '#{@name}' retrying MCP server: #{name}"
|
|
91
97
|
)
|
|
92
98
|
|
|
@@ -97,17 +103,19 @@ module RobotLab
|
|
|
97
103
|
@mcp_clients[name] = client
|
|
98
104
|
@failed_mcp_configs.delete(name)
|
|
99
105
|
discover_mcp_tools(client, name)
|
|
100
|
-
|
|
106
|
+
logger.info(
|
|
101
107
|
"Robot '#{@name}' successfully connected to MCP server '#{name}' on retry"
|
|
102
108
|
)
|
|
103
109
|
end
|
|
104
110
|
rescue StandardError => e
|
|
105
|
-
|
|
111
|
+
logger.warn(
|
|
106
112
|
"Robot '#{@name}' retry failed for MCP server '#{name}': #{e.message}"
|
|
107
113
|
)
|
|
108
114
|
end
|
|
109
115
|
end
|
|
110
116
|
|
|
117
|
+
# :reek:FeatureEnvy -- adapting each MCP tool definition into a local Tool is exactly this method's purpose.
|
|
118
|
+
# :reek:NestedIterators -- the inner block is the tool's execution closure, not an iteration.
|
|
111
119
|
def discover_mcp_tools(client, server_name)
|
|
112
120
|
tools = client.list_tools
|
|
113
121
|
|