robot_lab 0.3.0 → 0.3.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.
Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
  5. data/lib/robot_lab/version.rb +1 -1
  6. metadata +3 -253
  7. data/.architecture/AGENTS.md +0 -32
  8. data/.architecture/config.yml +0 -8
  9. data/.architecture/members.yml +0 -60
  10. data/.architecture/reviews/feature-free-will.md +0 -490
  11. data/.architecture/reviews/overall-codebase.md +0 -427
  12. data/.claude/settings.local.json +0 -57
  13. data/.codex/config.toml +0 -2
  14. data/.envrc +0 -6
  15. data/.github/workflows/deploy-github-pages.yml +0 -52
  16. data/.irbrc +0 -6
  17. data/.loki +0 -65
  18. data/.quality/reek_baseline.txt +0 -43
  19. data/.rubocop.yml +0 -10
  20. data/Archspec.rb +0 -44
  21. data/CLAUDE.md +0 -141
  22. data/COMMITS.md +0 -196
  23. data/Rakefile +0 -193
  24. data/_typos.toml +0 -21
  25. data/agent2agent_review.md +0 -192
  26. data/agentf_improvements.md +0 -253
  27. data/agents.md +0 -14
  28. data/docs/api/core/index.md +0 -147
  29. data/docs/api/core/memory.md +0 -578
  30. data/docs/api/core/network.md +0 -553
  31. data/docs/api/core/result.md +0 -211
  32. data/docs/api/core/robot.md +0 -1667
  33. data/docs/api/core/state.md +0 -145
  34. data/docs/api/core/tool.md +0 -520
  35. data/docs/api/errors.md +0 -323
  36. data/docs/api/hooks.md +0 -469
  37. data/docs/api/index.md +0 -137
  38. data/docs/api/mcp/client.md +0 -387
  39. data/docs/api/mcp/index.md +0 -267
  40. data/docs/api/mcp/server.md +0 -252
  41. data/docs/api/mcp/transports.md +0 -339
  42. data/docs/api/messages/index.md +0 -126
  43. data/docs/api/messages/text-message.md +0 -170
  44. data/docs/api/messages/tool-call-message.md +0 -206
  45. data/docs/api/messages/tool-result-message.md +0 -242
  46. data/docs/api/messages/user-message.md +0 -232
  47. data/docs/api/skills.md +0 -423
  48. data/docs/api/streaming/context.md +0 -280
  49. data/docs/api/streaming/events.md +0 -185
  50. data/docs/api/streaming/index.md +0 -156
  51. data/docs/api/support.md +0 -846
  52. data/docs/architecture/core-concepts.md +0 -575
  53. data/docs/architecture/index.md +0 -252
  54. data/docs/architecture/message-flow.md +0 -366
  55. data/docs/architecture/network-orchestration.md +0 -478
  56. data/docs/architecture/robot-execution.md +0 -396
  57. data/docs/architecture/state-management.md +0 -410
  58. data/docs/assets/css/custom.css +0 -56
  59. data/docs/assets/images/robot_lab.jpg +0 -0
  60. data/docs/concepts.md +0 -641
  61. data/docs/examples/basic-chat.md +0 -258
  62. data/docs/examples/index.md +0 -425
  63. data/docs/examples/mcp-server.md +0 -403
  64. data/docs/examples/multi-robot-network.md +0 -476
  65. data/docs/examples/tool-usage.md +0 -468
  66. data/docs/getting-started/configuration.md +0 -645
  67. data/docs/getting-started/index.md +0 -56
  68. data/docs/getting-started/installation.md +0 -197
  69. data/docs/getting-started/quick-start.md +0 -293
  70. data/docs/guides/building-robots.md +0 -1187
  71. data/docs/guides/creating-networks.md +0 -736
  72. data/docs/guides/hooks.md +0 -1206
  73. data/docs/guides/index.md +0 -78
  74. data/docs/guides/knowledge.md +0 -219
  75. data/docs/guides/mcp-integration.md +0 -740
  76. data/docs/guides/memory.md +0 -458
  77. data/docs/guides/observability.md +0 -733
  78. data/docs/guides/streaming.md +0 -323
  79. data/docs/guides/using-tools.md +0 -780
  80. data/docs/index.md +0 -280
  81. data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
  82. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
  83. data/examples/.envrc +0 -3
  84. data/examples/01_simple_robot.rb +0 -31
  85. data/examples/02_tools.rb +0 -109
  86. data/examples/03_network.rb +0 -118
  87. data/examples/04_mcp.rb +0 -217
  88. data/examples/05_streaming.rb +0 -137
  89. data/examples/06_prompt_templates.rb +0 -325
  90. data/examples/07_network_memory.rb +0 -313
  91. data/examples/08_llm_config.rb +0 -162
  92. data/examples/09_chaining.rb +0 -251
  93. data/examples/10_memory.rb +0 -315
  94. data/examples/11_network_introspection.rb +0 -239
  95. data/examples/12_message_bus.rb +0 -67
  96. data/examples/13_spawn.rb +0 -85
  97. data/examples/14_rusty_circuit/.envrc +0 -1
  98. data/examples/14_rusty_circuit/.gitignore +0 -1
  99. data/examples/14_rusty_circuit/README.md +0 -1
  100. data/examples/14_rusty_circuit/comic.rb +0 -149
  101. data/examples/14_rusty_circuit/display.rb +0 -217
  102. data/examples/14_rusty_circuit/heckler.rb +0 -65
  103. data/examples/14_rusty_circuit/open_mic.rb +0 -132
  104. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
  105. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
  106. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
  107. data/examples/14_rusty_circuit/scout.rb +0 -165
  108. data/examples/14_rusty_circuit/show.log +0 -234
  109. data/examples/15_memory_network_and_bus/.envrc +0 -1
  110. data/examples/15_memory_network_and_bus/README.md +0 -66
  111. data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
  112. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
  113. data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
  114. data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
  115. data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
  116. data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
  117. data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
  118. data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
  119. data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
  120. data/examples/15_memory_network_and_bus/output/memory.json +0 -13
  121. data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
  122. data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
  123. data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
  124. data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
  125. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
  126. data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
  127. data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
  128. data/examples/16_writers_room/.envrc +0 -1
  129. data/examples/16_writers_room/display.rb +0 -158
  130. data/examples/16_writers_room/output/.gitignore +0 -4
  131. data/examples/16_writers_room/output/README.md +0 -69
  132. data/examples/16_writers_room/output/opus_001.md +0 -263
  133. data/examples/16_writers_room/output/opus_001_notes.log +0 -470
  134. data/examples/16_writers_room/output/opus_002.md +0 -245
  135. data/examples/16_writers_room/output/opus_002_notes.log +0 -546
  136. data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
  137. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
  138. data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
  139. data/examples/16_writers_room/prompts/writer.md +0 -37
  140. data/examples/16_writers_room/room.rb +0 -186
  141. data/examples/16_writers_room/tools.rb +0 -173
  142. data/examples/16_writers_room/writer.rb +0 -121
  143. data/examples/16_writers_room/writers_room.rb +0 -256
  144. data/examples/17_skills.rb +0 -234
  145. data/examples/18_rails/.envrc +0 -3
  146. data/examples/18_rails/.gitignore +0 -5
  147. data/examples/18_rails/Gemfile +0 -11
  148. data/examples/18_rails/README.md +0 -67
  149. data/examples/18_rails/Rakefile +0 -4
  150. data/examples/18_rails/app/controllers/application_controller.rb +0 -4
  151. data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
  152. data/examples/18_rails/app/jobs/application_job.rb +0 -4
  153. data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
  154. data/examples/18_rails/app/models/application_record.rb +0 -5
  155. data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
  156. data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
  157. data/examples/18_rails/app/robots/chat_robot.rb +0 -25
  158. data/examples/18_rails/app/tools/time_tool.rb +0 -9
  159. data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
  160. data/examples/18_rails/app/views/chat/index.html.erb +0 -67
  161. data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
  162. data/examples/18_rails/bin/dev +0 -7
  163. data/examples/18_rails/bin/rails +0 -6
  164. data/examples/18_rails/bin/setup +0 -15
  165. data/examples/18_rails/config/application.rb +0 -33
  166. data/examples/18_rails/config/cable.yml +0 -2
  167. data/examples/18_rails/config/database.yml +0 -5
  168. data/examples/18_rails/config/environment.rb +0 -4
  169. data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
  170. data/examples/18_rails/config/routes.rb +0 -6
  171. data/examples/18_rails/config.ru +0 -4
  172. data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
  173. data/examples/19_token_tracking.rb +0 -138
  174. data/examples/20_circuit_breaker.rb +0 -147
  175. data/examples/21_learning_loop.rb +0 -181
  176. data/examples/22_context_compression.rb +0 -172
  177. data/examples/23_convergence.rb +0 -133
  178. data/examples/24_structured_delegation.rb +0 -151
  179. data/examples/25_history_search/conversation.jsonl +0 -30
  180. data/examples/25_history_search.rb +0 -133
  181. data/examples/26_document_store/api_versioning_adr.md +0 -52
  182. data/examples/26_document_store/incident_postmortem.md +0 -46
  183. data/examples/26_document_store/postgres_runbook.md +0 -49
  184. data/examples/26_document_store/redis_caching_guide.md +0 -48
  185. data/examples/26_document_store/sidekiq_guide.md +0 -51
  186. data/examples/26_document_store.rb +0 -140
  187. data/examples/27_incident_response/README.md +0 -65
  188. data/examples/27_incident_response/incident_response.rb +0 -261
  189. data/examples/28_mcp_discovery.rb +0 -113
  190. data/examples/29_ractor_tools.rb +0 -240
  191. data/examples/30_ractor_network.rb +0 -252
  192. data/examples/31_launch_assessment.rb +0 -246
  193. data/examples/32_newsletter_reader.rb +0 -193
  194. data/examples/33_stock_generator.rb +0 -80
  195. data/examples/33_stock_predictor.rb +0 -327
  196. data/examples/34_agentskills.rb +0 -76
  197. data/examples/35_hooks.rb +0 -266
  198. data/examples/README.md +0 -550
  199. data/examples/common.rb +0 -180
  200. data/examples/prompts/assistant.md +0 -5
  201. data/examples/prompts/audit_trail.md +0 -8
  202. data/examples/prompts/billing.md +0 -10
  203. data/examples/prompts/classifier.md +0 -7
  204. data/examples/prompts/comedian.md +0 -6
  205. data/examples/prompts/comedy_critic.md +0 -10
  206. data/examples/prompts/configurable.md +0 -9
  207. data/examples/prompts/dispatcher.md +0 -12
  208. data/examples/prompts/entity_extractor.md +0 -14
  209. data/examples/prompts/escalation.md +0 -42
  210. data/examples/prompts/frontmatter_mcp_test.md +0 -9
  211. data/examples/prompts/frontmatter_named_test.md +0 -5
  212. data/examples/prompts/frontmatter_tools_test.md +0 -6
  213. data/examples/prompts/general.md +0 -7
  214. data/examples/prompts/github_assistant.md +0 -14
  215. data/examples/prompts/helper.md +0 -4
  216. data/examples/prompts/incident_responder.md +0 -18
  217. data/examples/prompts/keyword_extractor.md +0 -11
  218. data/examples/prompts/llm_config_demo.md +0 -20
  219. data/examples/prompts/order_support.md +0 -35
  220. data/examples/prompts/os_advocate.md +0 -13
  221. data/examples/prompts/os_chief.md +0 -13
  222. data/examples/prompts/os_editor.md +0 -13
  223. data/examples/prompts/parameterized_main_test.md +0 -6
  224. data/examples/prompts/pii_redactor.md +0 -7
  225. data/examples/prompts/product_support.md +0 -37
  226. data/examples/prompts/runbook_protocol.md +0 -12
  227. data/examples/prompts/sentiment_analyzer.md +0 -12
  228. data/examples/prompts/skill_a_test.md +0 -4
  229. data/examples/prompts/skill_b_test.md +0 -4
  230. data/examples/prompts/skill_config_test.md +0 -5
  231. data/examples/prompts/skill_cycle_a_test.md +0 -6
  232. data/examples/prompts/skill_cycle_b_test.md +0 -6
  233. data/examples/prompts/skill_description_test.md +0 -4
  234. data/examples/prompts/skill_leaf_test.md +0 -4
  235. data/examples/prompts/skill_nested_test.md +0 -6
  236. data/examples/prompts/skill_refs_main_test.md +0 -6
  237. data/examples/prompts/skill_self_ref_test.md +0 -6
  238. data/examples/prompts/skill_with_mcp_test.md +0 -9
  239. data/examples/prompts/skill_with_params_test.md +0 -6
  240. data/examples/prompts/skill_with_robot_name_test.md +0 -5
  241. data/examples/prompts/skill_with_tools_test.md +0 -6
  242. data/examples/prompts/sre_compliance.md +0 -10
  243. data/examples/prompts/structured_output.md +0 -7
  244. data/examples/prompts/synthesizer.md +0 -17
  245. data/examples/prompts/technical.md +0 -10
  246. data/examples/prompts/template_with_skills_test.md +0 -6
  247. data/examples/prompts/triage.md +0 -22
  248. data/examples/ruboruby.md +0 -423
  249. data/examples/run_all.rb +0 -60
  250. data/examples/xyzzy.rb +0 -97
  251. data/logfile +0 -8
  252. data/mkdocs.yml +0 -209
  253. data/robot_concurrency.md +0 -38
  254. data/simple_acp_review.md +0 -298
  255. data/temp.md +0 -6
  256. data/tool_manifest_plan.md +0 -155
