llm.rb 11.2.0 → 11.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +85 -11
  3. data/README.md +137 -144
  4. data/lib/llm/a2a.rb +2 -2
  5. data/lib/llm/active_record/acts_as_agent.rb +7 -0
  6. data/lib/llm/active_record/acts_as_llm.rb +7 -0
  7. data/lib/llm/agent.rb +26 -5
  8. data/lib/llm/cost.rb +1 -1
  9. data/lib/llm/error.rb +4 -0
  10. data/lib/llm/function/fiber_group.rb +2 -2
  11. data/lib/llm/function/task_group.rb +2 -2
  12. data/lib/llm/function/thread_group.rb +3 -3
  13. data/lib/llm/pipe.rb +1 -1
  14. data/lib/llm/providers/anthropic/error_handler.rb +2 -0
  15. data/lib/llm/providers/anthropic/request_adapter.rb +1 -1
  16. data/lib/llm/providers/bedrock/error_handler.rb +1 -1
  17. data/lib/llm/providers/bedrock/request_adapter/completion.rb +5 -5
  18. data/lib/llm/providers/bedrock/request_adapter.rb +3 -3
  19. data/lib/llm/providers/bedrock/response_adapter/completion.rb +2 -2
  20. data/lib/llm/providers/bedrock/response_adapter.rb +2 -2
  21. data/lib/llm/providers/deepseek/request_adapter.rb +1 -1
  22. data/lib/llm/providers/google/error_handler.rb +2 -0
  23. data/lib/llm/providers/google/request_adapter.rb +1 -1
  24. data/lib/llm/providers/ollama/error_handler.rb +2 -0
  25. data/lib/llm/providers/ollama/request_adapter.rb +1 -1
  26. data/lib/llm/providers/openai/error_handler.rb +2 -0
  27. data/lib/llm/providers/openai/request_adapter.rb +1 -1
  28. data/lib/llm/registry.rb +2 -2
  29. data/lib/llm/response.rb +1 -1
  30. data/lib/llm/schema/object.rb +1 -1
  31. data/lib/llm/stream.rb +1 -1
  32. data/lib/llm/tool.rb +2 -2
  33. data/lib/llm/transport/http.rb +2 -2
  34. data/lib/llm/transport/persistent_http.rb +1 -1
  35. data/lib/llm/transport/response/http.rb +1 -1
  36. data/lib/llm/utils.rb +1 -1
  37. data/lib/llm/version.rb +1 -1
  38. data/lib/llm.rb +11 -8
  39. data/llm.gemspec +11 -9
  40. data/resources/deepdive.md +432 -0
  41. metadata +28 -15
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @!parse
4
+ # module ::ActiveRecord
5
+ # class Base
6
+ # end
7
+ # end
8
+
3
9
  module LLM::ActiveRecord
4
10
  ##
5
11
  # ActiveRecord integration for persisting {LLM::Agent LLM::Agent} state.
@@ -134,4 +140,5 @@ module LLM::ActiveRecord
134
140
  end
135
141
  end
136
142
 
143
+ # @!parse ::ActiveRecord::Base.extend(LLM::ActiveRecord::ActsAsAgent)
137
144
  ::ActiveRecord::Base.extend(LLM::ActiveRecord::ActsAsAgent)
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @!parse
4
+ # module ::ActiveRecord
5
+ # class Base
6
+ # end
7
+ # end
8
+
3
9
  module LLM::ActiveRecord
4
10
  ##
5
11
  # ActiveRecord integration for persisting {LLM::Context LLM::Context} state.
@@ -222,4 +228,5 @@ module LLM::ActiveRecord
222
228
  end
223
229
  end
224
230
 
231
+ # @!parse ::ActiveRecord::Base.extend(LLM::ActiveRecord::ActsAsLLM)
225
232
  ::ActiveRecord::Base.extend(LLM::ActiveRecord::ActsAsLLM)
data/lib/llm/agent.rb CHANGED
@@ -72,7 +72,11 @@ module LLM
72
72
  # Returns the current skills when no argument is provided
73
73
  def self.skills(*skills, &block)
74
74
  return @skills if skills.empty? && !block
