llm.rb 15.0.3 → 15.2.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +433 -3
  3. data/README.md +188 -71
  4. data/bin/llm.rb +50 -7
  5. data/data/alibaba.json +912 -823
  6. data/data/anthropic.json +234 -187
  7. data/data/bedrock.json +3702 -2058
  8. data/data/deepinfra.json +1288 -951
  9. data/data/deepseek.json +87 -53
  10. data/data/google.json +670 -670
  11. data/data/mistral.json +501 -460
  12. data/data/moonshot.json +43 -248
  13. data/data/openai.json +1008 -914
  14. data/data/openrouter.json +14417 -0
  15. data/data/xai.json +213 -201
  16. data/data/zai.json +242 -149
  17. data/docs/deepdive/advanced/compaction.md +5 -5
  18. data/docs/deepdive/advanced/context.md +8 -6
  19. data/docs/deepdive/advanced/guard.md +2 -2
  20. data/docs/deepdive/features/builtin_tools.md +93 -22
  21. data/docs/deepdive/features/{repl.md → console.md} +28 -28
  22. data/docs/deepdive/features/database.md +3 -3
  23. data/docs/deepdive/fundamentals/agents.md +13 -12
  24. data/docs/deepdive/fundamentals/providers.md +91 -6
  25. data/docs/deepdive/fundamentals/skills.md +14 -6
  26. data/docs/deepdive/fundamentals/stream.md +4 -4
  27. data/docs/deepdive/fundamentals/tools.md +63 -31
  28. data/docs/deepdive/reference/cost.md +2 -2
  29. data/docs/deepdive/reference/model_registry.md +2 -2
  30. data/docs/deepdive/reference/tracer.md +15 -13
  31. data/docs/deepdive.md +2 -2
  32. data/lib/llm/active_record/acts_as_agent.rb +9 -5
  33. data/lib/llm/agent.rb +40 -15
  34. data/lib/llm/{repl → console}/bar.rb +3 -3
  35. data/lib/llm/{repl → console}/buffer.rb +24 -9
  36. data/lib/llm/{repl → console}/color.rb +2 -2
  37. data/lib/llm/{repl → console}/command.rb +12 -12
  38. data/lib/llm/{repl → console}/commands/exit.rb +4 -4
  39. data/lib/llm/{repl → console}/commands/help.rb +1 -1
  40. data/lib/llm/{repl/commands/compact.rb → console/commands/keep.rb} +11 -9
  41. data/lib/llm/{repl → console}/commands/model.rb +2 -2
  42. data/lib/llm/{repl → console}/input/cache.rb +2 -2
  43. data/lib/llm/{repl → console}/input/char.rb +2 -2
  44. data/lib/llm/{repl → console}/input/row.rb +1 -1
  45. data/lib/llm/{repl → console}/input.rb +18 -10
  46. data/lib/llm/console/markdown/parser.rb +78 -0
  47. data/lib/llm/{repl → console}/markdown/table.rb +8 -5
  48. data/lib/llm/{repl → console}/markdown.rb +13 -30
  49. data/lib/llm/console/node.rb +69 -0
  50. data/lib/llm/{repl → console}/status.rb +11 -11
  51. data/lib/llm/{repl → console}/stream.rb +36 -9
  52. data/lib/llm/{repl → console}/walker.rb +1 -1
  53. data/lib/llm/{repl → console}/window.rb +17 -17
  54. data/lib/llm/{repl.rb → console.rb} +39 -19
  55. data/lib/llm/context/deserializer.rb +2 -1
  56. data/lib/llm/context.rb +29 -13
  57. data/lib/llm/cost.rb +13 -0
  58. data/lib/llm/function/async/reactor.rb +20 -1
  59. data/lib/llm/function/fork/task.rb +14 -10
  60. data/lib/llm/function.rb +1 -1
  61. data/lib/llm/json_adapter.rb +40 -28
  62. data/lib/llm/message.rb +7 -0
  63. data/lib/llm/provider.rb +31 -10
  64. data/lib/llm/providers/alibaba.rb +1 -1
  65. data/lib/llm/providers/anthropic.rb +1 -1
  66. data/lib/llm/providers/bedrock/models.rb +2 -2
  67. data/lib/llm/providers/bedrock.rb +1 -1
  68. data/lib/llm/providers/deepseek.rb +1 -1
  69. data/lib/llm/providers/google.rb +1 -1
  70. data/lib/llm/providers/ollama.rb +1 -1
  71. data/lib/llm/providers/openai/responses.rb +2 -1
  72. data/lib/llm/providers/openai.rb +2 -1
  73. data/lib/llm/providers/openrouter.rb +87 -0
  74. data/lib/llm/schema/leaf.rb +34 -2
  75. data/lib/llm/schema.rb +4 -2
  76. data/lib/llm/sequel/agent.rb +9 -5
  77. data/lib/llm/skill.rb +7 -1
  78. data/lib/llm/stream.rb +8 -3
  79. data/lib/llm/tool/param.rb +5 -1
  80. data/lib/llm/tool.rb +5 -0
  81. data/lib/llm/tools/bundle.rb +53 -0
  82. data/lib/llm/tools/edit-file.rb +7 -2
  83. data/lib/llm/tools/exec.rb +78 -0
  84. data/lib/llm/tools/git.rb +27 -26
  85. data/lib/llm/tools/mkdir.rb +12 -19
  86. data/lib/llm/tools/read_file.rb +69 -9
  87. data/lib/llm/tools/rg.rb +20 -24
  88. data/lib/llm/tools/ruby.rb +17 -25
  89. data/lib/llm/tools/utils.rb +75 -2
  90. data/lib/llm/tools/write_file.rb +4 -1
  91. data/lib/llm/tracer/logger.rb +2 -2
  92. data/lib/llm/tracer/pretty_logger.rb +4 -4
  93. data/lib/llm/tracer/telemetry.rb +2 -2
  94. data/lib/llm/tracer.rb +33 -0
  95. data/lib/llm/transport/curb.rb +5 -3
  96. data/lib/llm/transport/http.rb +5 -2
  97. data/lib/llm/transport/persistent_http.rb +6 -4
  98. data/lib/llm/transport/utils.rb +8 -6
  99. data/lib/llm/version.rb +1 -1
  100. data/lib/llm.rb +18 -12
  101. data/llm.gemspec +8 -8
  102. metadata +80 -37
  103. data/lib/llm/repl/node.rb +0 -44
  104. data/lib/llm/tools/shell.rb +0 -55
