llm.rb 12.6.0 → 13.0.0

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +387 -0
  3. data/LICENSE +21 -93
  4. data/README.md +46 -155
  5. data/data/deepinfra.json +3 -0
  6. data/data/xai.json +1 -1
  7. data/lib/llm/a2a.rb +1 -1
  8. data/lib/llm/active_record/acts_as_llm.rb +6 -6
  9. data/lib/llm/agent.rb +62 -23
  10. data/lib/llm/buffer.rb +85 -3
  11. data/lib/llm/compactor/null.rb +19 -0
  12. data/lib/llm/compactor/truncate.rb +80 -0
  13. data/lib/llm/compactor.rb +42 -124
  14. data/lib/llm/context.rb +31 -37
  15. data/lib/llm/contract.rb +4 -25
  16. data/lib/llm/function/array.rb +15 -14
  17. data/lib/llm/function/async/group.rb +54 -0
  18. data/lib/llm/function/async/reactor.rb +48 -0
  19. data/lib/llm/function/async/task.rb +83 -0
  20. data/lib/llm/function/fiber/group.rb +46 -0
  21. data/lib/llm/function/fiber/task.rb +62 -0
  22. data/lib/llm/function/{fork_group.rb → fork/group.rb} +14 -5
  23. data/lib/llm/function/fork/job.rb +2 -2
  24. data/lib/llm/function/fork/task.rb +19 -10
  25. data/lib/llm/function/group.rb +40 -0
  26. data/lib/llm/function/{ractor_group.rb → ractor/group.rb} +13 -5
  27. data/lib/llm/function/ractor/job.rb +9 -3
  28. data/lib/llm/function/ractor/mailbox.rb +2 -0
  29. data/lib/llm/function/ractor/task.rb +23 -15
  30. data/lib/llm/function/{call_group.rb → sequential/group.rb} +12 -8
  31. data/lib/llm/function/sequential/task.rb +49 -0
  32. data/lib/llm/function/task.rb +25 -48
  33. data/lib/llm/function/thread/group.rb +46 -0
  34. data/lib/llm/function/thread/task.rb +60 -0
  35. data/lib/llm/function.rb +54 -64
  36. data/lib/llm/loop_guard.rb +1 -2
  37. data/lib/llm/mcp.rb +22 -0
  38. data/lib/llm/object.rb +2 -1
  39. data/lib/llm/provider.rb +6 -3
  40. data/lib/llm/providers/google.rb +2 -2
  41. data/lib/llm/repl/command.rb +35 -8
  42. data/lib/llm/repl/commands/compact.rb +33 -0
  43. data/lib/llm/repl/input.rb +80 -15
  44. data/lib/llm/repl/markdown/table.rb +76 -0
  45. data/lib/llm/repl/markdown.rb +31 -1
  46. data/lib/llm/repl/status.rb +1 -1
  47. data/lib/llm/repl/stream.rb +10 -3
  48. data/lib/llm/repl/transcript.rb +1 -1
  49. data/lib/llm/repl/walker.rb +46 -0
  50. data/lib/llm/repl.rb +18 -12
  51. data/lib/llm/response.rb +10 -0
  52. data/lib/llm/schema/leaf.rb +5 -0
  53. data/lib/llm/schema/object.rb +11 -5
  54. data/lib/llm/sequel/plugin.rb +6 -6
  55. data/lib/llm/stream.rb +24 -17
  56. data/lib/llm/tool.rb +20 -4
  57. data/lib/llm/tools/chdir.rb +0 -2
  58. data/lib/llm/tools/git.rb +8 -4
  59. data/lib/llm/tools/mkdir.rb +1 -1
  60. data/lib/llm/tools/pwd.rb +0 -2
  61. data/lib/llm/tools/read_file.rb +0 -2
  62. data/lib/llm/tools/rg.rb +8 -4
  63. data/lib/llm/tools/shell.rb +8 -4
  64. data/lib/llm/tools/utils.rb +31 -0
  65. data/lib/llm/version.rb +1 -1
  66. data/lib/llm.rb +25 -5
  67. data/llm.gemspec +3 -3
  68. data/resources/deepdive.md +645 -58
  69. metadata +24 -13
  70. data/lib/llm/function/call_task.rb +0 -46
  71. data/lib/llm/function/fiber_group.rb +0 -105
  72. data/lib/llm/function/task_group.rb +0 -97
  73. data/lib/llm/function/thread_group.rb +0 -102
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # frozen_string_literal
4
-
5
3
  class LLM::Tool
6
4
  ##
7
5
  # The {LLM::Tool::Shell} class implements a tool that can
@@ -12,11 +10,16 @@ class LLM::Tool
12
10
  # by managing the tool loop manually through
13
11
  # {LLM::Context LLM::Context}.
14
12
  class Shell < self
13
+ require_relative "utils"
14
+ include Utils
15
+
15
16
  name "shell"
16
17
  description "run a shell command"
17
18
  parameter :name, String, "the command name"
18
19
  parameter :arguments, Array[String], "one or more command arguments"
20
+ parameter :timeout, Integer, "the maximum allowed time for the command to run (in seconds)"
19
21
  required %i[name]
22
+ defaults arguments: [], timeout: 60
20
23
 
21
24
  ##
22
25
  # @param [String] name
@@ -24,8 +27,9 @@ class LLM::Tool
24
27
  # @param [Array<String>] arguments
25
28
  # One or more command-line arguments
26
29
  # @return [Hash]