75
- @skills = block || skills.flatten
75
+ if skills.size == 1 and skills.grep(Symbol).any?
76
+ @skills = skills.first
77
+ else
78
+ @skills = block || skills.flatten
79
+ end
76
80
  end
77
81
 
78
82
  ##
@@ -160,18 +164,35 @@ module LLM
160
164
  ##
161
165
  # Set or get the tool names that require confirmation before they can run.
162
166
  #
167
+ # When a single Symbol is given, it is stored as-is and resolved at
168
+ # initialization time by calling the method with that name on the agent
169
+ # instance. This allows dynamic tool confirmation lists.
170
+ #
171
+ # @example
172
+ # class MyAgent < LLM::Agent
173
+ # confirm :tools_that_need_confirmation
174
+ #
175
+ # def tools_that_need_confirmation
176
+ # some_condition ? %w[delete destroy] : %w[delete]
177
+ # end
178
+ # end
179
+ #
163
180
  # @param [String, Symbol, Array<String, Symbol>, Proc] tool_names
164
181
  # One or more tool names.
165
182
  # @param [Proc] block
166
183
  # An optional, lazy-evaluated Proc
167
- # @return [Array<String>, Proc, nil]
184
+ # @return [Array<String>, Proc, Symbol, nil]
168
185
  def self.confirm(*tool_names, &block)
169
186
  return @confirm if tool_names.empty? && !block
170
- @confirm = block || tool_names.flatten.map(&:to_s)
187
+ if tool_names.size == 1 && tool_names.grep(Symbol).any?
188
+ @confirm = tool_names.first
189
+ else
190
+ @confirm = block || tool_names.flatten.map(&:to_s)
191
+ end
171
192
  end
172
193
 
173
194
  ##
174
- # @param [LLM::Provider] provider
195
+ # @param [LLM::Provider] llm
175
196
  # A provider
176
197
  # @param [Hash] params
177
198
  # The parameters to maintain throughout the conversation.
@@ -190,7 +211,7 @@ module LLM
190
211
  fields_ivar = %i[tracer concurrency instructions confirm]
191
212
  fields.each do |field|
192
213
  resolvable = params.key?(field) ? params.delete(field) : self.class.public_send(field)
193
- resolve_symbol = !%i[concurrency confirm].include?(field)
214
+ resolve_symbol = !%i[concurrency].include?(field)
194
215
  resolved = resolvable != nil ? resolve_option(self, resolvable, resolve_symbol:) : resolvable
195
216
  resolved = [*resolved].map(&:to_s) if field == :confirm && resolved
196
217
  if field == :model
data/lib/llm/cost.rb CHANGED
@@ -37,7 +37,7 @@ class LLM::Cost < Struct.new(
37
37
  )
38
38
  ##
39
39
  # Build a cost breakdown from token usage and model pricing.
40
- # @param [LLM::Context]
40
+ # @param [LLM::Context] ctx
41
41
  # Context used to resolve provider, model, and token usage
42
42
  # @return [LLM::Cost]
43
43
  def self.from(ctx)
data/lib/llm/error.rb CHANGED
@@ -35,6 +35,10 @@ module LLM
35
35
  # HTTPServerError
36
36
  ServerError = Class.new(Error)
37
37
 
38
+ ##
39
+ # HTTPNotFound
40
+ NotFoundError = Class.new(Error)
41
+
38
42
  ##
39
43
  # When an given an input object that is not understood
40
44
  FormatError = Class.new(Error)
@@ -3,7 +3,7 @@
3
3
  class LLM::Function
4
4
  ##
5
5
  # The {LLM::Function::FiberGroup} class wraps an array of
6
- # {Fiber} objects that are running {LLM::Function} calls
6
+ # `Fiber` objects that are running {LLM::Function} calls
7
7
  # concurrently using scheduler-backed fibers.
8
8
  #
9
9
  # This class provides the same interface as {LLM::Function::ThreadGroup}
@@ -26,7 +26,7 @@ class LLM::Function
26
26
  # of fiber objects.
27
27
  #
28
28
  # @param [Array<Fiber>] fibers