data/llm.gemspec CHANGED
@@ -11,11 +11,8 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "Ruby's capable AI runtime"
12
12
  spec.description = <<~DESCRIPTION
13
13
  llm.rb is an advanced runtime for building agentic AI applications on CRuby.
14
- It has zero runtime dependencies by default, it supports concurrent and parallel
15
- tool execution and has a single coherent API that spans 13+ providers. Streaming,
16
- tools, guards, compaction, the REPL, builtin MCP/A2A support and the database
17
- integrations all build on the same three concepts: providers, contexts, and
18
- agents.
14
+ It has zero runtime dependencies by default, supports concurrent and parallel
15
+ tool execution and has a single coherent API that spans 14+ providers.
19
16
  DESCRIPTION
20
17
 
21
18
  spec.license = "MIT"
@@ -53,10 +50,11 @@ DESCRIPTION
53
50
  spec.add_development_dependency "yard", "~> 0.9.37"
54
51
  spec.add_development_dependency "redcarpet", "~> 3.6"
55
52
  spec.add_development_dependency "webrick", "~> 1.8"
56
- spec.add_development_dependency "test-cmd.rb", "~> 1.1.0"
53
+ spec.add_development_dependency "test-cmd.rb", "~> 2.7.1"
57
54
  spec.add_development_dependency "rake", "~> 13.0"
58
55
  spec.add_development_dependency "rspec", "~> 3.0"
59
- spec.add_development_dependency "standard", "~> 1.50"
56
+ spec.add_development_dependency "standard", "= 1.54.0"
57
+ spec.add_development_dependency "rubocop", "= 1.84.2"
60
58
  spec.add_development_dependency "vcr", "~> 6.0"
61
59
  spec.add_development_dependency "dotenv", "~> 2.8"
62
60
  spec.add_development_dependency "net-http-persistent", "~> 4.0"
