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,264 @@
|
|
|
1
|
+
# MCP Transports
|
|
2
|
+
|
|
3
|
+
Communication methods for MCP connections.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Transports handle the low-level communication between MCP clients and servers. RobotLab supports multiple transport types for different deployment scenarios.
|
|
8
|
+
|
|
9
|
+
## Transport Types
|
|
10
|
+
|
|
11
|
+
### Stdio
|
|
12
|
+
|
|
13
|
+
Standard input/output for local process communication.
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
{
|
|
17
|
+
type: "stdio",
|
|
18
|
+
command: "npx",
|
|
19
|
+
args: ["@modelcontextprotocol/server-filesystem", "/path"],
|
|
20
|
+
env: { "DEBUG" => "true" }
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Options:**
|
|
25
|
+
|
|
26
|
+
| Option | Type | Description |
|
|
27
|
+
|--------|------|-------------|
|
|
28
|
+
| `command` | `String` | Executable command |
|
|
29
|
+
| `args` | `Array` | Command arguments |
|
|
30
|
+
| `env` | `Hash` | Environment variables |
|
|
31
|
+
| `cwd` | `String` | Working directory |
|
|
32
|
+
|
|
33
|
+
**Use Cases:**
|
|
34
|
+
|
|
35
|
+
- Local development
|
|
36
|
+
- CLI tools
|
|
37
|
+
- Subprocess servers
|
|
38
|
+
|
|
39
|
+
### WebSocket
|
|
40
|
+
|
|
41
|
+
Bidirectional real-time communication.
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
{
|
|
45
|
+
type: "websocket",
|
|
46
|
+
url: "wss://mcp.example.com/ws",
|
|
47
|
+
headers: { "Authorization" => "Bearer token" }
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Options:**
|
|
52
|
+
|
|
53
|
+
| Option | Type | Description |
|
|
54
|
+
|--------|------|-------------|
|
|
55
|
+
| `url` | `String` | WebSocket endpoint |
|
|
56
|
+
| `headers` | `Hash` | HTTP headers |
|
|
57
|
+
| `ping_interval` | `Integer` | Keep-alive interval (seconds) |
|
|
58
|
+
|
|
59
|
+
**Use Cases:**
|
|
60
|
+
|
|
61
|
+
- Remote servers
|
|
62
|
+
- Real-time applications
|
|
63
|
+
- Long-running connections
|
|
64
|
+
|
|
65
|
+
### SSE (Server-Sent Events)
|
|
66
|
+
|
|
67
|
+
Unidirectional server-to-client streaming.
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
{
|
|
71
|
+
type: "sse",
|
|
72
|
+
url: "https://mcp.example.com/sse",
|
|
73
|
+
headers: { "Authorization" => "Bearer token" }
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Options:**
|
|
78
|
+
|
|
79
|
+
| Option | Type | Description |
|
|
80
|
+
|--------|------|-------------|
|
|
81
|
+
| `url` | `String` | SSE endpoint |
|
|
82
|
+
| `headers` | `Hash` | HTTP headers |
|
|
83
|
+
| `post_url` | `String` | Endpoint for client messages |
|
|
84
|
+
|
|
85
|
+
**Use Cases:**
|
|
86
|
+
|
|
87
|
+
- Firewall-friendly connections
|
|
88
|
+
- Browser-based clients
|
|
89
|
+
- Streaming responses
|
|
90
|
+
|
|
91
|
+
### HTTP
|
|
92
|
+
|
|
93
|
+
Request/response communication.
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
{
|
|
97
|
+
type: "http",
|
|
98
|
+
url: "https://mcp.example.com/mcp",
|
|
99
|
+
headers: { "Authorization" => "Bearer token" },
|
|
100
|
+
timeout: 30
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Options:**
|
|
105
|
+
|
|
106
|
+
| Option | Type | Description |
|
|
107
|
+
|--------|------|-------------|
|
|
108
|
+
| `url` | `String` | HTTP endpoint |
|
|
109
|
+
| `headers` | `Hash` | HTTP headers |
|
|
110
|
+
| `timeout` | `Integer` | Request timeout (seconds) |
|
|
111
|
+
| `retry` | `Integer` | Retry attempts |
|
|
112
|
+
|
|
113
|
+
**Use Cases:**
|
|
114
|
+
|
|
115
|
+
- Simple integrations
|
|
116
|
+
- Stateless operations
|
|
117
|
+
- Load-balanced servers
|
|
118
|
+
|
|
119
|
+
## Examples
|
|
120
|
+
|
|
121
|
+
### Local Server with Stdio
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
network = RobotLab.create_network do
|
|
125
|
+
mcp [
|
|
126
|
+
{
|
|
127
|
+
name: "filesystem",
|
|
128
|
+
transport: {
|
|
129
|
+
type: "stdio",
|
|
130
|
+
command: "npx",
|
|
131
|
+
args: ["@modelcontextprotocol/server-filesystem", "/home/user/docs"]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Remote Server with WebSocket
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
network = RobotLab.create_network do
|
|
142
|
+
mcp [
|
|
143
|
+
{
|
|
144
|
+
name: "remote_tools",
|
|
145
|
+
transport: {
|
|
146
|
+
type: "websocket",
|
|
147
|
+
url: "wss://tools.example.com/mcp",
|
|
148
|
+
headers: {
|
|
149
|
+
"Authorization" => "Bearer #{ENV['MCP_TOKEN']}"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
end
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Multiple Transports
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
network = RobotLab.create_network do
|
|
161
|
+
mcp [
|
|
162
|
+
# Local filesystem
|
|
163
|
+
{
|
|
164
|
+
name: "fs",
|
|
165
|
+
transport: { type: "stdio", command: "mcp-fs" }
|
|
166
|
+
},
|
|
167
|
+
# Remote API
|
|
168
|
+
{
|
|
169
|
+
name: "api",
|
|
170
|
+
transport: {
|
|
171
|
+
type: "http",
|
|
172
|
+
url: "https://api.example.com/mcp"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
# Real-time service
|
|
176
|
+
{
|
|
177
|
+
name: "realtime",
|
|
178
|
+
transport: {
|
|
179
|
+
type: "websocket",
|
|
180
|
+
url: "wss://realtime.example.com/mcp"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
end
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Custom Transport
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
class CustomTransport
|
|
191
|
+
def initialize(options)
|
|
192
|
+
@options = options
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def connect
|
|
196
|
+
# Establish connection
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def disconnect
|
|
200
|
+
# Close connection
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def send(message)
|
|
204
|
+
# Send message to server
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def receive
|
|
208
|
+
# Receive message from server
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
RobotLab::MCP.register_transport(:custom, CustomTransport)
|
|
213
|
+
|
|
214
|
+
# Use custom transport
|
|
215
|
+
{
|
|
216
|
+
type: "custom",
|
|
217
|
+
option1: "value1"
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Connection Lifecycle
|
|
222
|
+
|
|
223
|
+
```mermaid
|
|
224
|
+
sequenceDiagram
|
|
225
|
+
participant C as Client
|
|
226
|
+
participant T as Transport
|
|
227
|
+
participant S as Server
|
|
228
|
+
|
|
229
|
+
C->>T: connect()
|
|
230
|
+
T->>S: Establish connection
|
|
231
|
+
S-->>T: Connection established
|
|
232
|
+
T-->>C: Connected
|
|
233
|
+
|
|
234
|
+
C->>T: send(request)
|
|
235
|
+
T->>S: Forward request
|
|
236
|
+
S-->>T: Response
|
|
237
|
+
T-->>C: receive() → response
|
|
238
|
+
|
|
239
|
+
C->>T: disconnect()
|
|
240
|
+
T->>S: Close connection
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Error Handling
|
|
244
|
+
|
|
245
|
+
```ruby
|
|
246
|
+
begin
|
|
247
|
+
client.connect
|
|
248
|
+
rescue RobotLab::MCP::ConnectionError => e
|
|
249
|
+
case e.transport
|
|
250
|
+
when "stdio"
|
|
251
|
+
puts "Command failed: #{e.message}"
|
|
252
|
+
when "websocket"
|
|
253
|
+
puts "WebSocket error: #{e.message}"
|
|
254
|
+
when "http"
|
|
255
|
+
puts "HTTP error: #{e.status} - #{e.message}"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## See Also
|
|
261
|
+
|
|
262
|
+
- [MCP Overview](index.md)
|
|
263
|
+
- [MCP Client](client.md)
|
|
264
|
+
- [MCP Server](server.md)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Messages
|
|
2
|
+
|
|
3
|
+
Message types for LLM conversation representation.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
RobotLab uses a structured message system to represent conversations between users, assistants, and tools.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# User input
|
|
11
|
+
user_msg = UserMessage.new("Hello", thread_id: "123")
|
|
12
|
+
|
|
13
|
+
# Assistant response
|
|
14
|
+
text_msg = TextMessage.new("Hi there!")
|
|
15
|
+
|
|
16
|
+
# Tool interaction
|
|
17
|
+
tool_call = ToolCallMessage.new(id: "call_1", name: "get_weather", input: { city: "NYC" })
|
|
18
|
+
tool_result = ToolResultMessage.new(id: "call_1", result: { temp: 72 })
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Message Hierarchy
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Message (base)
|
|
25
|
+
├── UserMessage - User input with metadata
|
|
26
|
+
├── TextMessage - Assistant text response
|
|
27
|
+
├── ToolMessage - Tool-related messages
|
|
28
|
+
│ ├── ToolCallMessage - Tool invocation
|
|
29
|
+
│ └── ToolResultMessage - Tool result
|
|
30
|
+
└── SystemMessage - System prompts
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Common Interface
|
|
34
|
+
|
|
35
|
+
All messages implement:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
message.role # => Symbol (:user, :assistant, :tool)
|
|
39
|
+
message.content # => String or structured data
|
|
40
|
+
message.to_h # => Hash representation
|
|
41
|
+
message.to_json # => JSON string
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Classes
|
|
45
|
+
|
|
46
|
+
| Class | Description |
|
|
47
|
+
|-------|-------------|
|
|
48
|
+
| [UserMessage](user-message.md) | User input with thread and metadata |
|
|
49
|
+
| [TextMessage](text-message.md) | Assistant text response |
|
|
50
|
+
| [ToolCallMessage](tool-call-message.md) | Tool invocation request |
|
|
51
|
+
| [ToolResultMessage](tool-result-message.md) | Tool execution result |
|
|
52
|
+
|
|
53
|
+
## Usage in State
|
|
54
|
+
|
|
55
|
+
Messages are typically accessed through state:
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
state.messages # => Array<Message>
|
|
59
|
+
|
|
60
|
+
# Format for LLM
|
|
61
|
+
state.format_history # => Array<Hash>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## See Also
|
|
65
|
+
|
|
66
|
+
- [State](../core/state.md)
|
|
67
|
+
- [Message Flow Architecture](../../architecture/message-flow.md)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# TextMessage
|
|
2
|
+
|
|
3
|
+
Assistant text response.
|
|
4
|
+
|
|
5
|
+
## Class: `RobotLab::TextMessage`
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
message = TextMessage.new("Hello! How can I help you today?")
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
TextMessage.new(content)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Parameters:**
|
|
18
|
+
|
|
19
|
+
| Name | Type | Description |
|
|
20
|
+
|------|------|-------------|
|
|
21
|
+
| `content` | `String` | Response text |
|
|
22
|
+
|
|
23
|
+
## Attributes
|
|
24
|
+
|
|
25
|
+
### content
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
message.content # => String
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The response text.
|
|
32
|
+
|
|
33
|
+
### role
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
message.role # => :assistant
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Always returns `:assistant`.
|
|
40
|
+
|
|
41
|
+
## Methods
|
|
42
|
+
|
|
43
|
+
### to_h
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
message.to_h # => Hash
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Hash representation.
|
|
50
|
+
|
|
51
|
+
**Returns:**
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
{
|
|
55
|
+
role: :assistant,
|
|
56
|
+
content: "Hello! How can I help you today?"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### to_json
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
message.to_json # => String
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
JSON representation.
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Basic Response
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
message = TextMessage.new("Your order has shipped!")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### In Robot Results
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
result = robot.run(state: state)
|
|
80
|
+
|
|
81
|
+
# Extract text messages
|
|
82
|
+
result.output.each do |msg|
|
|
83
|
+
if msg.is_a?(TextMessage)
|
|
84
|
+
puts msg.content
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Filtering Text Content
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
# Get only text responses from results
|
|
93
|
+
text_responses = state.results.flat_map(&:output).select do |msg|
|
|
94
|
+
msg.is_a?(TextMessage)
|
|
95
|
+
end.map(&:content)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## See Also
|
|
99
|
+
|
|
100
|
+
- [UserMessage](user-message.md)
|
|
101
|
+
- [ToolCallMessage](tool-call-message.md)
|
|
102
|
+
- [Robot](../core/robot.md)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# ToolCallMessage
|
|
2
|
+
|
|
3
|
+
Tool invocation request from the LLM.
|
|
4
|
+
|
|
5
|
+
## Class: `RobotLab::ToolCallMessage`
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
message = ToolCallMessage.new(
|
|
9
|
+
id: "call_abc123",
|
|
10
|
+
name: "get_weather",
|
|
11
|
+
input: { city: "New York", units: "fahrenheit" }
|
|
12
|
+
)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Constructor
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
ToolCallMessage.new(id:, name:, input:)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Parameters:**
|
|
22
|
+
|
|
23
|
+
| Name | Type | Description |
|
|
24
|
+
|------|------|-------------|
|
|
25
|
+
| `id` | `String` | Unique call identifier |
|
|
26
|
+
| `name` | `String` | Tool name |
|
|
27
|
+
| `input` | `Hash` | Tool parameters |
|
|
28
|
+
|
|
29
|
+
## Attributes
|
|
30
|
+
|
|
31
|
+
### id
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
message.id # => String
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Unique identifier for this tool call. Used to match with `ToolResultMessage`.
|
|
38
|
+
|
|
39
|
+
### name
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
message.name # => String
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Name of the tool being invoked.
|
|
46
|
+
|
|
47
|
+
### input
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
message.input # => Hash
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Parameters passed to the tool.
|
|
54
|
+
|
|
55
|
+
### role
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
message.role # => :assistant
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Always returns `:assistant` (the LLM initiates tool calls).
|
|
62
|
+
|
|
63
|
+
## Methods
|
|
64
|
+
|
|
65
|
+
### to_h
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
message.to_h # => Hash
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Hash representation.
|
|
72
|
+
|
|
73
|
+
**Returns:**
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
{
|
|
77
|
+
role: :assistant,
|
|
78
|
+
tool_call: {
|
|
79
|
+
id: "call_abc123",
|
|
80
|
+
name: "get_weather",
|
|
81
|
+
input: { city: "New York", units: "fahrenheit" }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### to_json
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
message.to_json # => String
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
JSON representation.
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
### Basic Tool Call
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
call = ToolCallMessage.new(
|
|
100
|
+
id: "call_1",
|
|
101
|
+
name: "search_orders",
|
|
102
|
+
input: { user_id: "123", status: "pending" }
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Processing Tool Calls
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
result.output.each do |msg|
|
|
110
|
+
case msg
|
|
111
|
+
when ToolCallMessage
|
|
112
|
+
puts "Tool called: #{msg.name}"
|
|
113
|
+
puts "Parameters: #{msg.input.inspect}"
|
|
114
|
+
when ToolResultMessage
|
|
115
|
+
puts "Result for #{msg.id}: #{msg.result}"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### In Tool Execution Flow
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
# LLM returns a tool call
|
|
124
|
+
tool_call = ToolCallMessage.new(
|
|
125
|
+
id: "call_weather_1",
|
|
126
|
+
name: "get_weather",
|
|
127
|
+
input: { city: "Seattle" }
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Tool is executed
|
|
131
|
+
result = tool.call(tool_call.input, state: state)
|
|
132
|
+
|
|
133
|
+
# Result is recorded
|
|
134
|
+
tool_result = ToolResultMessage.new(
|
|
135
|
+
id: tool_call.id,
|
|
136
|
+
result: result
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## See Also
|
|
141
|
+
|
|
142
|
+
- [ToolResultMessage](tool-result-message.md)
|
|
143
|
+
- [Tool](../core/tool.md)
|
|
144
|
+
- [Using Tools Guide](../../guides/using-tools.md)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# ToolResultMessage
|
|
2
|
+
|
|
3
|
+
Result from tool execution.
|
|
4
|
+
|
|
5
|
+
## Class: `RobotLab::ToolResultMessage`
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
message = ToolResultMessage.new(
|
|
9
|
+
id: "call_abc123",
|
|
10
|
+
result: { temperature: 72, conditions: "sunny" }
|
|
11
|
+
)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Constructor
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
ToolResultMessage.new(id:, result:)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Parameters:**
|
|
21
|
+
|
|
22
|
+
| Name | Type | Description |
|
|
23
|
+
|------|------|-------------|
|
|
24
|
+
| `id` | `String` | Matching tool call ID |
|
|
25
|
+
| `result` | `Object` | Tool execution result |
|
|
26
|
+
|
|
27
|
+
## Attributes
|
|
28
|
+
|
|
29
|
+
### id
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
message.id # => String
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Identifier matching the corresponding `ToolCallMessage`.
|
|
36
|
+
|
|
37
|
+
### result
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
message.result # => Object
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The result returned by the tool. Can be any serializable object.
|
|
44
|
+
|
|
45
|
+
### role
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
message.role # => :tool
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Always returns `:tool`.
|
|
52
|
+
|
|
53
|
+
## Methods
|
|
54
|
+
|
|
55
|
+
### to_h
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
message.to_h # => Hash
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Hash representation.
|
|
62
|
+
|
|
63
|
+
**Returns:**
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
{
|
|
67
|
+
role: :tool,
|
|
68
|
+
tool_result: {
|
|
69
|
+
id: "call_abc123",
|
|
70
|
+
result: { temperature: 72, conditions: "sunny" }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### to_json
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
message.to_json # => String
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
JSON representation.
|
|
82
|
+
|
|
83
|
+
## Examples
|
|
84
|
+
|
|
85
|
+
### Basic Result
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
result = ToolResultMessage.new(
|
|
89
|
+
id: "call_1",
|
|
90
|
+
result: { success: true, order_id: "ord_123" }
|
|
91
|
+
)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### String Result
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
result = ToolResultMessage.new(
|
|
98
|
+
id: "call_time",
|
|
99
|
+
result: "2024-01-15T10:30:00Z"
|
|
100
|
+
)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Array Result
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
result = ToolResultMessage.new(
|
|
107
|
+
id: "call_search",
|
|
108
|
+
result: [
|
|
109
|
+
{ id: 1, name: "Product A" },
|
|
110
|
+
{ id: 2, name: "Product B" }
|
|
111
|
+
]
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Error Result
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
result = ToolResultMessage.new(
|
|
119
|
+
id: "call_order",
|
|
120
|
+
result: { success: false, error: "Order not found" }
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Matching with Tool Calls
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
# Process all tool interactions
|
|
128
|
+
result.output.each_cons(2) do |a, b|
|
|
129
|
+
if a.is_a?(ToolCallMessage) && b.is_a?(ToolResultMessage)
|
|
130
|
+
if a.id == b.id
|
|
131
|
+
puts "#{a.name}(#{a.input}) => #{b.result}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### In Result History
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
# Find all tool results from execution
|
|
141
|
+
tool_results = state.results
|
|
142
|
+
.flat_map(&:output)
|
|
143
|
+
.select { |m| m.is_a?(ToolResultMessage) }
|
|
144
|
+
|
|
145
|
+
tool_results.each do |tr|
|
|
146
|
+
puts "Tool result: #{tr.result}"
|
|
147
|
+
end
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## See Also
|
|
151
|
+
|
|
152
|
+
- [ToolCallMessage](tool-call-message.md)
|
|
153
|
+
- [Tool](../core/tool.md)
|
|
154
|
+
- [Using Tools Guide](../../guides/using-tools.md)
|