29
- # An array of fibers, each running an {LLM::Function#spawn_fiber} call.
29
+ # An array of fibers, each running an `LLM::Function#spawn_fiber` call.
30
30
  #
31
31
  # @return [LLM::Function::FiberGroup]
32
32
  # Returns a new fiber group.
@@ -3,7 +3,7 @@
3
3
  class LLM::Function
4
4
  ##
5
5
  # The {LLM::Function::TaskGroup} class wraps an array of
6
- # {Async::Task} objects that are running {LLM::Function} calls
6
+ # `Async::Task` objects that are running {LLM::Function} calls
7
7
  # concurrently using the async gem.
8
8
  #
9
9
  # This class provides the same interface as {LLM::Function::ThreadGroup}
@@ -27,7 +27,7 @@ class LLM::Function
27
27
  # of async task objects.
28
28
  #
29
29
  # @param [Array<Async::Task>] tasks
30
- # An array of async tasks, each running an {LLM::Function#spawn_async} call.
30
+ # An array of async tasks, each running an `LLM::Function#spawn_async` call.
31
31
  #
32
32
  # @return [LLM::Function::TaskGroup]
33
33
  # Returns a new task group.
@@ -3,7 +3,7 @@
3
3
  class LLM::Function
4
4
  ##
5
5
  # The {LLM::Function::ThreadGroup} class wraps an array of
6
- # {Thread} objects that are running {LLM::Function} calls
6
+ # `Thread` objects that are running {LLM::Function} calls
7
7
  # concurrently. It provides a single {#wait} method that
8
8
  # collects the {LLM::Function::Return} values from those
9
9
  # threads.
@@ -27,11 +27,11 @@ class LLM::Function
27
27
  class ThreadGroup
28
28
  ##
29
29
  # Creates a new {LLM::Function::ThreadGroup} from an array
30
- # of {Thread} objects.
30
+ # of `Thread` objects.
31
31
  #
32
32
  # @param [Array<Thread>] threads
33
33
  # An array of threads, each running an {LLM::Function#spawn}
34
- # call. The thread's {Thread#value} will be an
34
+ # call. The thread's `Thread#value` will be an
35
35
  # {LLM::Function::Return}.
36
36
  #
37
37
  # @return [LLM::Function::ThreadGroup]
data/lib/llm/pipe.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module LLM
4
4
  ##
5
5
  # The {LLM::Pipe LLM::Pipe} class wraps a pair of IO objects created by
6
- # {IO.pipe}. It is used by llm.rb internals to manage process and stream
6
+ # `IO.pipe`. It is used by llm.rb internals to manage process and stream
7
7
  # communication through one small interface.
8
8
  class Pipe
9
9
  ##
@@ -49,6 +49,8 @@ class LLM::Anthropic
49
49
  LLM::UnauthorizedError.new("Authentication error").tap { _1.response = res }
50
50
  elsif res.rate_limited?
51
51
  LLM::RateLimitError.new("Too many requests").tap { _1.response = res }
52
+ elsif res.not_found?
53
+ LLM::NotFoundError.new("Server response: not found (404)").tap { _1.response = res }
52
54
  else
53
55
  LLM::Error.new("Unexpected response").tap { _1.response = res }
54
56
  end
@@ -28,7 +28,7 @@ class LLM::Anthropic
28
28
  private
29
29
 
30
30
  ##
31
- # @param [Hash] params
31
+ # @param [Array<LLM::Function>] tools
32
32
  # @return [Hash]
33
33
  def adapt_tools(tools)
34
34
  return {} unless tools&.any?
@@ -53,7 +53,7 @@ class LLM::Bedrock
53
53
  elsif res.rate_limited?
54
54
  LLM::RateLimitError.new(message).tap { _1.response = res }
55
55
  elsif res.not_found?
56
- LLM::Error.new("Bedrock model not found: #{message}").tap { _1.response = res }
56
+ LLM::NotFoundError.new("Server response: not found (404)").tap { _1.response = res }
57
57
  else
58
58
  LLM::Error.new(message).tap { _1.response = res }
59
59
  end
@@ -5,11 +5,11 @@ module LLM::Bedrock::RequestAdapter
5
5
  # Adapts a single message to Bedrock Converse content blocks.
