robot_lab 0.2.6 → 0.2.7

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.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +124 -64
  3. data/docs/api/core/index.md +41 -15
  4. data/docs/api/core/memory.md +247 -29
  5. data/docs/api/core/network.md +255 -33
  6. data/docs/api/core/result.md +120 -32
  7. data/docs/api/core/robot.md +551 -61
  8. data/docs/api/core/state.md +87 -197
  9. data/docs/api/core/tool.md +165 -20
  10. data/docs/api/errors.md +110 -17
  11. data/docs/api/hooks.md +469 -0
  12. data/docs/api/index.md +80 -7
  13. data/docs/api/mcp/client.md +129 -35
  14. data/docs/api/mcp/index.md +164 -23
  15. data/docs/api/mcp/server.md +27 -3
  16. data/docs/api/mcp/transports.md +94 -22
  17. data/docs/api/messages/index.md +26 -3
  18. data/docs/api/messages/text-message.md +33 -11
  19. data/docs/api/messages/tool-call-message.md +27 -4
  20. data/docs/api/messages/tool-result-message.md +23 -4
  21. data/docs/api/messages/user-message.md +45 -8
  22. data/docs/api/skills.md +519 -0
  23. data/docs/api/streaming/context.md +28 -5
  24. data/docs/api/streaming/index.md +57 -11
  25. data/docs/api/support.md +846 -0
  26. data/docs/architecture/core-concepts.md +79 -31
  27. data/docs/architecture/index.md +86 -11
  28. data/docs/architecture/message-flow.md +66 -29
  29. data/docs/architecture/network-orchestration.md +145 -38
  30. data/docs/architecture/robot-execution.md +172 -90
  31. data/docs/architecture/state-management.md +31 -12
  32. data/docs/concepts.md +176 -21
  33. data/docs/examples/basic-chat.md +72 -19
  34. data/docs/examples/index.md +117 -31
  35. data/docs/examples/mcp-server.md +154 -45
  36. data/docs/examples/multi-robot-network.md +91 -21
  37. data/docs/examples/tool-usage.md +104 -37
  38. data/docs/getting-started/configuration.md +284 -97
  39. data/docs/getting-started/installation.md +53 -41
  40. data/docs/getting-started/quick-start.md +51 -6
  41. data/docs/guides/building-robots.md +258 -50
  42. data/docs/guides/creating-networks.md +214 -30
  43. data/docs/guides/hooks.md +141 -54
  44. data/docs/guides/knowledge.md +35 -4
  45. data/docs/guides/mcp-integration.md +211 -44
  46. data/docs/guides/memory.md +103 -12
  47. data/docs/guides/observability.md +95 -47
  48. data/docs/guides/streaming.md +184 -125
  49. data/docs/guides/using-tools.md +237 -17
  50. data/docs/index.md +36 -4
  51. data/examples/01_simple_robot.rb +2 -2
  52. data/examples/02_tools.rb +14 -4
  53. data/examples/03_network.rb +12 -7
  54. data/examples/04_mcp.rb +11 -4
  55. data/examples/05_streaming.rb +8 -5
  56. data/examples/06_prompt_templates.rb +13 -9
  57. data/examples/07_network_memory.rb +5 -5
  58. data/examples/08_llm_config.rb +20 -15
  59. data/examples/09_chaining.rb +4 -4
  60. data/examples/11_network_introspection.rb +4 -4
  61. data/examples/12_message_bus.rb +2 -2
  62. data/examples/13_spawn.rb +2 -2
  63. data/examples/14_rusty_circuit/README.md +1 -0
  64. data/examples/14_rusty_circuit/comic.rb +7 -3
  65. data/examples/14_rusty_circuit/display.rb +14 -0
  66. data/examples/14_rusty_circuit/heckler.rb +8 -6
  67. data/examples/14_rusty_circuit/open_mic.rb +17 -6
  68. data/examples/14_rusty_circuit/scout.rb +17 -10
  69. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +14 -10
  70. data/examples/15_memory_network_and_bus/linux_writer.rb +2 -2
  71. data/examples/15_memory_network_and_bus/os_editor.rb +3 -1
  72. data/examples/15_memory_network_and_bus/os_writer.rb +4 -1
  73. data/examples/16_writers_room/writer.rb +22 -22
  74. data/examples/16_writers_room/writers_room.rb +2 -0
  75. data/examples/17_skills.rb +14 -13
  76. data/examples/18_rails/README.md +20 -1
  77. data/examples/18_rails/app/controllers/chat_controller.rb +5 -1
  78. data/examples/18_rails/app/jobs/robot_run_job.rb +11 -5
  79. data/examples/18_rails/app/robots/chat_robot.rb +11 -0
  80. data/examples/18_rails/config/initializers/robot_lab.rb +8 -0
  81. data/examples/19_token_tracking.rb +25 -9
  82. data/examples/20_circuit_breaker.rb +10 -7
  83. data/examples/21_learning_loop.rb +42 -16
  84. data/examples/22_context_compression.rb +23 -23
  85. data/examples/23_convergence.rb +24 -17
  86. data/examples/24_structured_delegation.rb +13 -8
  87. data/examples/25_history_search.rb +12 -8
  88. data/examples/27_incident_response/incident_response.rb +31 -13
  89. data/examples/28_mcp_discovery.rb +17 -13
  90. data/examples/29_ractor_tools.rb +4 -2
  91. data/examples/30_ractor_network.rb +22 -17
  92. data/examples/31_launch_assessment.rb +20 -9
  93. data/examples/32_newsletter_reader.rb +7 -2
  94. data/examples/33_stock_predictor.rb +34 -13
  95. data/examples/34_agentskills.rb +7 -3
  96. data/examples/35_hooks.rb +18 -8
  97. data/examples/README.md +199 -45
  98. data/examples/common.rb +79 -11
  99. data/examples/xyzzy.rb +8 -1
  100. data/lib/robot_lab/config.rb +10 -5
  101. data/lib/robot_lab/names.rb +402 -0
  102. data/lib/robot_lab/robot/agent_skill_matching.rb +1 -3
  103. data/lib/robot_lab/robot/bus_messaging.rb +16 -8
  104. data/lib/robot_lab/robot/template_rendering.rb +16 -3
  105. data/lib/robot_lab/robot.rb +23 -2
  106. data/lib/robot_lab/version.rb +1 -1
  107. data/lib/robot_lab.rb +21 -15
  108. data/mkdocs.yml +6 -1
  109. metadata +7 -2