@@ -65,10 +63,12 @@ DESCRIPTION
65
63
  spec.add_development_dependency "activerecord", "~> 8.0"
66
64
  spec.add_development_dependency "sequel", "~> 5.0"
67
65
  spec.add_development_dependency "sqlite3", "~> 2.0"
68
- spec.add_development_dependency "xchan.rb", "~> 0.22"
66
+ spec.add_development_dependency "xchan.rb", "~> 0.23"
69
67
  spec.add_development_dependency "pg", "~> 1.5"
70
68
  spec.add_development_dependency "irb", "~> 1.18"
71
69
  spec.add_development_dependency "curb", "~> 1.3"
72
70
  spec.add_development_dependency "curses", "~> 1.6"
73
71
  spec.add_development_dependency "kramdown", "~> 2.5"
72
+ spec.add_development_dependency "unicode-display_width", "~> 3.2"
73
+ spec.add_development_dependency "async", "~> 2.45"
74
74
  end
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.3
4
+ version: 15.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Gleeson
@@ -73,14 +73,14 @@ dependencies:
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: 1.1.0
76
+ version: 2.7.1
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: 1.1.0
83
+ version: 2.7.1
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: rake
86
86
  requirement: !ruby/object:Gem::Requirement
@@ -113,16 +113,30 @@ dependencies:
113
113
  name: standard
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
- - - "~>"
116
+ - - '='
117
117
  - !ruby/object:Gem::Version
118
- version: '1.50'
118
+ version: 1.54.0
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - "~>"
123
+ - - '='
124
124
  - !ruby/object:Gem::Version
125
- version: '1.50'
125
+ version: 1.54.0
126
+ - !ruby/object:Gem::Dependency
127
+ name: rubocop
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '='
131
+ - !ruby/object:Gem::Version
132
+ version: 1.84.2
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - '='
138
+ - !ruby/object:Gem::Version
139
+ version: 1.84.2
126
140
  - !ruby/object:Gem::Dependency
127
141
  name: vcr
128
142
  requirement: !ruby/object:Gem::Requirement
@@ -241,14 +255,14 @@ dependencies:
241
255
  requirements:
242
256
  - - "~>"
243
257
  - !ruby/object:Gem::Version
244
- version: '0.22'
258
+ version: '0.23'
245
259
  type: :development
246
260
  prerelease: false
247
261
  version_requirements: !ruby/object:Gem::Requirement
248
262
  requirements:
249
263
  - - "~>"
250
264
  - !ruby/object:Gem::Version
251
- version: '0.22'
265
+ version: '0.23'
252
266
  - !ruby/object:Gem::Dependency
253
267
  name: pg
254
268
  requirement: !ruby/object:Gem::Requirement
@@ -319,13 +333,38 @@ dependencies:
319
333
  - - "~>"
320
334
  - !ruby/object:Gem::Version
321
335
  version: '2.5'
336
+ - !ruby/object:Gem::Dependency
337
+ name: unicode-display_width
338
+ requirement: !ruby/object:Gem::Requirement
339
+ requirements:
340
+ - - "~>"
341
+ - !ruby/object:Gem::Version
342
+ version: '3.2'
343
+ type: :development
344
+ prerelease: false
345
+ version_requirements: !ruby/object:Gem::Requirement
346
+ requirements:
347
+ - - "~>"
348
+ - !ruby/object:Gem::Version
349
+ version: '3.2'
350
+ - !ruby/object:Gem::Dependency
351
+ name: async
352
+ requirement: !ruby/object:Gem::Requirement
353
+ requirements:
354
+ - - "~>"
355
+ - !ruby/object:Gem::Version
356
+ version: '2.45'
357
+ type: :development
358
+ prerelease: false
359
+ version_requirements: !ruby/object:Gem::Requirement
360
+ requirements:
361
+ - - "~>"
362
+ - !ruby/object:Gem::Version
363
+ version: '2.45'
322
364
  description: |
323
365
  llm.rb is an advanced runtime for building agentic AI applications on CRuby.
