robot_lab 0.0.1 → 0.0.6

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 (187) 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 +140 -0
  5. data/README.md +263 -48
  6. data/Rakefile +71 -1
  7. data/docs/api/core/index.md +53 -46
  8. data/docs/api/core/memory.md +200 -154
  9. data/docs/api/core/network.md +13 -3
  10. data/docs/api/core/robot.md +490 -130
  11. data/docs/api/core/state.md +55 -73
  12. data/docs/api/core/tool.md +205 -209
  13. data/docs/api/index.md +7 -28
  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/messages/index.md +35 -20
  19. data/docs/api/messages/text-message.md +67 -21
  20. data/docs/api/messages/tool-call-message.md +80 -41
  21. data/docs/api/messages/tool-result-message.md +119 -50
  22. data/docs/api/messages/user-message.md +48 -24
  23. data/docs/api/streaming/context.md +157 -74
  24. data/docs/api/streaming/events.md +114 -166
  25. data/docs/api/streaming/index.md +74 -72
  26. data/docs/architecture/core-concepts.md +360 -116
  27. data/docs/architecture/index.md +97 -59
  28. data/docs/architecture/message-flow.md +138 -129
  29. data/docs/architecture/network-orchestration.md +197 -50
  30. data/docs/architecture/robot-execution.md +199 -146
  31. data/docs/architecture/state-management.md +255 -187
  32. data/docs/concepts.md +311 -49
  33. data/docs/examples/basic-chat.md +89 -77
  34. data/docs/examples/index.md +222 -47
  35. data/docs/examples/mcp-server.md +207 -203
  36. data/docs/examples/multi-robot-network.md +129 -35
  37. data/docs/examples/rails-application.md +159 -160
  38. data/docs/examples/tool-usage.md +295 -204
  39. data/docs/getting-started/configuration.md +347 -154
  40. data/docs/getting-started/index.md +1 -1
  41. data/docs/getting-started/installation.md +22 -13
  42. data/docs/getting-started/quick-start.md +166 -121
  43. data/docs/guides/building-robots.md +418 -212
  44. data/docs/guides/creating-networks.md +143 -24
  45. data/docs/guides/index.md +0 -5
  46. data/docs/guides/mcp-integration.md +152 -113
  47. data/docs/guides/memory.md +220 -164
  48. data/docs/guides/rails-integration.md +244 -162
  49. data/docs/guides/streaming.md +137 -187
  50. data/docs/guides/using-tools.md +259 -212
  51. data/docs/index.md +46 -41
  52. data/examples/01_simple_robot.rb +6 -9
  53. data/examples/02_tools.rb +6 -9
  54. data/examples/03_network.rb +19 -17
  55. data/examples/04_mcp.rb +5 -8
  56. data/examples/05_streaming.rb +5 -8
  57. data/examples/06_prompt_templates.rb +42 -37
  58. data/examples/07_network_memory.rb +13 -14
  59. data/examples/08_llm_config.rb +169 -0
  60. data/examples/09_chaining.rb +262 -0
  61. data/examples/10_memory.rb +331 -0
  62. data/examples/11_network_introspection.rb +253 -0
  63. data/examples/12_message_bus.rb +74 -0
  64. data/examples/13_spawn.rb +90 -0
  65. data/examples/14_rusty_circuit/comic.rb +143 -0
  66. data/examples/14_rusty_circuit/display.rb +203 -0
  67. data/examples/14_rusty_circuit/heckler.rb +63 -0
  68. data/examples/14_rusty_circuit/open_mic.rb +123 -0
  69. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +20 -0
  70. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +23 -0
  71. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +20 -0
  72. data/examples/14_rusty_circuit/scout.rb +156 -0
  73. data/examples/14_rusty_circuit/scout_notes.md +89 -0
  74. data/examples/14_rusty_circuit/show.log +234 -0
  75. data/examples/15_memory_network_and_bus/editor_in_chief.rb +24 -0
  76. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +206 -0
  77. data/examples/15_memory_network_and_bus/linux_writer.rb +80 -0
  78. data/examples/15_memory_network_and_bus/os_editor.rb +46 -0
  79. data/examples/15_memory_network_and_bus/os_writer.rb +46 -0
  80. data/examples/15_memory_network_and_bus/output/combined_article.md +13 -0
  81. data/examples/15_memory_network_and_bus/output/final_article.md +15 -0
  82. data/examples/15_memory_network_and_bus/output/linux_draft.md +5 -0
  83. data/examples/15_memory_network_and_bus/output/mac_draft.md +7 -0
  84. data/examples/15_memory_network_and_bus/output/memory.json +13 -0
  85. data/examples/15_memory_network_and_bus/output/revision_1.md +19 -0
  86. data/examples/15_memory_network_and_bus/output/revision_2.md +15 -0
  87. data/examples/15_memory_network_and_bus/output/windows_draft.md +7 -0
  88. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +13 -0
  89. data/examples/15_memory_network_and_bus/prompts/os_chief.md +13 -0
  90. data/examples/15_memory_network_and_bus/prompts/os_editor.md +13 -0
  91. data/examples/16_writers_room/display.rb +158 -0
  92. data/examples/16_writers_room/output/.gitignore +2 -0
  93. data/examples/16_writers_room/output/opus_001.md +263 -0
  94. data/examples/16_writers_room/output/opus_001_notes.log +470 -0
  95. data/examples/16_writers_room/prompts/writer.md +37 -0
  96. data/examples/16_writers_room/room.rb +150 -0
  97. data/examples/16_writers_room/tools.rb +162 -0
  98. data/examples/16_writers_room/writer.rb +121 -0
  99. data/examples/16_writers_room/writers_room.rb +162 -0
  100. data/examples/README.md +197 -0
  101. data/examples/prompts/{assistant/system.txt.erb → assistant.md} +3 -0
  102. data/examples/prompts/{billing/system.txt.erb → billing.md} +3 -0
  103. data/examples/prompts/{classifier/system.txt.erb → classifier.md} +3 -0
  104. data/examples/prompts/comedian.md +6 -0
  105. data/examples/prompts/comedy_critic.md +10 -0
  106. data/examples/prompts/configurable.md +9 -0
  107. data/examples/prompts/dispatcher.md +12 -0
  108. data/examples/prompts/{entity_extractor/system.txt.erb → entity_extractor.md} +3 -0
  109. data/examples/prompts/{escalation/system.txt.erb → escalation.md} +7 -0
  110. data/examples/prompts/frontmatter_mcp_test.md +9 -0
  111. data/examples/prompts/frontmatter_named_test.md +5 -0
  112. data/examples/prompts/frontmatter_tools_test.md +6 -0
  113. data/examples/prompts/{general/system.txt.erb → general.md} +3 -0
  114. data/examples/prompts/{github_assistant/system.txt.erb → github_assistant.md} +8 -0
  115. data/examples/prompts/{helper/system.txt.erb → helper.md} +3 -0
  116. data/examples/prompts/{keyword_extractor/system.txt.erb → keyword_extractor.md} +3 -0
  117. data/examples/prompts/llm_config_demo.md +20 -0
  118. data/examples/prompts/{order_support/system.txt.erb → order_support.md} +8 -0
  119. data/examples/prompts/os_advocate.md +13 -0
  120. data/examples/prompts/os_chief.md +13 -0
  121. data/examples/prompts/os_editor.md +13 -0
  122. data/examples/prompts/{product_support/system.txt.erb → product_support.md} +7 -0
  123. data/examples/prompts/{sentiment_analyzer/system.txt.erb → sentiment_analyzer.md} +3 -0
  124. data/examples/prompts/{synthesizer/system.txt.erb → synthesizer.md} +3 -0
  125. data/examples/prompts/{technical/system.txt.erb → technical.md} +3 -0
  126. data/examples/prompts/{triage/system.txt.erb → triage.md} +6 -0
  127. data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -13
  128. data/lib/robot_lab/ask_user.rb +75 -0
  129. data/lib/robot_lab/config/defaults.yml +121 -0
  130. data/lib/robot_lab/config.rb +183 -0
  131. data/lib/robot_lab/error.rb +6 -0
  132. data/lib/robot_lab/mcp/client.rb +1 -1
  133. data/lib/robot_lab/memory.rb +10 -34
  134. data/lib/robot_lab/network.rb +13 -20
  135. data/lib/robot_lab/robot/bus_messaging.rb +239 -0
  136. data/lib/robot_lab/robot/mcp_management.rb +88 -0
  137. data/lib/robot_lab/robot/template_rendering.rb +130 -0
  138. data/lib/robot_lab/robot.rb +240 -330
  139. data/lib/robot_lab/robot_message.rb +44 -0
  140. data/lib/robot_lab/robot_result.rb +1 -0
  141. data/lib/robot_lab/run_config.rb +184 -0
  142. data/lib/robot_lab/state_proxy.rb +2 -12
  143. data/lib/robot_lab/streaming/context.rb +1 -1
  144. data/lib/robot_lab/task.rb +8 -1
  145. data/lib/robot_lab/tool.rb +108 -172
  146. data/lib/robot_lab/tool_config.rb +1 -1
  147. data/lib/robot_lab/tool_manifest.rb +2 -18
  148. data/lib/robot_lab/utils.rb +39 -0
  149. data/lib/robot_lab/version.rb +1 -1
  150. data/lib/robot_lab.rb +89 -57
  151. data/mkdocs.yml +0 -11
  152. metadata +121 -135
  153. data/docs/api/adapters/anthropic.md +0 -121
  154. data/docs/api/adapters/gemini.md +0 -133
  155. data/docs/api/adapters/index.md +0 -104
  156. data/docs/api/adapters/openai.md +0 -134
  157. data/docs/api/history/active-record-adapter.md +0 -195
  158. data/docs/api/history/config.md +0 -191
  159. data/docs/api/history/index.md +0 -132
  160. data/docs/api/history/thread-manager.md +0 -144
  161. data/docs/guides/history.md +0 -359
  162. data/examples/prompts/assistant/user.txt.erb +0 -1
  163. data/examples/prompts/billing/user.txt.erb +0 -1
  164. data/examples/prompts/classifier/user.txt.erb +0 -1
  165. data/examples/prompts/entity_extractor/user.txt.erb +0 -3
  166. data/examples/prompts/escalation/user.txt.erb +0 -34
  167. data/examples/prompts/general/user.txt.erb +0 -1
  168. data/examples/prompts/github_assistant/user.txt.erb +0 -1
  169. data/examples/prompts/helper/user.txt.erb +0 -1
  170. data/examples/prompts/keyword_extractor/user.txt.erb +0 -3
  171. data/examples/prompts/order_support/user.txt.erb +0 -22
  172. data/examples/prompts/product_support/user.txt.erb +0 -32
  173. data/examples/prompts/sentiment_analyzer/user.txt.erb +0 -3
  174. data/examples/prompts/synthesizer/user.txt.erb +0 -15
  175. data/examples/prompts/technical/user.txt.erb +0 -1
  176. data/examples/prompts/triage/user.txt.erb +0 -17
  177. data/lib/robot_lab/adapters/anthropic.rb +0 -163
  178. data/lib/robot_lab/adapters/base.rb +0 -85
  179. data/lib/robot_lab/adapters/gemini.rb +0 -193
  180. data/lib/robot_lab/adapters/openai.rb +0 -159
  181. data/lib/robot_lab/adapters/registry.rb +0 -81
  182. data/lib/robot_lab/configuration.rb +0 -143
  183. data/lib/robot_lab/errors.rb +0 -70
  184. data/lib/robot_lab/history/active_record_adapter.rb +0 -146
  185. data/lib/robot_lab/history/config.rb +0 -115
  186. data/lib/robot_lab/history/thread_manager.rb +0 -93
  187. data/lib/robot_lab/robotic_model.rb +0 -324
