robot_lab 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
  5. data/lib/robot_lab/version.rb +1 -1
  6. metadata +3 -253
  7. data/.architecture/AGENTS.md +0 -32
  8. data/.architecture/config.yml +0 -8
  9. data/.architecture/members.yml +0 -60
  10. data/.architecture/reviews/feature-free-will.md +0 -490
  11. data/.architecture/reviews/overall-codebase.md +0 -427
  12. data/.claude/settings.local.json +0 -57
  13. data/.codex/config.toml +0 -2
  14. data/.envrc +0 -6
  15. data/.github/workflows/deploy-github-pages.yml +0 -52
  16. data/.irbrc +0 -6
  17. data/.loki +0 -65
  18. data/.quality/reek_baseline.txt +0 -43
  19. data/.rubocop.yml +0 -10
  20. data/Archspec.rb +0 -44
  21. data/CLAUDE.md +0 -141
  22. data/COMMITS.md +0 -196
  23. data/Rakefile +0 -193
  24. data/_typos.toml +0 -21
  25. data/agent2agent_review.md +0 -192
  26. data/agentf_improvements.md +0 -253
  27. data/agents.md +0 -14
  28. data/docs/api/core/index.md +0 -147
  29. data/docs/api/core/memory.md +0 -578
  30. data/docs/api/core/network.md +0 -553
  31. data/docs/api/core/result.md +0 -211
  32. data/docs/api/core/robot.md +0 -1667
  33. data/docs/api/core/state.md +0 -145
  34. data/docs/api/core/tool.md +0 -520
  35. data/docs/api/errors.md +0 -323
  36. data/docs/api/hooks.md +0 -469
  37. data/docs/api/index.md +0 -137
  38. data/docs/api/mcp/client.md +0 -387
  39. data/docs/api/mcp/index.md +0 -267
  40. data/docs/api/mcp/server.md +0 -252
  41. data/docs/api/mcp/transports.md +0 -339
  42. data/docs/api/messages/index.md +0 -126
  43. data/docs/api/messages/text-message.md +0 -170
  44. data/docs/api/messages/tool-call-message.md +0 -206
  45. data/docs/api/messages/tool-result-message.md +0 -242
  46. data/docs/api/messages/user-message.md +0 -232
  47. data/docs/api/skills.md +0 -423
  48. data/docs/api/streaming/context.md +0 -280
  49. data/docs/api/streaming/events.md +0 -185
  50. data/docs/api/streaming/index.md +0 -156
  51. data/docs/api/support.md +0 -846
  52. data/docs/architecture/core-concepts.md +0 -575
  53. data/docs/architecture/index.md +0 -252
  54. data/docs/architecture/message-flow.md +0 -366
  55. data/docs/architecture/network-orchestration.md +0 -478
  56. data/docs/architecture/robot-execution.md +0 -396
  57. data/docs/architecture/state-management.md +0 -410
  58. data/docs/assets/css/custom.css +0 -56
  59. data/docs/assets/images/robot_lab.jpg +0 -0
  60. data/docs/concepts.md +0 -641
  61. data/docs/examples/basic-chat.md +0 -258
  62. data/docs/examples/index.md +0 -425
  63. data/docs/examples/mcp-server.md +0 -403
  64. data/docs/examples/multi-robot-network.md +0 -476
  65. data/docs/examples/tool-usage.md +0 -468
  66. data/docs/getting-started/configuration.md +0 -645
  67. data/docs/getting-started/index.md +0 -56
  68. data/docs/getting-started/installation.md +0 -197
  69. data/docs/getting-started/quick-start.md +0 -293
  70. data/docs/guides/building-robots.md +0 -1187
  71. data/docs/guides/creating-networks.md +0 -736
  72. data/docs/guides/hooks.md +0 -1206
  73. data/docs/guides/index.md +0 -78
  74. data/docs/guides/knowledge.md +0 -219
  75. data/docs/guides/mcp-integration.md +0 -740
  76. data/docs/guides/memory.md +0 -458
  77. data/docs/guides/observability.md +0 -733
  78. data/docs/guides/streaming.md +0 -323
  79. data/docs/guides/using-tools.md +0 -780
  80. data/docs/index.md +0 -280
  81. data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
  82. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
  83. data/examples/.envrc +0 -3
  84. data/examples/01_simple_robot.rb +0 -31
  85. data/examples/02_tools.rb +0 -109
  86. data/examples/03_network.rb +0 -118
  87. data/examples/04_mcp.rb +0 -217
  88. data/examples/05_streaming.rb +0 -137
  89. data/examples/06_prompt_templates.rb +0 -325
  90. data/examples/07_network_memory.rb +0 -313
  91. data/examples/08_llm_config.rb +0 -162
  92. data/examples/09_chaining.rb +0 -251
  93. data/examples/10_memory.rb +0 -315
  94. data/examples/11_network_introspection.rb +0 -239
  95. data/examples/12_message_bus.rb +0 -67
  96. data/examples/13_spawn.rb +0 -85
  97. data/examples/14_rusty_circuit/.envrc +0 -1
  98. data/examples/14_rusty_circuit/.gitignore +0 -1
  99. data/examples/14_rusty_circuit/README.md +0 -1
  100. data/examples/14_rusty_circuit/comic.rb +0 -149
  101. data/examples/14_rusty_circuit/display.rb +0 -217
  102. data/examples/14_rusty_circuit/heckler.rb +0 -65
  103. data/examples/14_rusty_circuit/open_mic.rb +0 -132
  104. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
  105. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
  106. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
  107. data/examples/14_rusty_circuit/scout.rb +0 -165
  108. data/examples/14_rusty_circuit/show.log +0 -234
  109. data/examples/15_memory_network_and_bus/.envrc +0 -1
  110. data/examples/15_memory_network_and_bus/README.md +0 -66
  111. data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
  112. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
  113. data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
  114. data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
  115. data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
  116. data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
  117. data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
  118. data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
  119. data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
  120. data/examples/15_memory_network_and_bus/output/memory.json +0 -13
  121. data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
  122. data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
  123. data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
  124. data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
  125. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
  126. data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
  127. data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
  128. data/examples/16_writers_room/.envrc +0 -1
  129. data/examples/16_writers_room/display.rb +0 -158
  130. data/examples/16_writers_room/output/.gitignore +0 -4
  131. data/examples/16_writers_room/output/README.md +0 -69
  132. data/examples/16_writers_room/output/opus_001.md +0 -263
  133. data/examples/16_writers_room/output/opus_001_notes.log +0 -470
  134. data/examples/16_writers_room/output/opus_002.md +0 -245
  135. data/examples/16_writers_room/output/opus_002_notes.log +0 -546
  136. data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
  137. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
  138. data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
  139. data/examples/16_writers_room/prompts/writer.md +0 -37
  140. data/examples/16_writers_room/room.rb +0 -186
  141. data/examples/16_writers_room/tools.rb +0 -173
  142. data/examples/16_writers_room/writer.rb +0 -121
  143. data/examples/16_writers_room/writers_room.rb +0 -256
  144. data/examples/17_skills.rb +0 -234
  145. data/examples/18_rails/.envrc +0 -3
  146. data/examples/18_rails/.gitignore +0 -5
  147. data/examples/18_rails/Gemfile +0 -11
  148. data/examples/18_rails/README.md +0 -67
  149. data/examples/18_rails/Rakefile +0 -4
  150. data/examples/18_rails/app/controllers/application_controller.rb +0 -4
  151. data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
  152. data/examples/18_rails/app/jobs/application_job.rb +0 -4
  153. data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
  154. data/examples/18_rails/app/models/application_record.rb +0 -5
  155. data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
  156. data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
  157. data/examples/18_rails/app/robots/chat_robot.rb +0 -25
  158. data/examples/18_rails/app/tools/time_tool.rb +0 -9
  159. data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
  160. data/examples/18_rails/app/views/chat/index.html.erb +0 -67
  161. data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
  162. data/examples/18_rails/bin/dev +0 -7
  163. data/examples/18_rails/bin/rails +0 -6
  164. data/examples/18_rails/bin/setup +0 -15
  165. data/examples/18_rails/config/application.rb +0 -33
  166. data/examples/18_rails/config/cable.yml +0 -2
  167. data/examples/18_rails/config/database.yml +0 -5
  168. data/examples/18_rails/config/environment.rb +0 -4
  169. data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
  170. data/examples/18_rails/config/routes.rb +0 -6
  171. data/examples/18_rails/config.ru +0 -4
  172. data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
  173. data/examples/19_token_tracking.rb +0 -138
  174. data/examples/20_circuit_breaker.rb +0 -147
  175. data/examples/21_learning_loop.rb +0 -181
  176. data/examples/22_context_compression.rb +0 -172
  177. data/examples/23_convergence.rb +0 -133
  178. data/examples/24_structured_delegation.rb +0 -151
  179. data/examples/25_history_search/conversation.jsonl +0 -30
  180. data/examples/25_history_search.rb +0 -133
  181. data/examples/26_document_store/api_versioning_adr.md +0 -52
  182. data/examples/26_document_store/incident_postmortem.md +0 -46
  183. data/examples/26_document_store/postgres_runbook.md +0 -49
  184. data/examples/26_document_store/redis_caching_guide.md +0 -48
  185. data/examples/26_document_store/sidekiq_guide.md +0 -51
  186. data/examples/26_document_store.rb +0 -140
  187. data/examples/27_incident_response/README.md +0 -65
  188. data/examples/27_incident_response/incident_response.rb +0 -261
  189. data/examples/28_mcp_discovery.rb +0 -113
  190. data/examples/29_ractor_tools.rb +0 -240
  191. data/examples/30_ractor_network.rb +0 -252
  192. data/examples/31_launch_assessment.rb +0 -246
  193. data/examples/32_newsletter_reader.rb +0 -193
  194. data/examples/33_stock_generator.rb +0 -80
  195. data/examples/33_stock_predictor.rb +0 -327
  196. data/examples/34_agentskills.rb +0 -76
  197. data/examples/35_hooks.rb +0 -266
  198. data/examples/README.md +0 -550
  199. data/examples/common.rb +0 -180
  200. data/examples/prompts/assistant.md +0 -5
  201. data/examples/prompts/audit_trail.md +0 -8
  202. data/examples/prompts/billing.md +0 -10
  203. data/examples/prompts/classifier.md +0 -7
  204. data/examples/prompts/comedian.md +0 -6
  205. data/examples/prompts/comedy_critic.md +0 -10
  206. data/examples/prompts/configurable.md +0 -9
  207. data/examples/prompts/dispatcher.md +0 -12
  208. data/examples/prompts/entity_extractor.md +0 -14
  209. data/examples/prompts/escalation.md +0 -42
  210. data/examples/prompts/frontmatter_mcp_test.md +0 -9
  211. data/examples/prompts/frontmatter_named_test.md +0 -5
  212. data/examples/prompts/frontmatter_tools_test.md +0 -6
  213. data/examples/prompts/general.md +0 -7
  214. data/examples/prompts/github_assistant.md +0 -14
  215. data/examples/prompts/helper.md +0 -4
  216. data/examples/prompts/incident_responder.md +0 -18
  217. data/examples/prompts/keyword_extractor.md +0 -11
  218. data/examples/prompts/llm_config_demo.md +0 -20
  219. data/examples/prompts/order_support.md +0 -35
  220. data/examples/prompts/os_advocate.md +0 -13
  221. data/examples/prompts/os_chief.md +0 -13
  222. data/examples/prompts/os_editor.md +0 -13
  223. data/examples/prompts/parameterized_main_test.md +0 -6
  224. data/examples/prompts/pii_redactor.md +0 -7
  225. data/examples/prompts/product_support.md +0 -37
  226. data/examples/prompts/runbook_protocol.md +0 -12
  227. data/examples/prompts/sentiment_analyzer.md +0 -12
  228. data/examples/prompts/skill_a_test.md +0 -4
  229. data/examples/prompts/skill_b_test.md +0 -4
  230. data/examples/prompts/skill_config_test.md +0 -5
  231. data/examples/prompts/skill_cycle_a_test.md +0 -6
  232. data/examples/prompts/skill_cycle_b_test.md +0 -6
  233. data/examples/prompts/skill_description_test.md +0 -4
  234. data/examples/prompts/skill_leaf_test.md +0 -4
  235. data/examples/prompts/skill_nested_test.md +0 -6
  236. data/examples/prompts/skill_refs_main_test.md +0 -6
  237. data/examples/prompts/skill_self_ref_test.md +0 -6
  238. data/examples/prompts/skill_with_mcp_test.md +0 -9
  239. data/examples/prompts/skill_with_params_test.md +0 -6
  240. data/examples/prompts/skill_with_robot_name_test.md +0 -5
  241. data/examples/prompts/skill_with_tools_test.md +0 -6
  242. data/examples/prompts/sre_compliance.md +0 -10
  243. data/examples/prompts/structured_output.md +0 -7
  244. data/examples/prompts/synthesizer.md +0 -17
  245. data/examples/prompts/technical.md +0 -10
  246. data/examples/prompts/template_with_skills_test.md +0 -6
  247. data/examples/prompts/triage.md +0 -22
  248. data/examples/ruboruby.md +0 -423
  249. data/examples/run_all.rb +0 -60
  250. data/examples/xyzzy.rb +0 -97
  251. data/logfile +0 -8
  252. data/mkdocs.yml +0 -209
  253. data/robot_concurrency.md +0 -38
  254. data/simple_acp_review.md +0 -298
  255. data/temp.md +0 -6
  256. data/tool_manifest_plan.md +0 -155