6
6
  #
7
7
  # Bedrock Converse content blocks include:
8
- # - {text: "..."}
9
- # - {image: {format: "png", source: {bytes: "..."}}}
10
- # - {document: {format: "pdf", name: "...", source: {bytes: "..."}}}
11
- # - {toolUse: {toolUseId: "...", name: "...", input: {...}}}
12
- # - {toolResult: {toolUseId: "...", content: [{text: "..."}]}}
8
+ # - { text: "..." }
9
+ # - { image: { format: "png", source: { bytes: "..." } } }
10
+ # - { document: { format: "pdf", name: "...", source: { bytes: "..." } } }
11
+ # - { toolUse: { toolUseId: "...", name: "...", input: ... } }
12
+ # - {toolResult: {toolUseId: "...", content: [{ text: "..." }]}}
13
13
  #
14
14
  # @api private
15
15
  class Completion
@@ -5,10 +5,10 @@ class LLM::Bedrock
5
5
  # Adapts llm.rb internal message format to Bedrock Converse API format.
6
6
  #
7
7
  # Bedrock Converse uses:
8
- # - system: [{text: "..."}] (top-level, separate from messages)
9
- # - messages: [{role: "user"|"assistant", content: [{...}, ...]}]
8
+ # - system: `[ { text: "..." } ]` (top-level, separate from messages)
9
+ # - messages: `[ { role: "user"|"assistant", content: [ ... ] } ]`
10
10
  # - Content blocks: text, image, document, toolUse, toolResult
11
- # - toolConfig: {tools: [{toolSpec: {name:, description:, inputSchema: {json: ...}}}]}
11
+ # - toolConfig: `{ tools: [ { toolSpec: { name:, description:, inputSchema: { json: ... } } } ] }`
12
12
  #
13
13
  # @api private
14
14
  module RequestAdapter
@@ -8,9 +8,9 @@ module LLM::Bedrock::ResponseAdapter
8
8
  # {
9
9
  # "output" => {"message" => {
10
10
  # "role" => "assistant",
11
- # "content" => [{"text" => "..."}, {"toolUse" => {...}}]
11
+ # "content" => `[ { "text" => "..." }, { "toolUse" => ... } ]`
12
12
  # }},
13
- # "usage" => {"inputTokens" => N, "outputTokens" => N},
13
+ # "usage" => `{ "inputTokens" => N, "outputTokens" => N }`,
14
14
  # "modelId" => "anthropic.claude-sonnet-4-20250514-v1:0",
15
15
  # "stopReason" => "end_turn"
16
16
  # }
@@ -6,8 +6,8 @@ class LLM::Bedrock
6
6
  #
7
7
  # Bedrock Converse returns:
8
8
  # {
9
- # output: {message: {role: "assistant", content: [{...}, ...]}},
10
- # usage: {inputTokens: N, outputTokens: N},
9
+ # output: `{ message: { role: "assistant", content: [ ... ] } }`,
10
+ # usage: `{ inputTokens: N, outputTokens: N }`,
11
11
  # modelId: "anthropic.claude-...",
12
12
  # stopReason: "end_turn" | "tool_use" | "max_tokens" | ...
13
13
  # }
@@ -18,7 +18,7 @@ class LLM::DeepSeek
18
18
  private
19
19
 
20
20
  ##
21
- # @param [Hash] params
21
+ # @param [Array<LLM::Function>] tools
22
22
  # @return [Hash]
23
23
  def adapt_tools(tools)
24
24
  (tools.nil? || tools.empty?) ? {} : {tools: tools.map { _1.adapt(self) }}
@@ -60,6 +60,8 @@ class LLM::Google
60
60
  end
61
61
  elsif res.rate_limited?
62
62
  LLM::RateLimitError.new("Too many requests").tap { _1.response = res }
63
+ elsif res.not_found?
64
+ LLM::NotFoundError.new("Server response: not found (404)").tap { _1.response = res }
63
65
  else
64
66
  LLM::Error.new("Unexpected response").tap { _1.response = res }
65
67
  end
@@ -29,7 +29,7 @@ class LLM::Google
29
29
  end