@@ -1,221 +1,205 @@
1
- # MCP Server
1
+ # MCP Server Configuration
2
2
 
3
- Expose tools via Model Context Protocol.
3
+ Data structure for MCP server connection configuration.
4
4
 
5
5
  ## Class: `RobotLab::MCP::Server`
6
6
 
7
- ```ruby
8
- server = RobotLab::MCP::Server.new(name: "my_tools")
7
+ `Server` is a configuration object that defines how to connect to an MCP server. It holds the server name and transport settings, and validates the configuration on construction.
9
8
 
10
- server.add_tool(
11
- name: "get_time",
12
- description: "Get current time",
13
- handler: ->(**_) { Time.now.iso8601 }
14
- )
9
+ This is **not** an MCP server implementation -- it is the configuration used by `MCP::Client` to establish a connection to an external MCP server.
15
10
 
16
- server.start(transport: :stdio)
11
+ ```ruby
12
+ server = RobotLab::MCP::Server.new(
13
+ name: "filesystem",
14
+ transport: { type: "stdio", command: "mcp-server-filesystem", args: ["--root", "/data"] }
15
+ )
17
16
  ```
18
17
 
19
18
  ## Constructor
20
19
 
21
20
  ```ruby
22
- Server.new(name:, version: "1.0.0")
21
+ Server.new(name:, transport:)
23
22
  ```
24
23
 
25
24
  **Parameters:**
26
25
 
27
26
  | Name | Type | Description |
28
27
  |------|------|-------------|
29
- | `name` | `String` | Server name |
30
- | `version` | `String` | Server version |
28
+ | `name` | `String` | Unique server identifier |
29
+ | `transport` | `Hash` | Transport configuration (must include `type`) |
31
30
 
32
- ## Attributes
31
+ **Raises:** `ArgumentError` if:
32
+ - The transport type is not one of the valid types
33
+ - A stdio transport is missing the `:command` key
34
+ - A network transport (ws, websocket, sse, streamable-http, http) is missing the `:url` key
33
35
 
34
- ### name
36
+ ## Valid Transport Types
35
37
 
36
38
  ```ruby
