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
data/Rakefile CHANGED
@@ -45,23 +45,93 @@ task :rubocop_fix do
45
45
  end
46
46
 
47
47
  namespace :examples do
48
+ # Map of subdirectory-based demos to their entry point scripts
49
+ SUBDIR_ENTRY_POINTS = {
50
+ "14_rusty_circuit" => "open_mic.rb",
51
+ "15_memory_network_and_bus" => "editorial_pipeline.rb",
52
+ "16_writers_room" => "writers_room.rb"
53
+ }.freeze
54
+
48
55
  desc "Run all examples"
49
56
  task :all do
57
+ # Single-file examples
50
58
  Dir.glob("examples/*.rb").sort.each do |example|
51
59
  puts "\n#{'=' * 60}"
52
60
  puts "Running: #{example}"
53
61
  puts '=' * 60
54
62
  ruby example
55
63
  end
64
+
65
+ # Subdirectory-based demos
66
+ SUBDIR_ENTRY_POINTS.each do |dir, entry|
67
+ path = "examples/#{dir}/#{entry}"
68
+ next unless File.exist?(path)
69
+
70
+ puts "\n#{'=' * 60}"
71
+ puts "Running: #{path}"
72
+ puts '=' * 60
73
+ ruby path
74
+ end
56
75
  end
57
76
 
58
77
  desc "Run a specific example by number (e.g., rake examples:run[1])"
59
78
  task :run, [:num] do |_t, args|
60
- example = Dir.glob("examples/#{args[:num].rjust(2, '0')}_*.rb").first
79
+ padded = args[:num].rjust(2, '0')
80
+
81
+ # Try single-file example first
82
+ example = Dir.glob("examples/#{padded}_*.rb").first
61
83
  if example
62
84
  ruby example
85
+ next
86
+ end
87
+
88
+ # Try subdirectory-based demo
89
+ dir = Dir.glob("examples/#{padded}_*/").first
90
+ if dir
91
+ dir_name = File.basename(dir)
92
+ entry = SUBDIR_ENTRY_POINTS[dir_name]
93
+ if entry && File.exist?(File.join(dir, entry))
94
+ ruby File.join(dir, entry)
95
+ else
96
+ puts "Example #{args[:num]} directory found (#{dir_name}) but no entry point configured"
97
+ end
63
98
  else
64
99
  puts "Example #{args[:num]} not found"
65
100
  end
66
101
  end
67
102
  end
103
+
104
+ namespace :docs do
105
+ desc "Build all documentation (YARD and MkDocs)"
106
+ task build: %i[yard mkdocs]
107
+
108
+ desc "Clean generated documentation"
109
+ task :clean do
110
+ rm_rf "doc"
111
+ rm_rf "site"
112
+ end
113
+
114
+ desc "Build YARD API documentation"
115
+ task :yard do
116
+ sh "yard doc"
117
+ end
118
+
119
+ namespace :yard do
120
+ desc "Serve YARD documentation locally"
121
+ task :serve do
122
+ sh "yard server --reload"
123
+ end
124
+ end
125
+
126
+ desc "Build MkDocs documentation"
127
+ task :mkdocs do
128
+ sh "mkdocs build"
129
+ end
130
+
131
+ namespace :mkdocs do
132
+ desc "Serve MkDocs documentation locally"
133
+ task :serve do
134
+ sh "mkdocs serve"
135
+ end
136
+ end
137
+ end
@@ -12,21 +12,21 @@ classDiagram
12
12
  +model: String
13
13
  +template: String
14
14
  +tools: Array~Tool~
15
- +run(state, network)
15
+ +run(message) Message
16
16
  }
17
17
 
18
18
  class Network {
19
19
  +name: String
20
20
  +robots: Hash
21
- +router: Proc
22
- +run(state)
21
+ +config: RunConfig
22
+ +run(message)
23
23
  }
24
24
 
