rails-llm 0.1.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.
data/lib/rails-llm.rb ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsLLM
4
+ extend self
5
+
6
+ require "rails"
7
+ require "llm"
8
+ require "redcarpet"
9
+ require "active_support/inflector"
10
+ require_relative "rails_llm/version"
11
+ require_relative "rails_llm/stream"
12
+ require_relative "rails_llm/engine"
13
+
14
+ ##
15
+ # @param [String] text
16
+ # @return [String]
17
+ def markdown(text)
18
+ renderer.render(text)
19
+ end
20
+
21
+ ##
22
+ # @return [Redcarpet::Markdown]
23
+ def renderer
24
+ @renderer ||= Redcarpet::Markdown.new(
25
+ Renderer,
26
+ fenced_code_blocks: true,
27
+ tables: true
28
+ )
29
+ end
30
+
31
+ ##
32
+ # @api private
33
+ class Renderer < Redcarpet::Render::HTML
34
+ def block_code(code, language)
35
+ language = language.to_s.strip
36
+ klass = language.empty? ? nil : "language-#{language}"
37
+ code = ERB::Util.html_escape(code)
38
+ if klass
39
+ %(<pre><code class="#{klass}">#{code}</code></pre>)
40
+ else
41
+ %(<pre><code>#{code}</code></pre>)
42
+ end
43
+ end
44
+ end
45
+
46
+ ActiveSupport::Inflector.inflections(:en) { _1.acronym "LLM" }
47
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsLLM
4
+ ##
5
+ # {RailsLLM::Engine} is the Rails engine that mounts the chat UI
6
+ # and provides the generator infrastructure.
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace RailsLLM
9
+
10
+ config.generators do |g|
11
+ g.test_framework :rspec, fixture: false
12
+ g.assets false
13
+ g.helper false
14
+ end
15
+
16
+ initializer "rails_llm.assets" do |app|
17
+ next unless app.config.respond_to?(:assets)
18
+ app.config.assets.precompile += %w[rails_llm/application.css rails_llm/application.js]
19
+ end
20
+
21
+ initializer "rails_llm.active_record" do
22
+ ActiveSupport.on_load(:active_record) do
23
+ require "llm/active_record"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "llm"
4
+
5
+ module RailsLLM
6
+ ##
7
+ # {Stream} enriches llm.rb's streaming with structured events
8
+ # for the chat UI. Captures content, reasoning, tool calls,
9
+ # and tool returns as structured events.
10
+ class Stream < LLM::Stream
11
+ attr_reader :reasoning_content, :tool_calls
12
+
13
+ def initialize(stream)
14
+ @stream = stream
15
+ @reasoning_content = +""
16
+ @tool_calls = []
17
+ @buffer = +""
18
+ end
19
+
20
+ ##
21
+ # @param [String] content
22
+ # @return [void]
23
+ def on_content(content)
24
+ @buffer << content
25
+ write(type: "content", content: RailsLLM.markdown(@buffer))
26
+ end
27
+
28
+ ##
29
+ # @param [String] content
30
+ # @return [void]
31
+ def on_reasoning_content(content)
32
+ @reasoning_content << content
33
+ end
34
+
35
+ ##
36
+ # @param [LLM::Function] tool
37
+ # @param [String, nil] error
38
+ # @return [void]
39
+ def on_tool_call(tool, error)
40
+ if error
41
+ queue << error
42
+ else
43
+ @tool_calls << {name: tool.name, arguments: tool.arguments}
44
+ write(type: "tool_call", name: tool.name, arguments: tool.arguments)
45
+ queue << ctx.spawn(tool, :call)
46
+ end
47
+ end
48
+
49
+ ##
50
+ # @param [LLM::Function] tool
51
+ # @param [LLM::Function::Return] result
52
+ # @return [void]
53
+ def on_tool_return(tool, result)
54
+ write(type: "tool_return", name: tool.name, result: result.value)
55
+ end
56
+
57
+ ##
58
+ # @return [void]
59
+ def finish
60
+ write(type: "done")
61
+ end
62
+
63
+ private
64
+
65
+ def write(payload)
66
+ @stream.write("#{LLM.json.dump(payload)}\n")
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsLLM
4
+ VERSION = "0.1.0"
5
+ end
data/lib/rails_llm.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rails-llm"
data/rails-llm.gemspec ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rails_llm/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rails-llm"
7
+ spec.version = RailsLLM::VERSION
8
+ spec.authors = ["0x1eef"]
9
+ spec.email = ["0x1eef@hardenedbsd.org"]
10
+
11
+ spec.description = <<~DESC.strip
12
+ RailsLLM integrates the llm.rb runtime and its features into Rails.
13
+
14
+ RailsLLM extends the builtin ActiveRecord support available to the llm.rb
15
+ runtime with a Rails integration that includes generators for getting set up quickly,
16
+ and an engine for a stream-capable chat interface that can be extended with your
17
+ own tools.
18
+
19
+ The llm.rb runtime runs on Ruby's standard library by default. loads optional pieces
20
+ only when needed, and offers a single runtime for providers, agents, tools, skills, MCP,
21
+ A2A (Agent2Agent), RAG (vector stores & embeddings), streaming, files, and persisted state.
22
+ DESC
23
+ spec.summary = spec.description
24
+
25
+ spec.homepage = "https://github.com/llmrb/rails-llm"
26
+ spec.license = "0BSD"
27
+ spec.required_ruby_version = ">= 3.1.0"
28
+
29
+ spec.metadata["homepage_uri"] = spec.homepage
30
+ spec.metadata["source_code_uri"] = spec.homepage
31
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/releases"
32
+ spec.metadata["documentation_uri"] = "https://0x1eef.github.io/x/llm.rb"
33
+ spec.metadata["rubygems_mfa_required"] = "true"
34
+
35
+ spec.files = Dir["lib/**/*", "app/**/*", "config/**/*"] +
36
+ %w[README.md LICENSE Gemfile rails-llm.gemspec]
37
+ spec.require_paths = ["lib"]
38
+
39
+ spec.add_dependency "llm.rb", "~> 11.0"
40
+ spec.add_dependency "redcarpet", "~> 3.6"
41
+ spec.add_dependency "railties", ">= 7.0"
42
+ spec.add_dependency "actioncable", ">= 7.0"
43
+ spec.add_dependency "activerecord", ">= 7.0"
44
+
45
+ spec.add_development_dependency "rspec-rails"
46
+ spec.add_development_dependency "sqlite3"
47
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-llm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - '0x1eef'
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: llm.rb
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '11.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '11.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: redcarpet
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.6'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.6'
40
+ - !ruby/object:Gem::Dependency
41
+ name: railties
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '7.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '7.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: actioncable
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '7.0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '7.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: activerecord
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '7.0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '7.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec-rails
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: sqlite3
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: |-
111
+ RailsLLM integrates the llm.rb runtime and its features into Rails.
112
+
113
+ RailsLLM extends the builtin ActiveRecord support available to the llm.rb
114
+ runtime with a Rails integration that includes generators for getting set up quickly,
115
+ and an engine for a stream-capable chat interface that can be extended with your
116
+ own tools.
117
+
118
+ The llm.rb runtime runs on Ruby's standard library by default. loads optional pieces
119
+ only when needed, and offers a single runtime for providers, agents, tools, skills, MCP,
120
+ A2A (Agent2Agent), RAG (vector stores & embeddings), streaming, files, and persisted state.
121
+ email:
122
+ - 0x1eef@hardenedbsd.org
123
+ executables: []
124
+ extensions: []
125
+ extra_rdoc_files: []
126
+ files:
127
+ - Gemfile
128
+ - LICENSE
129
+ - README.md
130
+ - app/assets/images/llm.png
131
+ - app/assets/javascripts/rails_llm/application.js
132
+ - app/controllers/rails_llm/agents_controller.rb
133
+ - app/views/layouts/rails_llm/application.html.erb
134
+ - app/views/rails_llm/agents/_message.html.erb
135
+ - app/views/rails_llm/agents/index.html.erb
136
+ - app/views/rails_llm/agents/show.html.erb
137
+ - config/routes.rb
138
+ - lib/generators/rails_llm/install_generator.rb
139
+ - lib/generators/rails_llm/templates/agent_model.rb.tt
140
+ - lib/generators/rails_llm/templates/initializer.rb.tt
141
+ - lib/generators/rails_llm/templates/knowledge_tool.rb.tt
142
+ - lib/generators/rails_llm/templates/migration.rb.tt
143
+ - lib/generators/rails_llm/ui_generator.rb
144
+ - lib/rails-llm.rb
145
+ - lib/rails_llm.rb
146
+ - lib/rails_llm/engine.rb
147
+ - lib/rails_llm/stream.rb
148
+ - lib/rails_llm/version.rb
149
+ - rails-llm.gemspec
150
+ homepage: https://github.com/llmrb/rails-llm
151
+ licenses:
152
+ - 0BSD
153
+ metadata:
154
+ homepage_uri: https://github.com/llmrb/rails-llm
155
+ source_code_uri: https://github.com/llmrb/rails-llm
156
+ changelog_uri: https://github.com/llmrb/rails-llm/releases
157
+ documentation_uri: https://0x1eef.github.io/x/llm.rb
158
+ rubygems_mfa_required: 'true'
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 3.1.0
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubygems_version: 4.0.6
174
+ specification_version: 4
175
+ summary: RailsLLM integrates the llm.rb runtime and its features into Rails. RailsLLM
176
+ extends the builtin ActiveRecord support available to the llm.rb runtime with a
177
+ Rails integration that includes generators for getting set up quickly, and an engine
178
+ for a stream-capable chat interface that can be extended with your own tools. The
179
+ llm.rb runtime runs on Ruby's standard library by default. loads optional pieces
180
+ only when needed, and offers a single runtime for providers, agents, tools, skills,
181
+ MCP, A2A (Agent2Agent), RAG (vector stores & embeddings), streaming, files, and
182
+ persisted state.
183
+ test_files: []