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.
- checksums.yaml +4 -4
- data/.github/workflows/deploy-github-pages.yml +9 -9
- data/.irbrc +6 -0
- data/CHANGELOG.md +90 -0
- data/README.md +203 -46
- data/Rakefile +70 -1
- data/docs/api/core/index.md +12 -0
- data/docs/api/core/robot.md +478 -130
- data/docs/api/core/tool.md +205 -209
- data/docs/api/history/active-record-adapter.md +174 -94
- data/docs/api/history/config.md +186 -93
- data/docs/api/history/index.md +57 -61
- data/docs/api/history/thread-manager.md +123 -73
- data/docs/api/mcp/client.md +119 -48
- data/docs/api/mcp/index.md +75 -60
- data/docs/api/mcp/server.md +120 -136
- data/docs/api/mcp/transports.md +172 -184
- data/docs/api/streaming/context.md +157 -74
- data/docs/api/streaming/events.md +114 -166
- data/docs/api/streaming/index.md +74 -72
- data/docs/architecture/core-concepts.md +361 -112
- data/docs/architecture/index.md +97 -59
- data/docs/architecture/message-flow.md +138 -129
- data/docs/architecture/network-orchestration.md +197 -50
- data/docs/architecture/robot-execution.md +199 -146
- data/docs/architecture/state-management.md +255 -187
- data/docs/concepts.md +312 -48
- data/docs/examples/basic-chat.md +89 -77
- data/docs/examples/index.md +222 -47
- data/docs/examples/mcp-server.md +207 -203
- data/docs/examples/multi-robot-network.md +129 -35
- data/docs/examples/rails-application.md +159 -160
- data/docs/examples/tool-usage.md +295 -204
- data/docs/getting-started/configuration.md +275 -162
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/installation.md +22 -13
- data/docs/getting-started/quick-start.md +166 -121
- data/docs/guides/building-robots.md +417 -212
- data/docs/guides/creating-networks.md +94 -24
- data/docs/guides/mcp-integration.md +152 -113
- data/docs/guides/memory.md +220 -164
- data/docs/guides/streaming.md +80 -110
- data/docs/guides/using-tools.md +259 -212
- data/docs/index.md +50 -37
- data/examples/01_simple_robot.rb +6 -9
- data/examples/02_tools.rb +6 -9
- data/examples/03_network.rb +13 -14
- data/examples/04_mcp.rb +5 -8
- data/examples/05_streaming.rb +5 -8
- data/examples/06_prompt_templates.rb +42 -37
- data/examples/07_network_memory.rb +13 -14
- data/examples/08_llm_config.rb +140 -0
- data/examples/09_chaining.rb +223 -0
- data/examples/10_memory.rb +331 -0
- data/examples/11_network_introspection.rb +230 -0
- data/examples/12_message_bus.rb +74 -0
- data/examples/13_spawn.rb +90 -0
- data/examples/14_rusty_circuit/comic.rb +143 -0
- data/examples/14_rusty_circuit/display.rb +203 -0
- data/examples/14_rusty_circuit/heckler.rb +57 -0
- data/examples/14_rusty_circuit/open_mic.rb +121 -0
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +20 -0
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +23 -0
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +20 -0
- data/examples/14_rusty_circuit/scout.rb +173 -0
- data/examples/14_rusty_circuit/scout_notes.md +89 -0
- data/examples/14_rusty_circuit/show.log +234 -0
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +24 -0
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +206 -0
- data/examples/15_memory_network_and_bus/linux_writer.rb +80 -0
- data/examples/15_memory_network_and_bus/os_editor.rb +46 -0
- data/examples/15_memory_network_and_bus/os_writer.rb +46 -0
- data/examples/15_memory_network_and_bus/output/combined_article.md +13 -0
- data/examples/15_memory_network_and_bus/output/final_article.md +15 -0
- data/examples/15_memory_network_and_bus/output/linux_draft.md +5 -0
- data/examples/15_memory_network_and_bus/output/mac_draft.md +7 -0
- data/examples/15_memory_network_and_bus/output/memory.json +13 -0
- data/examples/15_memory_network_and_bus/output/revision_1.md +19 -0
- data/examples/15_memory_network_and_bus/output/revision_2.md +15 -0
- data/examples/15_memory_network_and_bus/output/windows_draft.md +7 -0
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +13 -0
- data/examples/README.md +197 -0
- data/examples/prompts/{assistant/system.txt.erb → assistant.md} +3 -0
- data/examples/prompts/{billing/system.txt.erb → billing.md} +3 -0
- data/examples/prompts/{classifier/system.txt.erb → classifier.md} +3 -0
- data/examples/prompts/comedian.md +6 -0
- data/examples/prompts/comedy_critic.md +10 -0
- data/examples/prompts/configurable.md +9 -0
- data/examples/prompts/dispatcher.md +12 -0
- data/examples/prompts/{entity_extractor/system.txt.erb → entity_extractor.md} +3 -0
- data/examples/prompts/{escalation/system.txt.erb → escalation.md} +7 -0
- data/examples/prompts/frontmatter_mcp_test.md +9 -0
- data/examples/prompts/frontmatter_named_test.md +5 -0
- data/examples/prompts/frontmatter_tools_test.md +6 -0
- data/examples/prompts/{general/system.txt.erb → general.md} +3 -0
- data/examples/prompts/{github_assistant/system.txt.erb → github_assistant.md} +8 -0
- data/examples/prompts/{helper/system.txt.erb → helper.md} +3 -0
- data/examples/prompts/{keyword_extractor/system.txt.erb → keyword_extractor.md} +3 -0
- data/examples/prompts/llm_config_demo.md +20 -0
- data/examples/prompts/{order_support/system.txt.erb → order_support.md} +8 -0
- data/examples/prompts/os_advocate.md +13 -0
- data/examples/prompts/os_chief.md +13 -0
- data/examples/prompts/os_editor.md +13 -0
- data/examples/prompts/{product_support/system.txt.erb → product_support.md} +7 -0
- data/examples/prompts/{sentiment_analyzer/system.txt.erb → sentiment_analyzer.md} +3 -0
- data/examples/prompts/{synthesizer/system.txt.erb → synthesizer.md} +3 -0
- data/examples/prompts/{technical/system.txt.erb → technical.md} +3 -0
- data/examples/prompts/{triage/system.txt.erb → triage.md} +6 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +1 -1
- data/lib/robot_lab/adapters/openai.rb +2 -1
- data/lib/robot_lab/ask_user.rb +75 -0
- data/lib/robot_lab/config/defaults.yml +121 -0
- data/lib/robot_lab/config.rb +183 -0
- data/lib/robot_lab/error.rb +6 -0
- data/lib/robot_lab/mcp/client.rb +1 -1
- data/lib/robot_lab/memory.rb +2 -2
- data/lib/robot_lab/robot.rb +523 -249
- data/lib/robot_lab/robot_message.rb +44 -0
- data/lib/robot_lab/robot_result.rb +1 -0
- data/lib/robot_lab/robotic_model.rb +1 -1
- data/lib/robot_lab/streaming/context.rb +1 -1
- data/lib/robot_lab/tool.rb +108 -172
- data/lib/robot_lab/tool_config.rb +1 -1
- data/lib/robot_lab/tool_manifest.rb +2 -18
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +66 -55
- metadata +107 -116
- data/examples/prompts/assistant/user.txt.erb +0 -1
- data/examples/prompts/billing/user.txt.erb +0 -1
- data/examples/prompts/classifier/user.txt.erb +0 -1
- data/examples/prompts/entity_extractor/user.txt.erb +0 -3
- data/examples/prompts/escalation/user.txt.erb +0 -34
- data/examples/prompts/general/user.txt.erb +0 -1
- data/examples/prompts/github_assistant/user.txt.erb +0 -1
- data/examples/prompts/helper/user.txt.erb +0 -1
- data/examples/prompts/keyword_extractor/user.txt.erb +0 -3
- data/examples/prompts/order_support/user.txt.erb +0 -22
- data/examples/prompts/product_support/user.txt.erb +0 -32
- data/examples/prompts/sentiment_analyzer/user.txt.erb +0 -3
- data/examples/prompts/synthesizer/user.txt.erb +0 -15
- data/examples/prompts/technical/user.txt.erb +0 -1
- data/examples/prompts/triage/user.txt.erb +0 -17
- data/lib/robot_lab/configuration.rb +0 -143
data/docs/guides/streaming.md
CHANGED
|
@@ -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
|
|
7
|
+
Pass a block to `robot.run` to receive streaming events:
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
|
-
robot.
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
24
|
+
Receive text as it is generated:
|
|
24
25
|
|
|
25
26
|
```ruby
|
|
26
|
-
|
|
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
|
-
|
|
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
|
-
|
|
54
|
+
robot.run("Help me with my task") do |event|
|
|
54
55
|
case event[:event]
|
|
55
56
|
when "run.started"
|
|
56
|
-
puts "Starting
|
|
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` |
|
|
70
|
-
| `run.completed` |
|
|
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
|
-
##
|
|
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
|
-
|
|
79
|
+
Handle all event types in a single block:
|
|
98
80
|
|
|
99
81
|
```ruby
|
|
100
|
-
|
|
101
|
-
event:
|
|
102
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
225
|
+
## Without Streaming
|
|
255
226
|
|
|
256
|
-
|
|
227
|
+
When streaming is not needed, simply call `run` without a block:
|
|
257
228
|
|
|
258
229
|
```ruby
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
272
|
+
robot.run("Hello") do |event|
|
|
273
|
+
stream_to_client(event)
|
|
274
|
+
end
|
|
305
275
|
ensure
|
|
306
276
|
close_stream_connection
|
|
307
277
|
end
|