37
- server.name # => String
39
+ RobotLab::MCP::Server::VALID_TRANSPORT_TYPES
40
+ # => ["stdio", "sse", "ws", "websocket", "streamable-http", "http"]
38
41
  ```
39
42
 
40
- Server identifier.
43
+ ## Attributes
41
44
 
42
- ### version
45
+ ### name
43
46
 
44
47
  ```ruby
45
- server.version # => String
48
+ server.name # => String
46
49
  ```
47
50
 
48
- Server version.
51
+ The server identifier string.
49
52
 
50
- ### tools
53
+ ### transport
51
54
 
52
55
  ```ruby
53
- server.tools # => Array<Tool>
56
+ server.transport # => Hash
54
57
  ```
55
58
 
56
- Registered tools.
59
+ The normalized transport configuration hash (keys are symbols, type is downcased).
57
60
 
58
61
  ## Methods
59
62
 
60
- ### add_tool
63
+ ### transport_type
61
64
 
62
65
  ```ruby
63
- server.add_tool(
64
- name:,
65
- description:,
66
- parameters: {},
67
- handler:
68
- )
66
+ server.transport_type # => String
69
67
  ```
70
68
 
71
- Register a tool with the server.
69
+ Returns the transport type string (e.g., `"stdio"`, `"ws"`, `"sse"`).
72
70
 
73
- **Parameters:**
74
-
75
- | Name | Type | Description |
76
- |------|------|-------------|
77
- | `name` | `String` | Tool name |
78
- | `description` | `String` | Tool description |
79
- | `parameters` | `Hash` | Parameter schema |
80
- | `handler` | `Proc` | Execution function |
81
-
82
- ### remove_tool
71
+ ### to_h
83
72
 
84
73
  ```ruby