@@ -0,0 +1,402 @@
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 Metrics/ModuleLength
6
+ module RobotLab
7
+ # Fictional robot names
8
+ # rubocop:disable 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
+ # rubocop:enable Metrics/CollectionLiteralLength
398
+
399
+ def self.name = names.first
400
+ def self.names(how_many = 1) = NAMES.sample(how_many).sort
401
+ end
402
+ # rubocop:enable Metrics/ModuleLength
@@ -90,9 +90,7 @@ module RobotLab
90
90
  #
91
91
  # @return [String, nil]
92
92
  def current_agent_skill_instructions
93
- messages = @chat.instance_variable_get(:@messages)
94
- sys = messages&.find { |m| m.role.to_s == "system" }
95
- sys&.content
93
+ current_system_instructions
96
94
  end
97
95
  end
98
96
  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 handling them
16
- # inline. The BusPoller drains each group's queue sequentially on
17
- # a dedicated OS thread, so robot.run() calls never interleave.
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,8 +84,9 @@ 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 on the poller drain thread, so deliveries to this member
82
- # are handled one at a time (a long turn delays the next inbound message).
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)
@@ -165,8 +172,9 @@ module RobotLab
165
172
 
166
173
  # Assign a shared BusPoller from a Network.
167
174
  #
168
- # Stops any private poller this robot auto-created, then adopts
169
- # the network's shared poller for the given group.
175
+ # Drops any private poller this robot auto-created, then adopts
176
+ # the network's shared poller for the given group. Called by
177
+ # Network#task; groups are informational labels only.
170
178
  #
171
179
  # @param poller [BusPoller] the network's shared poller
172
180
  # @param group [Symbol] poller group for this robot (default: :default)