27
- def call(name:, arguments: nil)
30
+ def call(name:, arguments: [], timeout: 60)
28
31
  command = spawn(name:, arguments:)
32
+ wait(command:, timeout:)
29
33
  {ok: command.success?, stdout: command.stdout, stderr: command.stderr}
30
34
  end
31
35
 
@@ -42,7 +46,7 @@ class LLM::Tool
42
46
  .spawn
43
47
  end
44
48
 
45
- LLM.require "test-cmd.rb"
49
+ LLM.require "test-cmd.rb", "~> 1.1"
46
50
  Command = Test::Cmd
47
51
  end
48
52
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LLM::Tool
4
+ ##
5
+ # Shared utilities for tool implementations.
6
+ module Utils
7
+ ##
8
+ # Wait for a command to finish, or abort
9
+ # with an error when it exceeds the
10
+ # specified timeout.
11
+ # @param [Test::Cmd] command
12
+ # @param [Integer] timeout
13
+ # @return [void]
14
+ def wait(command:, timeout:)
15
+ start = now
16
+ while command.running?
17
+ if now - start > timeout
18
+ command.kill!
19
+ raise "command timed out after #{timeout}s"
20
+ end
21
+ sleep 0.01
22
+ end
23
+ end
24
+
25
+ ##
26
+ # @return [Numeric]
27
+ def now
28
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
29
+ end
30
+ end
31
+ end
data/lib/llm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LLM
4
- VERSION = "12.6.0"
4
+ VERSION = "13.0.0"
5
5
  end
data/lib/llm.rb CHANGED
@@ -1,8 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ##
4
+ # llm.rb is a zero-dependency AI runtime for Ruby. Twelve providers, six
5
+ # concurrency strategies, MCP and A2A, streaming tool calls with
6
+ # cancellation, context compaction, and ORM persistence.
7
+ #
8
+ # @example The three-step workflow
9
+ # require "llm"
10
+ # llm = LLM.deepseek(key: ENV["KEY"]) # 1. pick a provider
11
+ # agent = LLM::Agent.new(llm, stream: $stdout) # 2. create an agent
12
+ # agent.talk "Hello world" # 3. talk to it
13
+ #
14
+ # @see LLM::Agent The recommended high-level interface
15
+ # @see LLM::Context The low-level stateful runtime (advanced)
3
16
  module LLM
4
17
  require "stringio"
5
18
  require "securerandom"
19
+ require_relative "llm/compactor"
6
20
  require_relative "llm/json_adapter"
7
21
  require_relative "llm/tracer"
8
22
  require_relative "llm/error"
@@ -49,15 +63,21 @@ module LLM
49
63
 
50
64
  ##
51
65
  # Requires an optional runtime dependency
52
- # @raise [LLM::DependencyError]
66
+ # @param [String] name
67
+ # The name of a gem
68
+ # @param [String, nil] version
69
+ # Optional gem version
70
+ # @raise [LLM::LoadError]
53
71
  # When the dependency cannot be loaded
54
- def self.require(name)
55
- super
56
- rescue ::LoadError
72
+ def self.require(name, version = nil)
57
73
  names = {"xchan" => "xchan.rb", "net/http/persistent" => "net-http-persistent"}
74
+ gem(names[name] || name, version) if version
75
+ super(name)
76
+ rescue ::LoadError
58
77
  name = names[name] || name
59
78
  raise LLM::LoadError,
60
- "#{name} is an optional runtime dependency but it does not appear to be installed. " \
79
+ "#{name}#{version ? " #{version}" : ""} is an optional " \
80
+ "runtime dependency but it does not appear to be installed. " \
61
81
  "Consider 'gem install #{name}', adding '#{name}' to your Gemfile or " \
62
82
  "opting out of the functionality provided by '#{name}'"
63
83
  end
data/llm.gemspec CHANGED
@@ -16,7 +16,7 @@ functionality &ndash; such as ActiveRecord support &ndash; require
16
16
  optional dependencies that are opt-in.
17
17
  DESCRIPTION
18
18
 
19
- spec.license = "BUSL-1.1"
19
+ spec.license = "MIT"
20
20
  spec.required_ruby_version = ">= 3.3.0"
21
21
 
22
22
  spec.homepage = "https://r.uby.dev/llm/"
@@ -38,7 +38,7 @@ DESCRIPTION
38
38
  spec.add_development_dependency "yard", "~> 0.9.37"
39
39
  spec.add_development_dependency "redcarpet", "~> 3.6"
40
40
  spec.add_development_dependency "webrick", "~> 1.8"
41
- spec.add_development_dependency "test-cmd.rb", "~> 0.12.0"
41
+ spec.add_development_dependency "test-cmd.rb", "~> 1.1.0"
42
42
  spec.add_development_dependency "rake", "~> 13.0"
43
43
  spec.add_development_dependency "rspec", "~> 3.0"
44
44
  spec.add_development_dependency "standard", "~> 1.50"
@@ -50,7 +50,7 @@ DESCRIPTION
50
50
  spec.add_development_dependency "activerecord", "~> 8.0"
51
51
  spec.add_development_dependency "sequel", "~> 5.0"
52
52
  spec.add_development_dependency "sqlite3", "~> 2.0"
53
- spec.add_development_dependency "xchan.rb", "~> 0.20"
53
+ spec.add_development_dependency "xchan.rb", "~> 0.22"
54
54
  spec.add_development_dependency "pg", "~> 1.5"
55
55
  spec.add_development_dependency "irb", "~> 1.18"
56
56
  end