robot_lab 0.0.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.
- checksums.yaml +7 -0
- data/.envrc +1 -0
- data/.github/workflows/deploy-github-pages.yml +52 -0
- data/.github/workflows/deploy-yard-docs.yml +52 -0
- data/CHANGELOG.md +55 -0
- data/COMMITS.md +196 -0
- data/LICENSE.txt +21 -0
- data/README.md +332 -0
- data/Rakefile +67 -0
- data/docs/api/adapters/anthropic.md +121 -0
- data/docs/api/adapters/gemini.md +133 -0
- data/docs/api/adapters/index.md +104 -0
- data/docs/api/adapters/openai.md +134 -0
- data/docs/api/core/index.md +113 -0
- data/docs/api/core/memory.md +314 -0
- data/docs/api/core/network.md +291 -0
- data/docs/api/core/robot.md +273 -0
- data/docs/api/core/state.md +273 -0
- data/docs/api/core/tool.md +353 -0
- data/docs/api/history/active-record-adapter.md +195 -0
- data/docs/api/history/config.md +191 -0
- data/docs/api/history/index.md +132 -0
- data/docs/api/history/thread-manager.md +144 -0
- data/docs/api/index.md +82 -0
- data/docs/api/mcp/client.md +221 -0
- data/docs/api/mcp/index.md +111 -0
- data/docs/api/mcp/server.md +225 -0
- data/docs/api/mcp/transports.md +264 -0
- data/docs/api/messages/index.md +67 -0
- data/docs/api/messages/text-message.md +102 -0
- data/docs/api/messages/tool-call-message.md +144 -0
- data/docs/api/messages/tool-result-message.md +154 -0
- data/docs/api/messages/user-message.md +171 -0
- data/docs/api/streaming/context.md +174 -0
- data/docs/api/streaming/events.md +237 -0
- data/docs/api/streaming/index.md +108 -0
- data/docs/architecture/core-concepts.md +243 -0
- data/docs/architecture/index.md +138 -0
- data/docs/architecture/message-flow.md +320 -0
- data/docs/architecture/network-orchestration.md +216 -0
- data/docs/architecture/robot-execution.md +243 -0
- data/docs/architecture/state-management.md +323 -0
- data/docs/assets/css/custom.css +56 -0
- data/docs/assets/images/robot_lab.jpg +0 -0
- data/docs/concepts.md +216 -0
- data/docs/examples/basic-chat.md +193 -0
- data/docs/examples/index.md +129 -0
- data/docs/examples/mcp-server.md +290 -0
- data/docs/examples/multi-robot-network.md +312 -0
- data/docs/examples/rails-application.md +420 -0
- data/docs/examples/tool-usage.md +310 -0
- data/docs/getting-started/configuration.md +230 -0
- data/docs/getting-started/index.md +56 -0
- data/docs/getting-started/installation.md +179 -0
- data/docs/getting-started/quick-start.md +203 -0
- data/docs/guides/building-robots.md +376 -0
- data/docs/guides/creating-networks.md +366 -0
- data/docs/guides/history.md +359 -0
- data/docs/guides/index.md +68 -0
- data/docs/guides/mcp-integration.md +356 -0
- data/docs/guides/memory.md +309 -0
- data/docs/guides/rails-integration.md +432 -0
- data/docs/guides/streaming.md +314 -0
- data/docs/guides/using-tools.md +394 -0
- data/docs/index.md +160 -0
- data/examples/01_simple_robot.rb +38 -0
- data/examples/02_tools.rb +106 -0
- data/examples/03_network.rb +103 -0
- data/examples/04_mcp.rb +219 -0
- data/examples/05_streaming.rb +124 -0
- data/examples/06_prompt_templates.rb +324 -0
- data/examples/07_network_memory.rb +329 -0
- data/examples/prompts/assistant/system.txt.erb +2 -0
- data/examples/prompts/assistant/user.txt.erb +1 -0
- data/examples/prompts/billing/system.txt.erb +7 -0
- data/examples/prompts/billing/user.txt.erb +1 -0
- data/examples/prompts/classifier/system.txt.erb +4 -0
- data/examples/prompts/classifier/user.txt.erb +1 -0
- data/examples/prompts/entity_extractor/system.txt.erb +11 -0
- data/examples/prompts/entity_extractor/user.txt.erb +3 -0
- data/examples/prompts/escalation/system.txt.erb +35 -0
- data/examples/prompts/escalation/user.txt.erb +34 -0
- data/examples/prompts/general/system.txt.erb +4 -0
- data/examples/prompts/general/user.txt.erb +1 -0
- data/examples/prompts/github_assistant/system.txt.erb +6 -0
- data/examples/prompts/github_assistant/user.txt.erb +1 -0
- data/examples/prompts/helper/system.txt.erb +1 -0
- data/examples/prompts/helper/user.txt.erb +1 -0
- data/examples/prompts/keyword_extractor/system.txt.erb +8 -0
- data/examples/prompts/keyword_extractor/user.txt.erb +3 -0
- data/examples/prompts/order_support/system.txt.erb +27 -0
- data/examples/prompts/order_support/user.txt.erb +22 -0
- data/examples/prompts/product_support/system.txt.erb +30 -0
- data/examples/prompts/product_support/user.txt.erb +32 -0
- data/examples/prompts/sentiment_analyzer/system.txt.erb +9 -0
- data/examples/prompts/sentiment_analyzer/user.txt.erb +3 -0
- data/examples/prompts/synthesizer/system.txt.erb +14 -0
- data/examples/prompts/synthesizer/user.txt.erb +15 -0
- data/examples/prompts/technical/system.txt.erb +7 -0
- data/examples/prompts/technical/user.txt.erb +1 -0
- data/examples/prompts/triage/system.txt.erb +16 -0
- data/examples/prompts/triage/user.txt.erb +17 -0
- data/lib/generators/robot_lab/install_generator.rb +78 -0
- data/lib/generators/robot_lab/robot_generator.rb +55 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +41 -0
- data/lib/generators/robot_lab/templates/migration.rb.tt +32 -0
- data/lib/generators/robot_lab/templates/result_model.rb.tt +52 -0
- data/lib/generators/robot_lab/templates/robot.rb.tt +46 -0
- data/lib/generators/robot_lab/templates/robot_test.rb.tt +32 -0
- data/lib/generators/robot_lab/templates/routing_robot.rb.tt +53 -0
- data/lib/generators/robot_lab/templates/thread_model.rb.tt +40 -0
- data/lib/robot_lab/adapters/anthropic.rb +163 -0
- data/lib/robot_lab/adapters/base.rb +85 -0
- data/lib/robot_lab/adapters/gemini.rb +193 -0
- data/lib/robot_lab/adapters/openai.rb +159 -0
- data/lib/robot_lab/adapters/registry.rb +81 -0
- data/lib/robot_lab/configuration.rb +143 -0
- data/lib/robot_lab/error.rb +32 -0
- data/lib/robot_lab/errors.rb +70 -0
- data/lib/robot_lab/history/active_record_adapter.rb +146 -0
- data/lib/robot_lab/history/config.rb +115 -0
- data/lib/robot_lab/history/thread_manager.rb +93 -0
- data/lib/robot_lab/mcp/client.rb +210 -0
- data/lib/robot_lab/mcp/server.rb +84 -0
- data/lib/robot_lab/mcp/transports/base.rb +56 -0
- data/lib/robot_lab/mcp/transports/sse.rb +117 -0
- data/lib/robot_lab/mcp/transports/stdio.rb +133 -0
- data/lib/robot_lab/mcp/transports/streamable_http.rb +139 -0
- data/lib/robot_lab/mcp/transports/websocket.rb +108 -0
- data/lib/robot_lab/memory.rb +882 -0
- data/lib/robot_lab/memory_change.rb +123 -0
- data/lib/robot_lab/message.rb +357 -0
- data/lib/robot_lab/network.rb +350 -0
- data/lib/robot_lab/rails/engine.rb +29 -0
- data/lib/robot_lab/rails/railtie.rb +42 -0
- data/lib/robot_lab/robot.rb +560 -0
- data/lib/robot_lab/robot_result.rb +205 -0
- data/lib/robot_lab/robotic_model.rb +324 -0
- data/lib/robot_lab/state_proxy.rb +188 -0
- data/lib/robot_lab/streaming/context.rb +144 -0
- data/lib/robot_lab/streaming/events.rb +95 -0
- data/lib/robot_lab/streaming/sequence_counter.rb +48 -0
- data/lib/robot_lab/task.rb +117 -0
- data/lib/robot_lab/tool.rb +223 -0
- data/lib/robot_lab/tool_config.rb +112 -0
- data/lib/robot_lab/tool_manifest.rb +234 -0
- data/lib/robot_lab/user_message.rb +118 -0
- data/lib/robot_lab/version.rb +5 -0
- data/lib/robot_lab/waiter.rb +73 -0
- data/lib/robot_lab.rb +195 -0
- data/mkdocs.yml +214 -0
- data/sig/robot_lab.rbs +4 -0
- metadata +442 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# UserMessage
|
|
2
|
+
|
|
3
|
+
User input with conversation metadata.
|
|
4
|
+
|
|
5
|
+
## Class: `RobotLab::UserMessage`
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
message = UserMessage.new(
|
|
9
|
+
"What's my order status?",
|
|
10
|
+
thread_id: "thread_123",
|
|
11
|
+
system_prompt: "Be concise",
|
|
12
|
+
metadata: { source: "web" }
|
|
13
|
+
)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Constructor
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
UserMessage.new(content, thread_id: nil, system_prompt: nil, metadata: {})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Parameters:**
|
|
23
|
+
|
|
24
|
+
| Name | Type | Description |
|
|
25
|
+
|------|------|-------------|
|
|
26
|
+
| `content` | `String` | Message text |
|
|
27
|
+
| `thread_id` | `String`, `nil` | Conversation thread ID |
|
|
28
|
+
| `system_prompt` | `String`, `nil` | Override system prompt |
|
|
29
|
+
| `metadata` | `Hash` | Additional metadata |
|
|
30
|
+
|
|
31
|
+
## Attributes
|
|
32
|
+
|
|
33
|
+
### content
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
message.content # => String
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The message text.
|
|
40
|
+
|
|
41
|
+
### thread_id
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
message.thread_id # => String | nil
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Conversation thread identifier for history persistence.
|
|
48
|
+
|
|
49
|
+
### system_prompt
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
message.system_prompt # => String | nil
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Optional system prompt override for this message.
|
|
56
|
+
|
|
57
|
+
### metadata
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
message.metadata # => Hash
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Arbitrary metadata (source, timestamp, user info, etc.).
|
|
64
|
+
|
|
65
|
+
### id
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
message.id # => String (UUID)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Unique message identifier.
|
|
72
|
+
|
|
73
|
+
### created_at
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
message.created_at # => Time
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Message creation timestamp.
|
|
80
|
+
|
|
81
|
+
### role
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
message.role # => :user
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Always returns `:user`.
|
|
88
|
+
|
|
89
|
+
## Methods
|
|
90
|
+
|
|
91
|
+
### to_h
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
message.to_h # => Hash
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Hash representation.
|
|
98
|
+
|
|
99
|
+
**Returns:**
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
{
|
|
103
|
+
role: :user,
|
|
104
|
+
content: "What's my order status?",
|
|
105
|
+
id: "uuid-here",
|
|
106
|
+
thread_id: "thread_123",
|
|
107
|
+
created_at: "2024-01-15T10:30:00Z"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### to_json
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
message.to_json # => String
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
JSON representation.
|
|
118
|
+
|
|
119
|
+
## Examples
|
|
120
|
+
|
|
121
|
+
### Basic Message
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
message = UserMessage.new("Hello!")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### With Thread ID
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
message = UserMessage.new(
|
|
131
|
+
"Continue our conversation",
|
|
132
|
+
thread_id: "thread_abc123"
|
|
133
|
+
)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### With System Prompt Override
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
message = UserMessage.new(
|
|
140
|
+
"Translate this",
|
|
141
|
+
system_prompt: "You are a translator. Respond in Spanish."
|
|
142
|
+
)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### With Metadata
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
message = UserMessage.new(
|
|
149
|
+
"Help with my account",
|
|
150
|
+
metadata: {
|
|
151
|
+
source: "mobile_app",
|
|
152
|
+
user_id: "user_123",
|
|
153
|
+
session_id: "sess_456",
|
|
154
|
+
locale: "en-US"
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Creating State
|
|
160
|
+
|
|
161
|
+
```ruby
|
|
162
|
+
message = UserMessage.new("Help", thread_id: "thread_123")
|
|
163
|
+
state = RobotLab.create_state(message: message)
|
|
164
|
+
|
|
165
|
+
state.thread_id # => "thread_123"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## See Also
|
|
169
|
+
|
|
170
|
+
- [State](../core/state.md)
|
|
171
|
+
- [TextMessage](text-message.md)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# StreamingContext
|
|
2
|
+
|
|
3
|
+
Manages streaming state during execution.
|
|
4
|
+
|
|
5
|
+
## Class: `RobotLab::Streaming::Context`
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
context = RobotLab::Streaming::Context.new(callback: ->(e) { handle(e) })
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
Context.new(callback:, robot: nil, network: nil)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Parameters:**
|
|
18
|
+
|
|
19
|
+
| Name | Type | Description |
|
|
20
|
+
|------|------|-------------|
|
|
21
|
+
| `callback` | `Proc` | Event handler |
|
|
22
|
+
| `robot` | `Robot`, `nil` | Current robot |
|
|
23
|
+
| `network` | `NetworkRun`, `nil` | Network context |
|
|
24
|
+
|
|
25
|
+
## Attributes
|
|
26
|
+
|
|
27
|
+
### callback
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
context.callback # => Proc
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The event handler callback.
|
|
34
|
+
|
|
35
|
+
### robot
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
context.robot # => Robot | nil
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The currently executing robot.
|
|
42
|
+
|
|
43
|
+
### network
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
context.network # => NetworkRun | nil
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The network run context.
|
|
50
|
+
|
|
51
|
+
### buffer
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
context.buffer # => String
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Accumulated text content.
|
|
58
|
+
|
|
59
|
+
### tool_calls
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
context.tool_calls # => Array<ToolCallMessage>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Tool calls received during streaming.
|
|
66
|
+
|
|
67
|
+
## Methods
|
|
68
|
+
|
|
69
|
+
### emit
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
context.emit(event)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Send an event to the callback.
|
|
76
|
+
|
|
77
|
+
### emit_text
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
context.emit_text(text)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Emit a text delta event.
|
|
84
|
+
|
|
85
|
+
### emit_tool_call
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
context.emit_tool_call(id:, name:, input:)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Emit a tool call event.
|
|
92
|
+
|
|
93
|
+
### emit_error
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
context.emit_error(error)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Emit an error event.
|
|
100
|
+
|
|
101
|
+
### complete
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
context.complete
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Signal streaming completion.
|
|
108
|
+
|
|
109
|
+
### for_robot
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
new_context = context.for_robot(robot)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Create a child context for a specific robot.
|
|
116
|
+
|
|
117
|
+
## Examples
|
|
118
|
+
|
|
119
|
+
### Custom Context
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
context = RobotLab::Streaming::Context.new(
|
|
123
|
+
callback: ->(event) {
|
|
124
|
+
case event.type
|
|
125
|
+
when :text_delta
|
|
126
|
+
@output << event.text
|
|
127
|
+
when :complete
|
|
128
|
+
process_output(@output)
|
|
129
|
+
end
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Pass to robot
|
|
134
|
+
robot.run(state: state, streaming: context)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Accumulating Content
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
context = RobotLab::Streaming::Context.new(
|
|
141
|
+
callback: ->(event) {
|
|
142
|
+
print event.text if event.type == :text_delta
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
robot.run(state: state, streaming: context)
|
|
147
|
+
|
|
148
|
+
# Access accumulated content
|
|
149
|
+
puts "Total content: #{context.buffer}"
|
|
150
|
+
puts "Tool calls: #{context.tool_calls.size}"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Network Context
|
|
154
|
+
|
|
155
|
+
```ruby
|
|
156
|
+
context = RobotLab::Streaming::Context.new(
|
|
157
|
+
callback: ->(event) {
|
|
158
|
+
prefix = event.robot_name ? "[#{event.robot_name}] " : ""
|
|
159
|
+
case event.type
|
|
160
|
+
when :text_delta
|
|
161
|
+
print "#{prefix}#{event.text}"
|
|
162
|
+
when :robot_complete
|
|
163
|
+
puts "\n#{prefix}Complete"
|
|
164
|
+
end
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
network.run(state: state, streaming: context)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## See Also
|
|
172
|
+
|
|
173
|
+
- [Streaming Overview](index.md)
|
|
174
|
+
- [Events](events.md)
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Streaming Events
|
|
2
|
+
|
|
3
|
+
Event types for real-time response handling.
|
|
4
|
+
|
|
5
|
+
## Class: `RobotLab::Streaming::Event`
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
event.type # => Symbol
|
|
9
|
+
event.text # => String (for text events)
|
|
10
|
+
event.robot_name # => String (for robot events)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Event Types
|
|
14
|
+
|
|
15
|
+
### :start
|
|
16
|
+
|
|
17
|
+
Streaming has begun.
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
case event.type
|
|
21
|
+
when :start
|
|
22
|
+
puts "Starting..."
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Attributes:**
|
|
27
|
+
|
|
28
|
+
| Name | Type | Description |
|
|
29
|
+
|------|------|-------------|
|
|
30
|
+
| `robot_name` | `String`, `nil` | Robot name |
|
|
31
|
+
|
|
32
|
+
### :text_delta
|
|
33
|
+
|
|
34
|
+
A chunk of text was received.
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
case event.type
|
|
38
|
+
when :text_delta
|
|
39
|
+
print event.text
|
|
40
|
+
end
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Attributes:**
|
|
44
|
+
|
|
45
|
+
| Name | Type | Description |
|
|
46
|
+
|------|------|-------------|
|
|
47
|
+
| `text` | `String` | Text content |
|
|
48
|
+
| `robot_name` | `String`, `nil` | Source robot |
|
|
49
|
+
|
|
50
|
+
### :tool_call
|
|
51
|
+
|
|
52
|
+
A tool is being invoked.
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
case event.type
|
|
56
|
+
when :tool_call
|
|
57
|
+
puts "Calling #{event.name} with #{event.input}"
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Attributes:**
|
|
62
|
+
|
|
63
|
+
| Name | Type | Description |
|
|
64
|
+
|------|------|-------------|
|
|
65
|
+
| `id` | `String` | Tool call ID |
|
|
66
|
+
| `name` | `String` | Tool name |
|
|
67
|
+
| `input` | `Hash` | Tool parameters |
|
|
68
|
+
| `robot_name` | `String`, `nil` | Source robot |
|
|
69
|
+
|
|
70
|
+
### :tool_result
|
|
71
|
+
|
|
72
|
+
A tool has returned a result.
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
case event.type
|
|
76
|
+
when :tool_result
|
|
77
|
+
puts "#{event.name} returned: #{event.result}"
|
|
78
|
+
end
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Attributes:**
|
|
82
|
+
|
|
83
|
+
| Name | Type | Description |
|
|
84
|
+
|------|------|-------------|
|
|
85
|
+
| `id` | `String` | Tool call ID |
|
|
86
|
+
| `name` | `String` | Tool name |
|
|
87
|
+
| `result` | `Object` | Tool result |
|
|
88
|
+
| `robot_name` | `String`, `nil` | Source robot |
|
|
89
|
+
|
|
90
|
+
### :robot_start
|
|
91
|
+
|
|
92
|
+
A robot has started executing (network only).
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
case event.type
|
|
96
|
+
when :robot_start
|
|
97
|
+
puts "Robot #{event.robot_name} starting"
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Attributes:**
|
|
102
|
+
|
|
103
|
+
| Name | Type | Description |
|
|
104
|
+
|------|------|-------------|
|
|
105
|
+
| `robot_name` | `String` | Robot name |
|
|
106
|
+
|
|
107
|
+
### :robot_complete
|
|
108
|
+
|
|
109
|
+
A robot has finished executing (network only).
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
case event.type
|
|
113
|
+
when :robot_complete
|
|
114
|
+
puts "Robot #{event.robot_name} finished"
|
|
115
|
+
end
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Attributes:**
|
|
119
|
+
|
|
120
|
+
| Name | Type | Description |
|
|
121
|
+
|------|------|-------------|
|
|
122
|
+
| `robot_name` | `String` | Robot name |
|
|
123
|
+
| `result` | `RobotResult` | Execution result |
|
|
124
|
+
|
|
125
|
+
### :complete
|
|
126
|
+
|
|
127
|
+
All streaming has finished.
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
case event.type
|
|
131
|
+
when :complete
|
|
132
|
+
puts "All done!"
|
|
133
|
+
end
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### :error
|
|
137
|
+
|
|
138
|
+
An error occurred.
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
case event.type
|
|
142
|
+
when :error
|
|
143
|
+
puts "Error: #{event.error.message}"
|
|
144
|
+
end
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Attributes:**
|
|
148
|
+
|
|
149
|
+
| Name | Type | Description |
|
|
150
|
+
|------|------|-------------|
|
|
151
|
+
| `error` | `Exception` | The error |
|
|
152
|
+
| `robot_name` | `String`, `nil` | Source robot |
|
|
153
|
+
|
|
154
|
+
## Examples
|
|
155
|
+
|
|
156
|
+
### Complete Handler
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
robot.run(state: state) do |event|
|
|
160
|
+
case event.type
|
|
161
|
+
when :start
|
|
162
|
+
puts "=== Starting ==="
|
|
163
|
+
when :text_delta
|
|
164
|
+
print event.text
|
|
165
|
+
when :tool_call
|
|
166
|
+
puts "\n[Tool: #{event.name}]"
|
|
167
|
+
when :tool_result
|
|
168
|
+
puts "[Result: #{event.result.to_s.truncate(50)}]"
|
|
169
|
+
when :complete
|
|
170
|
+
puts "\n=== Complete ==="
|
|
171
|
+
when :error
|
|
172
|
+
puts "\n!!! Error: #{event.error.message}"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Network Handler
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
network.run(state: state) do |event|
|
|
181
|
+
robot = event.robot_name || "system"
|
|
182
|
+
|
|
183
|
+
case event.type
|
|
184
|
+
when :robot_start
|
|
185
|
+
puts "[#{robot}] Starting..."
|
|
186
|
+
when :text_delta
|
|
187
|
+
print event.text
|
|
188
|
+
when :tool_call
|
|
189
|
+
puts "\n[#{robot}] Calling #{event.name}"
|
|
190
|
+
when :robot_complete
|
|
191
|
+
puts "\n[#{robot}] Complete"
|
|
192
|
+
when :error
|
|
193
|
+
puts "\n[#{robot}] Error: #{event.error.message}"
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Filtering Events
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
# Only text
|
|
202
|
+
robot.run(state: state) do |event|
|
|
203
|
+
print event.text if event.type == :text_delta
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Only tools
|
|
207
|
+
robot.run(state: state) do |event|
|
|
208
|
+
if event.type == :tool_call
|
|
209
|
+
log_tool_usage(event.name, event.input)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Async Processing
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
queue = Queue.new
|
|
218
|
+
|
|
219
|
+
Thread.new do
|
|
220
|
+
loop do
|
|
221
|
+
event = queue.pop
|
|
222
|
+
break if event == :done
|
|
223
|
+
process_event(event)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
robot.run(state: state) do |event|
|
|
228
|
+
queue << event
|
|
229
|
+
queue << :done if event.type == :complete
|
|
230
|
+
end
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## See Also
|
|
234
|
+
|
|
235
|
+
- [Streaming Overview](index.md)
|
|
236
|
+
- [StreamingContext](context.md)
|
|
237
|
+
- [Streaming Guide](../../guides/streaming.md)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Streaming
|
|
2
|
+
|
|
3
|
+
Real-time response streaming from LLM providers.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Streaming allows you to receive LLM responses in real-time, token by token, enabling responsive user interfaces and progressive content display.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
result = robot.run(state: state) do |event|
|
|
11
|
+
case event.type
|
|
12
|
+
when :text_delta
|
|
13
|
+
print event.text
|
|
14
|
+
when :tool_call
|
|
15
|
+
puts "\nCalling tool: #{event.name}"
|
|
16
|
+
when :complete
|
|
17
|
+
puts "\nDone!"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
| Component | Description |
|
|
25
|
+
|-----------|-------------|
|
|
26
|
+
| [Context](context.md) | Streaming context and state |
|
|
27
|
+
| [Events](events.md) | Event types and handling |
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### Basic Streaming
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
robot.run(state: state) do |event|
|
|
35
|
+
print event.text if event.type == :text_delta
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### With Network
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
network.run(state: state) do |event|
|
|
43
|
+
case event.type
|
|
44
|
+
when :robot_start
|
|
45
|
+
puts "Robot #{event.robot_name} starting..."
|
|
46
|
+
when :text_delta
|
|
47
|
+
print event.text
|
|
48
|
+
when :robot_complete
|
|
49
|
+
puts "\nRobot #{event.robot_name} complete"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Event Types
|
|
55
|
+
|
|
56
|
+
| Event | Description |
|
|
57
|
+
|-------|-------------|
|
|
58
|
+
| `:start` | Streaming started |
|
|
59
|
+
| `:text_delta` | Text chunk received |
|
|
60
|
+
| `:tool_call` | Tool being called |
|
|
61
|
+
| `:tool_result` | Tool result received |
|
|
62
|
+
| `:robot_start` | Robot execution started |
|
|
63
|
+
| `:robot_complete` | Robot execution finished |
|
|
64
|
+
| `:complete` | All streaming finished |
|
|
65
|
+
| `:error` | Error occurred |
|
|
66
|
+
|
|
67
|
+
## Callback Patterns
|
|
68
|
+
|
|
69
|
+
### Proc/Lambda
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
callback = ->(event) {
|
|
73
|
+
print event.text if event.type == :text_delta
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
robot.run(state: state, streaming: callback)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Block
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
robot.run(state: state) do |event|
|
|
83
|
+
print event.text if event.type == :text_delta
|
|
84
|
+
end
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Object with `call`
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
class StreamHandler
|
|
91
|
+
def call(event)
|
|
92
|
+
case event.type
|
|
93
|
+
when :text_delta
|
|
94
|
+
broadcast(event.text)
|
|
95
|
+
when :error
|
|
96
|
+
log_error(event.error)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
robot.run(state: state, streaming: StreamHandler.new)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## See Also
|
|
105
|
+
|
|
106
|
+
- [Streaming Guide](../../guides/streaming.md)
|
|
107
|
+
- [Robot](../core/robot.md)
|
|
108
|
+
- [Network](../core/network.md)
|