robot_lab 0.0.4 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +64 -6
- data/Rakefile +2 -1
- data/docs/api/core/index.md +41 -46
- data/docs/api/core/memory.md +200 -154
- data/docs/api/core/network.md +13 -3
- data/docs/api/core/robot.md +38 -26
- data/docs/api/core/state.md +55 -73
- data/docs/api/index.md +7 -28
- data/docs/api/messages/index.md +35 -20
- data/docs/api/messages/text-message.md +67 -21
- data/docs/api/messages/tool-call-message.md +80 -41
- data/docs/api/messages/tool-result-message.md +119 -50
- data/docs/api/messages/user-message.md +48 -24
- data/docs/architecture/core-concepts.md +10 -15
- data/docs/concepts.md +5 -7
- data/docs/examples/index.md +2 -2
- data/docs/getting-started/configuration.md +80 -0
- data/docs/guides/building-robots.md +10 -9
- data/docs/guides/creating-networks.md +49 -0
- data/docs/guides/index.md +0 -5
- data/docs/guides/rails-integration.md +244 -162
- data/docs/guides/streaming.md +118 -138
- data/docs/index.md +0 -8
- data/examples/03_network.rb +10 -7
- data/examples/08_llm_config.rb +40 -11
- data/examples/09_chaining.rb +45 -6
- data/examples/11_network_introspection.rb +30 -7
- data/examples/12_message_bus.rb +1 -1
- data/examples/14_rusty_circuit/heckler.rb +14 -8
- data/examples/14_rusty_circuit/open_mic.rb +5 -3
- data/examples/14_rusty_circuit/scout.rb +14 -31
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +1 -1
- data/examples/16_writers_room/display.rb +158 -0
- data/examples/16_writers_room/output/.gitignore +2 -0
- data/examples/16_writers_room/output/opus_001.md +263 -0
- data/examples/16_writers_room/output/opus_001_notes.log +470 -0
- data/examples/16_writers_room/prompts/writer.md +37 -0
- data/examples/16_writers_room/room.rb +150 -0
- data/examples/16_writers_room/tools.rb +162 -0
- data/examples/16_writers_room/writer.rb +121 -0
- data/examples/16_writers_room/writers_room.rb +162 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -13
- data/lib/robot_lab/memory.rb +8 -32
- data/lib/robot_lab/network.rb +13 -20
- data/lib/robot_lab/robot/bus_messaging.rb +239 -0
- data/lib/robot_lab/robot/mcp_management.rb +88 -0
- data/lib/robot_lab/robot/template_rendering.rb +130 -0
- data/lib/robot_lab/robot.rb +56 -420
- data/lib/robot_lab/run_config.rb +184 -0
- data/lib/robot_lab/state_proxy.rb +2 -12
- data/lib/robot_lab/task.rb +8 -1
- data/lib/robot_lab/utils.rb +39 -0
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +29 -8
- data/mkdocs.yml +0 -11
- metadata +15 -20
- data/docs/api/adapters/anthropic.md +0 -121
- data/docs/api/adapters/gemini.md +0 -133
- data/docs/api/adapters/index.md +0 -104
- data/docs/api/adapters/openai.md +0 -134
- data/docs/api/history/active-record-adapter.md +0 -275
- data/docs/api/history/config.md +0 -284
- data/docs/api/history/index.md +0 -128
- data/docs/api/history/thread-manager.md +0 -194
- data/docs/guides/history.md +0 -359
- data/lib/robot_lab/adapters/anthropic.rb +0 -163
- data/lib/robot_lab/adapters/base.rb +0 -85
- data/lib/robot_lab/adapters/gemini.rb +0 -193
- data/lib/robot_lab/adapters/openai.rb +0 -160
- data/lib/robot_lab/adapters/registry.rb +0 -81
- data/lib/robot_lab/errors.rb +0 -70
- data/lib/robot_lab/history/active_record_adapter.rb +0 -146
- data/lib/robot_lab/history/config.rb +0 -115
- data/lib/robot_lab/history/thread_manager.rb +0 -93
- data/lib/robot_lab/robotic_model.rb +0 -324
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RobotLab
|
|
4
|
+
# Shared configuration object for LLM, tools, callbacks, and infrastructure.
|
|
5
|
+
#
|
|
6
|
+
# RunConfig provides a unified way to express operational defaults that flow
|
|
7
|
+
# through the configuration hierarchy:
|
|
8
|
+
#
|
|
9
|
+
# RobotLab.config -> Network -> Robot -> Template front matter -> Task -> Runtime
|
|
10
|
+
#
|
|
11
|
+
# Only explicitly set values are stored. Merge semantics: the more-specific
|
|
12
|
+
# config's non-nil values win over the less-specific config.
|
|
13
|
+
#
|
|
14
|
+
# @example Keyword construction
|
|
15
|
+
# config = RunConfig.new(model: "claude-sonnet-4", temperature: 0.7)
|
|
16
|
+
#
|
|
17
|
+
# @example Block DSL
|
|
18
|
+
# config = RunConfig.new do |c|
|
|
19
|
+
# c.model "claude-sonnet-4"
|
|
20
|
+
# c.temperature 0.7
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# @example Merge (more-specific wins)
|
|
24
|
+
# network_config = RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
|
|
25
|
+
# robot_config = RunConfig.new(temperature: 0.9)
|
|
26
|
+
# effective = network_config.merge(robot_config)
|
|
27
|
+
# effective.temperature #=> 0.9
|
|
28
|
+
# effective.model #=> "claude-sonnet-4"
|
|
29
|
+
#
|
|
30
|
+
class RunConfig
|
|
31
|
+
# LLM configuration fields (applied to chat via with_* methods)
|
|
32
|
+
LLM_FIELDS = %i[
|
|
33
|
+
model temperature top_p top_k max_tokens
|
|
34
|
+
presence_penalty frequency_penalty stop
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
37
|
+
# Tool-related fields
|
|
38
|
+
TOOL_FIELDS = %i[mcp tools].freeze
|
|
39
|
+
|
|
40
|
+
# Callback fields (Procs)
|
|
41
|
+
CALLBACK_FIELDS = %i[on_tool_call on_tool_result].freeze
|
|
42
|
+
|
|
43
|
+
# Infrastructure fields
|
|
44
|
+
INFRA_FIELDS = %i[bus enable_cache].freeze
|
|
45
|
+
|
|
46
|
+
# All recognized fields
|
|
47
|
+
FIELDS = (LLM_FIELDS + TOOL_FIELDS + CALLBACK_FIELDS + INFRA_FIELDS).freeze
|
|
48
|
+
|
|
49
|
+
# Fields that cannot be serialized to JSON (Procs, IO objects, etc.)
|
|
50
|
+
NON_SERIALIZABLE_FIELDS = (CALLBACK_FIELDS + %i[bus]).freeze
|
|
51
|
+
|
|
52
|
+
# Creates a new RunConfig.
|
|
53
|
+
#
|
|
54
|
+
# @param kwargs [Hash] field values to set
|
|
55
|
+
# @yield [self] optional block for DSL-style configuration
|
|
56
|
+
def initialize(**kwargs)
|
|
57
|
+
@fields = {}
|
|
58
|
+
|
|
59
|
+
kwargs.each do |key, value|
|
|
60
|
+
set(key, value)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
yield self if block_given?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Define getter/setter DSL methods for each field.
|
|
67
|
+
#
|
|
68
|
+
# With no arguments: returns the current value (getter).
|
|
69
|
+
# With one argument: sets the value and returns self (chainable setter).
|
|
70
|
+
FIELDS.each do |field|
|
|
71
|
+
define_method(field) do |value = :__unset__|
|
|
72
|
+
if value == :__unset__
|
|
73
|
+
@fields[field]
|
|
74
|
+
else
|
|
75
|
+
set(field, value)
|
|
76
|
+
self
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns a duplicate of the internal fields hash.
|
|
82
|
+
#
|
|
83
|
+
# @return [Hash] only the fields that have been explicitly set
|
|
84
|
+
def to_h
|
|
85
|
+
@fields.dup
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# Returns a JSON-safe hash (skips Procs, IO, and other non-serializable values).
|
|
90
|
+
#
|
|
91
|
+
# @return [Hash]
|
|
92
|
+
def to_json_hash
|
|
93
|
+
@fields.reject { |k, _| NON_SERIALIZABLE_FIELDS.include?(k) }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# Merges another RunConfig (or Hash) on top of this one.
|
|
98
|
+
# The other's non-nil values win. Returns a new RunConfig.
|
|
99
|
+
#
|
|
100
|
+
# @param other [RunConfig, Hash] the more-specific configuration
|
|
101
|
+
# @return [RunConfig] a new merged RunConfig
|
|
102
|
+
def merge(other)
|
|
103
|
+
other_hash = other.is_a?(RunConfig) ? other.to_h : other
|
|
104
|
+
merged = @fields.merge(other_hash) { |_k, old_v, new_v| new_v.nil? ? old_v : new_v }
|
|
105
|
+
self.class.new(**merged)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Applies LLM fields to a chat object via its with_* methods.
|
|
110
|
+
#
|
|
111
|
+
# @param chat [Object] a RubyLLM::Chat (or similar) that responds to with_model, with_temperature, etc.
|
|
112
|
+
def apply_to(chat)
|
|
113
|
+
LLM_FIELDS.each do |field|
|
|
114
|
+
value = @fields[field]
|
|
115
|
+
next unless value
|
|
116
|
+
|
|
117
|
+
method = :"with_#{field}"
|
|
118
|
+
chat.public_send(method, value) if chat.respond_to?(method)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# Build a RunConfig from prompt_manager front matter metadata.
|
|
124
|
+
#
|
|
125
|
+
# @param metadata [Object] a PM::Metadata object (responds to field names)
|
|
126
|
+
# @return [RunConfig]
|
|
127
|
+
def self.from_front_matter(metadata)
|
|
128
|
+
fields = {}
|
|
129
|
+
|
|
130
|
+
LLM_FIELDS.each do |key|
|
|
131
|
+
value = metadata.respond_to?(key) ? metadata.send(key) : nil
|
|
132
|
+
fields[key] = value if value
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Extract tool-related fields
|
|
136
|
+
%i[mcp tools].each do |key|
|
|
137
|
+
value = metadata.respond_to?(key) ? metadata.send(key) : nil
|
|
138
|
+
fields[key] = value if value
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
new(**fields)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# @return [Boolean] true if no fields have been set
|
|
146
|
+
def empty?
|
|
147
|
+
@fields.empty?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# @param field [Symbol] the field name
|
|
152
|
+
# @return [Boolean] true if the field has been explicitly set
|
|
153
|
+
def key?(field)
|
|
154
|
+
@fields.key?(field)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# @param other [RunConfig] the other RunConfig to compare
|
|
159
|
+
# @return [Boolean]
|
|
160
|
+
def ==(other)
|
|
161
|
+
other.is_a?(RunConfig) && to_h == other.to_h
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# @return [String]
|
|
166
|
+
def inspect
|
|
167
|
+
"#<#{self.class} #{@fields.inspect}>"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
private
|
|
171
|
+
|
|
172
|
+
# Validates and stores a field value. Nil removes the key.
|
|
173
|
+
def set(field, value)
|
|
174
|
+
field = field.to_sym
|
|
175
|
+
raise ArgumentError, "Unknown RunConfig field: #{field}" unless FIELDS.include?(field)
|
|
176
|
+
|
|
177
|
+
if value.nil?
|
|
178
|
+
@fields.delete(field)
|
|
179
|
+
else
|
|
180
|
+
@fields[field] = value
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
@@ -16,6 +16,8 @@ module RobotLab
|
|
|
16
16
|
# proxy.to_h # => { count: 1, name: "test" }
|
|
17
17
|
#
|
|
18
18
|
class StateProxy
|
|
19
|
+
include Utils
|
|
20
|
+
|
|
19
21
|
# Creates a new StateProxy.
|
|
20
22
|
#
|
|
21
23
|
# @param data [Hash] the initial data
|
|
@@ -172,17 +174,5 @@ module RobotLab
|
|
|
172
174
|
"#<RobotLab::StateProxy #{@data.inspect}>"
|
|
173
175
|
end
|
|
174
176
|
|
|
175
|
-
private
|
|
176
|
-
|
|
177
|
-
def deep_dup(obj)
|
|
178
|
-
case obj
|
|
179
|
-
when Hash
|
|
180
|
-
obj.transform_values { |v| deep_dup(v) }
|
|
181
|
-
when Array
|
|
182
|
-
obj.map { |v| deep_dup(v) }
|
|
183
|
-
else
|
|
184
|
-
obj.dup rescue obj
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
177
|
end
|
|
188
178
|
end
|
data/lib/robot_lab/task.rb
CHANGED
|
@@ -39,13 +39,14 @@ module RobotLab
|
|
|
39
39
|
# @param tools [Symbol, Array] tools config (:none, :inherit, or array)
|
|
40
40
|
# @param memory [Memory, Hash, nil] task-specific memory
|
|
41
41
|
#
|
|
42
|
-
def initialize(name:, robot:, context: {}, mcp: :none, tools: :none, memory: nil)
|
|
42
|
+
def initialize(name:, robot:, context: {}, mcp: :none, tools: :none, memory: nil, config: nil)
|
|
43
43
|
@name = name.to_sym
|
|
44
44
|
@robot = robot
|
|
45
45
|
@context = context
|
|
46
46
|
@mcp = mcp
|
|
47
47
|
@tools = tools
|
|
48
48
|
@memory = memory
|
|
49
|
+
@config = config
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
# SimpleFlow step interface
|
|
@@ -68,6 +69,12 @@ module RobotLab
|
|
|
68
69
|
run_params[:tools] = @tools unless @tools == :none
|
|
69
70
|
run_params[:memory] = @memory if @memory
|
|
70
71
|
|
|
72
|
+
# Merge task's config on top of network's config
|
|
73
|
+
if @config
|
|
74
|
+
network_rc = run_params[:network_config]
|
|
75
|
+
run_params[:network_config] = network_rc ? network_rc.merge(@config) : @config
|
|
76
|
+
end
|
|
77
|
+
|
|
71
78
|
# Create enhanced result with merged params
|
|
72
79
|
enhanced_result = result.with_context(:run_params, run_params)
|
|
73
80
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RobotLab
|
|
4
|
+
# Shared utility methods used across multiple classes.
|
|
5
|
+
#
|
|
6
|
+
# Include this module to get `dispatch_async` and `deep_dup`
|
|
7
|
+
# as private instance methods.
|
|
8
|
+
module Utils
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Dispatch a block asynchronously using Async fibers.
|
|
12
|
+
#
|
|
13
|
+
# When already inside an Async reactor, creates a child task.
|
|
14
|
+
# Otherwise, creates a temporary reactor that runs the block
|
|
15
|
+
# and cleans up automatically.
|
|
16
|
+
def dispatch_async(&block)
|
|
17
|
+
Async do
|
|
18
|
+
block.call
|
|
19
|
+
rescue => e
|
|
20
|
+
RobotLab.config.logger.error("dispatch_async error: #{e.class}: #{e.message}")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Deep-duplicate a nested Hash/Array structure.
|
|
25
|
+
#
|
|
26
|
+
# @param obj [Object] the object to duplicate
|
|
27
|
+
# @return [Object] the deep copy
|
|
28
|
+
def deep_dup(obj)
|
|
29
|
+
case obj
|
|
30
|
+
when Hash
|
|
31
|
+
obj.transform_values { |v| deep_dup(v) }
|
|
32
|
+
when Array
|
|
33
|
+
obj.map { |v| deep_dup(v) }
|
|
34
|
+
else
|
|
35
|
+
obj.dup rescue obj
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/robot_lab/version.rb
CHANGED
data/lib/robot_lab.rb
CHANGED
|
@@ -51,11 +51,11 @@ end
|
|
|
51
51
|
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
|
52
52
|
loader.ignore("#{__dir__}/generators")
|
|
53
53
|
loader.ignore("#{__dir__}/robot_lab/rails")
|
|
54
|
+
loader.ignore("#{__dir__}/robot_lab/robot")
|
|
54
55
|
|
|
55
56
|
# Custom inflections for classes that don't follow Zeitwerk naming conventions
|
|
56
57
|
loader.inflector.inflect(
|
|
57
58
|
'robot_lab' => 'RobotLab',
|
|
58
|
-
'robotic_model' => 'RoboticModel',
|
|
59
59
|
'mcp' => 'MCP',
|
|
60
60
|
'openai' => 'OpenAI',
|
|
61
61
|
'sse' => 'SSE',
|
|
@@ -63,12 +63,18 @@ loader.inflector.inflect(
|
|
|
63
63
|
'websocket' => 'WebSocket'
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
# NOTE: adapters/ is NOT collapsed since files define RobotLab::Adapters::* classes
|
|
67
|
-
|
|
68
66
|
loader.setup
|
|
69
67
|
|
|
70
|
-
#
|
|
71
|
-
|
|
68
|
+
# These files define multiple classes that Zeitwerk cannot autoload
|
|
69
|
+
# individually (e.g. TextMessage lives in message.rb, not text_message.rb).
|
|
70
|
+
# Require them explicitly so their constants are available without eager loading.
|
|
71
|
+
require_relative 'robot_lab/error'
|
|
72
|
+
require_relative 'robot_lab/message'
|
|
73
|
+
require_relative 'robot_lab/memory'
|
|
74
|
+
|
|
75
|
+
# Eager load everything in Rails or when explicitly requested.
|
|
76
|
+
# Otherwise Zeitwerk's lazy autoloading keeps boot fast.
|
|
77
|
+
loader.eager_load if defined?(Rails::Engine) || ENV["ROBOT_LAB_EAGER_LOAD"]
|
|
72
78
|
|
|
73
79
|
module RobotLab
|
|
74
80
|
# Error classes are defined in lib/robot_lab/error.rb
|
|
@@ -94,6 +100,20 @@ module RobotLab
|
|
|
94
100
|
end
|
|
95
101
|
|
|
96
102
|
|
|
103
|
+
# Yields the Config object for block-style configuration.
|
|
104
|
+
#
|
|
105
|
+
# @yield [Config] the config instance
|
|
106
|
+
# @return [Config] the config instance
|
|
107
|
+
#
|
|
108
|
+
# @example
|
|
109
|
+
# RobotLab.configure do |c|
|
|
110
|
+
# c.default_model = "claude-sonnet-4"
|
|
111
|
+
# end
|
|
112
|
+
def configure
|
|
113
|
+
yield config
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
97
117
|
# Reload configuration from all sources.
|
|
98
118
|
#
|
|
99
119
|
# Clears the cached Config instance, forcing it to be
|
|
@@ -132,7 +152,7 @@ module RobotLab
|
|
|
132
152
|
# name: "helper",
|
|
133
153
|
# system_prompt: "You are a helpful assistant."
|
|
134
154
|
# )
|
|
135
|
-
def build(name: "robot", template: nil, system_prompt: nil, context: {}, enable_cache: true, bus: nil, **options)
|
|
155
|
+
def build(name: "robot", template: nil, system_prompt: nil, context: {}, enable_cache: true, bus: nil, config: nil, **options)
|
|
136
156
|
Robot.new(
|
|
137
157
|
name: name,
|
|
138
158
|
template: template,
|
|
@@ -140,6 +160,7 @@ module RobotLab
|
|
|
140
160
|
context: context,
|
|
141
161
|
enable_cache: enable_cache,
|
|
142
162
|
bus: bus,
|
|
163
|
+
config: config,
|
|
143
164
|
**options
|
|
144
165
|
)
|
|
145
166
|
end
|
|
@@ -172,8 +193,8 @@ module RobotLab
|
|
|
172
193
|
# step :entities, entity_bot, depends_on: [:fetch]
|
|
173
194
|
# step :merge, merger, depends_on: [:sentiment, :entities]
|
|
174
195
|
# end
|
|
175
|
-
def create_network(name:, concurrency: :auto, &block)
|
|
176
|
-
Network.new(name: name, concurrency: concurrency, &block)
|
|
196
|
+
def create_network(name:, concurrency: :auto, config: nil, &block)
|
|
197
|
+
Network.new(name: name, concurrency: concurrency, config: config, &block)
|
|
177
198
|
end
|
|
178
199
|
|
|
179
200
|
|
data/mkdocs.yml
CHANGED
|
@@ -168,7 +168,6 @@ nav:
|
|
|
168
168
|
- Using Tools: guides/using-tools.md
|
|
169
169
|
- MCP Integration: guides/mcp-integration.md
|
|
170
170
|
- Streaming Responses: guides/streaming.md
|
|
171
|
-
- Conversation History: guides/history.md
|
|
172
171
|
- Memory System: guides/memory.md
|
|
173
172
|
- Rails Integration: guides/rails-integration.md
|
|
174
173
|
- API Reference:
|
|
@@ -186,11 +185,6 @@ nav:
|
|
|
186
185
|
- TextMessage: api/messages/text-message.md
|
|
187
186
|
- ToolCallMessage: api/messages/tool-call-message.md
|
|
188
187
|
- ToolResultMessage: api/messages/tool-result-message.md
|
|
189
|
-
- Adapters:
|
|
190
|
-
- api/adapters/index.md
|
|
191
|
-
- Anthropic: api/adapters/anthropic.md
|
|
192
|
-
- OpenAI: api/adapters/openai.md
|
|
193
|
-
- Gemini: api/adapters/gemini.md
|
|
194
188
|
- MCP:
|
|
195
189
|
- api/mcp/index.md
|
|
196
190
|
- Client: api/mcp/client.md
|
|
@@ -200,11 +194,6 @@ nav:
|
|
|
200
194
|
- api/streaming/index.md
|
|
201
195
|
- Context: api/streaming/context.md
|
|
202
196
|
- Events: api/streaming/events.md
|
|
203
|
-
- History:
|
|
204
|
-
- api/history/index.md
|
|
205
|
-
- Config: api/history/config.md
|
|
206
|
-
- ThreadManager: api/history/thread-manager.md
|
|
207
|
-
- ActiveRecordAdapter: api/history/active-record-adapter.md
|
|
208
197
|
- Examples:
|
|
209
198
|
- examples/index.md
|
|
210
199
|
- Basic Chat: examples/basic-chat.md
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: robot_lab
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dewayne VanHoozer
|
|
@@ -227,20 +227,12 @@ files:
|
|
|
227
227
|
- LICENSE.txt
|
|
228
228
|
- README.md
|
|
229
229
|
- Rakefile
|
|
230
|
-
- docs/api/adapters/anthropic.md
|
|
231
|
-
- docs/api/adapters/gemini.md
|
|
232
|
-
- docs/api/adapters/index.md
|
|
233
|
-
- docs/api/adapters/openai.md
|
|
234
230
|
- docs/api/core/index.md
|
|
235
231
|
- docs/api/core/memory.md
|
|
236
232
|
- docs/api/core/network.md
|
|
237
233
|
- docs/api/core/robot.md
|
|
238
234
|
- docs/api/core/state.md
|
|
239
235
|
- docs/api/core/tool.md
|
|
240
|
-
- docs/api/history/active-record-adapter.md
|
|
241
|
-
- docs/api/history/config.md
|
|
242
|
-
- docs/api/history/index.md
|
|
243
|
-
- docs/api/history/thread-manager.md
|
|
244
236
|
- docs/api/index.md
|
|
245
237
|
- docs/api/mcp/client.md
|
|
246
238
|
- docs/api/mcp/index.md
|
|
@@ -275,7 +267,6 @@ files:
|
|
|
275
267
|
- docs/getting-started/quick-start.md
|
|
276
268
|
- docs/guides/building-robots.md
|
|
277
269
|
- docs/guides/creating-networks.md
|
|
278
|
-
- docs/guides/history.md
|
|
279
270
|
- docs/guides/index.md
|
|
280
271
|
- docs/guides/mcp-integration.md
|
|
281
272
|
- docs/guides/memory.md
|
|
@@ -322,6 +313,15 @@ files:
|
|
|
322
313
|
- examples/15_memory_network_and_bus/prompts/os_advocate.md
|
|
323
314
|
- examples/15_memory_network_and_bus/prompts/os_chief.md
|
|
324
315
|
- examples/15_memory_network_and_bus/prompts/os_editor.md
|
|
316
|
+
- examples/16_writers_room/display.rb
|
|
317
|
+
- examples/16_writers_room/output/.gitignore
|
|
318
|
+
- examples/16_writers_room/output/opus_001.md
|
|
319
|
+
- examples/16_writers_room/output/opus_001_notes.log
|
|
320
|
+
- examples/16_writers_room/prompts/writer.md
|
|
321
|
+
- examples/16_writers_room/room.rb
|
|
322
|
+
- examples/16_writers_room/tools.rb
|
|
323
|
+
- examples/16_writers_room/writer.rb
|
|
324
|
+
- examples/16_writers_room/writers_room.rb
|
|
325
325
|
- examples/README.md
|
|
326
326
|
- examples/prompts/assistant.md
|
|
327
327
|
- examples/prompts/billing.md
|
|
@@ -359,19 +359,10 @@ files:
|
|
|
359
359
|
- lib/generators/robot_lab/templates/routing_robot.rb.tt
|
|
360
360
|
- lib/generators/robot_lab/templates/thread_model.rb.tt
|
|
361
361
|
- lib/robot_lab.rb
|
|
362
|
-
- lib/robot_lab/adapters/anthropic.rb
|
|
363
|
-
- lib/robot_lab/adapters/base.rb
|
|
364
|
-
- lib/robot_lab/adapters/gemini.rb
|
|
365
|
-
- lib/robot_lab/adapters/openai.rb
|
|
366
|
-
- lib/robot_lab/adapters/registry.rb
|
|
367
362
|
- lib/robot_lab/ask_user.rb
|
|
368
363
|
- lib/robot_lab/config.rb
|
|
369
364
|
- lib/robot_lab/config/defaults.yml
|
|
370
365
|
- lib/robot_lab/error.rb
|
|
371
|
-
- lib/robot_lab/errors.rb
|
|
372
|
-
- lib/robot_lab/history/active_record_adapter.rb
|
|
373
|
-
- lib/robot_lab/history/config.rb
|
|
374
|
-
- lib/robot_lab/history/thread_manager.rb
|
|
375
366
|
- lib/robot_lab/mcp/client.rb
|
|
376
367
|
- lib/robot_lab/mcp/server.rb
|
|
377
368
|
- lib/robot_lab/mcp/transports/base.rb
|
|
@@ -386,9 +377,12 @@ files:
|
|
|
386
377
|
- lib/robot_lab/rails/engine.rb
|
|
387
378
|
- lib/robot_lab/rails/railtie.rb
|
|
388
379
|
- lib/robot_lab/robot.rb
|
|
380
|
+
- lib/robot_lab/robot/bus_messaging.rb
|
|
381
|
+
- lib/robot_lab/robot/mcp_management.rb
|
|
382
|
+
- lib/robot_lab/robot/template_rendering.rb
|
|
389
383
|
- lib/robot_lab/robot_message.rb
|
|
390
384
|
- lib/robot_lab/robot_result.rb
|
|
391
|
-
- lib/robot_lab/
|
|
385
|
+
- lib/robot_lab/run_config.rb
|
|
392
386
|
- lib/robot_lab/state_proxy.rb
|
|
393
387
|
- lib/robot_lab/streaming/context.rb
|
|
394
388
|
- lib/robot_lab/streaming/events.rb
|
|
@@ -398,6 +392,7 @@ files:
|
|
|
398
392
|
- lib/robot_lab/tool_config.rb
|
|
399
393
|
- lib/robot_lab/tool_manifest.rb
|
|
400
394
|
- lib/robot_lab/user_message.rb
|
|
395
|
+
- lib/robot_lab/utils.rb
|
|
401
396
|
- lib/robot_lab/version.rb
|
|
402
397
|
- lib/robot_lab/waiter.rb
|
|
403
398
|
- mkdocs.yml
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# Anthropic Adapter
|
|
2
|
-
|
|
3
|
-
Adapter for Claude models via Anthropic API.
|
|
4
|
-
|
|
5
|
-
## Class: `RobotLab::Adapters::Anthropic`
|
|
6
|
-
|
|
7
|
-
```ruby
|
|
8
|
-
# Automatically used for Claude models
|
|
9
|
-
robot = RobotLab.build do
|
|
10
|
-
model "claude-sonnet-4"
|
|
11
|
-
end
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Supported Models
|
|
15
|
-
|
|
16
|
-
| Model | Description |
|
|
17
|
-
|-------|-------------|
|
|
18
|
-
| `claude-sonnet-4` | Latest Sonnet (recommended) |
|
|
19
|
-
| `claude-opus-4` | Most capable model |
|
|
20
|
-
| `claude-3-5-sonnet-latest` | Claude 3.5 Sonnet |
|
|
21
|
-
| `claude-3-5-haiku-latest` | Fast, efficient model |
|
|
22
|
-
|
|
23
|
-
## Configuration
|
|
24
|
-
|
|
25
|
-
### API Key
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
export ANTHROPIC_API_KEY="sk-ant-api03-..."
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Options
|
|
32
|
-
|
|
33
|
-
```ruby
|
|
34
|
-
RobotLab.configure do |config|
|
|
35
|
-
config.adapter_options = {
|
|
36
|
-
anthropic: {
|
|
37
|
-
base_url: "https://api.anthropic.com",
|
|
38
|
-
api_version: "2024-01-01",
|
|
39
|
-
timeout: 120,
|
|
40
|
-
max_tokens: 4096
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
end
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Features
|
|
47
|
-
|
|
48
|
-
### Streaming
|
|
49
|
-
|
|
50
|
-
```ruby
|
|
51
|
-
result = robot.run(state: state) do |event|
|
|
52
|
-
case event
|
|
53
|
-
when :text_delta
|
|
54
|
-
print event.text
|
|
55
|
-
when :tool_call
|
|
56
|
-
puts "Calling: #{event.name}"
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Tool Use
|
|
62
|
-
|
|
63
|
-
Tools are automatically converted to Anthropic's format:
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
robot = RobotLab.build do
|
|
67
|
-
model "claude-sonnet-4"
|
|
68
|
-
|
|
69
|
-
tool :search do
|
|
70
|
-
description "Search the database"
|
|
71
|
-
parameter :query, type: :string, required: true
|
|
72
|
-
handler { |query:, **_| Database.search(query) }
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Extended Thinking
|
|
78
|
-
|
|
79
|
-
For complex reasoning tasks:
|
|
80
|
-
|
|
81
|
-
```ruby
|
|
82
|
-
robot = RobotLab.build do
|
|
83
|
-
model "claude-sonnet-4"
|
|
84
|
-
# Extended thinking is automatically enabled for supported models
|
|
85
|
-
end
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Response Format
|
|
89
|
-
|
|
90
|
-
```ruby
|
|
91
|
-
{
|
|
92
|
-
content: [TextMessage, ...],
|
|
93
|
-
tool_calls: [ToolCallMessage, ...],
|
|
94
|
-
usage: {
|
|
95
|
-
input_tokens: 150,
|
|
96
|
-
output_tokens: 250,
|
|
97
|
-
cache_creation_input_tokens: 0,
|
|
98
|
-
cache_read_input_tokens: 0
|
|
99
|
-
},
|
|
100
|
-
stop_reason: "end_turn"
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Error Handling
|
|
105
|
-
|
|
106
|
-
```ruby
|
|
107
|
-
begin
|
|
108
|
-
result = robot.run(state: state)
|
|
109
|
-
rescue RobotLab::Adapters::RateLimitError => e
|
|
110
|
-
sleep(e.retry_after)
|
|
111
|
-
retry
|
|
112
|
-
rescue RobotLab::Adapters::APIError => e
|
|
113
|
-
logger.error("Anthropic API error: #{e.message}")
|
|
114
|
-
end
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## See Also
|
|
118
|
-
|
|
119
|
-
- [Adapters Overview](index.md)
|
|
120
|
-
- [Streaming Guide](../../guides/streaming.md)
|
|
121
|
-
- [Anthropic API Documentation](https://docs.anthropic.com/)
|