@@ -223,7 +231,7 @@ module RobotLab
223
231
  @bus_poller.enqueue(robot: self, delivery: delivery, group: @bus_poller_group)
224
232
  end
225
233
 
226
- # Process a single delivery (called by BusPoller drain thread).
234
+ # Process a single delivery (called by BusPoller during its inline drain).
227
235
  def process_delivery(delivery)
228
236
  message = delivery.message
229
237
  correlate_reply(message) if message.reply?
@@ -64,6 +64,10 @@ module RobotLab
64
64
 
65
65
  # Re-render the template with run-time context merged into build-time context.
66
66
  # prompt_manager parameters may be required (null) and only available at run time.
67
+ #
68
+ # Re-rendering replaces the system message, so the inline system_prompt must be
69
+ # re-appended here exactly as apply_system_prompt does at construction --
70
+ # otherwise it would be silently dropped on any run that supplies context.
67
71
  def rerender_template(run_context)
68
72
  merged = (@build_context || {}).merge(run_context)
69
73
  resolved_ctx = resolve_context(merged, network: nil)
@@ -81,15 +85,24 @@ module RobotLab
81
85
  bodies << body if body
82
86
  end
83
87
 
84
- combined = bodies.join("\n\n")
85
- @chat.with_instructions(combined)
88
+ @chat.with_instructions(with_system_prompt_appended(bodies.join("\n\n")))
86
89
  else
87
90
  parsed = PM.parse(@template)
88
91
  rendered = parsed.to_s(**resolved_ctx)
89
- @chat.with_instructions(rendered)
92
+ @chat.with_instructions(with_system_prompt_appended(rendered))
90
93
  end
91
94
  end
92
95
 
96
+ # Append the inline system_prompt to freshly rendered template text.
97
+ #
98
+ # @param rendered [String] newly rendered template body
99
+ # @return [String] rendered text with system_prompt appended, if one is set
100
+ def with_system_prompt_appended(rendered)
101
+ return rendered unless @system_prompt
102
+
103
+ [rendered, @system_prompt].reject { |s| s.to_s.empty? }.join("\n\n")
104
+ end
105
+
93
106
  # Orchestrate skill expansion and template application.
94
107
  #
95
108
  # @param skill_ids [Array<Symbol>] skill IDs from constructor + front matter
@@ -666,8 +666,27 @@ module RobotLab
666
666
  end
667
667
  end
668
668
 
669
+ # Append the inline system prompt to whatever apply_template already set.
670
+ #
671
+ # The template renders first and establishes the base instructions; the
672
+ # inline system_prompt is appended so both survive. Combining into a single
673
+ # system message (rather than using with_instructions(append: true), which
674
+ # adds a second one) keeps readers that look at only the first system
675
+ # message -- notably AgentSkillMatching's snapshot/restore -- correct.
669
676
  def apply_system_prompt
670
- @chat.with_instructions(@system_prompt) if @system_prompt
677
+ return unless @system_prompt
678
+
679
+ base = current_system_instructions.to_s
680
+ combined = [base, @system_prompt].reject(&:empty?).join("\n\n")
681
+ @chat.with_instructions(combined)
682
+ end
683
+
684
+ # Content of the chat's system message, or nil when none is set.
685
+ #
686
+ # @return [String, nil]
687
+ def current_system_instructions
688
+ messages = @chat.instance_variable_get(:@messages)
689
+ messages&.find { |m| m.role.to_s == "system" }&.content
671
690
  end
672
691
 
673
692
  def apply_chat_params
@@ -757,7 +776,9 @@ module RobotLab
757
776
  # is the definitive choke point: tools are fully resolved (MCP connected)
758
777
  # and about to be handed to the chat, so the cap holds no matter how the
759
778
  # tools were configured, filtered, or connected. Cap value comes from
760
- # RunConfig#max_tools, defaulting to DEFAULT_MAX_TOOLS; nil/<=0 disables it.
779
+ # RunConfig#max_tools, defaulting to DEFAULT_MAX_TOOLS; a nil, zero, or
780
+ # negative max_tools falls back to that default, so the cap cannot be
781
+ # disabled from configuration.
761
782
  #
762
783
  # @param tools [Array<Tool>] the resolved tools