30
30
 
31
31
  ##
32
- # @param [Hash] params
32
+ # @param [Array<LLM::Function>] tools
33
33
  # @return [Hash]
34
34
  def adapt_tools(tools)
35
35
  return {} unless tools&.any?
@@ -49,6 +49,8 @@ class LLM::Ollama
49
49
  LLM::UnauthorizedError.new("Authentication error").tap { _1.response = res }
50
50
  elsif res.rate_limited?
51
51
  LLM::RateLimitError.new("Too many requests").tap { _1.response = res }
52
+ elsif res.not_found?
53
+ LLM::NotFoundError.new("Server response: not found (404)").tap { _1.response = res }
52
54
  else
53
55
  LLM::Error.new("Unexpected response").tap { _1.response = res }
54
56
  end
@@ -19,7 +19,7 @@ class LLM::Ollama
19
19
  private
20
20
 
21
21
  ##
22
- # @param [Hash] params
22
+ # @param [Array<LLM::Function>] tools
23
23
  # @return [Hash]
24
24
  def adapt_tools(tools)
25
25
  return {} unless tools&.any?
@@ -55,6 +55,8 @@ class LLM::OpenAI
55
55
  LLM::UnauthorizedError.new("Authentication error").tap { _1.response = res }
56
56
  elsif res.rate_limited?
57
57
  LLM::RateLimitError.new("Too many requests").tap { _1.response = res }
58
+ elsif res.not_found?
59
+ LLM::NotFoundError.new("Server response: not found (404)").tap { _1.response = res }
58
60
  else
59
61
  error = body["error"] || {}
60
62
  case error["type"]
@@ -42,7 +42,7 @@ class LLM::OpenAI
42
42
  end
43
43
 
44
44
  ##
45
- # @param [Hash] params
45
+ # @param [Array<LLM::Function>] tools
46
46
  # @return [Hash]
47
47
  def adapt_tools(tools)
48
48
  if tools.nil? || tools.empty?
data/lib/llm/registry.rb CHANGED
@@ -12,7 +12,7 @@ class LLM::Registry
12
12
  ##
13
13
  # @raise [LLM::Error]
14
14
  # Might raise an error
15
- # @param [Symbol]
15
+ # @param [Symbol] name
16
16
  # A provider name
17
17
  # @return [LLM::Registry]
18
18
  def self.for(name)
@@ -71,7 +71,7 @@ class LLM::Registry
71
71
  end
72
72
 
73
73
  ##
74
- # Similar to #{find} but returns the block's return value
74
+ # Similar to `#find` but returns the block's return value
75
75
  # @return [Object, nil]
76
76
  def find_map(pair)
77
77
  result = nil
data/lib/llm/response.rb CHANGED
@@ -14,7 +14,7 @@ module LLM
14
14
  # through {#res}. When the default net/http transport is in use,
15
15
  # {LLM::Transport::Response::HTTP
16
16
  # LLM::Transport::Response::HTTP} keeps the
17
- # original {Net::HTTPResponse Net::HTTPResponse} available through
17
+ # original `Net::HTTPResponse` available through
18
18
  # its own {LLM::Transport::Response::HTTP#res #res}.
19
19
  class Response
20
20
  require "json"
@@ -12,7 +12,7 @@ class LLM::Schema
12
12
  attr_reader :properties
13
13
 
14
14
  ##
15
- # @param params [Hash]
15
+ # @param [Hash] properties
16
16
  # A hash of properties
17
17
  # @return [LLM::Schema::Object]
18
18
  def initialize(properties)
data/lib/llm/stream.rb CHANGED
@@ -15,7 +15,7 @@ module LLM
15
15
  # therefore block streaming progress and should generally return as
16
16
  # quickly as possible.
17
17
  #
18
- # The most common callback is {#on_content}, which also maps to {#<<}.
18
+ # The most common callback is {#on_content}, which also maps to `#<<`.
19
19
  # Providers may also call {#on_reasoning_content} and {#on_tool_call} when
20
20
  # that data is available. Runtime features such as context compaction may
21
21
  # also emit lifecycle callbacks like {#on_transform} or {#on_compaction}.