324
- It has zero runtime dependencies by default, it supports concurrent and parallel
325
- tool execution and has a single coherent API that spans 13+ providers. Streaming,
326
- tools, guards, compaction, the REPL, builtin MCP/A2A support and the database
327
- integrations all build on the same three concepts: providers, contexts, and
328
- agents.
366
+ It has zero runtime dependencies by default, supports concurrent and parallel
367
+ tool execution and has a single coherent API that spans 14+ providers.
329
368
  email:
330
369
  - robert@r.uby.dev
331
370
  executables:
@@ -346,6 +385,7 @@ files:
346
385
  - data/mistral.json
347
386
  - data/moonshot.json
348
387
  - data/openai.json
388
+ - data/openrouter.json
349
389
  - data/xai.json
350
390
  - data/zai.json
351
391
  - docs/deepdive.md
@@ -357,9 +397,9 @@ files:
357
397
  - docs/deepdive/advanced/transports.md
358
398
  - docs/deepdive/features/builtin_tools.md
359
399
  - docs/deepdive/features/concurrency.md
400
+ - docs/deepdive/features/console.md
360
401
  - docs/deepdive/features/database.md
361
402
  - docs/deepdive/features/embeddings.md
362
- - docs/deepdive/features/repl.md
363
403
  - docs/deepdive/fundamentals/agents.md
364
404
  - docs/deepdive/fundamentals/providers.md
365
405
  - docs/deepdive/fundamentals/schema.md
@@ -394,6 +434,27 @@ files:
394
434
  - lib/llm/compactor.rb
395
435
  - lib/llm/compactor/null.rb
396
436
  - lib/llm/compactor/truncate.rb
437
+ - lib/llm/console.rb
438
+ - lib/llm/console/bar.rb
439
+ - lib/llm/console/buffer.rb
440
+ - lib/llm/console/color.rb
441
+ - lib/llm/console/command.rb
442
+ - lib/llm/console/commands/exit.rb
443
+ - lib/llm/console/commands/help.rb
444
+ - lib/llm/console/commands/keep.rb
445
+ - lib/llm/console/commands/model.rb
446
+ - lib/llm/console/input.rb
447
+ - lib/llm/console/input/cache.rb
448
+ - lib/llm/console/input/char.rb
449
+ - lib/llm/console/input/row.rb
450
+ - lib/llm/console/markdown.rb
451
+ - lib/llm/console/markdown/parser.rb
452
+ - lib/llm/console/markdown/table.rb
453
+ - lib/llm/console/node.rb
454
+ - lib/llm/console/status.rb
455
+ - lib/llm/console/stream.rb
456
+ - lib/llm/console/walker.rb
457
+ - lib/llm/console/window.rb
397
458
  - lib/llm/context.rb
398
459
  - lib/llm/context/deserializer.rb
399
460
  - lib/llm/context/serializer.rb
@@ -551,31 +612,12 @@ files:
551
612
  - lib/llm/providers/openai/schema.rb
552
613
  - lib/llm/providers/openai/stream_parser.rb
553
614
  - lib/llm/providers/openai/vector_stores.rb
615
+ - lib/llm/providers/openrouter.rb
554
616
  - lib/llm/providers/xai.rb
555
617
  - lib/llm/providers/xai/images.rb
556
618
  - lib/llm/providers/zai.rb
557
619
  - lib/llm/registry.rb
558
620
  - lib/llm/registry/model.rb
559
- - lib/llm/repl.rb
560
- - lib/llm/repl/bar.rb
561
- - lib/llm/repl/buffer.rb
562
- - lib/llm/repl/color.rb
563
- - lib/llm/repl/command.rb
564
- - lib/llm/repl/commands/compact.rb
565
- - lib/llm/repl/commands/exit.rb
566
- - lib/llm/repl/commands/help.rb
567
- - lib/llm/repl/commands/model.rb
568
- - lib/llm/repl/input.rb
569
- - lib/llm/repl/input/cache.rb
570
- - lib/llm/repl/input/char.rb
571
- - lib/llm/repl/input/row.rb
572
- - lib/llm/repl/markdown.rb
573
- - lib/llm/repl/markdown/table.rb
574
- - lib/llm/repl/node.rb
575
- - lib/llm/repl/status.rb
576
- - lib/llm/repl/stream.rb
577
- - lib/llm/repl/walker.rb
578
- - lib/llm/repl/window.rb
579
621
  - lib/llm/response.rb