763
784
  # @return [Array<Tool>] at most `max_tools` tools
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RobotLab
4
- VERSION = "0.2.6"
4
+ VERSION = "0.2.7"
5
5
  end
data/lib/robot_lab.rb CHANGED
@@ -24,9 +24,9 @@ require 'typed_bus'
24
24
  #
25
25
  # @example Creating a network of robots
26
26
  # network = RobotLab.create_network(name: "pipeline") do
27
- # step :analyzer, analyzer, depends_on: :none
28
- # step :writer, writer, depends_on: [:analyzer]
29
- # step :reviewer, reviewer, depends_on: [:writer]
27
+ # task :analyzer, analyzer, depends_on: :none
28
+ # task :writer, writer, depends_on: [:analyzer]
29
+ # task :reviewer, reviewer, depends_on: [:writer]
30
30
  # end
31
31
  # result = network.run(message: "Process this document")
32
32
  #
@@ -35,7 +35,7 @@ require 'typed_bus'
35
35
  # # ROBOT_LAB_DEFAULT_MODEL=gpt-4
36
36
  # # ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY=sk-ant-...
37
37
  #
38
- # # Or via config files (~/.config/robot_lab/config.yml or ./config/robot_lab.yml)
38
+ # # Or via config files (~/.config/robot_lab/robot_lab.yml or ./config/robot_lab.yml)
39
39
  # # See lib/robot_lab/config/defaults.yml for all options
40
40
  #
41
41
  # # Access configuration values:
@@ -47,6 +47,7 @@ end
47
47
 
48
48
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
49
49
  loader.ignore("#{__dir__}/robot_lab/robot")
50
+ loader.ignore("#{__dir__}/robot_lab/names.rb")
50
51
 
51
52
  # Custom inflections for classes that don't follow Zeitwerk naming conventions