85
- server.remove_tool(name)
74
+ server.to_h # => { name: "...", transport: { ... } }
86
75
  ```
87
76
 
88
- Unregister a tool.
77
+ Converts the server configuration to a hash representation.
78
+
79
+ ## Transport Configuration Options
89
80
 
90
- ### start
81
+ ### Stdio Transport
82
+
83
+ For local MCP servers running as subprocesses:
91
84
 
92
85
  ```ruby
93
- server.start(transport: :stdio, **options)
86
+ Server.new(
87
+ name: "filesystem",
88
+ transport: {
89
+ type: "stdio",
90
+ command: "mcp-server-filesystem", # Required
91
+ args: ["--root", "/data"], # Optional
92
+ env: { "DEBUG" => "true" } # Optional
93
+ }
94
+ )
94
95
  ```
95
96
 
96
- Start the server.
97
+ | Key | Type | Required | Description |
98
+ |-----|------|----------|-------------|
99
+ | `type` | `String` | Yes | Must be `"stdio"` |
100
+ | `command` | `String` | Yes | Executable command |
101
+ | `args` | `Array<String>` | No | Command arguments |
102
+ | `env` | `Hash` | No | Environment variables |
97
103
 
98
- **Transport Options:**
104
+ ### WebSocket Transport
99
105
 
100
- | Transport | Options |
101
- |-----------|---------|
102
- | `:stdio` | None |
103
- | `:websocket` | `port:`, `host:` |
104
- | `:sse` | `port:`, `host:`, `path:` |
105
- | `:http` | `port:`, `host:`, `path:` |
106
-
107
- ### stop
106
+ For bidirectional real-time communication:
108
107
 
109
108
  ```ruby