data/lib/llm/tool.rb CHANGED
@@ -63,7 +63,7 @@ class LLM::Tool
63
63
  ##
64
64
  # @param [LLM::A2A] a2a
65
65
  # The A2A client that will execute the tool call
66
- # @param [LLM::A2A::Card::Skill]
66
+ # @param [LLM::A2A::Card::Skill] skill
67
67
  # An A2A tool
68
68
  # @return [Class<LLM::Tool>]
69
69
  # Returns a subclass of LLM::Tool
@@ -124,7 +124,7 @@ class LLM::Tool
124
124
 
125
125
  ##
126
126
  # Registers the tool as a function when inherited
127
- # @param [Class] klass The subclass
127
+ # @param [Class] tool The subclass
128
128
  # @return [void]
129
129
  def self.inherited(tool)
130
130
  LLM.lock(:inherited) do
@@ -5,7 +5,7 @@ require "net/http"
5
5
  class LLM::Transport
6
6
  ##
7
7
  # The {LLM::Transport::HTTP LLM::Transport::HTTP} transport is the
8
- # built-in adapter for Ruby's {Net::HTTP Net::HTTP}. It manages
8
+ # built-in adapter for Ruby's `Net::HTTP`. It manages
9
9
  # transient HTTP connections, tracks active requests by owner, and
10
10
  # interrupts in-flight requests when needed.
11
11
  #
@@ -69,7 +69,7 @@ class LLM::Transport
69
69
 
70
70
  ##
71
71
  # Performs a request on the current HTTP transport.
72
- # Accepts both {Net::HTTPRequest} and {LLM::Transport::Request}.
72
+ # Accepts both `Net::HTTPRequest` and {LLM::Transport::Request}.
73
73
  #
74
74
  # @param [Net::HTTPRequest, LLM::Transport::Request] request
75
75
  # @param [Fiber] owner
@@ -81,7 +81,7 @@ class LLM::Transport
81
81
 
82
82
  ##
83
83
  # Performs a request on the current HTTP transport.
84
- # Accepts both {Net::HTTPRequest} and {LLM::Transport::Request}.
84
+ # Accepts both `Net::HTTPRequest` and {LLM::Transport::Request}.
85
85
  #
86
86
  # @param [Net::HTTPRequest, LLM::Transport::Request] request
87
87
  # @param [Fiber] owner
@@ -3,7 +3,7 @@
3
3
  class LLM::Transport::Response
4
4
  ##
5
5
  # {LLM::Transport::Response::HTTP LLM::Transport::Response::HTTP}
6
- # adapts a {Net::HTTPResponse Net::HTTPResponse} to the
6
+ # adapts a `Net::HTTPResponse` to the
7
7
  # {LLM::Transport::Response LLM::Transport::Response} interface.
8
8
  #
9
9
  # This is the default wrapper for responses produced by the built-in
data/lib/llm/utils.rb CHANGED
@@ -45,7 +45,7 @@ module LLM
45
45
  # Returns the Ruby module or class name for an object.
46
46
  #
47
47
  # This bypasses overridden `#name` implementations by binding
48
- # {Module#name} directly.
48
+ # `Module#name` directly.
49
49
  #
50
50
  # @param [Module] obj
51
51
  # @return [String, nil]
data/lib/llm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LLM
4
- VERSION = "11.2.0"
4
+ VERSION = "11.3.1"
5
5
  end
data/lib/llm.rb CHANGED
@@ -181,16 +181,19 @@ module LLM
181
181
  end
182
182
 
183
183
  ##
184
- # @param [Hash, nil] stdio
185
- # @option stdio [Array<String>] :argv
184
+ # @param [Hash] opts
185
+ # MCP client options
186
+ # @option opts [Hash, nil] :stdio
187
+ # Standard I/O transport options
188
+ # @option opts [Array<String>] :stdio/:argv
186
189
  # The command to run for the MCP process
187
- # @option stdio [Hash] :env
190
+ # @option opts [Hash] :stdio/:env
188
191
  # The environment variables to set for the MCP process
189
- # @option stdio [String, nil] :cwd
192
+ # @option opts [String, nil] :stdio/:cwd
190
193
  # The working directory for the MCP process