52
53
  loader.inflector.inflect(
@@ -71,6 +72,11 @@ require_relative 'robot_lab/hooks'
71
72
  require_relative 'robot_lab/message'
72
73
  require_relative 'robot_lab/memory'
73
74
 
75
+ # names.rb defines the NAMES data constant plus helper methods directly on
76
+ # RobotLab, not a RobotLab::Names class/module, so Zeitwerk can't autoload it
77
+ # by convention — ignored above and required explicitly instead.
78
+ require_relative 'robot_lab/names'
79
+
74
80
  # Eager load everything in Rails or when explicitly requested.
75
81
  # Otherwise Zeitwerk's lazy autoloading keeps boot fast.
76
82
  loader.eager_load if defined?(Rails::Engine) || ENV["ROBOT_LAB_EAGER_LOAD"]
@@ -145,7 +151,7 @@ module RobotLab
145
151
  # Configuration is automatically loaded from:
146
152
  # - Bundled defaults (lib/robot_lab/config/defaults.yml)
147
153
  # - Environment-specific overrides (development, test, production)
148
- # - XDG config files (~/.config/robot_lab/config.yml)
154
+ # - XDG config file (~/.config/robot_lab/robot_lab.yml)
149
155
  # - Project config (./config/robot_lab.yml)
150
156
  # - Environment variables (ROBOT_LAB_*)
151
157
  #
@@ -246,28 +252,28 @@ module RobotLab
246
252
  #
247
253
  # @param name [String] the unique identifier for the network
248
254
  # @param concurrency [Symbol] concurrency model (:auto, :threads, :async)
249
- # @yield Block for defining pipeline steps
255
+ # @yield Block for defining pipeline tasks (the DSL method is `task`)
250
256
  # @return [Network] a new Network instance
251
257
  #
252
258
  # @example Sequential pipeline
253
259
  # network = RobotLab.create_network(name: "pipeline") do
254
- # step :first, robot1, depends_on: :none
255
- # step :second, robot2, depends_on: [:first]
260
+ # task :first, robot1, depends_on: :none
261
+ # task :second, robot2, depends_on: [:first]
256
262
  # end
257
263
  #
258
264
  # @example With optional routing
259
265
  # network = RobotLab.create_network(name: "support") do
260
- # step :classifier, classifier, depends_on: :none
261
- # step :billing, billing_robot, depends_on: :optional
262
- # step :technical, technical_robot, depends_on: :optional
266
+ # task :classifier, classifier, depends_on: :none
267
+ # task :billing, billing_robot, depends_on: :optional
268
+ # task :technical, technical_robot, depends_on: :optional
263
269
  # end
264
270
  #
265
271
  # @example Parallel execution
266
272
  # network = RobotLab.create_network(name: "analysis") do
267
- # step :fetch, fetcher, depends_on: :none
268
- # step :sentiment, sentiment_bot, depends_on: [:fetch]
269
- # step :entities, entity_bot, depends_on: [:fetch]
270
- # step :merge, merger, depends_on: [:sentiment, :entities]
273
+ # task :fetch, fetcher, depends_on: :none
274
+ # task :sentiment, sentiment_bot, depends_on: [:fetch]
275
+ # task :entities, entity_bot, depends_on: [:fetch]
276
+ # task :merge, merger, depends_on: [:sentiment, :entities]
271
277
  # end
272
278
  def create_network(name:, concurrency: :auto, config: nil, &)
273
279
  Network.new(name: name, concurrency: concurrency, config: config, &)
data/mkdocs.yml CHANGED
@@ -177,10 +177,15 @@ nav:
177
177
  - Core Classes:
178
178
  - api/core/index.md
179
179
  - Robot: api/core/robot.md
180
+ - RobotResult: api/core/result.md
180
181
  - Network: api/core/network.md
181
- - State: api/core/state.md
182
182
  - Tool: api/core/tool.md
183
183
  - Memory: api/core/memory.md
184
+ - StateProxy: api/core/state.md
185
+ - Hooks: api/hooks.md
186
+ - Skills: api/skills.md
187
+ - Support Classes: api/support.md
188
+ - Errors: api/errors.md
184
189
  - Messages:
185
190
  - api/messages/index.md
186
191
  - UserMessage: api/messages/user-message.md
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robot_lab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
@@ -235,6 +235,7 @@ files:
235
235
  - docs/api/core/state.md
236
236
  - docs/api/core/tool.md
237
237
  - docs/api/errors.md
238
+ - docs/api/hooks.md
238
239
  - docs/api/index.md
239
240
  - docs/api/mcp/client.md
240
241
  - docs/api/mcp/index.md
@@ -245,9 +246,11 @@ files:
245
246
  - docs/api/messages/tool-call-message.md
246
247
  - docs/api/messages/tool-result-message.md
247
248
  - docs/api/messages/user-message.md
249
+ - docs/api/skills.md
248
250
  - docs/api/streaming/context.md
249
251
  - docs/api/streaming/events.md
250
252
  - docs/api/streaming/index.md
253
+ - docs/api/support.md
251
254
  - docs/architecture/core-concepts.md
252
255
  - docs/architecture/index.md
253
256
  - docs/architecture/message-flow.md
@@ -295,6 +298,7 @@ files:
295
298
  - examples/13_spawn.rb
296
299
  - examples/14_rusty_circuit/.envrc
297
300
  - examples/14_rusty_circuit/.gitignore
301
+ - examples/14_rusty_circuit/README.md
298
302
  - examples/14_rusty_circuit/comic.rb
299
303
  - examples/14_rusty_circuit/display.rb
300
304
  - examples/14_rusty_circuit/heckler.rb
@@ -473,6 +477,7 @@ files:
473
477
  - lib/robot_lab/memory.rb
474
478
  - lib/robot_lab/memory_change.rb
475
479
  - lib/robot_lab/message.rb
480
+ - lib/robot_lab/names.rb
476
481
  - lib/robot_lab/narrator.rb
477
482
  - lib/robot_lab/network.rb
478
483
  - lib/robot_lab/robot.rb
@@ -536,7 +541,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
536
541
  - !ruby/object:Gem::Version
537
542
  version: '0'
538
543
  requirements: []
539
- rubygems_version: 4.0.17
544
+ rubygems_version: 4.0.19
540
545
  specification_version: 4
541
546
  summary: Ruby framework for building and orchestrating multi-robot LLM workflows
542
547
  test_files: []