robot_lab 0.3.0 → 0.5.0

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 (274) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +60 -0
  3. data/README.md +29 -19
  4. data/lib/robot_lab/errors.rb +4 -0
  5. data/lib/robot_lab/hook_context.rb +9 -2
  6. data/lib/robot_lab/mcp/registry.rb +99 -0
  7. data/lib/robot_lab/mcp/server.rb +47 -83
  8. data/lib/robot_lab/mcp/server_discovery.rb +22 -9
  9. data/lib/robot_lab/mcp.rb +259 -0
  10. data/lib/robot_lab/robot/mcp_management.rb +159 -105
  11. data/lib/robot_lab/robot/tool_call_gating.rb +144 -0
  12. data/lib/robot_lab/robot.rb +72 -99
  13. data/lib/robot_lab/run_config.rb +3 -2
  14. data/lib/robot_lab/tool.rb +8 -23
  15. data/lib/robot_lab/version.rb +1 -1
  16. data/lib/robot_lab.rb +1 -4
  17. metadata +16 -292
  18. data/.architecture/AGENTS.md +0 -32
  19. data/.architecture/config.yml +0 -8
  20. data/.architecture/members.yml +0 -60
  21. data/.architecture/reviews/feature-free-will.md +0 -490
  22. data/.architecture/reviews/overall-codebase.md +0 -427
  23. data/.claude/settings.local.json +0 -57
  24. data/.codex/config.toml +0 -2
  25. data/.envrc +0 -6
  26. data/.github/workflows/deploy-github-pages.yml +0 -52
  27. data/.irbrc +0 -6
  28. data/.loki +0 -65
  29. data/.quality/reek_baseline.txt +0 -43
  30. data/.rubocop.yml +0 -10
  31. data/Archspec.rb +0 -44
  32. data/CLAUDE.md +0 -141
  33. data/COMMITS.md +0 -196
  34. data/Rakefile +0 -193
  35. data/_typos.toml +0 -21
  36. data/agent2agent_review.md +0 -192
  37. data/agentf_improvements.md +0 -253
  38. data/agents.md +0 -14
  39. data/docs/api/core/index.md +0 -147
  40. data/docs/api/core/memory.md +0 -578
  41. data/docs/api/core/network.md +0 -553
  42. data/docs/api/core/result.md +0 -211
  43. data/docs/api/core/robot.md +0 -1667
  44. data/docs/api/core/state.md +0 -145
  45. data/docs/api/core/tool.md +0 -520
  46. data/docs/api/errors.md +0 -323
  47. data/docs/api/hooks.md +0 -469
  48. data/docs/api/index.md +0 -137
  49. data/docs/api/mcp/client.md +0 -387
  50. data/docs/api/mcp/index.md +0 -267
  51. data/docs/api/mcp/server.md +0 -252
  52. data/docs/api/mcp/transports.md +0 -339
  53. data/docs/api/messages/index.md +0 -126
  54. data/docs/api/messages/text-message.md +0 -170
  55. data/docs/api/messages/tool-call-message.md +0 -206
  56. data/docs/api/messages/tool-result-message.md +0 -242
  57. data/docs/api/messages/user-message.md +0 -232
  58. data/docs/api/skills.md +0 -423
  59. data/docs/api/streaming/context.md +0 -280
  60. data/docs/api/streaming/events.md +0 -185
  61. data/docs/api/streaming/index.md +0 -156
  62. data/docs/api/support.md +0 -846
  63. data/docs/architecture/core-concepts.md +0 -575
  64. data/docs/architecture/index.md +0 -252
  65. data/docs/architecture/message-flow.md +0 -366
  66. data/docs/architecture/network-orchestration.md +0 -478
  67. data/docs/architecture/robot-execution.md +0 -396
  68. data/docs/architecture/state-management.md +0 -410
  69. data/docs/assets/css/custom.css +0 -56
  70. data/docs/assets/images/robot_lab.jpg +0 -0
  71. data/docs/concepts.md +0 -641
  72. data/docs/examples/basic-chat.md +0 -258
  73. data/docs/examples/index.md +0 -425
  74. data/docs/examples/mcp-server.md +0 -403
  75. data/docs/examples/multi-robot-network.md +0 -476
  76. data/docs/examples/tool-usage.md +0 -468
  77. data/docs/getting-started/configuration.md +0 -645
  78. data/docs/getting-started/index.md +0 -56
  79. data/docs/getting-started/installation.md +0 -197
  80. data/docs/getting-started/quick-start.md +0 -293
  81. data/docs/guides/building-robots.md +0 -1187
  82. data/docs/guides/creating-networks.md +0 -736
  83. data/docs/guides/hooks.md +0 -1206
  84. data/docs/guides/index.md +0 -78
  85. data/docs/guides/knowledge.md +0 -219
  86. data/docs/guides/mcp-integration.md +0 -740
  87. data/docs/guides/memory.md +0 -458
  88. data/docs/guides/observability.md +0 -733
  89. data/docs/guides/streaming.md +0 -323
  90. data/docs/guides/using-tools.md +0 -780
  91. data/docs/index.md +0 -280
  92. data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
  93. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
  94. data/examples/.envrc +0 -3
  95. data/examples/01_simple_robot.rb +0 -31
  96. data/examples/02_tools.rb +0 -109
  97. data/examples/03_network.rb +0 -118
  98. data/examples/04_mcp.rb +0 -217
  99. data/examples/05_streaming.rb +0 -137
  100. data/examples/06_prompt_templates.rb +0 -325
  101. data/examples/07_network_memory.rb +0 -313
  102. data/examples/08_llm_config.rb +0 -162
  103. data/examples/09_chaining.rb +0 -251
  104. data/examples/10_memory.rb +0 -315
  105. data/examples/11_network_introspection.rb +0 -239
  106. data/examples/12_message_bus.rb +0 -67
  107. data/examples/13_spawn.rb +0 -85
  108. data/examples/14_rusty_circuit/.envrc +0 -1
  109. data/examples/14_rusty_circuit/.gitignore +0 -1
  110. data/examples/14_rusty_circuit/README.md +0 -1
  111. data/examples/14_rusty_circuit/comic.rb +0 -149
  112. data/examples/14_rusty_circuit/display.rb +0 -217
  113. data/examples/14_rusty_circuit/heckler.rb +0 -65
  114. data/examples/14_rusty_circuit/open_mic.rb +0 -132
  115. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
  116. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
  117. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
  118. data/examples/14_rusty_circuit/scout.rb +0 -165
  119. data/examples/14_rusty_circuit/show.log +0 -234
  120. data/examples/15_memory_network_and_bus/.envrc +0 -1
  121. data/examples/15_memory_network_and_bus/README.md +0 -66
  122. data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
  123. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
  124. data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
  125. data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
  126. data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
  127. data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
  128. data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
  129. data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
  130. data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
  131. data/examples/15_memory_network_and_bus/output/memory.json +0 -13
  132. data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
  133. data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
  134. data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
  135. data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
  136. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
  137. data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
  138. data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
  139. data/examples/16_writers_room/.envrc +0 -1
  140. data/examples/16_writers_room/display.rb +0 -158
  141. data/examples/16_writers_room/output/.gitignore +0 -4
  142. data/examples/16_writers_room/output/README.md +0 -69
  143. data/examples/16_writers_room/output/opus_001.md +0 -263
  144. data/examples/16_writers_room/output/opus_001_notes.log +0 -470
  145. data/examples/16_writers_room/output/opus_002.md +0 -245
  146. data/examples/16_writers_room/output/opus_002_notes.log +0 -546
  147. data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
  148. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
  149. data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
  150. data/examples/16_writers_room/prompts/writer.md +0 -37
  151. data/examples/16_writers_room/room.rb +0 -186
  152. data/examples/16_writers_room/tools.rb +0 -173
  153. data/examples/16_writers_room/writer.rb +0 -121
  154. data/examples/16_writers_room/writers_room.rb +0 -256
  155. data/examples/17_skills.rb +0 -234
  156. data/examples/18_rails/.envrc +0 -3
  157. data/examples/18_rails/.gitignore +0 -5
  158. data/examples/18_rails/Gemfile +0 -11
  159. data/examples/18_rails/README.md +0 -67
  160. data/examples/18_rails/Rakefile +0 -4
  161. data/examples/18_rails/app/controllers/application_controller.rb +0 -4
  162. data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
  163. data/examples/18_rails/app/jobs/application_job.rb +0 -4
  164. data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
  165. data/examples/18_rails/app/models/application_record.rb +0 -5
  166. data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
  167. data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
  168. data/examples/18_rails/app/robots/chat_robot.rb +0 -25
  169. data/examples/18_rails/app/tools/time_tool.rb +0 -9
  170. data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
  171. data/examples/18_rails/app/views/chat/index.html.erb +0 -67
  172. data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
  173. data/examples/18_rails/bin/dev +0 -7
  174. data/examples/18_rails/bin/rails +0 -6
  175. data/examples/18_rails/bin/setup +0 -15
  176. data/examples/18_rails/config/application.rb +0 -33
  177. data/examples/18_rails/config/cable.yml +0 -2
  178. data/examples/18_rails/config/database.yml +0 -5
  179. data/examples/18_rails/config/environment.rb +0 -4
  180. data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
  181. data/examples/18_rails/config/routes.rb +0 -6
  182. data/examples/18_rails/config.ru +0 -4
  183. data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
  184. data/examples/19_token_tracking.rb +0 -138
  185. data/examples/20_circuit_breaker.rb +0 -147
  186. data/examples/21_learning_loop.rb +0 -181
  187. data/examples/22_context_compression.rb +0 -172
  188. data/examples/23_convergence.rb +0 -133
  189. data/examples/24_structured_delegation.rb +0 -151
  190. data/examples/25_history_search/conversation.jsonl +0 -30
  191. data/examples/25_history_search.rb +0 -133
  192. data/examples/26_document_store/api_versioning_adr.md +0 -52
  193. data/examples/26_document_store/incident_postmortem.md +0 -46
  194. data/examples/26_document_store/postgres_runbook.md +0 -49
  195. data/examples/26_document_store/redis_caching_guide.md +0 -48
  196. data/examples/26_document_store/sidekiq_guide.md +0 -51
  197. data/examples/26_document_store.rb +0 -140
  198. data/examples/27_incident_response/README.md +0 -65
  199. data/examples/27_incident_response/incident_response.rb +0 -261
  200. data/examples/28_mcp_discovery.rb +0 -113
  201. data/examples/29_ractor_tools.rb +0 -240
  202. data/examples/30_ractor_network.rb +0 -252
  203. data/examples/31_launch_assessment.rb +0 -246
  204. data/examples/32_newsletter_reader.rb +0 -193
  205. data/examples/33_stock_generator.rb +0 -80
  206. data/examples/33_stock_predictor.rb +0 -327
  207. data/examples/34_agentskills.rb +0 -76
  208. data/examples/35_hooks.rb +0 -266
  209. data/examples/README.md +0 -550
  210. data/examples/common.rb +0 -180
  211. data/examples/prompts/assistant.md +0 -5
  212. data/examples/prompts/audit_trail.md +0 -8
  213. data/examples/prompts/billing.md +0 -10
  214. data/examples/prompts/classifier.md +0 -7
  215. data/examples/prompts/comedian.md +0 -6
  216. data/examples/prompts/comedy_critic.md +0 -10
  217. data/examples/prompts/configurable.md +0 -9
  218. data/examples/prompts/dispatcher.md +0 -12
  219. data/examples/prompts/entity_extractor.md +0 -14
  220. data/examples/prompts/escalation.md +0 -42
  221. data/examples/prompts/frontmatter_mcp_test.md +0 -9
  222. data/examples/prompts/frontmatter_named_test.md +0 -5
  223. data/examples/prompts/frontmatter_tools_test.md +0 -6
  224. data/examples/prompts/general.md +0 -7
  225. data/examples/prompts/github_assistant.md +0 -14
  226. data/examples/prompts/helper.md +0 -4
  227. data/examples/prompts/incident_responder.md +0 -18
  228. data/examples/prompts/keyword_extractor.md +0 -11
  229. data/examples/prompts/llm_config_demo.md +0 -20
  230. data/examples/prompts/order_support.md +0 -35
  231. data/examples/prompts/os_advocate.md +0 -13
  232. data/examples/prompts/os_chief.md +0 -13
  233. data/examples/prompts/os_editor.md +0 -13
  234. data/examples/prompts/parameterized_main_test.md +0 -6
  235. data/examples/prompts/pii_redactor.md +0 -7
  236. data/examples/prompts/product_support.md +0 -37
  237. data/examples/prompts/runbook_protocol.md +0 -12
  238. data/examples/prompts/sentiment_analyzer.md +0 -12
  239. data/examples/prompts/skill_a_test.md +0 -4
  240. data/examples/prompts/skill_b_test.md +0 -4
  241. data/examples/prompts/skill_config_test.md +0 -5
  242. data/examples/prompts/skill_cycle_a_test.md +0 -6
  243. data/examples/prompts/skill_cycle_b_test.md +0 -6
  244. data/examples/prompts/skill_description_test.md +0 -4
  245. data/examples/prompts/skill_leaf_test.md +0 -4
  246. data/examples/prompts/skill_nested_test.md +0 -6
  247. data/examples/prompts/skill_refs_main_test.md +0 -6
  248. data/examples/prompts/skill_self_ref_test.md +0 -6
  249. data/examples/prompts/skill_with_mcp_test.md +0 -9
  250. data/examples/prompts/skill_with_params_test.md +0 -6
  251. data/examples/prompts/skill_with_robot_name_test.md +0 -5
  252. data/examples/prompts/skill_with_tools_test.md +0 -6
  253. data/examples/prompts/sre_compliance.md +0 -10
  254. data/examples/prompts/structured_output.md +0 -7
  255. data/examples/prompts/synthesizer.md +0 -17
  256. data/examples/prompts/technical.md +0 -10
  257. data/examples/prompts/template_with_skills_test.md +0 -6
  258. data/examples/prompts/triage.md +0 -22
  259. data/examples/ruboruby.md +0 -423
  260. data/examples/run_all.rb +0 -60
  261. data/examples/xyzzy.rb +0 -97
  262. data/lib/robot_lab/mcp/client.rb +0 -223
  263. data/lib/robot_lab/mcp/connection_poller.rb +0 -195
  264. data/lib/robot_lab/mcp/transports/base.rb +0 -64
  265. data/lib/robot_lab/mcp/transports/sse.rb +0 -120
  266. data/lib/robot_lab/mcp/transports/stdio.rb +0 -170
  267. data/lib/robot_lab/mcp/transports/streamable_http.rb +0 -141
  268. data/lib/robot_lab/mcp/transports/websocket.rb +0 -111
  269. data/logfile +0 -8
  270. data/mkdocs.yml +0 -209
  271. data/robot_concurrency.md +0 -38
  272. data/simple_acp_review.md +0 -298
  273. data/temp.md +0 -6
  274. data/tool_manifest_plan.md +0 -155
