llm.rb 15.0.0 → 15.0.2
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 +47 -0
- data/README.md +7 -0
- data/lib/llm/active_record/acts_as_agent.rb +1 -1
- data/lib/llm/active_record/acts_as_llm.rb +1 -1
- data/lib/llm/agent.rb +70 -48
- data/lib/llm/context.rb +7 -1
- data/lib/llm/mcp.rb +31 -6
- data/lib/llm/sequel/agent.rb +1 -1
- data/lib/llm/sequel/plugin.rb +1 -1
- data/lib/llm/utils.rb +23 -1
- data/lib/llm/version.rb +1 -1
- data/llm.gemspec +9 -3
- metadata +7 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c86e9ccde2cc0844b5172935bc222c1adf3cda8b0f49e84730179bcc635b2d2b
|
|
4
|
+
data.tar.gz: 60c740c3dc2c20d8b1d86de55ae5ef25eb7bbe5b5b567f3766c059b37520efcc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd1901c5bebd659b242db55ed91ea4f538832c24b4ab119b80f46ae987fc5166823fa70174d9f545c079addd90487eb379b1dfd6eeea2365d045a831b861134e
|
|
7
|
+
data.tar.gz: 5949efbaa7381fb0cab7328e64c08af4022a8b976a24b8b24901c167c67cd060f912a7054956a7942cd7cf67b3f0aa226ad5aec608bcd273bfa1aa25d3ffb5d0
|
data/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,53 @@
|
|
|
15
15
|
|
|
16
16
|
## What's next
|
|
17
17
|
|
|
18
|
+
## v15.0.2
|
|
19
|
+
|
|
20
|
+
Changes since `v15.0.1`.
|
|
21
|
+
|
|
22
|
+
This release fixes a concurrency race in MCP tool calls by
|
|
23
|
+
reference-counting the transport session, so overlapping tool calls
|
|
24
|
+
reuse the running transport instead of racing `start`/`stop`.
|
|
25
|
+
|
|
26
|
+
### Fix
|
|
27
|
+
|
|
28
|
+
* **mcp: fix concurrent MCP tool call race** <br>
|
|
29
|
+
`LLM::MCP` now reference-counts its transport session: the first
|
|
30
|
+
caller starts the transport and the last caller stops it. Concurrent
|
|
31
|
+
or overlapping tool calls reuse the running transport instead of
|
|
32
|
+
racing `start`/`stop`, avoiding "MCP transport is not running" errors
|
|
33
|
+
that could occur with the `async` strategy. An externally started
|
|
34
|
+
transport is never stopped by a borrower.
|
|
35
|
+
|
|
36
|
+
## v15.0.1
|
|
37
|
+
|
|
38
|
+
Changes since `v15.0.0`.
|
|
39
|
+
|
|
40
|
+
This release fixes agent `set` handling of single `Symbol`/`Proc`
|
|
41
|
+
values and resolves ORM options as `Symbol`s through the bound record
|
|
42
|
+
instead of the `LLM::Agent` instance.
|
|
43
|
+
|
|
44
|
+
### Agent
|
|
45
|
+
|
|
46
|
+
* **agent: fix `set (skills|tools): Symbol|Proc`** <br>
|
|
47
|
+
The `skills`, `tools`, `confirm`, and `schema` class accessors now
|
|
48
|
+
consistently resolve a single `Symbol` or `Proc` lazily at agent
|
|
49
|
+
initialization, so `LLM::Agent.set(skills: proc { [...] })` and
|
|
50
|
+
`LLM::Agent.set(tools: :tools)` no longer raise. The `set` family
|
|
51
|
+
shares one `single_callable?` helper rather than each accessor
|
|
52
|
+
duplicating its own logic.
|
|
53
|
+
|
|
54
|
+
### Fix
|
|
55
|
+
|
|
56
|
+
* **orm: resolve a `Symbol` through the bound record** <br>
|
|
57
|
+
When an ORM model using `acts_as_agent` (ActiveRecord), `plugin :agent`
|
|
58
|
+
(Sequel), or `acts_as_llm` / `plugin :llm` configures an option as a
|
|
59
|
+
`Symbol`, that symbol is now resolved on the model instance (or its
|
|
60
|
+
bound record) instead of the `LLM::Agent` instance. The contexts and
|
|
61
|
+
agents built by the wrappers are now bound to the record, so a model like
|
|
62
|
+
`agent.set :tools` with a `tools` method on the record works as
|
|
63
|
+
expected.
|
|
64
|
+
|
|
18
65
|
## v15.0.0
|
|
19
66
|
|
|
20
67
|
Changes since `v14.0.0`.
|
data/README.md
CHANGED
|
@@ -25,6 +25,13 @@ Once you learn the fundamentals, everything else falls into place
|
|
|
25
25
|
naturally. Some features, such as ActiveRecord support, require
|
|
26
26
|
optional dependencies that are opt-in.
|
|
27
27
|
|
|
28
|
+
The best way to learn about llm.rb is to ask [the official chatbot](https://r.uby.dev)
|
|
29
|
+
a question. It is connected to the llm.rb GitHub repository, backed by
|
|
30
|
+
ActiveRecord and uses the builtin MCP feature to connect to GitHub. If
|
|
31
|
+
you want to know more then simply [ask the chatbot](https://r.uby.dev) and
|
|
32
|
+
you should get an answer that is grounded in the source code. It is 100%
|
|
33
|
+
free to use and powered by DeepSeek under the hood.
|
|
34
|
+
|
|
28
35
|
## Install
|
|
29
36
|
|
|
30
37
|
```bash
|
|
@@ -126,7 +126,7 @@ module LLM::ActiveRecord
|
|
|
126
126
|
@ctx ||= begin
|
|
127
127
|
options = self.class.llm_plugin_options
|
|
128
128
|
params = Utils.resolve_options(self, options[:context], EMPTY_HASH).dup
|
|
129
|
-
ctx = self.class.agent.new(llm, params.compact)
|
|
129
|
+
ctx = self.class.agent.new(llm, params.compact.merge(record: self))
|
|
130
130
|
columns = Utils.columns(options)
|
|
131
131
|
data = self[columns[:data_column]]
|
|
132
132
|
if data.nil? || data == ""
|
|
@@ -243,7 +243,7 @@ module LLM::ActiveRecord
|
|
|
243
243
|
options = self.class.llm_plugin_options
|
|
244
244
|
columns = Utils.columns(options)
|
|
245
245
|
params = Utils.resolve_options(self, options[:context], EMPTY_HASH).dup
|
|
246
|
-
ctx = LLM::Context.new(llm, params.compact)
|
|
246
|
+
ctx = LLM::Context.new(llm, params.compact.merge(record: self))
|
|
247
247
|
data = self[columns[:data_column]]
|
|
248
248
|
if data.nil? || data == ""
|
|
249
249
|
ctx
|
data/lib/llm/agent.rb
CHANGED
|
@@ -57,14 +57,16 @@ module LLM
|
|
|
57
57
|
##
|
|
58
58
|
# Ugh :)
|
|
59
59
|
# @api private
|
|
60
|
-
FIELDS = %i[
|
|
60
|
+
FIELDS = %i[record
|
|
61
|
+
name description
|
|
61
62
|
path tool_budget
|
|
62
63
|
retry_budget model
|
|
63
64
|
skills schema
|
|
64
65
|
tracer stream
|
|
65
66
|
tools concurrency
|
|
66
67
|
instructions confirm]
|
|
67
|
-
IVARS = %i[
|
|
68
|
+
IVARS = %i[record
|
|
69
|
+
name description
|
|
68
70
|
path tool_budget
|
|
69
71
|
tracer concurrency
|
|
70
72
|
instructions confirm]
|
|
@@ -169,10 +171,21 @@ module LLM
|
|
|
169
171
|
# @return [String, nil]
|
|
170
172
|
# Returns the current model when no argument is provided
|
|
171
173
|
def self.model(model = nil, &block)
|
|
172
|
-
return @model if model.nil?
|
|
174
|
+
return @model if model.nil? and !block
|
|
173
175
|
@model = block || model
|
|
174
176
|
end
|
|
175
177
|
|
|
178
|
+
##
|
|
179
|
+
# Set or get the default schema
|
|
180
|
+
# @param [#to_json, nil] schema
|
|
181
|
+
# The schema
|
|
182
|
+
# @return [#to_json, nil]
|
|
183
|
+
# Returns the current schema when no argument is provided
|
|
184
|
+
def self.schema(schema = nil, &block)
|
|
185
|
+
return @schema if schema.nil? and !block
|
|
186
|
+
@schema = block || schema
|
|
187
|
+
end
|
|
188
|
+
|
|
176
189
|
##
|
|
177
190
|
# Set or get the default tools
|
|
178
191
|
# @param [Array<LLM::Function>, nil] tools
|
|
@@ -180,11 +193,13 @@ module LLM
|
|
|
180
193
|
# @return [Array<LLM::Function>]
|
|
181
194
|
# Returns the current tools when no argument is provided
|
|
182
195
|
def self.tools(*tools, &block)
|
|
183
|
-
return @tools || [] if tools.empty?
|
|
184
|
-
if
|
|
196
|
+
return @tools || [] if tools.empty? and !block
|
|
197
|
+
if block
|
|
198
|
+
@tools = block
|
|
199
|
+
elsif single_callable?(tools)
|
|
185
200
|
@tools = tools.first
|
|
186
201
|
else
|
|
187
|
-
@tools =
|
|
202
|
+
@tools = tools.flatten
|
|
188
203
|
end
|
|
189
204
|
end
|
|
190
205
|
|
|
@@ -195,23 +210,46 @@ module LLM
|
|
|
195
210
|
# @return [Array<String>, nil]
|
|
196
211
|
# Returns the current skills when no argument is provided
|
|
197
212
|
def self.skills(*skills, &block)
|
|
198
|
-
return @skills if skills.empty?
|
|
199
|
-
if
|
|
213
|
+
return @skills if skills.empty? and !block
|
|
214
|
+
if block
|
|
215
|
+
@skills = block
|
|
216
|
+
elsif single_callable?(skills)
|
|
200
217
|
@skills = skills.first
|
|
201
218
|
else
|
|
202
|
-
@skills =
|
|
219
|
+
@skills = skills.flatten
|
|
203
220
|
end
|
|
204
221
|
end
|
|
205
222
|
|
|
206
223
|
##
|
|
207
|
-
# Set or get the
|
|
208
|
-
#
|
|
209
|
-
#
|
|
210
|
-
#
|
|
211
|
-
#
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
224
|
+
# Set or get the tool names that require confirmation before they can run.
|
|
225
|
+
#
|
|
226
|
+
# When a single Symbol is given, it is stored as-is and resolved at
|
|
227
|
+
# initialization time by calling the method with that name on the agent
|
|
228
|
+
# instance. This allows dynamic tool confirmation lists.
|
|
229
|
+
#
|
|
230
|
+
# @example
|
|
231
|
+
# class MyAgent < LLM::Agent
|
|
232
|
+
# confirm :tools_that_need_confirmation
|
|
233
|
+
#
|
|
234
|
+
# def tools_that_need_confirmation
|
|
235
|
+
# some_condition ? %w[delete destroy] : %w[delete]
|
|
236
|
+
# end
|
|
237
|
+
# end
|
|
238
|
+
#
|
|
239
|
+
# @param [String, Symbol, Array<String, Symbol>, Proc] tool_names
|
|
240
|
+
# One or more tool names.
|
|
241
|
+
# @param [Proc] block
|
|
242
|
+
# An optional, lazy-evaluated Proc
|
|
243
|
+
# @return [Array<String>, Proc, Symbol, nil]
|
|
244
|
+
def self.confirm(*tool_names, &block)
|
|
245
|
+
return @confirm if tool_names.empty? and !block
|
|
246
|
+
if block
|
|
247
|
+
@confirm = block
|
|
248
|
+
elsif single_callable?(tool_names)
|
|
249
|
+
@confirm = tool_names.first
|
|
250
|
+
else
|
|
251
|
+
@confirm = tool_names.flatten.map(&:to_s)
|
|
252
|
+
end
|
|
215
253
|
end
|
|
216
254
|
|
|
217
255
|
##
|
|
@@ -285,36 +323,6 @@ module LLM
|
|
|
285
323
|
@stream = block || stream
|
|
286
324
|
end
|
|
287
325
|
|
|
288
|
-
##
|
|
289
|
-
# Set or get the tool names that require confirmation before they can run.
|
|
290
|
-
#
|
|
291
|
-
# When a single Symbol is given, it is stored as-is and resolved at
|
|
292
|
-
# initialization time by calling the method with that name on the agent
|
|
293
|
-
# instance. This allows dynamic tool confirmation lists.
|
|
294
|
-
#
|
|
295
|
-
# @example
|
|
296
|
-
# class MyAgent < LLM::Agent
|
|
297
|
-
# confirm :tools_that_need_confirmation
|
|
298
|
-
#
|
|
299
|
-
# def tools_that_need_confirmation
|
|
300
|
-
# some_condition ? %w[delete destroy] : %w[delete]
|
|
301
|
-
# end
|
|
302
|
-
# end
|
|
303
|
-
#
|
|
304
|
-
# @param [String, Symbol, Array<String, Symbol>, Proc] tool_names
|
|
305
|
-
# One or more tool names.
|
|
306
|
-
# @param [Proc] block
|
|
307
|
-
# An optional, lazy-evaluated Proc
|
|
308
|
-
# @return [Array<String>, Proc, Symbol, nil]
|
|
309
|
-
def self.confirm(*tool_names, &block)
|
|
310
|
-
return @confirm if tool_names.empty? && !block
|
|
311
|
-
if tool_names.size == 1 && tool_names.grep(Symbol).any?
|
|
312
|
-
@confirm = tool_names.first
|
|
313
|
-
else
|
|
314
|
-
@confirm = block || tool_names.flatten.map(&:to_s)
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
|
|
318
326
|
##
|
|
319
327
|
# Set the file path where an agent's memory
|
|
320
328
|
# can be restored from, and written to.
|
|
@@ -370,6 +378,13 @@ module LLM
|
|
|
370
378
|
end
|
|
371
379
|
end
|
|
372
380
|
|
|
381
|
+
##
|
|
382
|
+
# @api private
|
|
383
|
+
def self.single_callable?(callable)
|
|
384
|
+
callable.size == 1 and (Proc === callable[0] or Symbol === callable[0])
|
|
385
|
+
end
|
|
386
|
+
private_class_method :single_callable?
|
|
387
|
+
|
|
373
388
|
##
|
|
374
389
|
# @param [LLM::Provider] llm
|
|
375
390
|
# A provider
|
|
@@ -389,7 +404,7 @@ module LLM
|
|
|
389
404
|
@llm = llm
|
|
390
405
|
fields, fields_ivar = FIELDS, IVARS
|
|
391
406
|
fields.each do |field|
|
|
392
|
-
resolvable = params.key?(field) ? params.delete(field) : self.class.public_send(field)
|
|
407
|
+
resolvable = params.key?(field) ? params.delete(field) : (self.class.respond_to?(field) ? self.class.public_send(field) : nil)
|
|
393
408
|
resolve_symbol = !%i[concurrency].include?(field)
|
|
394
409
|
resolved = resolvable != nil ? resolve_option(self, resolvable, resolve_symbol:) : resolvable
|
|
395
410
|
resolved = [*resolved].map(&:to_s) if field == :confirm && resolved
|
|
@@ -420,6 +435,13 @@ module LLM
|
|
|
420
435
|
@path
|
|
421
436
|
end
|
|
422
437
|
|
|
438
|
+
##
|
|
439
|
+
# Returns the ORM record this agent is bound to, or nil.
|
|
440
|
+
# @return [Object, nil]
|
|
441
|
+
def record
|
|
442
|
+
@record
|
|
443
|
+
end
|
|
444
|
+
|
|
423
445
|
##
|
|
424
446
|
# Returns the agent's description
|
|
425
447
|
# @return [String, nil]
|
data/lib/llm/context.rb
CHANGED
|
@@ -46,7 +46,7 @@ module LLM
|
|
|
46
46
|
# @api private
|
|
47
47
|
# @return [Array<Symbol>]
|
|
48
48
|
def self.params
|
|
49
|
-
%w[guard retry_budget concurrency transformer compactor]
|
|
49
|
+
%w[guard retry_budget concurrency transformer compactor record]
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
##
|
|
@@ -64,6 +64,11 @@ module LLM
|
|
|
64
64
|
# @return [Symbol]
|
|
65
65
|
attr_reader :mode
|
|
66
66
|
|
|
67
|
+
##
|
|
68
|
+
# Returns the ORM record this context is bound to, or nil.
|
|
69
|
+
# @return [Object, nil]
|
|
70
|
+
attr_reader :record
|
|
71
|
+
|
|
67
72
|
##
|
|
68
73
|
# @param [LLM::Provider] llm
|
|
69
74
|
# A provider
|
|
@@ -95,6 +100,7 @@ module LLM
|
|
|
95
100
|
def initialize(llm, params = {})
|
|
96
101
|
params = {}.merge!(params)
|
|
97
102
|
@llm = llm
|
|
103
|
+
@record = params.delete(:record)
|
|
98
104
|
@mode = params.delete(:mode) || (llm.name == :openai ? :responses : :completions)
|
|
99
105
|
tools = [*params.delete(:tools), *load_skills(params.delete(:skills))]
|
|
100
106
|
@params = {model: llm.default_model, schema: nil}.compact.merge!(params)
|
data/lib/llm/mcp.rb
CHANGED
|
@@ -87,7 +87,10 @@ class LLM::MCP
|
|
|
87
87
|
# @return [LLM::MCP] A new MCP instance
|
|
88
88
|
def initialize(stdio: nil, http: nil, timeout: 30)
|
|
89
89
|
@timeout = timeout
|
|
90
|
-
|
|
90
|
+
@lock = Mutex.new
|
|
91
|
+
@borrowers = 0
|
|
92
|
+
@owned = false
|
|
93
|
+
if stdio and http
|
|
91
94
|
raise ArgumentError, "stdio and http are mutually exclusive"
|
|
92
95
|
elsif stdio
|
|
93
96
|
@command = Command.new(**stdio)
|
|
@@ -125,7 +128,10 @@ class LLM::MCP
|
|
|
125
128
|
# Propagates errors raised by {#start}, the block itself, or {#stop}
|
|
126
129
|
# @return [void]
|
|
127
130
|
def run
|
|
128
|
-
|
|
131
|
+
@lock.synchronize do
|
|
132
|
+
start
|
|
133
|
+
@owned = false
|
|
134
|
+
end
|
|
129
135
|
yield
|
|
130
136
|
ensure
|
|
131
137
|
stop
|
|
@@ -182,13 +188,32 @@ class LLM::MCP
|
|
|
182
188
|
|
|
183
189
|
attr_reader :command, :transport, :timeout
|
|
184
190
|
|
|
191
|
+
##
|
|
192
|
+
# Borrows the transport for the duration of the block.
|
|
193
|
+
#
|
|
194
|
+
# The first borrower starts the transport, concurrent borrowers reuse
|
|
195
|
+
# it, and the last borrower stops it, so overlapping tool calls never
|
|
196
|
+
# race `start`/`stop` and trip over "MCP transport is not running".
|
|
197
|
+
# An externally started transport is never stopped by a borrower.
|
|
198
|
+
# @yield Runs while the transport is running
|
|
199
|
+
# @return [void]
|
|
185
200
|
def with_session
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
201
|
+
@lock.synchronize do
|
|
202
|
+
@borrowers += 1
|
|
203
|
+
unless transport.running?
|
|
204
|
+
start
|
|
205
|
+
@owned = true
|
|
206
|
+
end
|
|
207
|
+
end
|
|
189
208
|
yield
|
|
190
209
|
ensure
|
|
191
|
-
|
|
210
|
+
@lock.synchronize do
|
|
211
|
+
@borrowers -= 1
|
|
212
|
+
if @borrowers.zero? and @owned
|
|
213
|
+
@owned = false
|
|
214
|
+
stop
|
|
215
|
+
end
|
|
216
|
+
end
|
|
192
217
|
end
|
|
193
218
|
|
|
194
219
|
def adapt_content(content)
|
data/lib/llm/sequel/agent.rb
CHANGED
|
@@ -88,7 +88,7 @@ module LLM::Sequel
|
|
|
88
88
|
options = self.class.llm_plugin_options
|
|
89
89
|
columns = Agent::Utils.columns(options)
|
|
90
90
|
params = Agent::Utils.resolve_options(self, options[:context], Agent::EMPTY_HASH).dup
|
|
91
|
-
ctx = self.class.agent.new(llm, params.compact)
|
|
91
|
+
ctx = self.class.agent.new(llm, params.compact.merge(record: self))
|
|
92
92
|
data = self[columns[:data_column]]
|
|
93
93
|
if data.nil? || data == ""
|
|
94
94
|
ctx
|
data/lib/llm/sequel/plugin.rb
CHANGED
|
@@ -343,7 +343,7 @@ module LLM::Sequel
|
|
|
343
343
|
options = self.class.llm_plugin_options
|
|
344
344
|
columns = Utils.columns(options)
|
|
345
345
|
params = Utils.resolve_options(self, options[:context], Plugin::EMPTY_HASH).dup
|
|
346
|
-
ctx = LLM::Context.new(llm, params.compact)
|
|
346
|
+
ctx = LLM::Context.new(llm, params.compact.merge(record: self))
|
|
347
347
|
data = self[columns[:data_column]]
|
|
348
348
|
if data.nil? || data == ""
|
|
349
349
|
ctx
|
data/lib/llm/utils.rb
CHANGED
|
@@ -20,12 +20,34 @@ module LLM
|
|
|
20
20
|
def resolve_option(obj, option, resolve_symbol: true)
|
|
21
21
|
case option
|
|
22
22
|
when Proc then obj.instance_exec(&option)
|
|
23
|
-
when Symbol
|
|
23
|
+
when Symbol
|
|
24
|
+
if resolve_symbol
|
|
25
|
+
if obj.respond_to?(option, true) and record?(obj)
|
|
26
|
+
obj.send(option)
|
|
27
|
+
elsif obj.respond_to?(:record) and obj.record.respond_to?(option, true)
|
|
28
|
+
obj.record.send(option)
|
|
29
|
+
elsif obj.respond_to?(option, true)
|
|
30
|
+
obj.send(option)
|
|
31
|
+
else
|
|
32
|
+
raise ArgumentError, "unable to resolve #{option}"
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
option
|
|
36
|
+
end
|
|
24
37
|
when Hash then option.dup
|
|
25
38
|
else option
|
|
26
39
|
end
|
|
27
40
|
end
|
|
28
41
|
|
|
42
|
+
##
|
|
43
|
+
# Returns true when `obj` is an ActiveRecord or Sequel model.
|
|
44
|
+
# @param [Object] obj
|
|
45
|
+
# @api private
|
|
46
|
+
def record?(obj)
|
|
47
|
+
(defined?(::ActiveRecord::Base) and ::ActiveRecord::Base === obj) or
|
|
48
|
+
(defined?(::Sequel::Model) and ::Sequel::Model === obj)
|
|
49
|
+
end
|
|
50
|
+
|
|
29
51
|
##
|
|
30
52
|
# Normalizes an HTTP API base path.
|
|
31
53
|
#
|
data/lib/llm/version.rb
CHANGED
data/llm.gemspec
CHANGED
|
@@ -21,7 +21,7 @@ DESCRIPTION
|
|
|
21
21
|
spec.license = "MIT"
|
|
22
22
|
spec.required_ruby_version = ">= 3.3.0"
|
|
23
23
|
|
|
24
|
-
spec.homepage = "https://r.uby.dev
|
|
24
|
+
spec.homepage = "https://r.uby.dev"
|
|
25
25
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
26
26
|
spec.metadata["source_code_uri"] = "https://github.com/r-uby-dev/llm"
|
|
27
27
|
spec.metadata["documentation_uri"] = spec.homepage
|
|
@@ -38,9 +38,15 @@ DESCRIPTION
|
|
|
38
38
|
spec.executables = ["llm.rb"]
|
|
39
39
|
spec.require_paths = ["lib"]
|
|
40
40
|
spec.post_install_message = "\n" \
|
|
41
|
-
"
|
|
41
|
+
"Got a question about llm.rb? " \
|
|
42
42
|
"\n" \
|
|
43
|
-
"https://
|
|
43
|
+
"Ask the https://r.uby.dev chatbot." \
|
|
44
|
+
"\n" \
|
|
45
|
+
"It is connected to the official GitHub repository." \
|
|
46
|
+
"\n" \
|
|
47
|
+
"100% free to use." \
|
|
48
|
+
"\n" \
|
|
49
|
+
"Built with llm.rb and DeepSeek." \
|
|
44
50
|
"\n\n"
|
|
45
51
|
|
|
46
52
|
spec.add_development_dependency "webmock", "~> 3.24.0"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: llm.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 15.0.
|
|
4
|
+
version: 15.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Gleeson
|
|
@@ -644,19 +644,17 @@ files:
|
|
|
644
644
|
- lib/sequel/plugins/agent.rb
|
|
645
645
|
- lib/sequel/plugins/llm.rb
|
|
646
646
|
- llm.gemspec
|
|
647
|
-
homepage: https://r.uby.dev
|
|
647
|
+
homepage: https://r.uby.dev
|
|
648
648
|
licenses:
|
|
649
649
|
- MIT
|
|
650
650
|
metadata:
|
|
651
|
-
homepage_uri: https://r.uby.dev
|
|
651
|
+
homepage_uri: https://r.uby.dev
|
|
652
652
|
source_code_uri: https://github.com/r-uby-dev/llm
|
|
653
|
-
documentation_uri: https://r.uby.dev
|
|
653
|
+
documentation_uri: https://r.uby.dev
|
|
654
654
|
changelog_uri: https://github.com/r-uby-dev/llm/blob/main/CHANGELOG.md
|
|
655
|
-
post_install_message:
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
https://github.com/r-uby-dev/llm#readme
|
|
659
|
-
|
|
655
|
+
post_install_message: "\nGot a question about llm.rb? \nAsk the https://r.uby.dev
|
|
656
|
+
chatbot.\nIt is connected to the official GitHub repository.\n100% free to use.\nBuilt
|
|
657
|
+
with llm.rb and DeepSeek.\n\n"
|
|
660
658
|
rdoc_options: []
|
|
661
659
|
require_paths:
|
|
662
660
|
- lib
|
|
@@ -675,4 +673,3 @@ rubygems_version: 4.0.16
|
|
|
675
673
|
specification_version: 4
|
|
676
674
|
summary: Ruby's capable AI runtime
|
|
677
675
|
test_files: []
|
|
678
|
-
...
|