ruby_llm-agents 1.2.0 → 1.2.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.
- checksums.yaml +4 -4
- data/app/views/layouts/ruby_llm/agents/application.html.erb +1 -1
- data/app/views/ruby_llm/agents/agents/_empty_state.html.erb +22 -19
- data/app/views/ruby_llm/agents/workflows/_empty_state.html.erb +22 -0
- data/app/views/ruby_llm/agents/workflows/index.html.erb +1 -1
- data/lib/ruby_llm/agents/core/configuration.rb +18 -26
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/rails/engine.rb +22 -28
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6f99247af4fcb9e76776ab2658bac4914d5b869423258bf3827583212447146
|
|
4
|
+
data.tar.gz: a6927cced434962ed4b923717d7fd582e983c3091ac8172554afb68671a2514d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c98ae91fde73edf152ac4efc5665fe5da30e17ec14ff9f2f9128102bf4665530f55196e705dc371f0dac2354af4ab7a2102be9c04b3b7ec2e8331b7b5445ce23
|
|
7
|
+
data.tar.gz: af36432d85c4ac5ee6219eba846411dd4ffaa0ba8d8c9998550ea3d3e757fd125fa8a2bea3cc5c98a0387db519cc03b45d1fd3f3d63de5facc2dc84338b02692
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
<%
|
|
215
215
|
nav_items = [
|
|
216
216
|
{ path: ruby_llm_agents.root_path, label: "Dashboard", icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />' },
|
|
217
|
-
{ path: ruby_llm_agents.agents_path, label: "Agents", icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9
|
|
217
|
+
{ path: ruby_llm_agents.agents_path, label: "Agents", icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>' },
|
|
218
218
|
{ path: ruby_llm_agents.workflows_path, label: "Workflows", icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zm0 8a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zm12 0a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"/>' },
|
|
219
219
|
{ path: ruby_llm_agents.executions_path, label: "Executions", icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" />' },
|
|
220
220
|
{ path: ruby_llm_agents.tenants_path, label: "Tenants", icon: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />' }
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<div class="bg-white dark:bg-gray-800 rounded-lg shadow p-8 text-center">
|
|
6
|
-
<svg class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
7
|
-
<% if is_workflow %>
|
|
8
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zm0 8a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zm12 0a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"/>
|
|
9
|
-
<% else %>
|
|
10
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
|
11
|
-
<% end %>
|
|
1
|
+
<div class="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-8 text-center">
|
|
2
|
+
<!-- Agent Icon - Blue -->
|
|
3
|
+
<svg class="mx-auto h-16 w-16 text-blue-500 dark:text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
4
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
|
|
12
5
|
</svg>
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
|
|
7
|
+
<h3 class="mt-4 text-lg font-medium text-gray-900 dark:text-gray-100">
|
|
8
|
+
No agents yet
|
|
15
9
|
</h3>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<% else %>
|
|
20
|
-
Create an agent by running <code class="bg-gray-100 dark:bg-gray-700 dark:text-gray-200 px-1 rounded">rails g ruby_llm_agents:agent YourAgentName</code>
|
|
21
|
-
<% end %>
|
|
10
|
+
|
|
11
|
+
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400 max-w-md mx-auto">
|
|
12
|
+
Create an agent by inheriting from <code class="bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 px-1.5 py-0.5 rounded font-mono text-xs">ApplicationAgent</code>
|
|
22
13
|
</p>
|
|
14
|
+
|
|
15
|
+
<!-- Code Example -->
|
|
16
|
+
<div class="mt-6 max-w-sm mx-auto">
|
|
17
|
+
<pre class="bg-gray-900 dark:bg-gray-950 rounded-lg p-4 text-left text-sm overflow-x-auto"><code class="text-gray-300"><span class="text-pink-400">class</span> <span class="text-yellow-300">MyAgent</span> <span class="text-pink-400"><</span> <span class="text-yellow-300">ApplicationAgent</span>
|
|
18
|
+
<span class="text-purple-400">model</span> <span class="text-green-400">"gpt-4o-mini"</span>
|
|
19
|
+
<span class="text-purple-400">param</span> <span class="text-blue-400">:query</span>, <span class="text-blue-400">required:</span> <span class="text-orange-400">true</span>
|
|
20
|
+
|
|
21
|
+
<span class="text-pink-400">def</span> <span class="text-blue-300">user_prompt</span>
|
|
22
|
+
<span class="text-gray-300">query</span>
|
|
23
|
+
<span class="text-pink-400">end</span>
|
|
24
|
+
<span class="text-pink-400">end</span></code></pre>
|
|
25
|
+
</div>
|
|
23
26
|
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<div class="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-8 text-center">
|
|
2
|
+
<!-- Workflow Icon - Emerald -->
|
|
3
|
+
<svg class="mx-auto h-16 w-16 text-emerald-500 dark:text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
4
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>
|
|
5
|
+
</svg>
|
|
6
|
+
|
|
7
|
+
<h3 class="mt-4 text-lg font-medium text-gray-900 dark:text-gray-100">
|
|
8
|
+
No workflows yet
|
|
9
|
+
</h3>
|
|
10
|
+
|
|
11
|
+
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400 max-w-md mx-auto">
|
|
12
|
+
Create a workflow by inheriting from <code class="bg-emerald-100 dark:bg-emerald-900/50 text-emerald-700 dark:text-emerald-300 px-1.5 py-0.5 rounded font-mono text-xs">ApplicationWorkflow</code> and defining steps
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<!-- Code Example -->
|
|
16
|
+
<div class="mt-6 max-w-sm mx-auto">
|
|
17
|
+
<pre class="bg-gray-900 dark:bg-gray-950 rounded-lg p-4 text-left text-sm overflow-x-auto"><code class="text-gray-300"><span class="text-pink-400">class</span> <span class="text-yellow-300">MyWorkflow</span> <span class="text-pink-400"><</span> <span class="text-yellow-300">ApplicationWorkflow</span>
|
|
18
|
+
<span class="text-purple-400">step</span> <span class="text-emerald-400">:analyze</span>, <span class="text-yellow-300">AnalyzerAgent</span>
|
|
19
|
+
<span class="text-purple-400">step</span> <span class="text-emerald-400">:summarize</span>, <span class="text-yellow-300">SummarizerAgent</span>
|
|
20
|
+
<span class="text-pink-400">end</span></code></pre>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
9
|
<% if @workflows.empty? %>
|
|
10
|
-
<%= render "ruby_llm/agents/
|
|
10
|
+
<%= render "ruby_llm/agents/workflows/empty_state" %>
|
|
11
11
|
<% else %>
|
|
12
12
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
|
|
13
13
|
<div class="overflow-x-auto">
|
|
@@ -353,21 +353,21 @@ module RubyLLM
|
|
|
353
353
|
# config.async_max_concurrency = 20
|
|
354
354
|
|
|
355
355
|
# @!attribute [rw] root_directory
|
|
356
|
-
# The root directory name under app/ for all
|
|
356
|
+
# The root directory name under app/ for all agent components.
|
|
357
357
|
# This allows customization of the directory structure.
|
|
358
|
-
# @return [String] Directory name (default: "
|
|
358
|
+
# @return [String] Directory name (default: "agents")
|
|
359
359
|
# @example
|
|
360
|
-
# config.root_directory = "ai" # Creates app/ai/ instead of app/
|
|
360
|
+
# config.root_directory = "ai" # Creates app/ai/ instead of app/agents/
|
|
361
361
|
|
|
362
362
|
# @!attribute [rw] root_namespace
|
|
363
|
-
# The root namespace for all
|
|
364
|
-
#
|
|
365
|
-
# Set to nil or "" to use no namespace
|
|
366
|
-
# @return [String, nil] Namespace (default:
|
|
363
|
+
# The root namespace for all agent component classes.
|
|
364
|
+
# When set, subdirectory namespaces are prefixed with this.
|
|
365
|
+
# Set to nil or "" to use no root namespace.
|
|
366
|
+
# @return [String, nil] Namespace (default: nil)
|
|
367
367
|
# @example Custom namespace
|
|
368
|
-
# config.root_namespace = "AI" #
|
|
369
|
-
# @example No namespace (
|
|
370
|
-
# config.root_namespace = nil #
|
|
368
|
+
# config.root_namespace = "AI" # app/agents/embedders -> AI::Embedders
|
|
369
|
+
# @example No namespace (default)
|
|
370
|
+
# config.root_namespace = nil # app/agents/embedders -> Embedders
|
|
371
371
|
|
|
372
372
|
# Attributes without validation (simple accessors)
|
|
373
373
|
attr_accessor :default_model,
|
|
@@ -821,26 +821,18 @@ module RubyLLM
|
|
|
821
821
|
|
|
822
822
|
# Returns the full namespace for a given category
|
|
823
823
|
#
|
|
824
|
-
# @param category [Symbol, nil] Category (
|
|
824
|
+
# @param category [Symbol, String, nil] Category (e.g., :embedders, :images, or nil for root)
|
|
825
825
|
# @return [String, nil] Full namespace string, or nil if no namespace configured
|
|
826
|
-
# @example With root_namespace = "
|
|
827
|
-
# namespace_for(:
|
|
828
|
-
# namespace_for(nil)
|
|
826
|
+
# @example With root_namespace = "AI"
|
|
827
|
+
# namespace_for(:embedders) #=> "AI::Embedders"
|
|
828
|
+
# namespace_for(nil) #=> "AI"
|
|
829
829
|
# @example With no namespace (root_namespace = nil)
|
|
830
|
-
# namespace_for(:
|
|
831
|
-
# namespace_for(nil)
|
|
830
|
+
# namespace_for(:embedders) #=> "Embedders"
|
|
831
|
+
# namespace_for(nil) #=> nil
|
|
832
832
|
def namespace_for(category = nil)
|
|
833
|
-
category_namespace =
|
|
834
|
-
when :images then "Images"
|
|
835
|
-
when :audio then "Audio"
|
|
836
|
-
when :embedders then "Embedders"
|
|
837
|
-
when :moderators then "Moderators"
|
|
838
|
-
when :workflows then "Workflows"
|
|
839
|
-
when :text then "Text"
|
|
840
|
-
when :image then "Image"
|
|
841
|
-
end
|
|
833
|
+
category_namespace = category&.to_s&.camelize
|
|
842
834
|
|
|
843
|
-
if root_namespace
|
|
835
|
+
if root_namespace.present?
|
|
844
836
|
category_namespace ? "#{root_namespace}::#{category_namespace}" : root_namespace
|
|
845
837
|
else
|
|
846
838
|
category_namespace
|
|
@@ -170,14 +170,16 @@ module RubyLLM
|
|
|
170
170
|
g.factory_bot dir: "spec/factories"
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
# Adds the host app's
|
|
173
|
+
# Adds the host app's agent directories to Rails autoload paths
|
|
174
174
|
#
|
|
175
|
-
# This allows agent classes and other
|
|
175
|
+
# This allows agent classes and other components defined in app/agents/
|
|
176
176
|
# to be automatically loaded without explicit requires.
|
|
177
177
|
#
|
|
178
|
-
# Supports
|
|
179
|
-
#
|
|
180
|
-
#
|
|
178
|
+
# Supports subdirectory namespacing:
|
|
179
|
+
# - app/agents/ (top-level, no namespace)
|
|
180
|
+
# - app/agents/embedders/ -> Embedders namespace
|
|
181
|
+
# - app/agents/images/ -> Images namespace
|
|
182
|
+
# - app/workflows/ (top-level, no namespace)
|
|
181
183
|
#
|
|
182
184
|
# @api private
|
|
183
185
|
initializer "ruby_llm_agents.autoload_agents", before: :set_autoload_paths do |app|
|
|
@@ -210,42 +212,34 @@ module RubyLLM
|
|
|
210
212
|
|
|
211
213
|
# Determines the namespace constant for a given path
|
|
212
214
|
#
|
|
213
|
-
# @param path [String] Relative path like "app/
|
|
215
|
+
# @param path [String] Relative path like "app/agents/embedders"
|
|
214
216
|
# @param config [Configuration] Current configuration
|
|
215
217
|
# @return [Module, nil] Namespace module or nil for top-level
|
|
216
218
|
# @api private
|
|
217
219
|
def self.namespace_for_path(path, config)
|
|
218
|
-
# Parse the path to determine namespace
|
|
219
220
|
parts = path.split("/")
|
|
220
|
-
return nil unless parts.length >= 3
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
# app/workflows -> no namespace (top-level workflows)
|
|
223
|
+
return nil if parts == ["app", "workflows"]
|
|
223
224
|
|
|
224
|
-
#
|
|
225
|
+
# Need at least app/{root_directory}
|
|
226
|
+
return nil unless parts.length >= 2 && parts[0] == "app"
|
|
227
|
+
return nil unless parts[1] == config.root_directory
|
|
228
|
+
|
|
229
|
+
# app/agents -> no namespace (root level)
|
|
230
|
+
return nil if parts.length == 2
|
|
231
|
+
|
|
232
|
+
# app/agents/embedders -> Embedders namespace
|
|
233
|
+
subdirectory = parts[2]
|
|
225
234
|
namespace_name = if config.root_namespace.blank?
|
|
226
|
-
|
|
227
|
-
case category
|
|
228
|
-
when "audio", "image", "text"
|
|
229
|
-
category.camelize # "Audio", "Image", "Text"
|
|
230
|
-
else
|
|
231
|
-
nil # Top-level for agents, workflows, tools
|
|
232
|
-
end
|
|
235
|
+
subdirectory.camelize
|
|
233
236
|
else
|
|
234
|
-
#
|
|
235
|
-
case category
|
|
236
|
-
when "audio", "image", "text"
|
|
237
|
-
"#{config.root_namespace}::#{category.camelize}"
|
|
238
|
-
else
|
|
239
|
-
config.root_namespace
|
|
240
|
-
end
|
|
237
|
+
"#{config.root_namespace}::#{subdirectory.camelize}"
|
|
241
238
|
end
|
|
242
239
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
# Return the constant, creating intermediate modules if needed
|
|
240
|
+
# Create the namespace module if needed
|
|
246
241
|
namespace_name.constantize
|
|
247
242
|
rescue NameError
|
|
248
|
-
# Create the namespace module if it doesn't exist
|
|
249
243
|
namespace_name.split("::").inject(Object) do |mod, name|
|
|
250
244
|
mod.const_defined?(name, false) ? mod.const_get(name) : mod.const_set(name, Module.new)
|
|
251
245
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_llm-agents
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- adham90
|
|
@@ -159,6 +159,7 @@ files:
|
|
|
159
159
|
- app/views/ruby_llm/agents/tenants/edit.html.erb
|
|
160
160
|
- app/views/ruby_llm/agents/tenants/index.html.erb
|
|
161
161
|
- app/views/ruby_llm/agents/tenants/show.html.erb
|
|
162
|
+
- app/views/ruby_llm/agents/workflows/_empty_state.html.erb
|
|
162
163
|
- app/views/ruby_llm/agents/workflows/_step_performance.html.erb
|
|
163
164
|
- app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb
|
|
164
165
|
- app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb
|