110
- server.stop
109
+ Server.new(
110
+ name: "neon",
111
+ transport: {
112
+ type: "ws",
113
+ url: "ws://localhost:8080" # Required
114
+ }
115
+ )
111
116
  ```
112
117
 
113
- Stop the server.
118
+ | Key | Type | Required | Description |
119
+ |-----|------|----------|-------------|
120
+ | `type` | `String` | Yes | `"ws"` or `"websocket"` |
121
+ | `url` | `String` | Yes | WebSocket endpoint URL |
114
122
 
115
- ## Examples
123
+ ### SSE Transport
116
124
 
117
- ### Basic Server
125
+ For server-sent events streaming:
118
126
 
119
127
  ```ruby
120
- server = RobotLab::MCP::Server.new(name: "utilities")
121
-
122
- server.add_tool(
123
- name: "echo",
124
- description: "Echo back the input",
125
- parameters: {
126
- message: { type: "string", required: true }
127
- },
128
- handler: ->(message:) { message }
128
+ Server.new(
129
+ name: "streaming",
130
+ transport: {
131
+ type: "sse",
132
+ url: "http://localhost:8080/sse" # Required
133
+ }
129
134
  )
130
-
131
- server.start(transport: :stdio)
132
135
  ```
133
136
 
134
- ### Database Tools Server
137
+ | Key | Type | Required | Description |
138
+ |-----|------|----------|-------------|
139
+ | `type` | `String` | Yes | Must be `"sse"` |
140
+ | `url` | `String` | Yes | SSE endpoint URL |
135
141
 
136
- ```ruby
137
- server = RobotLab::MCP::Server.new(name: "database")
138
-
139
- server.add_tool(
140
- name: "query_users",
141
- description: "Query users by criteria",
142
- parameters: {
143
- status: { type: "string", enum: ["active", "inactive"] },
144
- limit: { type: "integer", default: 10 }
145
- },
146
- handler: ->(status: nil, limit: 10) {
147
- scope = User.all
148
- scope = scope.where(status: status) if status
149
- scope.limit(limit).map(&:to_h)
150
- }
151
- )
142
+ ### Streamable HTTP Transport
152
143
 
153
- server.add_tool(
154
- name: "get_user",
155
- description: "Get user by ID",
156
- parameters: {
157
- id: { type: "string", required: true }
158
- },
159
- handler: ->(id:) {
160
- user = User.find_by(id: id)
161
- user ? user.to_h : { error: "Not found" }
144
+ For HTTP-based communication with session management:
145
+
146
+ ```ruby
147
+ Server.new(
148
+ name: "api",
149
+ transport: {
150
+ type: "streamable-http",
151
+ url: "https://server.smithery.ai/neon/mcp", # Required
152
+ session_id: "abc123", # Optional
153
+ auth_provider: -> { "Bearer #{token}" } # Optional
162
154
  }
163
155
  )
164
-
165
- server.start(transport: :websocket, port: 8080)
166
156
  ```
167
157
 
168
- ### From Robot Tools
158
+ | Key | Type | Required | Description |
159
+ |-----|------|----------|-------------|
160
+ | `type` | `String` | Yes | `"streamable-http"` or `"http"` |
161
+ | `url` | `String` | Yes | HTTP endpoint URL |
162
+ | `session_id` | `String` | No | Session identifier |
163
+ | `auth_provider` | `Proc` | No | Authentication callback returning auth header value |
169
164
 
170
- ```ruby
171
- # Convert existing robot tools to MCP server
172
- robot = RobotLab.build do
173
- name "assistant"
174
-
175
- tool :calculate do
176
- description "Perform calculation"
177
- parameter :expression, type: :string, required: true
178
- handler { |expression:, **_| eval(expression) }
179
- end
180
- end
181
-
182
- server = RobotLab::MCP::Server.from_robot(robot)
183
- server.start(transport: :stdio)
184
- ```
165
+ ## Examples
185
166
 
186
- ### HTTP Server
167
+ ### Multiple Server Configurations
187
168
 
188
169
  ```ruby
189
- server = RobotLab::MCP::Server.new(name: "api_tools")
190
-
191
- server.add_tool(
192
- name: "fetch_data",
193
- description: "Fetch data from API",
194
- parameters: {
195
- endpoint: { type: "string", required: true }
170
+ servers = [
171
+ {
172
+ name: "filesystem",
173
+ transport: { type: "stdio", command: "mcp-server-filesystem", args: ["/data"] }
174
+ },
175
+ {
176
+ name: "github",
177
+ transport: { type: "stdio", command: "mcp-server-github" }
196
178
  },
197
- handler: ->(endpoint:) {
198
- response = HTTP.get("https://api.example.com/#{endpoint}")
199
- JSON.parse(response.body)
179
+ {
180
+ name: "database",
181
+ transport: { type: "ws", url: "ws://localhost:9090" }
200
182
  }
201
- )
183
+ ]
202
184
 
203
- server.start(transport: :http, port: 3001, path: "/mcp")
185
+ # Pass directly to a robot
186
+ robot = Robot.new(
187
+ name: "dev_assistant",
188
+ system_prompt: "You help with development tasks.",
189
+ mcp: servers
190
+ )
204
191
  ```
205
192
 
206
- ### With Resources
193
+ ### Creating a Client from a Server
207
194
 
208
195
  ```ruby
209
- server = RobotLab::MCP::Server.new(name: "files")
210
-
211
- server.add_resource(
212
- uri: "file://config",
213
- name: "Configuration",
214
- description: "Application configuration",
215
- handler: -> { File.read("config.yml") }
196
+ server = RobotLab::MCP::Server.new(
197
+ name: "tools",
198
+ transport: { type: "ws", url: "ws://localhost:8080" }
216
199
  )
217
200
 
218
- server.start(transport: :stdio)
201
+ client = RobotLab::MCP::Client.new(server)
202
+ client.connect
219
203
  ```
220
204
 
221
205
  ## See Also