580
622
  - lib/llm/schema.rb
581
623
  - lib/llm/schema/all_of.rb
@@ -605,8 +647,10 @@ files:
605
647
  - lib/llm/tool.rb
606
648
  - lib/llm/tool/param.rb
607
649
  - lib/llm/tools.rb
650
+ - lib/llm/tools/bundle.rb
608
651
  - lib/llm/tools/chdir.rb
609
652
  - lib/llm/tools/edit-file.rb
653
+ - lib/llm/tools/exec.rb
610
654
  - lib/llm/tools/git.rb
611
655
  - lib/llm/tools/ls.rb
612
656
  - lib/llm/tools/mkdir.rb
@@ -614,7 +658,6 @@ files:
614
658
  - lib/llm/tools/read_file.rb
615
659
  - lib/llm/tools/rg.rb
616
660
  - lib/llm/tools/ruby.rb
617
- - lib/llm/tools/shell.rb
618
661
  - lib/llm/tools/utils.rb
619
662
  - lib/llm/tools/which.rb
620
663
  - lib/llm/tools/write_file.rb
@@ -669,7 +712,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
669
712
  - !ruby/object:Gem::Version
670
713
  version: '0'
671
714
  requirements: []
672
- rubygems_version: 4.0.16
715
+ rubygems_version: 4.0.20
673
716
  specification_version: 4
674
717
  summary: Ruby's capable AI runtime
675
718
  test_files: []
data/lib/llm/repl/node.rb DELETED
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LLM::Repl
4
- ##
5
- # The {LLM::Repl::Node LLM::Repl::Node} class wraps a piece
6
- # of text and optional curses attributes.
7
- # @api private
8
- class Node
9
- ##
10
- # @return [String]
11
- attr_reader :text
12
-
13
- ##
14
- # @return [Integer, nil]
15
- attr_reader :attrs
16
-
17
- ##
18
- # @param [String] text
19
- # @param [Integer, nil] attrs
20
- # @return [LLM::Repl::Node]
21
- def initialize(text, attrs = nil)
22
- @text = text.to_s
23
- @attrs = attrs
24
- end
25
-
26
- ##
27
- # @return [Integer]
28
- def size
29
- @text.size
30
- end
31
- alias_method :length, :size
32
-
33
- ##
34
- # Hash-like lookup.
35
- # @param [Symbol] key
36
- # @return [String, Integer, nil]
37
- def [](key)
38
- case key
39
- when :text then @text
40
- when :attrs then @attrs
41
- end
42
- end
43
- end
44
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LLM::Tool
4
- ##
5
- # The {LLM::Tool::Shell} class implements a tool that can
6
- # spawn a command. That can be dangerous given a low-quality
7
- # model, or a high-quality model that simply makes a bad
8
- # decision. The risk can be reduced through a confirmation
9
- # step such as {LLM::Agent.confirm LLM::Agent.confirm}, or
10
- # by managing the tool loop manually through
11
- # {LLM::Context LLM::Context}.
12
- class Shell < self
13
- require_relative "utils"
14
- include Utils
15
-
16
- name "shell"
17
- description "run a shell command"
18
- parameter :name, String, "the command name"
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)"
21
- required %i[name]
22
- defaults arguments: [], timeout: 60
23
-
24
- ##
25
- # @param [String] name
26
- # The name of a command
27
- # @param [Array<String>] arguments
28
- # One or more command-line arguments
29
- # @return [Hash]
30
- def call(name:, arguments: [], timeout: 60)
31
- command = spawn(name:, arguments:)
32
- wait(command:, timeout:)
33
- {ok: command.success?, stdout: command.stdout, stderr: command.stderr}
34
- rescue LLM::Interrupt
35
- command.kill! if command&.running?
36
- raise
37
- end
38
-
39
- private
40
-
41
- ##
42
- # @param [String] name
43
- # @param [Array<String>] arguments
44
- # @return [Command]
45
- def spawn(name:, arguments:)
46
- Command
47
- .new(name)
48
- .argv(*[*arguments])
49
- .spawn
50
- end
51
-
52
- LLM.require "test-cmd.rb", "~> 1.1"
53
- Command = Test::Cmd
54
- end
55
- end