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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -1
- data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
- data/lib/robot_lab/version.rb +1 -1
- metadata +3 -253
- data/.architecture/AGENTS.md +0 -32
- data/.architecture/config.yml +0 -8
- data/.architecture/members.yml +0 -60
- data/.architecture/reviews/feature-free-will.md +0 -490
- data/.architecture/reviews/overall-codebase.md +0 -427
- data/.claude/settings.local.json +0 -57
- data/.codex/config.toml +0 -2
- data/.envrc +0 -6
- data/.github/workflows/deploy-github-pages.yml +0 -52
- data/.irbrc +0 -6
- data/.loki +0 -65
- data/.quality/reek_baseline.txt +0 -43
- data/.rubocop.yml +0 -10
- data/Archspec.rb +0 -44
- data/CLAUDE.md +0 -141
- data/COMMITS.md +0 -196
- data/Rakefile +0 -193
- data/_typos.toml +0 -21
- data/agent2agent_review.md +0 -192
- data/agentf_improvements.md +0 -253
- data/agents.md +0 -14
- data/docs/api/core/index.md +0 -147
- data/docs/api/core/memory.md +0 -578
- data/docs/api/core/network.md +0 -553
- data/docs/api/core/result.md +0 -211
- data/docs/api/core/robot.md +0 -1667
- data/docs/api/core/state.md +0 -145
- data/docs/api/core/tool.md +0 -520
- data/docs/api/errors.md +0 -323
- data/docs/api/hooks.md +0 -469
- data/docs/api/index.md +0 -137
- data/docs/api/mcp/client.md +0 -387
- data/docs/api/mcp/index.md +0 -267
- data/docs/api/mcp/server.md +0 -252
- data/docs/api/mcp/transports.md +0 -339
- data/docs/api/messages/index.md +0 -126
- data/docs/api/messages/text-message.md +0 -170
- data/docs/api/messages/tool-call-message.md +0 -206
- data/docs/api/messages/tool-result-message.md +0 -242
- data/docs/api/messages/user-message.md +0 -232
- data/docs/api/skills.md +0 -423
- data/docs/api/streaming/context.md +0 -280
- data/docs/api/streaming/events.md +0 -185
- data/docs/api/streaming/index.md +0 -156
- data/docs/api/support.md +0 -846
- data/docs/architecture/core-concepts.md +0 -575
- data/docs/architecture/index.md +0 -252
- data/docs/architecture/message-flow.md +0 -366
- data/docs/architecture/network-orchestration.md +0 -478
- data/docs/architecture/robot-execution.md +0 -396
- data/docs/architecture/state-management.md +0 -410
- data/docs/assets/css/custom.css +0 -56
- data/docs/assets/images/robot_lab.jpg +0 -0
- data/docs/concepts.md +0 -641
- data/docs/examples/basic-chat.md +0 -258
- data/docs/examples/index.md +0 -425
- data/docs/examples/mcp-server.md +0 -403
- data/docs/examples/multi-robot-network.md +0 -476
- data/docs/examples/tool-usage.md +0 -468
- data/docs/getting-started/configuration.md +0 -645
- data/docs/getting-started/index.md +0 -56
- data/docs/getting-started/installation.md +0 -197
- data/docs/getting-started/quick-start.md +0 -293
- data/docs/guides/building-robots.md +0 -1187
- data/docs/guides/creating-networks.md +0 -736
- data/docs/guides/hooks.md +0 -1206
- data/docs/guides/index.md +0 -78
- data/docs/guides/knowledge.md +0 -219
- data/docs/guides/mcp-integration.md +0 -740
- data/docs/guides/memory.md +0 -458
- data/docs/guides/observability.md +0 -733
- data/docs/guides/streaming.md +0 -323
- data/docs/guides/using-tools.md +0 -780
- data/docs/index.md +0 -280
- data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
- data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
- data/examples/.envrc +0 -3
- data/examples/01_simple_robot.rb +0 -31
- data/examples/02_tools.rb +0 -109
- data/examples/03_network.rb +0 -118
- data/examples/04_mcp.rb +0 -217
- data/examples/05_streaming.rb +0 -137
- data/examples/06_prompt_templates.rb +0 -325
- data/examples/07_network_memory.rb +0 -313
- data/examples/08_llm_config.rb +0 -162
- data/examples/09_chaining.rb +0 -251
- data/examples/10_memory.rb +0 -315
- data/examples/11_network_introspection.rb +0 -239
- data/examples/12_message_bus.rb +0 -67
- data/examples/13_spawn.rb +0 -85
- data/examples/14_rusty_circuit/.envrc +0 -1
- data/examples/14_rusty_circuit/.gitignore +0 -1
- data/examples/14_rusty_circuit/README.md +0 -1
- data/examples/14_rusty_circuit/comic.rb +0 -149
- data/examples/14_rusty_circuit/display.rb +0 -217
- data/examples/14_rusty_circuit/heckler.rb +0 -65
- data/examples/14_rusty_circuit/open_mic.rb +0 -132
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
- data/examples/14_rusty_circuit/scout.rb +0 -165
- data/examples/14_rusty_circuit/show.log +0 -234
- data/examples/15_memory_network_and_bus/.envrc +0 -1
- data/examples/15_memory_network_and_bus/README.md +0 -66
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
- data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
- data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
- data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
- data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
- data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
- data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
- data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
- data/examples/15_memory_network_and_bus/output/memory.json +0 -13
- data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
- data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
- data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
- data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
- data/examples/16_writers_room/.envrc +0 -1
- data/examples/16_writers_room/display.rb +0 -158
- data/examples/16_writers_room/output/.gitignore +0 -4
- data/examples/16_writers_room/output/README.md +0 -69
- data/examples/16_writers_room/output/opus_001.md +0 -263
- data/examples/16_writers_room/output/opus_001_notes.log +0 -470
- data/examples/16_writers_room/output/opus_002.md +0 -245
- data/examples/16_writers_room/output/opus_002_notes.log +0 -546
- data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
- data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
- data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
- data/examples/16_writers_room/prompts/writer.md +0 -37
- data/examples/16_writers_room/room.rb +0 -186
- data/examples/16_writers_room/tools.rb +0 -173
- data/examples/16_writers_room/writer.rb +0 -121
- data/examples/16_writers_room/writers_room.rb +0 -256
- data/examples/17_skills.rb +0 -234
- data/examples/18_rails/.envrc +0 -3
- data/examples/18_rails/.gitignore +0 -5
- data/examples/18_rails/Gemfile +0 -11
- data/examples/18_rails/README.md +0 -67
- data/examples/18_rails/Rakefile +0 -4
- data/examples/18_rails/app/controllers/application_controller.rb +0 -4
- data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
- data/examples/18_rails/app/jobs/application_job.rb +0 -4
- data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
- data/examples/18_rails/app/models/application_record.rb +0 -5
- data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
- data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
- data/examples/18_rails/app/robots/chat_robot.rb +0 -25
- data/examples/18_rails/app/tools/time_tool.rb +0 -9
- data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
- data/examples/18_rails/app/views/chat/index.html.erb +0 -67
- data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
- data/examples/18_rails/bin/dev +0 -7
- data/examples/18_rails/bin/rails +0 -6
- data/examples/18_rails/bin/setup +0 -15
- data/examples/18_rails/config/application.rb +0 -33
- data/examples/18_rails/config/cable.yml +0 -2
- data/examples/18_rails/config/database.yml +0 -5
- data/examples/18_rails/config/environment.rb +0 -4
- data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
- data/examples/18_rails/config/routes.rb +0 -6
- data/examples/18_rails/config.ru +0 -4
- data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
- data/examples/19_token_tracking.rb +0 -138
- data/examples/20_circuit_breaker.rb +0 -147
- data/examples/21_learning_loop.rb +0 -181
- data/examples/22_context_compression.rb +0 -172
- data/examples/23_convergence.rb +0 -133
- data/examples/24_structured_delegation.rb +0 -151
- data/examples/25_history_search/conversation.jsonl +0 -30
- data/examples/25_history_search.rb +0 -133
- data/examples/26_document_store/api_versioning_adr.md +0 -52
- data/examples/26_document_store/incident_postmortem.md +0 -46
- data/examples/26_document_store/postgres_runbook.md +0 -49
- data/examples/26_document_store/redis_caching_guide.md +0 -48
- data/examples/26_document_store/sidekiq_guide.md +0 -51
- data/examples/26_document_store.rb +0 -140
- data/examples/27_incident_response/README.md +0 -65
- data/examples/27_incident_response/incident_response.rb +0 -261
- data/examples/28_mcp_discovery.rb +0 -113
- data/examples/29_ractor_tools.rb +0 -240
- data/examples/30_ractor_network.rb +0 -252
- data/examples/31_launch_assessment.rb +0 -246
- data/examples/32_newsletter_reader.rb +0 -193
- data/examples/33_stock_generator.rb +0 -80
- data/examples/33_stock_predictor.rb +0 -327
- data/examples/34_agentskills.rb +0 -76
- data/examples/35_hooks.rb +0 -266
- data/examples/README.md +0 -550
- data/examples/common.rb +0 -180
- data/examples/prompts/assistant.md +0 -5
- data/examples/prompts/audit_trail.md +0 -8
- data/examples/prompts/billing.md +0 -10
- data/examples/prompts/classifier.md +0 -7
- data/examples/prompts/comedian.md +0 -6
- data/examples/prompts/comedy_critic.md +0 -10
- data/examples/prompts/configurable.md +0 -9
- data/examples/prompts/dispatcher.md +0 -12
- data/examples/prompts/entity_extractor.md +0 -14
- data/examples/prompts/escalation.md +0 -42
- data/examples/prompts/frontmatter_mcp_test.md +0 -9
- data/examples/prompts/frontmatter_named_test.md +0 -5
- data/examples/prompts/frontmatter_tools_test.md +0 -6
- data/examples/prompts/general.md +0 -7
- data/examples/prompts/github_assistant.md +0 -14
- data/examples/prompts/helper.md +0 -4
- data/examples/prompts/incident_responder.md +0 -18
- data/examples/prompts/keyword_extractor.md +0 -11
- data/examples/prompts/llm_config_demo.md +0 -20
- data/examples/prompts/order_support.md +0 -35
- data/examples/prompts/os_advocate.md +0 -13
- data/examples/prompts/os_chief.md +0 -13
- data/examples/prompts/os_editor.md +0 -13
- data/examples/prompts/parameterized_main_test.md +0 -6
- data/examples/prompts/pii_redactor.md +0 -7
- data/examples/prompts/product_support.md +0 -37
- data/examples/prompts/runbook_protocol.md +0 -12
- data/examples/prompts/sentiment_analyzer.md +0 -12
- data/examples/prompts/skill_a_test.md +0 -4
- data/examples/prompts/skill_b_test.md +0 -4
- data/examples/prompts/skill_config_test.md +0 -5
- data/examples/prompts/skill_cycle_a_test.md +0 -6
- data/examples/prompts/skill_cycle_b_test.md +0 -6
- data/examples/prompts/skill_description_test.md +0 -4
- data/examples/prompts/skill_leaf_test.md +0 -4
- data/examples/prompts/skill_nested_test.md +0 -6
- data/examples/prompts/skill_refs_main_test.md +0 -6
- data/examples/prompts/skill_self_ref_test.md +0 -6
- data/examples/prompts/skill_with_mcp_test.md +0 -9
- data/examples/prompts/skill_with_params_test.md +0 -6
- data/examples/prompts/skill_with_robot_name_test.md +0 -5
- data/examples/prompts/skill_with_tools_test.md +0 -6
- data/examples/prompts/sre_compliance.md +0 -10
- data/examples/prompts/structured_output.md +0 -7
- data/examples/prompts/synthesizer.md +0 -17
- data/examples/prompts/technical.md +0 -10
- data/examples/prompts/template_with_skills_test.md +0 -6
- data/examples/prompts/triage.md +0 -22
- data/examples/ruboruby.md +0 -423
- data/examples/run_all.rb +0 -60
- data/examples/xyzzy.rb +0 -97
- data/logfile +0 -8
- data/mkdocs.yml +0 -209
- data/robot_concurrency.md +0 -38
- data/simple_acp_review.md +0 -298
- data/temp.md +0 -6
- data/tool_manifest_plan.md +0 -155
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Example 7: Network Memory with Concurrent Robots
|
|
5
|
-
#
|
|
6
|
-
# Demonstrates the reactive shared memory system where:
|
|
7
|
-
# - Multiple robots run concurrently and write to shared memory
|
|
8
|
-
# - Robots can wait for values written by other robots
|
|
9
|
-
# - Subscriptions provide real-time notifications of memory changes
|
|
10
|
-
# - Network broadcast sends messages to all robots
|
|
11
|
-
#
|
|
12
|
-
# Architecture:
|
|
13
|
-
# ┌─────────────────────────────────────────────────────────────┐
|
|
14
|
-
# │ PARALLEL ANALYSIS │
|
|
15
|
-
# │ │
|
|
16
|
-
# │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
17
|
-
# │ │ Sentiment │ │ Entities │ │ Keywords │ │
|
|
18
|
-
# │ │ Analyzer │ │ Extractor │ │ Extractor │ │
|
|
19
|
-
# │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
|
20
|
-
# │ │ │ │ │
|
|
21
|
-
# │ ▼ ▼ ▼ │
|
|
22
|
-
# │ memory.set( memory.set( memory.set( │
|
|
23
|
-
# │ :sentiment) :entities) :keywords) │
|
|
24
|
-
# │ │ │ │ │
|
|
25
|
-
# │ └────────────────┼────────────────┘ │
|
|
26
|
-
# │ ▼ │
|
|
27
|
-
# │ ┌──────────────────────────────────────────────────────┐ │
|
|
28
|
-
# │ │ SHARED MEMORY │ │
|
|
29
|
-
# │ │ { sentiment: {...}, entities: {...}, keywords: {...} │ │
|
|
30
|
-
# │ └──────────────────────────────────────────────────────┘ │
|
|
31
|
-
# │ │ │
|
|
32
|
-
# │ ▼ │
|
|
33
|
-
# │ ┌──────────────────────────────────────────────────────┐ │
|
|
34
|
-
# │ │ Synthesizer │ │
|
|
35
|
-
# │ │ memory.get(:sentiment, :entities, :keywords, │ │
|
|
36
|
-
# │ │ wait: true) │ │
|
|
37
|
-
# │ └──────────────────────────────────────────────────────┘ │
|
|
38
|
-
# │ │
|
|
39
|
-
# └─────────────────────────────────────────────────────────────┘
|
|
40
|
-
#
|
|
41
|
-
# Usage:
|
|
42
|
-
# ruby examples/07_network_memory.rb
|
|
43
|
-
|
|
44
|
-
require_relative "common"
|
|
45
|
-
require "json"
|
|
46
|
-
|
|
47
|
-
banner "Network Memory with Concurrent Robots"
|
|
48
|
-
|
|
49
|
-
# -----------------------------------------------------------------------------
|
|
50
|
-
# Custom Robot Classes that Write to Shared Memory
|
|
51
|
-
# -----------------------------------------------------------------------------
|
|
52
|
-
|
|
53
|
-
# Base class for analysis robots that write results to memory
|
|
54
|
-
class AnalysisRobot < RobotLab::Robot
|
|
55
|
-
def initialize(memory_key:, **opts)
|
|
56
|
-
super(**opts)
|
|
57
|
-
@memory_key = memory_key
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def call(result)
|
|
61
|
-
run_context = extract_run_context(result)
|
|
62
|
-
network_memory = run_context.delete(:network_memory)
|
|
63
|
-
message = run_context.delete(:message)
|
|
64
|
-
|
|
65
|
-
robot_result = run(message, network_memory: network_memory, **run_context)
|
|
66
|
-
|
|
67
|
-
# Parse the JSON response and write to shared memory
|
|
68
|
-
if network_memory
|
|
69
|
-
content = robot_result.reply.to_s
|
|
70
|
-
|
|
71
|
-
# Set writer before writing to memory
|
|
72
|
-
network_memory.current_writer = @name
|
|
73
|
-
|
|
74
|
-
begin
|
|
75
|
-
parsed = JSON.parse(content)
|
|
76
|
-
network_memory.set(@memory_key, parsed)
|
|
77
|
-
puts " [#{@name}] Wrote JSON to memory[:#{@memory_key}]"
|
|
78
|
-
rescue JSON::ParserError
|
|
79
|
-
# If not valid JSON, store the raw text
|
|
80
|
-
network_memory.set(@memory_key, content)
|
|
81
|
-
puts " [#{@name}] Wrote text to memory[:#{@memory_key}]"
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
result
|
|
86
|
-
.with_context(@name.to_sym, robot_result)
|
|
87
|
-
.continue(robot_result)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Synthesizer robot that reads from shared memory and synthesizes results
|
|
92
|
-
class SynthesizerRobot < RobotLab::Robot
|
|
93
|
-
def call(result)
|
|
94
|
-
run_context = extract_run_context(result)
|
|
95
|
-
network_memory = run_context.delete(:network_memory)
|
|
96
|
-
message = run_context.delete(:message)
|
|
97
|
-
|
|
98
|
-
puts " [#{@name}] Reading analysis results from memory..."
|
|
99
|
-
|
|
100
|
-
if network_memory
|
|
101
|
-
# Read results from memory - they should already be there since
|
|
102
|
-
# SimpleFlow ensures our dependencies completed first
|
|
103
|
-
sentiment = network_memory.get(:sentiment)
|
|
104
|
-
entities = network_memory.get(:entities)
|
|
105
|
-
keywords = network_memory.get(:keywords)
|
|
106
|
-
|
|
107
|
-
puts " [#{@name}] Got sentiment: #{sentiment.nil? ? 'nil' : 'present'}"
|
|
108
|
-
puts " [#{@name}] Got entities: #{entities.nil? ? 'nil' : 'present'}"
|
|
109
|
-
puts " [#{@name}] Got keywords: #{keywords.nil? ? 'nil' : 'present'}"
|
|
110
|
-
|
|
111
|
-
# Format for the template
|
|
112
|
-
run_context[:sentiment] = format_for_template(sentiment)
|
|
113
|
-
run_context[:entities] = format_for_template(entities)
|
|
114
|
-
run_context[:keywords] = format_for_template(keywords)
|
|
115
|
-
else
|
|
116
|
-
run_context[:sentiment] = "Not available"
|
|
117
|
-
run_context[:entities] = "Not available"
|
|
118
|
-
run_context[:keywords] = "Not available"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
robot_result = run(message, network_memory: network_memory, **run_context)
|
|
122
|
-
|
|
123
|
-
result
|
|
124
|
-
.with_context(@name.to_sym, robot_result)
|
|
125
|
-
.continue(robot_result)
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
private
|
|
129
|
-
|
|
130
|
-
def format_for_template(value)
|
|
131
|
-
case value
|
|
132
|
-
when Hash, Array
|
|
133
|
-
JSON.pretty_generate(value)
|
|
134
|
-
when nil
|
|
135
|
-
"Not available"
|
|
136
|
-
else
|
|
137
|
-
value.to_s
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# -----------------------------------------------------------------------------
|
|
143
|
-
# Create the Robots
|
|
144
|
-
# -----------------------------------------------------------------------------
|
|
145
|
-
|
|
146
|
-
sentiment_robot = AnalysisRobot.new(
|
|
147
|
-
name: "sentiment_analyzer",
|
|
148
|
-
template: :sentiment_analyzer,
|
|
149
|
-
memory_key: :sentiment,
|
|
150
|
-
**llm_opts
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
entity_robot = AnalysisRobot.new(
|
|
154
|
-
name: "entity_extractor",
|
|
155
|
-
template: :entity_extractor,
|
|
156
|
-
memory_key: :entities,
|
|
157
|
-
**llm_opts
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
keyword_robot = AnalysisRobot.new(
|
|
161
|
-
name: "keyword_extractor",
|
|
162
|
-
template: :keyword_extractor,
|
|
163
|
-
memory_key: :keywords,
|
|
164
|
-
**llm_opts
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
synthesizer = SynthesizerRobot.new(
|
|
168
|
-
name: "synthesizer",
|
|
169
|
-
template: :synthesizer,
|
|
170
|
-
**llm_opts
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
# -----------------------------------------------------------------------------
|
|
174
|
-
# Create the Network with Shared Memory
|
|
175
|
-
# -----------------------------------------------------------------------------
|
|
176
|
-
|
|
177
|
-
network = RobotLab.create_network(name: "parallel_analysis") do
|
|
178
|
-
# Three analysis robots run in parallel (all depend on nothing)
|
|
179
|
-
task :sentiment, sentiment_robot, depends_on: :none
|
|
180
|
-
task :entities, entity_robot, depends_on: :none
|
|
181
|
-
task :keywords, keyword_robot, depends_on: :none
|
|
182
|
-
|
|
183
|
-
# Synthesizer waits for all three to complete
|
|
184
|
-
task :synthesize, synthesizer, depends_on: [:sentiment, :entities, :keywords]
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
# -----------------------------------------------------------------------------
|
|
188
|
-
# Set Up Memory Subscriptions (for monitoring)
|
|
189
|
-
# -----------------------------------------------------------------------------
|
|
190
|
-
|
|
191
|
-
puts "Setting up memory subscriptions for monitoring..."
|
|
192
|
-
puts
|
|
193
|
-
|
|
194
|
-
# Note: In concurrent execution, change.writer may be unreliable due to race
|
|
195
|
-
# conditions. For production use, consider including writer info in the value.
|
|
196
|
-
network.memory.subscribe(:sentiment, :entities, :keywords) do |change|
|
|
197
|
-
value_preview = case change.value
|
|
198
|
-
when Hash then change.value.keys.join(", ")
|
|
199
|
-
when String then change.value[0..50]
|
|
200
|
-
else change.value.class.name
|
|
201
|
-
end
|
|
202
|
-
puts " [MONITOR] Memory[:#{change.key}] updated with keys: #{value_preview}"
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
# -----------------------------------------------------------------------------
|
|
206
|
-
# Set Up Broadcast Handler
|
|
207
|
-
# -----------------------------------------------------------------------------
|
|
208
|
-
|
|
209
|
-
network.on_broadcast do |message|
|
|
210
|
-
puts " [BROADCAST] #{message[:payload][:event]}: #{message[:payload][:details]}"
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
# -----------------------------------------------------------------------------
|
|
214
|
-
# Run the Network
|
|
215
|
-
# -----------------------------------------------------------------------------
|
|
216
|
-
|
|
217
|
-
sample_text = <<~TEXT
|
|
218
|
-
Apple Inc. announced today that CEO Tim Cook will be presenting the new iPhone 15
|
|
219
|
-
at their headquarters in Cupertino, California on September 12th, 2024.
|
|
220
|
-
Industry analysts are extremely excited about the new features, though some
|
|
221
|
-
consumer advocates have expressed concerns about the expected price increase.
|
|
222
|
-
Samsung and Google are reportedly preparing competitive responses for later this year.
|
|
223
|
-
TEXT
|
|
224
|
-
|
|
225
|
-
puts "Network structure:"
|
|
226
|
-
puts network.visualize
|
|
227
|
-
puts
|
|
228
|
-
hr
|
|
229
|
-
puts "Input text:"
|
|
230
|
-
puts sample_text.strip
|
|
231
|
-
hr
|
|
232
|
-
puts
|
|
233
|
-
|
|
234
|
-
# Send a broadcast before starting
|
|
235
|
-
network.broadcast(event: "analysis_started", details: "Beginning parallel analysis")
|
|
236
|
-
|
|
237
|
-
puts "Running parallel analysis..."
|
|
238
|
-
puts
|
|
239
|
-
start_time = Time.now
|
|
240
|
-
|
|
241
|
-
result = network.run(message: sample_text)
|
|
242
|
-
|
|
243
|
-
elapsed = Time.now - start_time
|
|
244
|
-
puts
|
|
245
|
-
hr
|
|
246
|
-
puts "Analysis complete in #{elapsed.round(2)} seconds"
|
|
247
|
-
hr
|
|
248
|
-
|
|
249
|
-
# Send completion broadcast
|
|
250
|
-
network.broadcast(event: "analysis_complete", details: "All robots finished")
|
|
251
|
-
|
|
252
|
-
# -----------------------------------------------------------------------------
|
|
253
|
-
# Display Results
|
|
254
|
-
# -----------------------------------------------------------------------------
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
section "Final Synthesis"
|
|
258
|
-
|
|
259
|
-
if result.value.is_a?(RobotLab::RobotResult)
|
|
260
|
-
puts result.value.reply
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
section "Memory State"
|
|
265
|
-
|
|
266
|
-
# Show what's in shared memory
|
|
267
|
-
memory = network.memory
|
|
268
|
-
puts "Sentiment: #{memory.get(:sentiment)&.to_json}"
|
|
269
|
-
puts
|
|
270
|
-
puts "Entities: #{memory.get(:entities)&.to_json}"
|
|
271
|
-
puts
|
|
272
|
-
puts "Keywords: #{memory.get(:keywords)&.to_json}"
|
|
273
|
-
|
|
274
|
-
# -----------------------------------------------------------------------------
|
|
275
|
-
# Demonstrate Blocking Wait (without pipeline dependencies)
|
|
276
|
-
# -----------------------------------------------------------------------------
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
section "Demonstrating Blocking Wait"
|
|
280
|
-
|
|
281
|
-
# Create a fresh memory for this demo
|
|
282
|
-
demo_memory = RobotLab::Memory.new(network_name: "wait_demo")
|
|
283
|
-
|
|
284
|
-
# Simulate a concurrent scenario where one thread waits for another
|
|
285
|
-
puts "Starting writer thread (will write after 1 second)..."
|
|
286
|
-
puts "Starting reader thread (will wait for value)..."
|
|
287
|
-
|
|
288
|
-
reader_result = nil
|
|
289
|
-
writer_done = false
|
|
290
|
-
|
|
291
|
-
reader = Thread.new do
|
|
292
|
-
start = Time.now
|
|
293
|
-
puts " [reader] Waiting for :delayed_result..."
|
|
294
|
-
value = demo_memory.get(:delayed_result, wait: 10)
|
|
295
|
-
elapsed = Time.now - start
|
|
296
|
-
reader_result = value
|
|
297
|
-
puts " [reader] Got value after #{elapsed.round(2)}s: #{value}"
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
writer = Thread.new do
|
|
301
|
-
sleep 1
|
|
302
|
-
demo_memory.set(:delayed_result, { status: "complete", data: [1, 2, 3] })
|
|
303
|
-
writer_done = true
|
|
304
|
-
puts " [writer] Wrote :delayed_result to memory"
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
# Wait for both threads
|
|
308
|
-
writer.join
|
|
309
|
-
reader.join
|
|
310
|
-
|
|
311
|
-
puts
|
|
312
|
-
puts "Blocking wait demonstration complete!"
|
|
313
|
-
puts "Reader received: #{reader_result.inspect}"
|
data/examples/08_llm_config.rb
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Example 8: LLM Configuration via MywayConfig
|
|
5
|
-
#
|
|
6
|
-
# Demonstrates how RobotLab uses MywayConfig for environment-specific
|
|
7
|
-
# configuration (similar to Rails database.yml).
|
|
8
|
-
#
|
|
9
|
-
# Configuration is loaded from multiple sources in priority order:
|
|
10
|
-
# 1. Bundled defaults (lib/robot_lab/config/defaults.yml)
|
|
11
|
-
# 2. Environment-specific overrides (development, test, production)
|
|
12
|
-
# 3. XDG user config (~/.config/robot_lab/config.yml)
|
|
13
|
-
# 4. Project config (./config/robot_lab.yml)
|
|
14
|
-
# 5. Environment variables (ROBOT_LAB_*)
|
|
15
|
-
# 6. Template front matter (model, temperature, etc. in .md YAML header)
|
|
16
|
-
# 7. Constructor parameters (model:, temperature:, etc. passed to Robot.new)
|
|
17
|
-
# 8. with_* methods (runtime chaining, e.g. robot.with_temperature(0.9))
|
|
18
|
-
# 9. Run-time context (kwargs passed to robot.run that re-render the template)
|
|
19
|
-
#
|
|
20
|
-
# Environment is determined by ROBOT_LAB_ENV, RAILS_ENV, or RACK_ENV.
|
|
21
|
-
#
|
|
22
|
-
# Environment variable examples:
|
|
23
|
-
# ROBOT_LAB_RUBY_LLM__MODEL=qwen/qwen3.8-27b
|
|
24
|
-
# ROBOT_LAB_RUBY_LLM__REQUEST_TIMEOUT=180
|
|
25
|
-
# LMS_API_BASE=http://localhost:1234/v1
|
|
26
|
-
#
|
|
27
|
-
# Usage:
|
|
28
|
-
# ruby examples/08_llm_config.rb
|
|
29
|
-
# ROBOT_LAB_ENV=test ruby examples/08_llm_config.rb
|
|
30
|
-
# ROBOT_LAB_ENV=production ruby examples/08_llm_config.rb
|
|
31
|
-
|
|
32
|
-
require_relative "common"
|
|
33
|
-
|
|
34
|
-
# =============================================================================
|
|
35
|
-
# Demonstration
|
|
36
|
-
# =============================================================================
|
|
37
|
-
|
|
38
|
-
banner "LLM Configuration via MywayConfig"
|
|
39
|
-
|
|
40
|
-
# --- Gather environment from the user via AskUser ---
|
|
41
|
-
ask = RobotLab::AskUser.new
|
|
42
|
-
env = ask.call(
|
|
43
|
-
"question" => "Which environment should the demo run in?",
|
|
44
|
-
"choices" => %w[development test production],
|
|
45
|
-
"default" => ENV['ROBOT_LAB_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development"
|
|
46
|
-
)
|
|
47
|
-
puts
|
|
48
|
-
|
|
49
|
-
# Display configuration values (hiding sensitive keys)
|
|
50
|
-
config = RobotLab.config
|
|
51
|
-
|
|
52
|
-
puts "Core Settings:"
|
|
53
|
-
puts " max_iterations: #{config.max_iterations}"
|
|
54
|
-
puts " streaming_enabled: #{config.streaming_enabled}"
|
|
55
|
-
puts " template_path: #{config.template_path || '(default)'}"
|
|
56
|
-
puts
|
|
57
|
-
|
|
58
|
-
puts "RubyLLM Settings:"
|
|
59
|
-
puts " model: #{config.ruby_llm.model}"
|
|
60
|
-
puts " provider: #{config.ruby_llm.provider}"
|
|
61
|
-
puts " request_timeout: #{config.ruby_llm.request_timeout}s"
|
|
62
|
-
puts " max_retries: #{config.ruby_llm.max_retries}"
|
|
63
|
-
puts " log_level: #{config.ruby_llm.log_level}"
|
|
64
|
-
|
|
65
|
-
# Show where the LLM traffic actually goes
|
|
66
|
-
puts " lms_api_base: #{LMS_API_BASE}"
|
|
67
|
-
puts " (local inference — no API key in play)"
|
|
68
|
-
puts
|
|
69
|
-
|
|
70
|
-
section "Configuration Hierarchy (highest priority first)"
|
|
71
|
-
puts
|
|
72
|
-
puts " Per-Robot (override global settings for a specific robot):"
|
|
73
|
-
puts " 11. Run-time context: kwargs to robot.run re-render template"
|
|
74
|
-
puts " 10. with_* methods: robot.with_temperature(0.9).ask(...)"
|
|
75
|
-
puts " 9. Constructor params: Robot.new(model: ..., temperature: ...)"
|
|
76
|
-
puts " 8. Template front matter: model, temperature, etc. in .md YAML header"
|
|
77
|
-
puts " 7. Robot RunConfig: config: passed to Robot constructor"
|
|
78
|
-
puts
|
|
79
|
-
puts " Network/Task (shared defaults for a group of robots):"
|
|
80
|
-
puts " 6. Task RunConfig: config: passed to task() in network"
|
|
81
|
-
puts " 5. Network RunConfig: config: passed to create_network()"
|
|
82
|
-
puts
|
|
83
|
-
puts " Global (apply to all robots unless overridden):"
|
|
84
|
-
puts " 4. Environment variables: ROBOT_LAB_RUBY_LLM__MODEL, etc."
|
|
85
|
-
puts " 3. Project config: ./config/robot_lab.yml"
|
|
86
|
-
puts " 2. User config: ~/.config/robot_lab/config.yml"
|
|
87
|
-
puts " 1. Bundled defaults: lib/robot_lab/config/defaults.yml + env overrides"
|
|
88
|
-
|
|
89
|
-
section "RunConfig: Shared Operational Defaults"
|
|
90
|
-
|
|
91
|
-
shared = RobotLab::RunConfig.new(model: LLM[:default].model, temperature: 0.5)
|
|
92
|
-
puts " shared = RunConfig.new(model: #{LLM[:default].model.inspect}, temperature: 0.5)"
|
|
93
|
-
puts " shared.to_h => #{shared.to_h.inspect}"
|
|
94
|
-
puts
|
|
95
|
-
puts " Note: RunConfig carries no `provider` field, so an LM Studio model still"
|
|
96
|
-
puts " needs provider: passed to each robot alongside the shared config."
|
|
97
|
-
puts
|
|
98
|
-
|
|
99
|
-
creative = RobotLab::RunConfig.new(temperature: 0.9)
|
|
100
|
-
merged = shared.merge(creative)
|
|
101
|
-
puts " creative = RunConfig.new(temperature: 0.9)"
|
|
102
|
-
puts " merged = shared.merge(creative)"
|
|
103
|
-
puts " merged.to_h => #{merged.to_h.inspect}"
|
|
104
|
-
puts " (model inherited from shared, temperature overridden by creative)"
|
|
105
|
-
puts
|
|
106
|
-
|
|
107
|
-
# Create a robot using the configuration
|
|
108
|
-
robot = RobotLab.build(
|
|
109
|
-
**llm_opts,
|
|
110
|
-
name: "config_demo",
|
|
111
|
-
template: :llm_config_demo,
|
|
112
|
-
local_tools: [RobotLab::AskUser],
|
|
113
|
-
# These are TEMPLATE parameters, not robot kwargs — the template renders
|
|
114
|
-
# them into its prompt text.
|
|
115
|
-
context: {
|
|
116
|
-
environment: env,
|
|
117
|
-
model: LLM[:default].model,
|
|
118
|
-
provider: LLM[:default].provider
|
|
119
|
-
}
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
puts "Running robot with #{env} configuration..."
|
|
123
|
-
puts "Model: #{robot.model}"
|
|
124
|
-
puts
|
|
125
|
-
|
|
126
|
-
# Run the robot
|
|
127
|
-
result = robot.run(
|
|
128
|
-
"Briefly explain how environment-specific LLM configuration works " \
|
|
129
|
-
"and why it's useful."
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
# Display the result
|
|
133
|
-
puts "Response:"
|
|
134
|
-
result.output.each do |message|
|
|
135
|
-
puts message.content if message.respond_to?(:content)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
puts <<~FOOTER
|
|
139
|
-
|
|
140
|
-
#{"=" * 70}
|
|
141
|
-
Configuration demonstrated successfully!
|
|
142
|
-
|
|
143
|
-
Configuration flows through three layers:
|
|
144
|
-
Global (MywayConfig): YAML defaults, env overrides, XDG, env vars
|
|
145
|
-
Network/Task (RunConfig): shared defaults for groups of robots
|
|
146
|
-
Per-Robot: RunConfig, template front matter, constructor params, with_*
|
|
147
|
-
|
|
148
|
-
RunConfig lets you express shared defaults that flow through the hierarchy:
|
|
149
|
-
shared = RobotLab::RunConfig.new(model: #{LLM[:default].model.inspect}, temperature: 0.5)
|
|
150
|
-
network = RobotLab.create_network(name: "team", config: shared) { ... }
|
|
151
|
-
robot = RobotLab.build(name: "bot", config: shared, temperature: 0.9)
|
|
152
|
-
|
|
153
|
-
Example environment variable overrides:
|
|
154
|
-
ROBOT_LAB_RUBY_LLM__MODEL=#{LLM[:default].model}
|
|
155
|
-
ROBOT_LAB_RUBY_LLM__REQUEST_TIMEOUT=180
|
|
156
|
-
LMS_API_BASE=http://localhost:1234/v1
|
|
157
|
-
|
|
158
|
-
Try running with different environments:
|
|
159
|
-
ROBOT_LAB_ENV=test ruby examples/08_llm_config.rb
|
|
160
|
-
ROBOT_LAB_ENV=production ruby examples/08_llm_config.rb
|
|
161
|
-
#{"=" * 70}
|
|
162
|
-
FOOTER
|