@@ -1,313 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Example 7: Network Memory with Concurrent Robots
5
- #
6
- # Demonstrates the reactive shared memory system where:
7
- # - Multiple robots run concurrently and write to shared memory
8
- # - Robots can wait for values written by other robots
9
- # - Subscriptions provide real-time notifications of memory changes
10
- # - Network broadcast sends messages to all robots
11
- #
12
- # Architecture:
13
- # ┌─────────────────────────────────────────────────────────────┐
14
- # │ PARALLEL ANALYSIS │
15
- # │ │
16
- # │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
17
- # │ │ Sentiment │ │ Entities │ │ Keywords │ │
18
- # │ │ Analyzer │ │ Extractor │ │ Extractor │ │
19
- # │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
20
- # │ │ │ │ │
21
- # │ ▼ ▼ ▼ │
22
- # │ memory.set( memory.set( memory.set( │
23
- # │ :sentiment) :entities) :keywords) │
24
- # │ │ │ │ │
25
- # │ └────────────────┼────────────────┘ │
26
- # │ ▼ │
27
- # │ ┌──────────────────────────────────────────────────────┐ │
28
- # │ │ SHARED MEMORY │ │
29
- # │ │ { sentiment: {...}, entities: {...}, keywords: {...} │ │
30
- # │ └──────────────────────────────────────────────────────┘ │
31
- # │ │ │
32
- # │ ▼ │
33
- # │ ┌──────────────────────────────────────────────────────┐ │
34
- # │ │ Synthesizer │ │
35
- # │ │ memory.get(:sentiment, :entities, :keywords, │ │
36
- # │ │ wait: true) │ │
37
- # │ └──────────────────────────────────────────────────────┘ │
38
- # │ │
39
- # └─────────────────────────────────────────────────────────────┘
40
- #
41
- # Usage:
42
- # ruby examples/07_network_memory.rb
43
-
44
- require_relative "common"
45
- require "json"
46
-
47
- banner "Network Memory with Concurrent Robots"
48
-
49
- # -----------------------------------------------------------------------------
50
- # Custom Robot Classes that Write to Shared Memory
51
- # -----------------------------------------------------------------------------
52
-
53
- # Base class for analysis robots that write results to memory
54
- class AnalysisRobot < RobotLab::Robot
55
- def initialize(memory_key:, **opts)
56
- super(**opts)
57
- @memory_key = memory_key
58
- end
59
-
60
- def call(result)
61
- run_context = extract_run_context(result)
62
- network_memory = run_context.delete(:network_memory)
63
- message = run_context.delete(:message)
64
-
65
- robot_result = run(message, network_memory: network_memory, **run_context)
66
-
67
- # Parse the JSON response and write to shared memory
68
- if network_memory
69
- content = robot_result.reply.to_s
70
-
71
- # Set writer before writing to memory
72
- network_memory.current_writer = @name
73
-
74
- begin
75
- parsed = JSON.parse(content)
76
- network_memory.set(@memory_key, parsed)
77
- puts " [#{@name}] Wrote JSON to memory[:#{@memory_key}]"
78
- rescue JSON::ParserError
79
- # If not valid JSON, store the raw text
80
- network_memory.set(@memory_key, content)
81
- puts " [#{@name}] Wrote text to memory[:#{@memory_key}]"
82
- end
83
- end
84
-
85
- result
86
- .with_context(@name.to_sym, robot_result)
87
- .continue(robot_result)
88
- end
89
- end
90
-
91
- # Synthesizer robot that reads from shared memory and synthesizes results
92
- class SynthesizerRobot < RobotLab::Robot
93
- def call(result)
94
- run_context = extract_run_context(result)
95
- network_memory = run_context.delete(:network_memory)
96
- message = run_context.delete(:message)
97
-
98
- puts " [#{@name}] Reading analysis results from memory..."
99
-
100
- if network_memory
101
- # Read results from memory - they should already be there since
102
- # SimpleFlow ensures our dependencies completed first
103
- sentiment = network_memory.get(:sentiment)
104
- entities = network_memory.get(:entities)
105
- keywords = network_memory.get(:keywords)
106
-
107
- puts " [#{@name}] Got sentiment: #{sentiment.nil? ? 'nil' : 'present'}"
108
- puts " [#{@name}] Got entities: #{entities.nil? ? 'nil' : 'present'}"
109
- puts " [#{@name}] Got keywords: #{keywords.nil? ? 'nil' : 'present'}"
110
-
111
- # Format for the template
112
- run_context[:sentiment] = format_for_template(sentiment)
113
- run_context[:entities] = format_for_template(entities)
114
- run_context[:keywords] = format_for_template(keywords)
115
- else
116
- run_context[:sentiment] = "Not available"
117
- run_context[:entities] = "Not available"
118
- run_context[:keywords] = "Not available"
119
- end
120
-
121
- robot_result = run(message, network_memory: network_memory, **run_context)
122
-
123
- result
124
- .with_context(@name.to_sym, robot_result)
125
- .continue(robot_result)
126
- end
127
-
128
- private
129
-
130
- def format_for_template(value)
131
- case value
132
- when Hash, Array
133
- JSON.pretty_generate(value)
134
- when nil
135
- "Not available"
136
- else
137
- value.to_s
138
- end
139
- end
140
- end
141
-
142
- # -----------------------------------------------------------------------------
143
- # Create the Robots
144
- # -----------------------------------------------------------------------------
145
-
146
- sentiment_robot = AnalysisRobot.new(
147
- name: "sentiment_analyzer",
148
- template: :sentiment_analyzer,
149
- memory_key: :sentiment,
150
- **llm_opts
151
- )
152
-
153
- entity_robot = AnalysisRobot.new(
154
- name: "entity_extractor",
155
- template: :entity_extractor,
156
- memory_key: :entities,
157
- **llm_opts
158
- )
159
-
160
- keyword_robot = AnalysisRobot.new(
161
- name: "keyword_extractor",
162
- template: :keyword_extractor,
163
- memory_key: :keywords,
164
- **llm_opts
165
- )
166
-
167
- synthesizer = SynthesizerRobot.new(
168
- name: "synthesizer",
169
- template: :synthesizer,
170
- **llm_opts
171
- )
172
-
173
- # -----------------------------------------------------------------------------
174
- # Create the Network with Shared Memory
175
- # -----------------------------------------------------------------------------
176
-
177
- network = RobotLab.create_network(name: "parallel_analysis") do
178
- # Three analysis robots run in parallel (all depend on nothing)
179
- task :sentiment, sentiment_robot, depends_on: :none
180
- task :entities, entity_robot, depends_on: :none
181
- task :keywords, keyword_robot, depends_on: :none
182
-
183
- # Synthesizer waits for all three to complete
184
- task :synthesize, synthesizer, depends_on: [:sentiment, :entities, :keywords]
185
- end
186
-
187
- # -----------------------------------------------------------------------------
188
- # Set Up Memory Subscriptions (for monitoring)
189
- # -----------------------------------------------------------------------------
190
-
191
- puts "Setting up memory subscriptions for monitoring..."
192
- puts
193
-
194
- # Note: In concurrent execution, change.writer may be unreliable due to race
195
- # conditions. For production use, consider including writer info in the value.
196
- network.memory.subscribe(:sentiment, :entities, :keywords) do |change|
197
- value_preview = case change.value
198
- when Hash then change.value.keys.join(", ")
199
- when String then change.value[0..50]
200
- else change.value.class.name
201
- end
202
- puts " [MONITOR] Memory[:#{change.key}] updated with keys: #{value_preview}"
203
- end
204
-
205
- # -----------------------------------------------------------------------------
206
- # Set Up Broadcast Handler
207
- # -----------------------------------------------------------------------------
208
-
209
- network.on_broadcast do |message|
210
- puts " [BROADCAST] #{message[:payload][:event]}: #{message[:payload][:details]}"
211
- end
212
-
213
- # -----------------------------------------------------------------------------
214
- # Run the Network
215
- # -----------------------------------------------------------------------------
216
-
217
- sample_text = <<~TEXT
218
- Apple Inc. announced today that CEO Tim Cook will be presenting the new iPhone 15
219
- at their headquarters in Cupertino, California on September 12th, 2024.
220
- Industry analysts are extremely excited about the new features, though some
221
- consumer advocates have expressed concerns about the expected price increase.
222
- Samsung and Google are reportedly preparing competitive responses for later this year.
223
- TEXT
224
-
225
- puts "Network structure:"
226
- puts network.visualize
227
- puts
228
- hr
229
- puts "Input text:"
230
- puts sample_text.strip
231
- hr
232
- puts
233
-
234
- # Send a broadcast before starting
235
- network.broadcast(event: "analysis_started", details: "Beginning parallel analysis")
236
-
237
- puts "Running parallel analysis..."
238
- puts
239
- start_time = Time.now
240
-
241
- result = network.run(message: sample_text)
242
-
243
- elapsed = Time.now - start_time
244
- puts
245
- hr
246
- puts "Analysis complete in #{elapsed.round(2)} seconds"
247
- hr
248
-
249
- # Send completion broadcast
250
- network.broadcast(event: "analysis_complete", details: "All robots finished")
251
-
252
- # -----------------------------------------------------------------------------
253
- # Display Results
254
- # -----------------------------------------------------------------------------
255
-
256
-
257
- section "Final Synthesis"
258
-
259
- if result.value.is_a?(RobotLab::RobotResult)
260
- puts result.value.reply
261
- end
262
-
263
-
264
- section "Memory State"
265
-
266
- # Show what's in shared memory
267
- memory = network.memory
268
- puts "Sentiment: #{memory.get(:sentiment)&.to_json}"
269
- puts
270
- puts "Entities: #{memory.get(:entities)&.to_json}"
271
- puts
272
- puts "Keywords: #{memory.get(:keywords)&.to_json}"
273
-
274
- # -----------------------------------------------------------------------------
275
- # Demonstrate Blocking Wait (without pipeline dependencies)
276
- # -----------------------------------------------------------------------------
277
-
278
-
279
- section "Demonstrating Blocking Wait"
280
-
281
- # Create a fresh memory for this demo
282
- demo_memory = RobotLab::Memory.new(network_name: "wait_demo")
283
-
284
- # Simulate a concurrent scenario where one thread waits for another
285
- puts "Starting writer thread (will write after 1 second)..."
286
- puts "Starting reader thread (will wait for value)..."
287
-
288
- reader_result = nil
289
- writer_done = false
290
-
291
- reader = Thread.new do
292
- start = Time.now
293
- puts " [reader] Waiting for :delayed_result..."
294
- value = demo_memory.get(:delayed_result, wait: 10)
295
- elapsed = Time.now - start
296
- reader_result = value
297
- puts " [reader] Got value after #{elapsed.round(2)}s: #{value}"
298
- end
299
-
300
- writer = Thread.new do
301
- sleep 1
302
- demo_memory.set(:delayed_result, { status: "complete", data: [1, 2, 3] })
303
- writer_done = true
304
- puts " [writer] Wrote :delayed_result to memory"
305
- end
306
-
307
- # Wait for both threads
308
- writer.join
309
- reader.join
310
-
311
- puts
312
- puts "Blocking wait demonstration complete!"
313
- puts "Reader received: #{reader_result.inspect}"
@@ -1,162 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Example 8: LLM Configuration via MywayConfig
5
- #
6
- # Demonstrates how RobotLab uses MywayConfig for environment-specific
7
- # configuration (similar to Rails database.yml).
8
- #
9
- # Configuration is loaded from multiple sources in priority order:
10
- # 1. Bundled defaults (lib/robot_lab/config/defaults.yml)
11
- # 2. Environment-specific overrides (development, test, production)
12
- # 3. XDG user config (~/.config/robot_lab/config.yml)
13
- # 4. Project config (./config/robot_lab.yml)
14
- # 5. Environment variables (ROBOT_LAB_*)
15
- # 6. Template front matter (model, temperature, etc. in .md YAML header)
16
- # 7. Constructor parameters (model:, temperature:, etc. passed to Robot.new)
17
- # 8. with_* methods (runtime chaining, e.g. robot.with_temperature(0.9))
18
- # 9. Run-time context (kwargs passed to robot.run that re-render the template)
19
- #
20
- # Environment is determined by ROBOT_LAB_ENV, RAILS_ENV, or RACK_ENV.
21
- #
22
- # Environment variable examples:
23
- # ROBOT_LAB_RUBY_LLM__MODEL=qwen/qwen3.8-27b
24
- # ROBOT_LAB_RUBY_LLM__REQUEST_TIMEOUT=180
25
- # LMS_API_BASE=http://localhost:1234/v1
26
- #
27
- # Usage:
28
- # ruby examples/08_llm_config.rb
29
- # ROBOT_LAB_ENV=test ruby examples/08_llm_config.rb
30
- # ROBOT_LAB_ENV=production ruby examples/08_llm_config.rb
31
-
32
- require_relative "common"
33
-
34
- # =============================================================================
35
- # Demonstration
36
- # =============================================================================
37
-
38
- banner "LLM Configuration via MywayConfig"
39
-
40
- # --- Gather environment from the user via AskUser ---
41
- ask = RobotLab::AskUser.new
42
- env = ask.call(
43
- "question" => "Which environment should the demo run in?",
44
- "choices" => %w[development test production],
45
- "default" => ENV['ROBOT_LAB_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development"
46
- )
47
- puts
48
-
49
- # Display configuration values (hiding sensitive keys)
50
- config = RobotLab.config
51
-
52
- puts "Core Settings:"
53
- puts " max_iterations: #{config.max_iterations}"
54
- puts " streaming_enabled: #{config.streaming_enabled}"
55
- puts " template_path: #{config.template_path || '(default)'}"
56
- puts
57
-
58
- puts "RubyLLM Settings:"
59
- puts " model: #{config.ruby_llm.model}"
60
- puts " provider: #{config.ruby_llm.provider}"
61
- puts " request_timeout: #{config.ruby_llm.request_timeout}s"
62
- puts " max_retries: #{config.ruby_llm.max_retries}"
63
- puts " log_level: #{config.ruby_llm.log_level}"
64
-
65
- # Show where the LLM traffic actually goes
66
- puts " lms_api_base: #{LMS_API_BASE}"
67
- puts " (local inference — no API key in play)"
68
- puts
69
-
70
- section "Configuration Hierarchy (highest priority first)"
71
- puts
72
- puts " Per-Robot (override global settings for a specific robot):"
73
- puts " 11. Run-time context: kwargs to robot.run re-render template"
74
- puts " 10. with_* methods: robot.with_temperature(0.9).ask(...)"
75
- puts " 9. Constructor params: Robot.new(model: ..., temperature: ...)"
76
- puts " 8. Template front matter: model, temperature, etc. in .md YAML header"
77
- puts " 7. Robot RunConfig: config: passed to Robot constructor"
78
- puts
79
- puts " Network/Task (shared defaults for a group of robots):"
80
- puts " 6. Task RunConfig: config: passed to task() in network"
81
- puts " 5. Network RunConfig: config: passed to create_network()"
82
- puts
83
- puts " Global (apply to all robots unless overridden):"
84
- puts " 4. Environment variables: ROBOT_LAB_RUBY_LLM__MODEL, etc."
85
- puts " 3. Project config: ./config/robot_lab.yml"
86
- puts " 2. User config: ~/.config/robot_lab/config.yml"
87
- puts " 1. Bundled defaults: lib/robot_lab/config/defaults.yml + env overrides"
88
-
89
- section "RunConfig: Shared Operational Defaults"
90
-
91
- shared = RobotLab::RunConfig.new(model: LLM[:default].model, temperature: 0.5)
92
- puts " shared = RunConfig.new(model: #{LLM[:default].model.inspect}, temperature: 0.5)"
93
- puts " shared.to_h => #{shared.to_h.inspect}"
94
- puts
95
- puts " Note: RunConfig carries no `provider` field, so an LM Studio model still"
96
- puts " needs provider: passed to each robot alongside the shared config."
97
- puts
98
-
99
- creative = RobotLab::RunConfig.new(temperature: 0.9)
100
- merged = shared.merge(creative)
101
- puts " creative = RunConfig.new(temperature: 0.9)"
102
- puts " merged = shared.merge(creative)"
103
- puts " merged.to_h => #{merged.to_h.inspect}"
104
- puts " (model inherited from shared, temperature overridden by creative)"
105
- puts
106
-
107
- # Create a robot using the configuration
108
- robot = RobotLab.build(
109
- **llm_opts,
110
- name: "config_demo",
111
- template: :llm_config_demo,
112
- local_tools: [RobotLab::AskUser],
113
- # These are TEMPLATE parameters, not robot kwargs — the template renders
114
- # them into its prompt text.
115
- context: {
116
- environment: env,
117
- model: LLM[:default].model,
118
- provider: LLM[:default].provider
119
- }
120
- )
121
-
122
- puts "Running robot with #{env} configuration..."
123
- puts "Model: #{robot.model}"
124
- puts
125
-
126
- # Run the robot
127
- result = robot.run(
128
- "Briefly explain how environment-specific LLM configuration works " \
129
- "and why it's useful."
130
- )
131
-
132
- # Display the result
133
- puts "Response:"
134
- result.output.each do |message|
135
- puts message.content if message.respond_to?(:content)
136
- end
137
-
138
- puts <<~FOOTER
139
-
140
- #{"=" * 70}
141
- Configuration demonstrated successfully!
142
-
143
- Configuration flows through three layers:
144
- Global (MywayConfig): YAML defaults, env overrides, XDG, env vars
145
- Network/Task (RunConfig): shared defaults for groups of robots
146
- Per-Robot: RunConfig, template front matter, constructor params, with_*
147
-
148
- RunConfig lets you express shared defaults that flow through the hierarchy:
149
- shared = RobotLab::RunConfig.new(model: #{LLM[:default].model.inspect}, temperature: 0.5)
150
- network = RobotLab.create_network(name: "team", config: shared) { ... }
151
- robot = RobotLab.build(name: "bot", config: shared, temperature: 0.9)
152
-
153
- Example environment variable overrides:
154
- ROBOT_LAB_RUBY_LLM__MODEL=#{LLM[:default].model}
155
- ROBOT_LAB_RUBY_LLM__REQUEST_TIMEOUT=180
156
- LMS_API_BASE=http://localhost:1234/v1
157
-
158
- Try running with different environments:
159
- ROBOT_LAB_ENV=test ruby examples/08_llm_config.rb
160
- ROBOT_LAB_ENV=production ruby examples/08_llm_config.rb
161
- #{"=" * 70}
162
- FOOTER