robot_lab 0.0.1 → 0.0.4

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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/deploy-github-pages.yml +9 -9
  3. data/.irbrc +6 -0
  4. data/CHANGELOG.md +90 -0
  5. data/README.md +203 -46
  6. data/Rakefile +70 -1
  7. data/docs/api/core/index.md +12 -0
  8. data/docs/api/core/robot.md +478 -130
  9. data/docs/api/core/tool.md +205 -209
  10. data/docs/api/history/active-record-adapter.md +174 -94
  11. data/docs/api/history/config.md +186 -93
  12. data/docs/api/history/index.md +57 -61
  13. data/docs/api/history/thread-manager.md +123 -73
  14. data/docs/api/mcp/client.md +119 -48
  15. data/docs/api/mcp/index.md +75 -60
  16. data/docs/api/mcp/server.md +120 -136
  17. data/docs/api/mcp/transports.md +172 -184
  18. data/docs/api/streaming/context.md +157 -74
  19. data/docs/api/streaming/events.md +114 -166
  20. data/docs/api/streaming/index.md +74 -72
  21. data/docs/architecture/core-concepts.md +361 -112
  22. data/docs/architecture/index.md +97 -59
  23. data/docs/architecture/message-flow.md +138 -129
  24. data/docs/architecture/network-orchestration.md +197 -50
  25. data/docs/architecture/robot-execution.md +199 -146
  26. data/docs/architecture/state-management.md +255 -187
  27. data/docs/concepts.md +312 -48
  28. data/docs/examples/basic-chat.md +89 -77
  29. data/docs/examples/index.md +222 -47
  30. data/docs/examples/mcp-server.md +207 -203
  31. data/docs/examples/multi-robot-network.md +129 -35
  32. data/docs/examples/rails-application.md +159 -160
  33. data/docs/examples/tool-usage.md +295 -204
  34. data/docs/getting-started/configuration.md +275 -162
  35. data/docs/getting-started/index.md +1 -1
  36. data/docs/getting-started/installation.md +22 -13
  37. data/docs/getting-started/quick-start.md +166 -121
  38. data/docs/guides/building-robots.md +417 -212
  39. data/docs/guides/creating-networks.md +94 -24
  40. data/docs/guides/mcp-integration.md +152 -113
  41. data/docs/guides/memory.md +220 -164
  42. data/docs/guides/streaming.md +80 -110
  43. data/docs/guides/using-tools.md +259 -212
  44. data/docs/index.md +50 -37
  45. data/examples/01_simple_robot.rb +6 -9
  46. data/examples/02_tools.rb +6 -9
  47. data/examples/03_network.rb +13 -14
  48. data/examples/04_mcp.rb +5 -8
  49. data/examples/05_streaming.rb +5 -8
  50. data/examples/06_prompt_templates.rb +42 -37
  51. data/examples/07_network_memory.rb +13 -14
  52. data/examples/08_llm_config.rb +140 -0
  53. data/examples/09_chaining.rb +223 -0
  54. data/examples/10_memory.rb +331 -0
  55. data/examples/11_network_introspection.rb +230 -0
  56. data/examples/12_message_bus.rb +74 -0
  57. data/examples/13_spawn.rb +90 -0
  58. data/examples/14_rusty_circuit/comic.rb +143 -0
  59. data/examples/14_rusty_circuit/display.rb +203 -0
  60. data/examples/14_rusty_circuit/heckler.rb +57 -0
  61. data/examples/14_rusty_circuit/open_mic.rb +121 -0
  62. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +20 -0
  63. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +23 -0
  64. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +20 -0
  65. data/examples/14_rusty_circuit/scout.rb +173 -0
  66. data/examples/14_rusty_circuit/scout_notes.md +89 -0
  67. data/examples/14_rusty_circuit/show.log +234 -0
  68. data/examples/15_memory_network_and_bus/editor_in_chief.rb +24 -0
  69. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +206 -0
  70. data/examples/15_memory_network_and_bus/linux_writer.rb +80 -0
  71. data/examples/15_memory_network_and_bus/os_editor.rb +46 -0
  72. data/examples/15_memory_network_and_bus/os_writer.rb +46 -0
  73. data/examples/15_memory_network_and_bus/output/combined_article.md +13 -0
  74. data/examples/15_memory_network_and_bus/output/final_article.md +15 -0
  75. data/examples/15_memory_network_and_bus/output/linux_draft.md +5 -0
  76. data/examples/15_memory_network_and_bus/output/mac_draft.md +7 -0
  77. data/examples/15_memory_network_and_bus/output/memory.json +13 -0
  78. data/examples/15_memory_network_and_bus/output/revision_1.md +19 -0
  79. data/examples/15_memory_network_and_bus/output/revision_2.md +15 -0
  80. data/examples/15_memory_network_and_bus/output/windows_draft.md +7 -0
  81. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +13 -0
  82. data/examples/15_memory_network_and_bus/prompts/os_chief.md +13 -0
  83. data/examples/15_memory_network_and_bus/prompts/os_editor.md +13 -0
  84. data/examples/README.md +197 -0
  85. data/examples/prompts/{assistant/system.txt.erb → assistant.md} +3 -0
  86. data/examples/prompts/{billing/system.txt.erb → billing.md} +3 -0
  87. data/examples/prompts/{classifier/system.txt.erb → classifier.md} +3 -0
  88. data/examples/prompts/comedian.md +6 -0
  89. data/examples/prompts/comedy_critic.md +10 -0
  90. data/examples/prompts/configurable.md +9 -0
  91. data/examples/prompts/dispatcher.md +12 -0
  92. data/examples/prompts/{entity_extractor/system.txt.erb → entity_extractor.md} +3 -0
  93. data/examples/prompts/{escalation/system.txt.erb → escalation.md} +7 -0
  94. data/examples/prompts/frontmatter_mcp_test.md +9 -0
  95. data/examples/prompts/frontmatter_named_test.md +5 -0
  96. data/examples/prompts/frontmatter_tools_test.md +6 -0
  97. data/examples/prompts/{general/system.txt.erb → general.md} +3 -0
  98. data/examples/prompts/{github_assistant/system.txt.erb → github_assistant.md} +8 -0
  99. data/examples/prompts/{helper/system.txt.erb → helper.md} +3 -0
  100. data/examples/prompts/{keyword_extractor/system.txt.erb → keyword_extractor.md} +3 -0
  101. data/examples/prompts/llm_config_demo.md +20 -0
  102. data/examples/prompts/{order_support/system.txt.erb → order_support.md} +8 -0
  103. data/examples/prompts/os_advocate.md +13 -0
  104. data/examples/prompts/os_chief.md +13 -0
  105. data/examples/prompts/os_editor.md +13 -0
  106. data/examples/prompts/{product_support/system.txt.erb → product_support.md} +7 -0
  107. data/examples/prompts/{sentiment_analyzer/system.txt.erb → sentiment_analyzer.md} +3 -0
  108. data/examples/prompts/{synthesizer/system.txt.erb → synthesizer.md} +3 -0
  109. data/examples/prompts/{technical/system.txt.erb → technical.md} +3 -0
  110. data/examples/prompts/{triage/system.txt.erb → triage.md} +6 -0
  111. data/lib/generators/robot_lab/templates/initializer.rb.tt +1 -1
  112. data/lib/robot_lab/adapters/openai.rb +2 -1
  113. data/lib/robot_lab/ask_user.rb +75 -0
  114. data/lib/robot_lab/config/defaults.yml +121 -0
  115. data/lib/robot_lab/config.rb +183 -0
  116. data/lib/robot_lab/error.rb +6 -0
  117. data/lib/robot_lab/mcp/client.rb +1 -1
  118. data/lib/robot_lab/memory.rb +2 -2
  119. data/lib/robot_lab/robot.rb +523 -249
  120. data/lib/robot_lab/robot_message.rb +44 -0
  121. data/lib/robot_lab/robot_result.rb +1 -0
  122. data/lib/robot_lab/robotic_model.rb +1 -1
  123. data/lib/robot_lab/streaming/context.rb +1 -1
  124. data/lib/robot_lab/tool.rb +108 -172
  125. data/lib/robot_lab/tool_config.rb +1 -1
  126. data/lib/robot_lab/tool_manifest.rb +2 -18
  127. data/lib/robot_lab/version.rb +1 -1
  128. data/lib/robot_lab.rb +66 -55
  129. metadata +107 -116
  130. data/examples/prompts/assistant/user.txt.erb +0 -1
  131. data/examples/prompts/billing/user.txt.erb +0 -1
  132. data/examples/prompts/classifier/user.txt.erb +0 -1
  133. data/examples/prompts/entity_extractor/user.txt.erb +0 -3
  134. data/examples/prompts/escalation/user.txt.erb +0 -34
  135. data/examples/prompts/general/user.txt.erb +0 -1
  136. data/examples/prompts/github_assistant/user.txt.erb +0 -1
  137. data/examples/prompts/helper/user.txt.erb +0 -1
  138. data/examples/prompts/keyword_extractor/user.txt.erb +0 -3
  139. data/examples/prompts/order_support/user.txt.erb +0 -22
  140. data/examples/prompts/product_support/user.txt.erb +0 -32
  141. data/examples/prompts/sentiment_analyzer/user.txt.erb +0 -3
  142. data/examples/prompts/synthesizer/user.txt.erb +0 -15
  143. data/examples/prompts/technical/user.txt.erb +0 -1
  144. data/examples/prompts/triage/user.txt.erb +0 -17
  145. data/lib/robot_lab/configuration.rb +0 -143