data/examples/xyzzy.rb DELETED
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # xyzzy.rb — single-file RobotLab hook extension demo
4
- #
5
- # Demonstrates the Hook handler class pattern: implement class methods for
6
- # every hook under a dedicated namespace and log each callback with its
7
- # context snapshot. Useful as a live trace of the full hook pipeline during
8
- # development.
9
- #
10
- # Fully Ractor-safe: no class-level mutable state. LOG_PATH is a frozen
11
- # string constant (shareable); each call opens its own file handle.
12
- #
13
- # stdout : one tagline per hook call → [xyzzy] HH:MM:SS.mmm hook_name
14
- # logfile: full context snapshot written to LOG_PATH via PP.pp
15
- #
16
- # The log destination is read from XYZZY_LOG_PATH at load time and frozen
17
- # into a constant. Set it BEFORE requiring this file to redirect the log;
18
- # there is deliberately no writer method, so the constant stays shareable.
19
- #
20
- # Usage (from any example that requires common):
21
- # ENV["XYZZY_LOG_PATH"] = "/tmp/xyzzy.log" # optional, must precede require
22
- # require_relative "xyzzy"
23
-
24
- require "pp"
25
- require "fileutils"
26
-
27
- module RobotLab
28
- class Xyzzy < Hook
29
- self.namespace = :xyzzy
30
-
31
- LOG_PATH = File.expand_path(
32
- ENV.fetch("XYZZY_LOG_PATH", "~/.robot_lab/xyzzy_hooks.log")
33
- ).freeze
34
- FileUtils.mkdir_p(File.dirname(LOG_PATH))
35
-
36
- class << self
37
- def before_run(ctx) = log_hook(:before_run, ctx)
38
- def after_run(ctx) = log_hook(:after_run, ctx)
39
- def on_error(ctx) = log_hook(:on_error, ctx)
40
- def before_llm_generation(ctx) = log_hook(:before_llm_generation, ctx)
41
- def after_llm_generation(ctx) = log_hook(:after_llm_generation, ctx)
42
- def before_tool_call(ctx) = log_hook(:before_tool_call, ctx)
43
- def after_tool_call(ctx) = log_hook(:after_tool_call, ctx)
44
- def before_network_run(ctx) = log_hook(:before_network_run, ctx)
45
- def after_network_run(ctx) = log_hook(:after_network_run, ctx)
46
- def before_task(ctx) = log_hook(:before_task, ctx)
47
- def after_task(ctx) = log_hook(:after_task, ctx)
48
-
49
- def around_run(ctx, &block)
50
- log_hook(:around_run, ctx)
51
- block.call
52
- end
53
-
54
- def around_llm_generation(ctx, &block)
55
- log_hook(:around_llm_generation, ctx)
56
- block.call
57
- end
58
-
59
- def around_tool_call(ctx, &block)
60
- log_hook(:around_tool_call, ctx)
61
- block.call
62
- end
63
-
64
- def around_network_run(ctx, &block)
65
- log_hook(:around_network_run, ctx)
66
- block.call
67
- end
68
-
69
- def around_task(ctx, &block)
70
- log_hook(:around_task, ctx)
71
- block.call
72
- end
73
-
74
- private
75
-
76
- def log_hook(hook_name, ctx)
77
- ts = Time.now.strftime('%H:%M:%S.%3N')
78
- snapshot = context_snapshot(ctx)
79
- $stdout.puts " [xyzzy] #{ts} #{hook_name}"
80
- File.open(LOG_PATH, "a") { |f| f.puts "#{ts} #{hook_name} | #{PP.pp(snapshot, +"").chomp}" }
81
- end
82
-
83
- def context_snapshot(ctx)
84
- {
85
- robot: ctx.respond_to?(:robot) ? ctx.robot&.name : nil,
86
- request: ctx.respond_to?(:request) ? ctx.request : nil,
87
- network: ctx.respond_to?(:network) ? ctx.network&.name : nil,
88
- task: ctx.respond_to?(:task) ? ctx.task : nil,
89
- error: ctx.respond_to?(:error) ? ctx.error&.message : nil
90
- }.compact
91
- end
92
- end
93
- end
94
- end
95
-
96
- RobotLab.register_extension(:xyzzy, RobotLab::Xyzzy) if RobotLab.respond_to?(:register_extension)
97
- RobotLab.on(RobotLab::Xyzzy)
data/logfile DELETED
@@ -1,8 +0,0 @@
1
- 2026-02-25 20:56:30.644 CST [47152] LOG: starting PostgreSQL 18.2 (Homebrew) on aarch64-apple-darwin25.2.0, compiled by Apple clang version 17.0.0 (clang-1700.6.3.2), 64-bit
2
- 2026-02-25 20:56:30.646 CST [47152] LOG: could not bind IPv6 address "::1": Address already in use
3
- 2026-02-25 20:56:30.646 CST [47152] HINT: Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
4
- 2026-02-25 20:56:30.646 CST [47152] LOG: could not bind IPv4 address "127.0.0.1": Address already in use
5
- 2026-02-25 20:56:30.646 CST [47152] HINT: Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
6
- 2026-02-25 20:56:30.646 CST [47152] WARNING: could not create listen socket for "localhost"
7
- 2026-02-25 20:56:30.646 CST [47152] FATAL: could not create any TCP/IP sockets
8
- 2026-02-25 20:56:30.646 CST [47152] LOG: database system is shut down
data/mkdocs.yml DELETED
@@ -1,209 +0,0 @@
1
- # MkDocs Configuration for RobotLab Documentation
2
- site_name: RobotLab
3
- site_description: Multi-robot LLM workflow orchestration for Ruby
4
- site_author: Dewayne VanHoozer
5
- site_url: https://madbomber.github.io/robot_lab
6
- copyright: Copyright &copy; 2025 Dewayne VanHoozer
7
-
8
- # Repository information
9
- repo_name: madbomber/robot_lab
10
- repo_url: https://github.com/madbomber/robot_lab
11
- edit_uri: edit/main/docs/
12
-
13
- # Configuration
14
- theme:
15
- name: material
16
-
17
- # Color scheme
18
- palette:
19
- - scheme: default
20
- primary: deep purple
21
- accent: amber
22
- toggle:
23
- icon: material/brightness-7
24
- name: Switch to dark mode
25
-
26
- - scheme: slate
27
- primary: deep purple
28
- accent: amber
29
- toggle:
30
- icon: material/brightness-4
31
- name: Switch to light mode
32
-
33
- # Typography
34
- font:
35
- text: Roboto
36
- code: Roboto Mono
37
-
38
- # Logo and icon
39
- icon:
40
- repo: fontawesome/brands/github
41
- logo: material/robot
42
-
43
- # Theme features
44
- features:
45
- - navigation.instant
46
- - navigation.tracking
47
- - navigation.tabs
48
- - navigation.tabs.sticky
49
- - navigation.path
50
- - navigation.indexes
51
- - navigation.top
52
- - navigation.footer
53
- - toc.follow
54
- - search.suggest
55
- - search.highlight
56
- - search.share
57
- - header.autohide
58
- - content.code.copy
59
- - content.code.annotate
60
- - content.tabs.link
61
- - content.tooltips
62
- - content.action.edit
63
- - content.action.view
64
-
65
- # Plugins
66
- plugins:
67
- - search:
68
- separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
69
- - tags
70
-
71
- # Extensions
72
- markdown_extensions:
73
- - abbr
74
- - admonition
75
- - attr_list
76
- - def_list
77
- - footnotes
78
- - md_in_html
79
- - tables
80
- - toc:
81
- permalink: true
82
- title: On this page
83
-
84
- - pymdownx.arithmatex:
85
- generic: true
86
- - pymdownx.betterem:
87
- smart_enable: all
88
- - pymdownx.caret
89
- - pymdownx.critic
90
- - pymdownx.details
91
- - pymdownx.emoji:
92
- emoji_generator: !!python/name:material.extensions.emoji.to_svg
93
- emoji_index: !!python/name:material.extensions.emoji.twemoji
94
- - pymdownx.highlight:
95
- anchor_linenums: true
96
- line_spans: __span
97
- pygments_lang_class: true
98
- - pymdownx.inlinehilite
99
- - pymdownx.keys
100
- - pymdownx.magiclink:
101
- repo_url_shorthand: true
102
- user: madbomber
103
- repo: robot_lab
104
- normalize_issue_symbols: true
105
- - pymdownx.mark
106
- - pymdownx.smartsymbols
107
- - pymdownx.snippets:
108
- check_paths: true
109
- - pymdownx.superfences:
110
- custom_fences:
111
- - name: mermaid
112
- class: mermaid
113
- format: !!python/name:pymdownx.superfences.fence_code_format
114
- - pymdownx.tabbed:
115
- alternate_style: true
116
- - pymdownx.tasklist:
117
- custom_checkbox: true
118
- - pymdownx.tilde
119
-
120
- # Extra CSS
121
- extra_css:
122
- - assets/css/custom.css
123
-
124
- # Social media and extra configuration
125
- extra:
126
- social:
127
- - icon: fontawesome/brands/github
128
- link: https://github.com/madbomber/robot_lab
129
- name: RobotLab on GitHub
130
- - icon: fontawesome/solid/gem
131
- link: https://rubygems.org/gems/robot_lab
132
- name: RobotLab on RubyGems
133
-
134
- analytics:
135
- feedback:
136
- title: Was this page helpful?
137
- ratings:
138
- - icon: material/emoticon-happy-outline
139
- name: This page was helpful
140
- data: 1
141
- note: Thanks for your feedback!
142
- - icon: material/emoticon-sad-outline
143
- name: This page could be improved
144
- data: 0
145
- note: Thanks for your feedback! Help us improve by creating an issue.
146
-
147
- # Navigation
148
- nav:
149
- - Home:
150
- - Overview: index.md
151
- - Concepts: concepts.md
152
- - Getting Started:
153
- - getting-started/index.md
154
- - Installation: getting-started/installation.md
155
- - Quick Start: getting-started/quick-start.md
156
- - Configuration: getting-started/configuration.md
157
- - Architecture:
158
- - architecture/index.md
159
- - Core Concepts: architecture/core-concepts.md
160
- - Robot Execution: architecture/robot-execution.md
161
- - Network Orchestration: architecture/network-orchestration.md
162
- - State Management: architecture/state-management.md
163
- - Message Flow: architecture/message-flow.md
164
- - Guides:
165
- - guides/index.md
166
- - Building Robots: guides/building-robots.md
167
- - Creating Networks: guides/creating-networks.md
168
- - Using Tools: guides/using-tools.md
169
- - MCP Integration: guides/mcp-integration.md
170
- - Streaming Responses: guides/streaming.md
171
- - Memory System: guides/memory.md
172
- - Observability & Safety: guides/observability.md
173
- - Hook System: guides/hooks.md
174
- - Knowledge Search: guides/knowledge.md
175
- - API Reference:
176
- - api/index.md
177
- - Core Classes:
178
- - api/core/index.md
179
- - Robot: api/core/robot.md
180
- - RobotResult: api/core/result.md
181
- - Network: api/core/network.md
182
- - Tool: api/core/tool.md
183
- - Memory: api/core/memory.md
184
- - StateProxy: api/core/state.md
185
- - Hooks: api/hooks.md
186
- - Skills: api/skills.md
187
- - Support Classes: api/support.md
188
- - Errors: api/errors.md
189
- - Messages:
190
- - api/messages/index.md
191
- - UserMessage: api/messages/user-message.md
192
- - TextMessage: api/messages/text-message.md
193
- - ToolCallMessage: api/messages/tool-call-message.md
194
- - ToolResultMessage: api/messages/tool-result-message.md
195
- - MCP:
196
- - api/mcp/index.md
197
- - Client: api/mcp/client.md
198
- - Server: api/mcp/server.md
199
- - Transports: api/mcp/transports.md
200
- - Streaming:
201
- - api/streaming/index.md
202
- - Context: api/streaming/context.md
203
- - Events: api/streaming/events.md
204
- - Examples:
205
- - examples/index.md
206
- - Basic Chat: examples/basic-chat.md
207
- - Multi-Robot Network: examples/multi-robot-network.md
208
- - Tool Usage: examples/tool-usage.md
209
- - MCP Server: examples/mcp-server.md
data/robot_concurrency.md DELETED
@@ -1,38 +0,0 @@
1
- # Ruby Concurrency Review — RobotLab
2
-
3
- Source: https://paolino.me/ruby-concurrency-what-actually-happens/
4
-
5
- ## What Applies to RobotLab
6
-
7
- ### 1. You're Already in the Right Model — Lean Into It
8
-
9
- RobotLab uses `async (~> 2.0)`, which is exactly the fiber-based scheduler the article describes. LLM calls are pure I/O-bound work (HTTP streaming), so fibers are the correct and lowest-cost primitive. The article validates this architecture choice. No changes needed here — but be deliberate about not mixing blocking thread-style calls into the `Async` reactor unnecessarily.
10
-
11
- ### 2. The Ractor Caution Is Real (Recent Commit: `feat(ractor-parallelism)`)
12
-
13
- The article is clear: Ractors in Ruby 4.0 are still experimental and practically incompatible with gems that use global state. RobotLab's dependencies (`ruby_llm`, `prompt_manager`, `zeitwerk`) almost certainly use global state. Worth auditing whether the new Ractor code hits `Ractor::IsolationError` under realistic load. The article's recommendation: **use Processes** for CPU parallelism if Rails-style gems are involved.
14
-
15
- ### 3. ~~The `Waiter` Class May Be Misfit in Fiber Context~~ — RESOLVED
16
-
17
- `lib/robot_lab/waiter.rb` was updated to use `IO.pipe` + `IO.select` instead of `ConditionVariable`. `IO.select` is hooked by the Ruby 3.1+ fiber scheduler protocol, so it correctly yields to the Async scheduler when called from within an Async task, and correctly blocks the calling thread when used outside one. `Async::Condition` was considered but rejected: it only works inside an Async block, whereas `Memory` is intentionally usable from both plain threads and Async fibers.
18
-
19
- ### 4. Parallel Network Execution — Check the Primitive
20
-
21
- `call_parallel()` in `Network` (built on `SimpleFlow::Pipeline`) — if it spawns OS threads rather than async tasks, you get heavier overhead than necessary for I/O-bound robot calls. The article's guidance: for I/O work, fiber-based `Async::Barrier` with concurrent tasks is 10-20x cheaper than threads.
22
-
23
- ### 5. Resource Semaphores for Parallel Networks
24
-
25
- When a Network runs multiple robots concurrently, each making LLM API calls, you can exhaust API rate limits or connection pools with no back-pressure. The article's semaphore pattern applies directly — cap in-flight robot tasks to match your API tier's concurrency limit. This is worth adding to `RunConfig` as a `max_concurrent_robots` infra field.
26
-
27
- ### 6. Colorless Concurrency — This Is Already Your Story
28
-
29
- The article's main point about Ruby fibers being "colorless" (no `async/await` propagation required) is directly reflected in how `robot.run("...")` stays synchronous-looking whether run standalone or in a parallel network. This is an underappreciated design strength worth highlighting in docs/README.
30
-
31
- ---
32
-
33
- ## Summary
34
-
35
- The async/fiber architecture is correct for LLM I/O work. The two actionable concerns are:
36
-
37
- 1. **Audit the Ractor code** for isolation errors with gem dependencies (`ruby_llm`, `prompt_manager`, `zeitwerk`).
38
- 2. **Check `Waiter`** (condition variable in `lib/robot_lab/waiter.rb`) — if called inside an `Async` reactor block, replace with `Async::Condition` to avoid stalling the reactor.
data/simple_acp_review.md DELETED
@@ -1,298 +0,0 @@
1
- # Review: `simple_acp` Ruby Library
2
-
3
- **Path:** `/Users/dewayne/sandbox/git_repos/madbomber/simple_acp`
4
- **Version:** 0.0.1
5
- **Protocol:** ACP (Agent Communication Protocol) — Bee AI community standard, not Google's A2A
6
- **Reviewed:** 2026-05-05
7
-
8
- ---
9
-
10
- ## What It Is
11
-
12
- A complete Ruby implementation of ACP — an HTTP+SSE protocol for communication between AI agents, applications, and humans. Provides both a server (Roda/Falcon) and a client (Faraday), with pluggable storage backends, streaming, stateful sessions, and an await/resume pattern for interactive multi-turn flows.
13
-
14
- ---
15
-
16
- ## Wire Protocol
17
-
18
- | Endpoint | Purpose |
19
- |---|---|
20
- | `GET /ping` | Health check |
21
- | `GET /agents` | List registered agents (params: limit, offset) |
22
- | `GET /agents/:name` | Agent manifest (capabilities, MIME types) |
23
- | `POST /runs` | Create a run (body: agent_name, input[], mode, session_id) |
24
- | `GET /runs/:id` | Run status |
25
- | `POST /runs/:id` | Resume an awaited run (body: await_resume, mode) |
26
- | `POST /runs/:id/cancel` | Cancel a run |
27
- | `GET /runs/:id/events` | Full SSE event history (params: limit, offset) |
28
- | `GET /session/:id` | Session state and history |
29
-
30
- ### Run Modes
31
-
32
- - `SYNC` — wait for completion, return finished run
33
- - `ASYNC` — return immediately with run ID, poll for completion
34
- - `STREAM` — SSE event stream for real-time progress
35
-
36
- ### Task State Machine
37
-
38
- `CREATED → IN_PROGRESS → AWAITING → COMPLETED / FAILED / CANCELLED / CANCELLING`
39
-
40
- ### Message Format (JSON)
41
-
42
- ```json
43
- {
44
- "role": "user|agent|agent/name",
45
- "parts": [
46
- {
47
- "name": "optional",
48
- "content_type": "text/plain|application/json|image/*",
49
- "content": "string or base64",
50
- "content_encoding": "plain|base64",
51
- "content_url": "https://...",
52
- "metadata": { "kind": "citation|trajectory", ... }
53
- }
54
- ],
55
- "created_at": "ISO8601",
56
- "completed_at": "ISO8601"
57
- }
58
- ```
59
-
60
- ### Run Response (JSON)
61
-
62
- ```json
63
- {
64
- "run_id": "uuid",
65
- "agent_name": "string",
66
- "session_id": "uuid|null",
67
- "status": "created|in-progress|awaiting|completed|failed|cancelled|cancelling",
68
- "output": [{ "role": "agent", "parts": [...] }],
69
- "error": { "code": "server_error|invalid_input|not_found", "message": "...", "data": null },
70
- "await_request": { "type": "message", "message": { ... } },
71
- "created_at": "ISO8601",
72
- "finished_at": "ISO8601"
73
- }
74
- ```
75
-
76
- ### SSE Event Types (11)
77
-
78
- `message.created`, `message.part`, `message.completed`, `run.created`, `run.in_progress`, `run.awaiting`, `run.completed`, `run.cancelled`, `run.failed`, `generic`, `error`
79
-
80
- ---
81
-
82
- ## Key Classes and Their Roles
83
-
84
- ### Server
85
-
86
- | Class | Role |
87
- |---|---|
88
- | `SimpleAcp::Server::Base` | Main server; registers agents, drives all execution modes |
89
- | `SimpleAcp::Server::App` | Roda HTTP router — maps endpoints to server methods |
90
- | `SimpleAcp::Server::Agent` | Wraps handler block; normalizes return types (String/Message/Array/Enumerator → consistent enumerable) |
91
- | `SimpleAcp::Server::Context` | Passed to handler blocks; provides `await_message`, `cancel!`, `history`, `state`, `log` |
92
- | `SimpleAcp::Server::FalconRunner` | Fiber-based Falcon server runner |
93
-
94
- ### Client
95
-
96
- | Class | Role |
97
- |---|---|
98
- | `SimpleAcp::Client::Base` | Faraday-based; all endpoints as snake_case methods |
99
- | `SimpleAcp::Client::SSE` | SSE event stream parser (event type + JSON data) |
100
-
101
- **Client methods:** `ping`, `agents`, `agent(name)`, `run_sync`, `run_async`, `run_stream`, `run_resume_sync`, `run_resume_stream`, `run_status`, `run_events`, `run_cancel`, `wait_for_run`, `use_session`, `clear_session`, `session(id)`
102
-
103
- ### Models
104
-
105
- | Class | Role |
106
- |---|---|
107
- | `SimpleAcp::Models::Message` | Role + array of `MessagePart`s; factory: `Message.user(...)`, `Message.agent(...)` |
108
- | `SimpleAcp::Models::MessagePart` | Content unit: text, JSON, image, URL; factory: `.text(s)`, `.json(h)`, `.image(data, mime)`, `.from_url(url, ct)` |
109
- | `SimpleAcp::Models::Run` | Execution lifecycle with state transitions: `start!`, `await!`, `complete!`, `fail!`, `cancel!` |
110
- | `SimpleAcp::Models::Session` | Conversation history (Message array) + arbitrary state dict; `add_to_history`, `set_state` |
111
- | `SimpleAcp::Models::AgentManifest` | Discovery: name, description, input/output MIME types, status, metadata |
112
- | `SimpleAcp::Models::AwaitRequest` | Prompt to display when agent pauses |
113
- | `SimpleAcp::Models::AwaitResume` | Client's response when resuming a paused run |
114
- | `SimpleAcp::Models::Events` | SSE event hierarchy (all 11 types); `sse_format` for wire encoding |
115
- | `SimpleAcp::Models::Error` | Structured error: code, message, data; factory: `.server_error`, `.invalid_input`, `.not_found` |
116
- | `SimpleAcp::Models::Metadata` | Agent metadata: citations, trajectory, authors, links, dependencies, capabilities |
117
-
118
- ### Storage (pluggable — duck-typed interface)
119
-
120
- | Class | Backend |
121
- |---|---|
122
- | `SimpleAcp::Storage::Memory` | `Concurrent::Map` — default, thread-safe |
123
- | `SimpleAcp::Storage::Redis` | Redis backend |
124
- | `SimpleAcp::Storage::PostgreSQL` | PostgreSQL via Sequel |
125
-
126
- **Interface:** `get_run`, `save_run`, `delete_run`, `list_runs`, `get_session`, `save_session`, `delete_session`, `add_event`, `get_events`, `close`, `ping`
127
-
128
- ---
129
-
130
- ## Agent DSL
131
-
132
- ```ruby
133
- server = SimpleAcp::Server::Base.new
134
-
135
- server.agent("assistant",
136
- description: "A helpful assistant",
137
- input_content_types: ["text/plain"],
138
- output_content_types: ["text/plain"]
139
- ) do |context|
140
- input = context.input.text_content
141
- result = my_robot.run(input).reply
142
- SimpleAcp::Models::Message.agent(result)
143
- end
144
-
145
- server.run(port: 9292)
146
- ```
147
-
148
- ### Streaming Agent
149
-
150
- ```ruby
151
- server.agent("streamer", description: "Streams responses") do |context|
152
- Enumerator.new do |yielder|
153
- my_robot.run(context.input.text_content) do |chunk|
154
- yielder << SimpleAcp::Models::MessagePart.text(chunk.content)
155
- end
156
- end
157
- end
158
- ```
159
-
160
- ### Await/Resume Agent (interactive)
161
-
162
- ```ruby
163
- server.agent("interactive", description: "Asks for clarification") do |context|
164
- clarification = context.await_message("Please clarify your intent:")
165
- answer = clarification.text_content
166
- result = my_robot.run("#{context.input.text_content} (clarification: #{answer})").reply
167
- SimpleAcp::Models::Message.agent(result)
168
- end
169
- ```
170
-
171
- ### Client Usage
172
-
173
- ```ruby
174
- client = SimpleAcp::Client::Base.new("http://localhost:9292")
175
-
176
- # Synchronous
177
- run = client.run_sync("assistant", input: "Hello")
178
- puts run.output.first.text_content
179
-
180
- # Streaming
181
- client.run_stream("streamer", input: "Tell me a story") do |event|
182
- print event.part.content if event.is_a?(SimpleAcp::Models::Events::MessagePartEvent)
183
- end
184
-
185
- # Async with polling
186
- run = client.run_async("assistant", input: "Long task")
187
- completed = client.wait_for_run(run.run_id, timeout: 60)
188
- ```
189
-
190
- ---
191
-
192
- ## Dependencies
193
-
194
- **Runtime:**
195
- - `roda (~> 3.0)` — Rack web framework
196
- - `falcon (~> 0.47)` — Fiber-based async HTTP server
197
- - `async (~> 2.0)` — Async I/O primitives
198
- - `async-http (~> 0.66)` — Async HTTP adapter
199
- - `faraday (~> 2.0)` — HTTP client
200
- - `concurrent-ruby (~> 1.2)` — Thread-safe data structures
201
- - `json_schemer (~> 2.0)` — JSON schema validation
202
- - `base64`, `uri` — stdlib backports for Ruby 3.4+
203
-
204
- **Optional storage:**
205
- - `redis (~> 5.0)`, `pg (~> 1.5)`, `sequel (~> 5.0)`
206
-
207
- **Development:**
208
- - `minitest (~> 5.0)`, `minitest-reporters`, `rack-test (~> 2.0)`, `webmock (~> 3.0)`
209
- - `rubocop (~> 1.0)`, `rake`, `bundler`, `debug_me`, `aigcm`
210
-
211
- ---
212
-
213
- ## Comparison: `simple_acp` vs. `agent2agent` (GIS gem)
214
-
215
- | Feature | `simple_acp` (yours) | `agent2agent` (GIS) |
216
- |---|---|---|
217
- | **Protocol** | ACP (Bee AI community) | A2A (Google) |
218
- | **Await/Resume** | First-class — agents pause, client resumes | `INPUT_REQUIRED` state only |
219
- | **Session state** | Arbitrary state dict + full history | Task-scoped only |
220
- | **Storage backends** | Memory, Redis, PostgreSQL | Memory, SQLite |
221
- | **HTTP framework** | Roda + Falcon | Pure Rack + Falcon |
222
- | **Client** | Faraday-based, full API surface | `async-http`, fiber-only |
223
- | **Content types** | Multimodal: text, JSON, image, URL refs | Text/JSON focused |
224
- | **Agent DSL** | Block-based, normalized return types | Block-based |
225
- | **Tests** | Minitest in `test/` | `scampi` inline |
226
- | **Proto/Schema** | JSON Schema via `json_schemer` | `.proto` file + 47-type JSON schema |
227
-
228
- ---
229
-
230
- ## Applicability to RobotLab
231
-
232
- ### High Value — Natural Fit
233
-
234
- **Robot-as-ACP-Agent:**
235
- Each `Robot` maps directly to an ACP agent registration:
236
-
237
- ```ruby
238
- server.agent(robot.name, description: robot.description) do |context|
239
- result = robot.run(context.input.text_content)
240
- SimpleAcp::Models::Message.agent(result.reply)
241
- end
242
- ```
243
-
244
- **Streaming robot output:**
245
- `run_stream` + SSE `message.part` events maps onto RubyLLM's streaming callbacks — emit one `MessagePartEvent` per chunk. Real-time progress for free.
246
-
247
- **Await/Resume ↔ AskUser:**
248
- `ctx.await_message(prompt)` / `ctx.resume_message` is a network-protocol equivalent of RobotLab's `AskUser` tool. Exposes interactive robot flows to web and API clients without a terminal dependency. This is the most direct protocol-level replacement for `AskUser`.
249
-
250
- **Session ↔ Memory:**
251
- `Session#state` (arbitrary dict) mirrors `Memory#data` (StateProxy). `Session#history` mirrors `Memory#messages`. A thin bridge adapter could keep them in sync, giving RobotLab robots persistent cross-request state without Redis.
252
-
253
- **Async runs ↔ background jobs:**
254
- `run_async` returns a run ID immediately; `wait_for_run` polls. Maps cleanly onto `RobotLab::Job` (ActiveJob) — the job creates the run, Turbo Streams broadcast `message.part` events as SSE.
255
-
256
- **Network-as-single-agent:**
257
- Expose an entire `Network` pipeline as one ACP agent — clients send one message, the network orchestrates internally across all robots, the final result comes back as one response. Callers don't need to know the internal topology.
258
-
259
- **PostgreSQL storage:**
260
- `SimpleAcp::Storage::PostgreSQL` aligns with RobotLab's Rails integration and existing ActiveRecord setup. No new infrastructure required.
261
-
262
- **Multimodal inputs:**
263
- `MessagePart` supports images, JSON blobs, and URL references out of the box — richer than plain text, useful for vision-capable robots or structured-data workflows.
264
-
265
- ### Integration Pattern
266
-
267
- ```ruby
268
- # Expose a RobotLab Network as an ACP server
269
- network = RobotLab.create_network(name: "support") { ... }
270
-
271
- server = SimpleAcp::Server::Base.new(
272
- storage: SimpleAcp::Storage::PostgreSQL.new(db_url)
273
- )
274
-
275
- server.agent("support",
276
- description: "Multi-robot support pipeline",
277
- input_content_types: ["text/plain"],
278
- output_content_types: ["text/plain"]
279
- ) do |context|
280
- memory = RobotLab.create_memory(
281
- data: { session_id: context.session_id }
282
- )
283
- result = network.run(message: context.input.text_content, memory: memory)
284
- SimpleAcp::Models::Message.agent(result.reply)
285
- end
286
- ```
287
-
288
- ---
289
-
290
- ## Bottom Line
291
-
292
- `simple_acp` is a cleaner fit for RobotLab than the `agent2agent` gem for three reasons:
293
-
294
- 1. **Await/resume directly replaces `AskUser`'s terminal dependency** with a proper HTTP protocol state — robots can request human input without blocking a terminal session
295
- 2. **PostgreSQL backend** aligns with the existing Rails integration — no SQLite impedance mismatch
296
- 3. **Multimodal message parts** (image, JSON, URL) give RobotLab robots richer input/output than plain text
297
-
298
- The most impactful integration would be a `RobotLab::ACPServer` adapter class that wraps any `Robot` or `Network` as an ACP agent, mapping `AskUser` calls to `await_message`, streaming callbacks to `message.part` events, and `RobotResult` to a completed `Message`.
data/temp.md DELETED
@@ -1,6 +0,0 @@
1
-
2
- You: /llms gpt-5 openai
3
-
4
- You: /llms gpt-5 openai 5.4
5
-
6
- You: /llms gpt-5 openai 5.4 -openrouter