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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/README.md +64 -6
  4. data/Rakefile +2 -1
  5. data/docs/api/core/index.md +41 -46
  6. data/docs/api/core/memory.md +200 -154
  7. data/docs/api/core/network.md +13 -3
  8. data/docs/api/core/robot.md +38 -26
  9. data/docs/api/core/state.md +55 -73
  10. data/docs/api/index.md +7 -28
  11. data/docs/api/messages/index.md +35 -20
  12. data/docs/api/messages/text-message.md +67 -21
  13. data/docs/api/messages/tool-call-message.md +80 -41
  14. data/docs/api/messages/tool-result-message.md +119 -50
  15. data/docs/api/messages/user-message.md +48 -24
  16. data/docs/architecture/core-concepts.md +10 -15
  17. data/docs/concepts.md +5 -7
  18. data/docs/examples/index.md +2 -2
  19. data/docs/getting-started/configuration.md +80 -0
  20. data/docs/guides/building-robots.md +10 -9
  21. data/docs/guides/creating-networks.md +49 -0
  22. data/docs/guides/index.md +0 -5
  23. data/docs/guides/rails-integration.md +244 -162
  24. data/docs/guides/streaming.md +118 -138
  25. data/docs/index.md +0 -8
  26. data/examples/03_network.rb +10 -7
  27. data/examples/08_llm_config.rb +40 -11
  28. data/examples/09_chaining.rb +45 -6
  29. data/examples/11_network_introspection.rb +30 -7
  30. data/examples/12_message_bus.rb +1 -1
  31. data/examples/14_rusty_circuit/heckler.rb +14 -8
  32. data/examples/14_rusty_circuit/open_mic.rb +5 -3
  33. data/examples/14_rusty_circuit/scout.rb +14 -31
  34. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +1 -1
  35. data/examples/16_writers_room/display.rb +158 -0
  36. data/examples/16_writers_room/output/.gitignore +2 -0
  37. data/examples/16_writers_room/output/opus_001.md +263 -0
  38. data/examples/16_writers_room/output/opus_001_notes.log +470 -0
  39. data/examples/16_writers_room/prompts/writer.md +37 -0
  40. data/examples/16_writers_room/room.rb +150 -0
  41. data/examples/16_writers_room/tools.rb +162 -0
  42. data/examples/16_writers_room/writer.rb +121 -0
  43. data/examples/16_writers_room/writers_room.rb +162 -0
  44. data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -13
  45. data/lib/robot_lab/memory.rb +8 -32
  46. data/lib/robot_lab/network.rb +13 -20
  47. data/lib/robot_lab/robot/bus_messaging.rb +239 -0
  48. data/lib/robot_lab/robot/mcp_management.rb +88 -0
  49. data/lib/robot_lab/robot/template_rendering.rb +130 -0
  50. data/lib/robot_lab/robot.rb +56 -420
  51. data/lib/robot_lab/run_config.rb +184 -0
  52. data/lib/robot_lab/state_proxy.rb +2 -12
  53. data/lib/robot_lab/task.rb +8 -1
  54. data/lib/robot_lab/utils.rb +39 -0
  55. data/lib/robot_lab/version.rb +1 -1
  56. data/lib/robot_lab.rb +29 -8
  57. data/mkdocs.yml +0 -11
  58. metadata +15 -20
  59. data/docs/api/adapters/anthropic.md +0 -121
  60. data/docs/api/adapters/gemini.md +0 -133
  61. data/docs/api/adapters/index.md +0 -104
  62. data/docs/api/adapters/openai.md +0 -134
  63. data/docs/api/history/active-record-adapter.md +0 -275
  64. data/docs/api/history/config.md +0 -284
  65. data/docs/api/history/index.md +0 -128
  66. data/docs/api/history/thread-manager.md +0 -194
  67. data/docs/guides/history.md +0 -359
  68. data/lib/robot_lab/adapters/anthropic.rb +0 -163
  69. data/lib/robot_lab/adapters/base.rb +0 -85
  70. data/lib/robot_lab/adapters/gemini.rb +0 -193
  71. data/lib/robot_lab/adapters/openai.rb +0 -160
  72. data/lib/robot_lab/adapters/registry.rb +0 -81
  73. data/lib/robot_lab/errors.rb +0 -70
  74. data/lib/robot_lab/history/active_record_adapter.rb +0 -146
  75. data/lib/robot_lab/history/config.rb +0 -115
  76. data/lib/robot_lab/history/thread_manager.rb +0 -93
  77. 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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RobotLab
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.6"
5
5
  end
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
- # Eager load for proper constant resolution
71
- loader.eager_load
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
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/robotic_model.rb
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/)