@@ -4,30 +4,31 @@ Stream LLM responses in real-time for better user experience.
4
4
 
5
5
  ## Basic Streaming
6
6
 
7
- Pass a callback to receive streaming events:
7
+ Pass a block to `robot.run` to receive streaming events:
8
8
 
9
9
  ```ruby
10
- robot.run(
11
- state: state,
12
- network: network,
13
- streaming: ->(event) {
14
- puts event.inspect
15
- }
10
+ robot = RobotLab.build(
11
+ name: "storyteller",
12
+ system_prompt: "You are a creative storyteller."
16
13
  )
14
+
15
+ robot.run("Tell me a story about a brave robot") do |event|
16
+ puts event.inspect
17
+ end
17
18
  ```
18
19
 
19
20
  ## Event Types
20
21
 
21
22
  ### Text Deltas
22
23
 
23
- Receive text as it's generated:
24
+ Receive text as it is generated:
24
25
 
25
26
  ```ruby
26
- streaming: ->(event) {
27
- if event[:event] == "delta"
27
+ robot.run("Tell me a story") do |event|
28
+ if event[:event] == "text.delta"
28
29
  print event[:data][:content]
29
30
  end
30
- }
31
+ end
31
32
  ```
32
33
 
33
34
  ### Tool Calls
@@ -35,14 +36,14 @@ streaming: ->(event) {
35
36
  Know when tools are being called:
36
37
 
37
38
  ```ruby
38
- streaming: ->(event) {
39
+ robot.run("What's the weather in Tokyo?") do |event|
39
40
  case event[:event]
40
41
  when "tool_call.start"
41
42
  puts "\nCalling: #{event[:data][:name]}"
42
43
  when "tool_call.complete"
43
44
  puts "Done: #{event[:data][:result]}"
44
45
  end
45
- }
46
+ end
46
47
  ```
47
48
 
48
49
  ### Lifecycle Events
@@ -50,57 +51,48 @@ streaming: ->(event) {
50
51
  Track execution lifecycle:
51
52
 
52
53
  ```ruby
53
- streaming: ->(event) {
54
+ robot.run("Help me with my task") do |event|
54
55
  case event[:event]
55
56
  when "run.started"
56
- puts "Starting run #{event[:data][:run_id]}"
57
+ puts "Starting..."
57
58
  when "run.completed"
58
59
  puts "Completed!"
59
60
  when "run.failed"
60
61
  puts "Failed: #{event[:data][:error]}"
61
62
  end
62
- }
63
+ end
63
64
  ```
64
65
 
65
66
  ## Event Reference
66
67
 
67
68
  | Event | Description | Data |
68
69
  |-------|-------------|------|
69
- | `run.started` | Network run began | `run_id`, `network` |
70
- | `run.completed` | Network run finished | `run_id`, `robot_count` |
70
+ | `run.started` | Execution began | `run_id` |
71
+ | `run.completed` | Execution finished | `run_id` |
71
72
  | `run.failed` | Error occurred | `run_id`, `error` |
72
- | `delta` | Text content chunk | `content` |
73
+ | `text.delta` | Text content chunk | `content` |
73
74
  | `tool_call.start` | Tool execution starting | `name`, `input` |
74
75
  | `tool_call.complete` | Tool execution done | `name`, `result` |
75
76
 
76
- ## Streaming Context
77
-
78
- For advanced control, use `Streaming::Context`:
79
-
80
- ```ruby
81
- context = RobotLab::Streaming::Context.new(
82
- run_id: SecureRandom.uuid,
83
- message_id: SecureRandom.uuid,
84
- scope: "network",
85
- publish: ->(event) { broadcast_to_client(event) }
86
- )
87
- ```
88
-
89
- ### Context Properties
90
-
91
- ```ruby
92
- context.run_id # Unique run identifier
93
- context.message_id # Unique message identifier
94
- context.scope # "network" or "robot"
95
- ```
77
+ ## Comprehensive Event Handling
96
78
 
97
- ### Publishing Events
79
+ Handle all event types in a single block:
98
80
 
99
81
  ```ruby
100
- context.publish_event(
101
- event: "custom.event",
102
- data: { key: "value" }
103
- )
82
+ robot.run("Analyze this data and generate a report") do |event|
83
+ case event[:event]
84
+ when "text.delta"
85
+ print event[:data][:content]
86
+ when "tool_call.start"
87
+ puts "\n[Tool] Calling: #{event[:data][:name]}"
88
+ when "tool_call.complete"
89
+ puts "[Tool] Done: #{event[:data][:name]}"
90
+ when "run.completed"
91
+ puts "\n--- Complete ---"
92
+ when "run.failed"
93
+ puts "\n[Error] #{event[:data][:error]}"
94
+ end
95
+ end
104
96
  ```
105
97
 
106
98
  ## Web Integration
@@ -110,14 +102,14 @@ context.publish_event(
110
102
  ```ruby
111
103
  class ChatChannel < ApplicationCable::Channel
112
104
  def receive(data)
113
- state = RobotLab.create_state(message: data["message"])
114
-
115
- network.run(
116
- state: state,
117
- streaming: ->(event) {
118
- transmit(event)
119
- }
105
+ robot = RobotLab.build(
106
+ name: "chat_bot",
107
+ system_prompt: "You are a helpful chat assistant."
120
108
  )
109
+
110
+ robot.run(data["message"]) do |event|
111
+ transmit(event)
112
+ end
121
113
  end
122
114
  end
123
115
  ```
@@ -131,14 +123,14 @@ class StreamController < ApplicationController
131
123
  def create
132
124
  response.headers["Content-Type"] = "text/event-stream"
133
125
 
134
- state = RobotLab.create_state(message: params[:message])
135
-
136
- network.run(
137
- state: state,
138
- streaming: ->(event) {
139
- response.stream.write("data: #{event.to_json}\n\n")
140
- }
126
+ robot = RobotLab.build(
127
+ name: "stream_bot",
128
+ system_prompt: "You are helpful."
141
129
  )
130
+
131
+ robot.run(params[:message]) do |event|
132
+ response.stream.write("data: #{event.to_json}\n\n")
133
+ end
142
134
  ensure
143
135
  response.stream.close
144
136
  end
@@ -150,36 +142,12 @@ end
150
142
  ```ruby
151
143
  # Using Faye WebSocket
152
144
  ws.on :message do |msg|
153
- state = RobotLab.create_state(message: msg.data)
154
-
155
- network.run(
156
- state: state,
157
- streaming: ->(event) {
158
- ws.send(event.to_json)
159
- }
160
- )
145
+ robot.run(msg.data) do |event|
146
+ ws.send(event.to_json)
147
+ end
161
148
  end
162
149
  ```
163
150
 
164
- ## Event Filtering
165
-
166
- ### Check Event Type
167
-
168
- ```ruby
169
- streaming: ->(event) {
170
- return unless RobotLab::Streaming::Events.delta?(event)
171
- print event[:data][:content]
172
- }
173
- ```
174
-
175
- ### Available Predicates
176
-
177
- ```ruby
178
- Streaming::Events.lifecycle?(event) # run.started, run.completed, etc.
179
- Streaming::Events.delta?(event) # Text content
180
- Streaming::Events.valid?(event) # Has required fields
181
- ```
182
-
183
151
  ## Buffering
184
152
 
185
153
  Buffer content for batch processing:
@@ -187,8 +155,8 @@ Buffer content for batch processing:
187
155
  ```ruby
188
156
  buffer = []
189
157
 
190
- streaming: ->(event) {
191
- if event[:event] == "delta"
158
+ robot.run("Generate a long response") do |event|
159
+ if event[:event] == "text.delta"
192
160
  buffer << event[:data][:content]
193
161
 
194
162
  # Flush every 10 chunks
@@ -197,9 +165,9 @@ streaming: ->(event) {
197
165
  buffer.clear
198
166
  end
199
167
  end
200
- }
168
+ end
201
169
 
202
- # Don't forget final flush
170
+ # Final flush
203
171
  process_batch(buffer.join) if buffer.any?
204
172
  ```
205
173
 
@@ -216,9 +184,9 @@ class StreamProgress
216
184
 
217
185
  def handle(event)
218
186
  case event[:event]
219
- when "delta"
187
+ when "text.delta"
220
188
  @chars += event[:data][:content].length
221
- puts "\rReceived #{@chars} characters..."
189
+ print "\rReceived #{@chars} characters..."
222
190
  when "tool_call.start"
223
191
  @tools += 1
224
192
  puts "\nTool call ##{@tools}: #{event[:data][:name]}"
@@ -227,7 +195,10 @@ class StreamProgress
227
195
  end
228
196
 
229
197
  progress = StreamProgress.new
230
- network.run(state: state, streaming: progress.method(:handle))
198
+
199
+ robot.run("Process this complex request") do |event|
200
+ progress.handle(event)
201
+ end
231
202
  ```
232
203
 
233
204
  ## Error Handling
@@ -235,12 +206,12 @@ network.run(state: state, streaming: progress.method(:handle))
235
206
  Handle streaming errors gracefully:
236
207
 
237
208
  ```ruby
238
- streaming: ->(event) {
209
+ robot.run("Analyze this") do |event|
239
210
  case event[:event]
240
211
  when "run.failed"
241
212
  log_error(event[:data][:error])
242
213
  notify_user("An error occurred")
243
- when "delta"
214
+ when "text.delta"
244
215
  begin
245
216
  broadcast(event)
246
217
  rescue BroadcastError => e
@@ -248,20 +219,17 @@ streaming: ->(event) {
248
219
  logger.warn "Broadcast failed: #{e.message}"
249
220
  end
250
221
  end
251
- }
222
+ end
252
223
  ```
253
224
 
254
- ## Disabling Streaming
225
+ ## Without Streaming
255
226
 
256
- Disable streaming when not needed:
227
+ When streaming is not needed, simply call `run` without a block:
257
228
 
258
229
  ```ruby
259
- RobotLab.configure do |config|
260
- config.streaming_enabled = false
261
- end
262
-
263
- # Or per-run
264
- network.run(state: state, streaming: nil)
230
+ # No streaming - returns RobotResult directly
231
+ result = robot.run("Hello!")
232
+ puts result.last_text_content
265
233
  ```
266
234
 
267
235
  ## Best Practices
@@ -269,39 +237,41 @@ network.run(state: state, streaming: nil)
269
237
  ### 1. Handle All Event Types
270
238
 
271
239
  ```ruby
272
- streaming: ->(event) {
240
+ robot.run("Hello") do |event|
273
241
  case event[:event]
274
- when "delta" then handle_delta(event)
242
+ when "text.delta" then handle_delta(event)
275
243
  when "tool_call.start" then show_tool_indicator(event)
276
244
  when "tool_call.complete" then hide_tool_indicator(event)
277
245
  when "run.completed" then finalize_response
278
246
  when "run.failed" then show_error(event)
279
247
  end
280
- }
248
+ end
281
249
  ```
282
250
 
283
251
  ### 2. Provide User Feedback
284
252
 
285
253
  ```ruby
286
- streaming: ->(event) {
254
+ robot.run("Process my request") do |event|
287
255
  case event[:event]
288
256
  when "run.started"
289
257
  show_typing_indicator
290
- when "delta"
258
+ when "text.delta"
291
259
  update_message(event[:data][:content])
292
260
  when "tool_call.start"
293
261
  show_status("Looking up information...")
294
262
  when "run.completed"
295
263
  hide_typing_indicator
296
264
  end
297
- }
265
+ end
298
266
  ```
299
267
 
300
268
  ### 3. Clean Up Resources
301
269
 
302
270
  ```ruby
303
271
  begin
304
- network.run(state: state, streaming: callback)
272
+ robot.run("Hello") do |event|
273
+ stream_to_client(event)
274
+ end
305
275
  ensure
306
276
  close_stream_connection
307
277
  end