25
- class State {
26
- +data: StateProxy
27
- +results: Array
28
- +messages: Array
29
- +memory: Memory
25
+ class RunConfig {
26
+ +model: String
27
+ +temperature: Float
28
+ +merge(other) RunConfig
29
+ +apply_to(chat)
30
30
  }
31
31
 
32
32
  class Tool {
@@ -37,16 +37,31 @@ classDiagram
37
37
  }
38
38
 
39
39
  class Memory {
40
- +remember(key, value)
41
- +recall(key)
42
- +forget(key)
43
- +scoped(namespace)
40
+ +set(key, value)
41
+ +get(key)
42
+ +delete(key)
43
+ +data: StateProxy
44
+ +results: Array
45
+ +messages: Array
46
+ +session_id: String
47
+ }
48
+
49
+ class RobotMessage {
50
+ +id: Integer
51
+ +from: String
52
+ +content: String
53
+ +in_reply_to: String
54
+ +key()
55
+ +reply?()
44
56
  }
45
57
 
46
58
  Network --> Robot : contains
59
+ Network --> RunConfig : uses
60
+ Robot --> RunConfig : uses
47
61
  Robot --> Tool : has
48
- State --> Memory : has
49
- Network --> State : uses
62
+ Robot --> Memory : uses
63
+ Network --> Memory : uses
64
+ Robot ..> RobotMessage : sends/receives
50
65
  ```
51
66
 
52
67
  ## Classes
@@ -55,59 +70,51 @@ classDiagram
55
70
  |-------|---------|
56
71
  | [Robot](robot.md) | LLM agent with personality, tools, and model configuration |
57
72
  | [Network](network.md) | Container for robots with routing and orchestration |
58
- | [State](state.md) | Conversation state with data, results, and memory |
73
+ | RunConfig | Shared configuration for LLM, tools, callbacks, and infrastructure |
59
74
  | [Tool](tool.md) | Callable function with parameters and handler |
60
- | [Memory](memory.md) | Namespaced key-value store for sharing data |
75
+ | [AskUser](tool.md#built-in-askuser) | Built-in tool for terminal-based user interaction |
76
+ | [Memory](memory.md) | Reactive key-value store for sharing data |
77
+ | RobotMessage | Typed envelope for bus-based inter-robot communication |
61
78
 
62
79
  ## Quick Examples
63
80
 
64
81
  ### Robot
65
82
 
66
83
  ```ruby
67
- robot = RobotLab.build do
68
- name "assistant"
69
- model "claude-sonnet-4"
70
- template "You are helpful."
71
-
72
- tool :greet do
73
- parameter :name, type: :string
74
- handler { |name:, **_| "Hello, #{name}!" }
75
- end
76
- end
84
+ robot = RobotLab.build(
85
+ name: "assistant",
86
+ model: "claude-sonnet-4",
87
+ system_prompt: "You are helpful.",
88
+ local_tools: [greet_tool]
89
+ )
90
+
91
+ result = robot.run("Hello!")
77
92
  ```
78
93
 
79
94
  ### Network
80
95
 
81
96
  ```ruby
82
- network = RobotLab.create_network do
83
- name "my_network"
84
- add_robot robot
85
- router ->(args) { args.call_count.zero? ? :assistant : nil }
97
+ network = RobotLab.create_network(name: "my_network") do
98
+ step :analyzer, analyzer_robot, depends_on: :none
99
+ step :writer, writer_robot, depends_on: [:analyzer]
86
100
  end
101
+
102
+ result = network.run(message: "Process this")
87
103
  ```
88
104
 
89
- ### State
105
+ ### Memory
90
106
 
91
107
  ```ruby
92
- state = RobotLab.create_state(
93
- message: "Hello",
94
- data: { user_id: "123" }
95
- )
108
+ memory = RobotLab.create_memory(data: { user_id: "123" })
109
+ memory.set(:category, "billing")
110
+ memory.get(:category) # => "billing"
96
111
  ```
97
112
 
98
113
  ### Tool
99
114
 
100
115
  ```ruby
101
- tool = RobotLab::Tool.new(
116
+ tool = RobotLab::Tool.create(
102
117
  name: "get_time",
103
- description: "Get current time",
104
- handler: ->(**, _) { Time.now.to_s }
105
- )
106
- ```
107
-
108
- ### Memory
109
-
110
- ```ruby
111
- state.memory.remember("key", "value")
112
- value = state.memory.recall("key")
118
+ description: "Get current time"
119
+ ) { |**_| Time.now.to_s }
113
120
  ```