191
194
  # @return [LLM::MCP]
192
- def mcp(**)
193
- LLM::MCP.new(**)
195
+ def mcp(**opts)
196
+ LLM::MCP.new(**opts)
194
197
  end
195
198
 
196
199
  ##
@@ -234,7 +237,7 @@ module LLM
234
237
  ##
235
238
  # Provides a thread-safe lock
236
239
  # @param [Symbol] name The name of the lock
237
- # @param [Proc] & The block to execute within the lock
240
+ # @param [Proc] block The block to execute within the lock
238
241
  # @return [void]
239
- def lock(name, &) = @monitors[name].synchronize(&)
242
+ def lock(name, &block) = @monitors[name].synchronize(&block)
240
243
  end
data/llm.gemspec CHANGED
@@ -5,12 +5,12 @@ require_relative "lib/llm/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "llm.rb"
7
7
  spec.version = LLM::VERSION
8
- spec.authors = ["Antar Azri", "0x1eef", "Christos Maris", "Rodrigo Serrano"]
9
- spec.email = ["azantar@proton.me", "0x1eef@hardenedbsd.org"]
8
+ spec.authors = ["Robert (0x1eef)", "Antar Azri", "Rodrigo Serrano"]
9
+ spec.email = ["robert@r.uby.dev"]
10
10
 
11
- spec.summary = "Ruby's most capable AI runtime"
11
+ spec.summary = "Ruby's capable AI runtime"
12
12
  spec.description = <<~DESC
13
- llm.rb is Ruby's most capable AI runtime.
13
+ llm.rb is Ruby's capable AI runtime.
14
14
 
15
15
  It runs on Ruby's standard library by default. loads optional pieces
16
16
  only when needed, and offers a single runtime for providers, agents,
@@ -28,23 +28,24 @@ Gem::Specification.new do |spec|
28
28
  spec.license = "0BSD"
29
29
  spec.required_ruby_version = ">= 3.3.0"
30
30
 
31
- spec.homepage = "https://llmrb.github.io"
31
+ spec.homepage = "https://r.uby.dev/llm/"
32
32
  spec.metadata["homepage_uri"] = spec.homepage
33
- spec.metadata["source_code_uri"] = "https://github.com/llmrb/llm.rb"
34
- spec.metadata["documentation_uri"] = "https://llmrb.github.io/llm.rb"
35
- spec.metadata["changelog_uri"] = "https://0x1eef.github.io/x/llm.rb/file.CHANGELOG.html"
33
+ spec.metadata["source_code_uri"] = "https://github.com/r-uby-dev/llm.rb"
34
+ spec.metadata["documentation_uri"] = spec.homepage
35
+ spec.metadata["changelog_uri"] = "https://r.uby.dev/api-docs/llm.rb/file.CHANGELOG.html"
36
36
 
37
37
  spec.files = Dir[
38
38
  "README.md", "LICENSE",
39
39
  "lib/*.rb", "lib/**/*.rb",
40
40
  "data/*.json", "CHANGELOG.md",
41
+ "resources/deepdive.md",
41
42
  "llm.gemspec"
42
43
  ]
43
44
  spec.require_paths = ["lib"]
44
45
 
45
46
  spec.add_development_dependency "webmock", "~> 3.24.0"
46
47
  spec.add_development_dependency "yard", "~> 0.9.37"
47
- spec.add_development_dependency "kramdown", "~> 2.4"
48
+ spec.add_development_dependency "redcarpet", "~> 3.6"
48
49
  spec.add_development_dependency "webrick", "~> 1.8"
49
50
  spec.add_development_dependency "test-cmd.rb", "~> 0.12.0"
50
51
  spec.add_development_dependency "rake", "~> 13.0"
@@ -60,4 +61,5 @@ Gem::Specification.new do |spec|
60
61
  spec.add_development_dependency "sqlite3", "~> 2.0"
61
62
  spec.add_development_dependency "xchan.rb", "~> 0.20"
62
63
  spec.add_development_dependency "pg", "~> 1.5"
64
+ spec.add_development_dependency "irb", "~> 1.18"
63
65
  end