@@ -1,185 +0,0 @@
1
- # Streaming::Events
2
-
3
- Event type constants and classification helpers for the streaming system.
4
-
5
- ## Module: `RobotLab::Streaming::Events`
6
-
7
- Defines all recognized event types as string constants and provides helper methods for classifying events.
8
-
9
- ```ruby
10
- RobotLab::Streaming::Events::TEXT_DELTA # => "text.delta"
11
- RobotLab::Streaming::Events::RUN_COMPLETED # => "run.completed"
12
- RobotLab::Streaming::Events.delta?("text.delta") # => true
13
- ```
14
-
15
- ## Event Type Constants
16
-
17
- ### Run Lifecycle Events
18
-
19
- | Constant | Value | Description |
20
- |----------|-------|-------------|
21
- | `RUN_STARTED` | `"run.started"` | A run has begun |
22
- | `RUN_COMPLETED` | `"run.completed"` | A run completed successfully |
23
- | `RUN_FAILED` | `"run.failed"` | A run failed with an error |
24
- | `RUN_INTERRUPTED` | `"run.interrupted"` | A run was interrupted |
25
-
26
- ### Step Events
27
-
28
- For durable execution tracking:
29
-
30
- | Constant | Value | Description |
31
- |----------|-------|-------------|
32
- | `STEP_STARTED` | `"step.started"` | A processing step has begun |
33
- | `STEP_COMPLETED` | `"step.completed"` | A processing step completed |
34
- | `STEP_FAILED` | `"step.failed"` | A processing step failed |
35
-
36
- ### Part Events
37
-
38
- For message composition tracking:
39
-
40
- | Constant | Value | Description |
41
- |----------|-------|-------------|
42
- | `PART_CREATED` | `"part.created"` | A message part was created |
43
- | `PART_COMPLETED` | `"part.completed"` | A message part completed |
44
- | `PART_FAILED` | `"part.failed"` | A message part failed |
45
-
46
- ### Content Delta Events
47
-
48
- Token-level streaming events:
49
-
50
- | Constant | Value | Description |
51
- |----------|-------|-------------|
52
- | `TEXT_DELTA` | `"text.delta"` | A chunk of text content was generated |
53
- | `TOOL_CALL_ARGUMENTS_DELTA` | `"tool_call.arguments.delta"` | A chunk of tool call arguments |
54
- | `TOOL_CALL_OUTPUT_DELTA` | `"tool_call.output.delta"` | A chunk of tool call output |
55
- | `REASONING_DELTA` | `"reasoning.delta"` | A chunk of reasoning/thinking content |
56
- | `DATA_DELTA` | `"data.delta"` | A chunk of structured data |
57
-
58
- ### Human-in-the-Loop Events
59
-
60
- | Constant | Value | Description |
61
- |----------|-------|-------------|
62
- | `HITL_REQUESTED` | `"hitl.requested"` | Human input has been requested |
63
- | `HITL_RESOLVED` | `"hitl.resolved"` | Human input has been provided |
64
-
65
- ### Metadata Events
66
-
67
- | Constant | Value | Description |
68
- |----------|-------|-------------|
69
- | `USAGE_UPDATED` | `"usage.updated"` | Token usage statistics updated |
70
- | `METADATA_UPDATED` | `"metadata.updated"` | Run metadata updated |
71
-
72
- ### Terminal Event
73
-
74
- | Constant | Value | Description |
75
- |----------|-------|-------------|
76
- | `STREAM_ENDED` | `"stream.ended"` | The stream has ended; no more events |
77
-
78
- ## Event Collections
79
-
80
- ### ALL_EVENTS
81
-
82
- ```ruby
83
- RobotLab::Streaming::Events::ALL_EVENTS
84
- # => Array of all event type strings (frozen)
85
- ```
86
-
87
- ### LIFECYCLE_EVENTS
88
-
89
- ```ruby
90
- RobotLab::Streaming::Events::LIFECYCLE_EVENTS
91
- # => ["run.started", "run.completed", "run.failed", "run.interrupted"]
92
- ```
93
-
94
- ### DELTA_EVENTS
95
-
96
- ```ruby
97
- RobotLab::Streaming::Events::DELTA_EVENTS
98
- # => ["text.delta", "tool_call.arguments.delta", "tool_call.output.delta",
99
- # "reasoning.delta", "data.delta"]
100
- ```
101
-
102
- ## Classification Methods
103
-
104
- ### Events.lifecycle?
105
-
106
- ```ruby
107
- RobotLab::Streaming::Events.lifecycle?("run.started") # => true
108
- RobotLab::Streaming::Events.lifecycle?("text.delta") # => false
109
- ```
110
-
111
- Returns `true` if the event is a run lifecycle event.
112
-
113
- ### Events.delta?
114
-
115
- ```ruby
116
- RobotLab::Streaming::Events.delta?("text.delta") # => true
117
- RobotLab::Streaming::Events.delta?("run.completed") # => false
118
- ```
119
-
120
- Returns `true` if the event is a content delta (token streaming) event.
121
-
122
- ### Events.valid?
123
-
124
- ```ruby
125
- RobotLab::Streaming::Events.valid?("text.delta") # => true
126
- RobotLab::Streaming::Events.valid?("unknown.event") # => false
127
- ```
128
-
129
- Returns `true` if the event is a recognized event type.
130
-
131
- ## Examples
132
-
133
- ### Filtering Events by Category
134
-
135
- ```ruby
136
- publish = ->(event) {
137
- event_type = event[:event]
138
-
139
- if RobotLab::Streaming::Events.delta?(event_type)
140
- # Handle streaming content
141
- print event[:data][:delta]
142
- elsif RobotLab::Streaming::Events.lifecycle?(event_type)
143
- # Handle lifecycle transitions
144
- puts "\n[#{event_type}] run_id=#{event[:data][:run_id]}"
145
- end
146
- }
147
- ```
148
-
149
- ### Using Constants for Event Matching
150
-
151
- ```ruby
152
- include RobotLab::Streaming::Events
153
-
154
- publish = ->(event) {
155
- case event[:event]
156
- when TEXT_DELTA
157
- print event[:data][:delta]
158
- when TOOL_CALL_ARGUMENTS_DELTA
159
- buffer_tool_args(event[:data])
160
- when RUN_COMPLETED
161
- puts "\nRun complete"
162
- when RUN_FAILED
163
- puts "\nRun failed: #{event[:data][:error]}"
164
- when STREAM_ENDED
165
- cleanup
166
- end
167
- }
168
- ```
169
-
170
- ### Validating Custom Events
171
-
172
- ```ruby
173
- def emit(event_type, data)
174
- unless RobotLab::Streaming::Events.valid?(event_type)
175
- raise ArgumentError, "Unknown event type: #{event_type}"
176
- end
177
-
178
- context.publish_event(event: event_type, data: data)
179
- end
180
- ```
181
-
182
- ## See Also
183
-
184
- - [Streaming Overview](index.md)
185
- - [Context](context.md)
@@ -1,156 +0,0 @@
1
- # Streaming
2
-
3
- A standalone event-publishing toolkit. **Not** the live streaming path.
4
-
5
- ## Status: not wired in
6
-
7
- `RobotLab::Streaming::Context`, `Streaming::Events`, and
8
- `Streaming::SequenceCounter` exist and work, but **nothing in the framework uses
9
- them**. `grep -rn "Streaming::" lib/` returns zero hits outside
10
- `lib/robot_lab/streaming/` itself: no robot, network, task, or hook ever
11
- constructs a `Streaming::Context`, and no framework code publishes any of the
12
- events listed below. Enabling this module does not make a robot stream.
13
-
14
- Treat this as a set of building blocks you may drive yourself — a vocabulary of
15
- event names plus a sequencing/ID helper — if you are writing your own
16
- event-broadcast layer (a websocket relay, a SSE endpoint, an audit feed).
17
-
18
- ### The real streaming API
19
-
20
- To actually receive tokens as a robot generates them, use `on_content:` and/or a
21
- block on `run`:
22
-
23
- ```ruby
24
- # Constructor / RunConfig callback — fires on every run
25
- robot = RobotLab.build(
26
- name: "assistant",
27
- system_prompt: "You are helpful.",
28
- on_content: ->(chunk) { print chunk.content }
29
- )
30
-
31
- # Or a block passed to run
32
- robot.run("Tell me a story") { |chunk| print chunk.content }
33
- ```
34
-
35
- Each callback receives a `RubyLLM::Chunk`. Use `chunk.content` — there is no
36
- `chunk.text`. If both are supplied, both fire, with the stored `on_content`
37
- first. `on_content` is read from the robot's own config at construction time; a
38
- network-level `config:` does not supply it.
39
-
40
- The config key `streaming_enabled` has zero consumers in `lib/` and does nothing.
41
-
42
- ## Overview
43
-
44
- The module provides structured event publishing with automatic sequencing,
45
- timestamping, and ID generation. Event names cover run lifecycle, content deltas
46
- (token streaming), tool calls, and metadata updates, and contexts can be nested
47
- so a network-level run and its child robot runs share one monotonic sequence.
48
-
49
- ```ruby
50
- publish = ->(event) {
51
- case event[:event]
52
- when "text.delta"
53
- print event[:data][:delta]
54
- when "run.completed"
55
- puts "\nDone!"
56
- end
57
- }
58
-
59
- context = RobotLab::Streaming::Context.new(
60
- run_id: SecureRandom.uuid,
61
- message_id: SecureRandom.uuid,
62
- scope: "robot",
63
- publish: publish
64
- )
65
-
66
- context.publish_event(event: "text.delta", data: { delta: "Hello" })
67
- ```
68
-
69
- ## Components
70
-
71
- | Component | Description |
72
- |-----------|-------------|
73
- | [Context](context.md) | Manages streaming state, sequencing, and event publishing |
74
- | [Events](events.md) | Event type constants and classification helpers |
75
- | `SequenceCounter` | Thread-safe monotonic counter for event ordering. Its only consumer is `Streaming::Context`, which is itself unused by the framework |
76
-
77
- ## Event Categories
78
-
79
- These are the names defined in `Streaming::Events`. They are constants and
80
- classification helpers only — no framework code emits any of them.
81
-
82
- | Category | Events | Description |
83
- |----------|--------|-------------|
84
- | Lifecycle | `run.started`, `run.completed`, `run.failed`, `run.interrupted` | Run-level state changes |
85
- | Steps | `step.started`, `step.completed`, `step.failed` | Durable execution steps |
86
- | Parts | `part.created`, `part.completed`, `part.failed` | Message composition parts |
87
- | Deltas | `text.delta`, `tool_call.arguments.delta`, `tool_call.output.delta`, `reasoning.delta`, `data.delta` | Token-level content streaming |
88
- | HITL | `hitl.requested`, `hitl.resolved` | Human-in-the-loop events |
89
- | Metadata | `usage.updated`, `metadata.updated` | Token usage and metadata |
90
- | Terminal | `stream.ended` | End of stream signal |
91
-
92
- `DELTA_EVENTS` has five members — `tool_call.output.delta` is easy to miss.
93
- `ALL_EVENTS` has twenty.
94
-
95
- ## Event Structure
96
-
97
- Each published event is a hash with the following shape:
98
-
99
- ```ruby
100
- {
101
- event: "text.delta", # Event type string
102
- data: { # Event payload (merged with context info)
103
- delta: "Hello", # Custom data
104
- run_id: "run_123", # Injected by context
105
- message_id: "msg_456", # Injected by context
106
- scope: "robot" # Injected by context
107
- },
108
- timestamp: 1707900000000, # Millisecond Unix timestamp
109
- sequence_number: 1, # Monotonically increasing
110
- id: "publish-1:text.delta" # Unique event ID
111
- }
112
- ```
113
-
114
- ## Quick Start
115
-
116
- ### Publishing Events
117
-
118
- ```ruby
119
- context = RobotLab::Streaming::Context.new(
120
- run_id: "run_123",
121
- message_id: "msg_456",
122
- scope: "network",
123
- publish: ->(event) { broadcast(event) }
124
- )
125
-
126
- context.publish_event(event: "run.started", data: { robot_name: "assistant" })
127
- context.publish_event(event: "text.delta", data: { delta: "Hello " })
128
- context.publish_event(event: "text.delta", data: { delta: "world!" })
129
- context.publish_event(event: "run.completed", data: {})
130
- ```
131
-
132
- ### Nested Contexts
133
-
134
- Contexts can be nested to model a parent run with child runs sharing one
135
- sequence. Note that no `Network` creates these — you would build the hierarchy
136
- yourself.
137
-
138
- ```ruby
139
- # Parent context for a run you are orchestrating
140
- network_context = RobotLab::Streaming::Context.new(
141
- run_id: "network_run_1",
142
- message_id: "msg_1",
143
- scope: "network",
144
- publish: ->(event) { stream_to_client(event) }
145
- )
146
-
147
- # Child context for each robot (shares the sequence counter)
148
- robot_context = network_context.create_child_context("robot_run_1")
149
- robot_context.publish_event(event: "text.delta", data: { delta: "Response" })
150
- ```
151
-
152
- ## See Also
153
-
154
- - [Context](context.md)
155
- - [Events](events.md)
156
- - [Robot](../core/robot.md) -- `on_content:`, and the block form of `run`, which is how streaming actually works