ruby_llm-agents 0.3.5 → 0.3.6
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/controllers/ruby_llm/agents/agents_controller.rb +2 -1
- data/app/services/ruby_llm/agents/agent_registry.rb +1 -0
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +13 -2
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +13 -2
- data/app/views/ruby_llm/agents/agents/show.html.erb +5 -0
- data/lib/generators/ruby_llm_agents/agent_generator.rb +9 -4
- data/lib/ruby_llm/agents/base/dsl.rb +11 -0
- data/lib/ruby_llm/agents/base/execution.rb +3 -2
- data/lib/ruby_llm/agents/version.rb +1 -1
- data/lib/ruby_llm/agents/workflow.rb +16 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40771a5bbdc5c7baea26c0900c6715e3e1033569154ebeb0d7cd60eff83d1389
|
|
4
|
+
data.tar.gz: bedbf16ff8717ebcdca79aa256f9aae489677baad1b848baa38d4d485b87c803
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3202614bf8c8209a1e9a589137440c804d2fcdc8fa2045840e4429963e06a0b4b1b25f82da99f6e1a5e3090afa1b149dec500d87ce59c09de946a3293e728962
|
|
7
|
+
data.tar.gz: '08d565511fc883fdb83377e4993dbd699a5ecce23cbfdc454c6372279fc275165dddfc5c0b4b4d1010f1dde3c4acdaca4f260d0c07b6cc7b9ad81e7b13cd4b41'
|
|
@@ -58,7 +58,7 @@ module RubyLLM
|
|
|
58
58
|
#
|
|
59
59
|
# @return [void]
|
|
60
60
|
def show
|
|
61
|
-
@agent_type = params[:id]
|
|
61
|
+
@agent_type = CGI.unescape(params[:id])
|
|
62
62
|
@agent_class = AgentRegistry.find(@agent_type)
|
|
63
63
|
@agent_active = @agent_class.present?
|
|
64
64
|
|
|
@@ -215,6 +215,7 @@ module RubyLLM
|
|
|
215
215
|
model: @agent_class.model,
|
|
216
216
|
temperature: @agent_class.temperature,
|
|
217
217
|
version: @agent_class.version,
|
|
218
|
+
description: @agent_class.respond_to?(:description) ? @agent_class.description : nil,
|
|
218
219
|
timeout: @agent_class.timeout,
|
|
219
220
|
cache_enabled: @agent_class.cache_enabled?,
|
|
220
221
|
cache_ttl: @agent_class.cache_ttl,
|
|
@@ -140,6 +140,7 @@ module RubyLLM
|
|
|
140
140
|
workflow_type: workflow_type,
|
|
141
141
|
workflow_children: workflow_children,
|
|
142
142
|
version: safe_call(agent_class, :version) || "N/A",
|
|
143
|
+
description: safe_call(agent_class, :description),
|
|
143
144
|
model: safe_call(agent_class, :model) || (is_workflow ? "workflow" : "N/A"),
|
|
144
145
|
temperature: safe_call(agent_class, :temperature),
|
|
145
146
|
timeout: safe_call(agent_class, :timeout),
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
<%= link_to ruby_llm_agents.agent_path(agent[:name]), class: "block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow" do %>
|
|
1
|
+
<%= link_to ruby_llm_agents.agent_path(ERB::Util.url_encode(agent[:name])), class: "block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow" do %>
|
|
2
2
|
<div class="p-4 sm:p-5">
|
|
3
3
|
<!-- Row 1: Agent name + badge + model/timestamp -->
|
|
4
4
|
<div class="flex items-center justify-between gap-2">
|
|
5
5
|
<div class="flex items-center gap-2 min-w-0">
|
|
6
6
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 truncate">
|
|
7
|
-
|
|
7
|
+
<% name_parts = agent[:name].gsub(/Agent$/, '').split('::') %>
|
|
8
|
+
<% if name_parts.length > 1 %>
|
|
9
|
+
<span class="text-gray-400 dark:text-gray-500 font-normal"><%= name_parts[0..-2].join('::') %>::</span>
|
|
10
|
+
<% end %>
|
|
11
|
+
<%= name_parts.last %>
|
|
8
12
|
</h3>
|
|
9
13
|
<span class="hidden sm:inline text-sm text-gray-500 dark:text-gray-400">v<%= agent[:version] %></span>
|
|
10
14
|
<% if agent[:active] %>
|
|
@@ -25,6 +29,13 @@
|
|
|
25
29
|
</span>
|
|
26
30
|
</div>
|
|
27
31
|
|
|
32
|
+
<!-- Description -->
|
|
33
|
+
<% if agent[:description].present? %>
|
|
34
|
+
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">
|
|
35
|
+
<%= agent[:description] %>
|
|
36
|
+
</p>
|
|
37
|
+
<% end %>
|
|
38
|
+
|
|
28
39
|
<!-- Row 2: Stats -->
|
|
29
40
|
<div class="mt-2 sm:mt-3 sm:border-t sm:border-gray-100 sm:dark:border-gray-700 sm:pt-3">
|
|
30
41
|
<!-- Mobile: compact inline -->
|
|
@@ -15,13 +15,17 @@
|
|
|
15
15
|
%>
|
|
16
16
|
|
|
17
17
|
<div x-data="{ expanded: false }" class="block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow border-l-4 <%= colors[:border] %>">
|
|
18
|
-
<%= link_to ruby_llm_agents.agent_path(workflow[:name]), class: "block p-4 sm:p-5" do %>
|
|
18
|
+
<%= link_to ruby_llm_agents.agent_path(ERB::Util.url_encode(workflow[:name])), class: "block p-4 sm:p-5" do %>
|
|
19
19
|
<!-- Header Row -->
|
|
20
20
|
<div class="flex items-center justify-between gap-2">
|
|
21
21
|
<div class="flex items-center gap-2 min-w-0">
|
|
22
22
|
<%= render "ruby_llm/agents/shared/workflow_type_badge", workflow_type: workflow[:workflow_type], size: :sm %>
|
|
23
23
|
<h3 class="font-semibold text-gray-900 dark:text-gray-100 truncate">
|
|
24
|
-
|
|
24
|
+
<% name_parts = workflow[:name].gsub(/Workflow$/, '').gsub(/Pipeline$|Parallel$|Router$/, '').split('::') %>
|
|
25
|
+
<% if name_parts.length > 1 %>
|
|
26
|
+
<span class="text-gray-400 dark:text-gray-500 font-normal"><%= name_parts[0..-2].join('::') %>::</span>
|
|
27
|
+
<% end %>
|
|
28
|
+
<%= name_parts.last %>
|
|
25
29
|
</h3>
|
|
26
30
|
<span class="hidden sm:inline text-sm text-gray-500 dark:text-gray-400">v<%= workflow[:version] %></span>
|
|
27
31
|
<% if workflow[:active] %>
|
|
@@ -35,6 +39,13 @@
|
|
|
35
39
|
</span>
|
|
36
40
|
</div>
|
|
37
41
|
|
|
42
|
+
<!-- Description -->
|
|
43
|
+
<% if workflow[:description].present? %>
|
|
44
|
+
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">
|
|
45
|
+
<%= workflow[:description] %>
|
|
46
|
+
</p>
|
|
47
|
+
<% end %>
|
|
48
|
+
|
|
38
49
|
<!-- Stats Row -->
|
|
39
50
|
<div class="mt-2 sm:mt-3 sm:border-t sm:border-gray-100 sm:dark:border-gray-700 sm:pt-3">
|
|
40
51
|
<% success_rate = workflow[:success_rate] || 0 %>
|
|
@@ -45,6 +45,11 @@
|
|
|
45
45
|
<%= @config[:model] %> · temp <%= @config[:temperature] %>
|
|
46
46
|
· timeout <%= @config[:timeout] %>s
|
|
47
47
|
</p>
|
|
48
|
+
<% if @config[:description].present? %>
|
|
49
|
+
<p class="text-gray-600 dark:text-gray-300 mt-2">
|
|
50
|
+
<%= @config[:description] %>
|
|
51
|
+
</p>
|
|
52
|
+
<% end %>
|
|
48
53
|
<% end %>
|
|
49
54
|
</div>
|
|
50
55
|
|
|
@@ -29,16 +29,21 @@ module RubyLlmAgents
|
|
|
29
29
|
desc: "Cache TTL (e.g., '1.hour', '30.minutes')"
|
|
30
30
|
|
|
31
31
|
def create_agent_file
|
|
32
|
-
|
|
32
|
+
# Support nested paths: "chat/support" -> "app/agents/chat/support_agent.rb"
|
|
33
|
+
# Rails' class_name handles namespacing: "chat/support" -> "Chat::Support"
|
|
34
|
+
agent_path = name.underscore
|
|
35
|
+
template "agent.rb.tt", "app/agents/#{agent_path}_agent.rb"
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def show_usage
|
|
39
|
+
# Build full class name from path (e.g., "chat/support" -> "Chat::Support")
|
|
40
|
+
full_class_name = name.split('/').map(&:camelize).join("::")
|
|
36
41
|
say ""
|
|
37
|
-
say "Agent #{
|
|
42
|
+
say "Agent #{full_class_name}Agent created!", :green
|
|
38
43
|
say ""
|
|
39
44
|
say "Usage:"
|
|
40
|
-
say " #{
|
|
41
|
-
say " #{
|
|
45
|
+
say " #{full_class_name}Agent.call(#{usage_params})"
|
|
46
|
+
say " #{full_class_name}Agent.call(#{usage_params}, dry_run: true)"
|
|
42
47
|
say ""
|
|
43
48
|
end
|
|
44
49
|
|
|
@@ -48,6 +48,17 @@ module RubyLLM
|
|
|
48
48
|
@version || inherited_or_default(:version, VERSION)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
# Sets or returns the description for this agent class
|
|
52
|
+
#
|
|
53
|
+
# @param value [String, nil] The description text
|
|
54
|
+
# @return [String, nil] The current description
|
|
55
|
+
# @example
|
|
56
|
+
# description "Searches the knowledge base for relevant documents"
|
|
57
|
+
def description(value = nil)
|
|
58
|
+
@description = value if value
|
|
59
|
+
@description || inherited_or_default(:description, nil)
|
|
60
|
+
end
|
|
61
|
+
|
|
51
62
|
# Sets or returns the timeout in seconds for LLM requests
|
|
52
63
|
#
|
|
53
64
|
# @param value [Integer, nil] Timeout in seconds
|
|
@@ -233,9 +233,10 @@ module RubyLLM
|
|
|
233
233
|
# @param msgs [Array<Hash>] Messages with :role and :content keys
|
|
234
234
|
# @return [RubyLLM::Chat] Client with messages applied
|
|
235
235
|
def apply_messages(client, msgs)
|
|
236
|
-
msgs.
|
|
237
|
-
|
|
236
|
+
msgs.each do |message|
|
|
237
|
+
client.add_message(role: message[:role].to_sym, content: message[:content])
|
|
238
238
|
end
|
|
239
|
+
client
|
|
239
240
|
end
|
|
240
241
|
|
|
241
242
|
# Builds a client with pre-populated conversation history
|
|
@@ -42,6 +42,10 @@ module RubyLLM
|
|
|
42
42
|
# @return [Float, nil] Maximum cost threshold for the workflow
|
|
43
43
|
attr_accessor :_max_cost
|
|
44
44
|
|
|
45
|
+
# @!attribute [rw] description
|
|
46
|
+
# @return [String, nil] Description of the workflow
|
|
47
|
+
attr_accessor :_description
|
|
48
|
+
|
|
45
49
|
# Sets or returns the workflow version
|
|
46
50
|
#
|
|
47
51
|
# @param value [String, nil] Version string to set
|
|
@@ -78,6 +82,18 @@ module RubyLLM
|
|
|
78
82
|
end
|
|
79
83
|
end
|
|
80
84
|
|
|
85
|
+
# Sets or returns the workflow description
|
|
86
|
+
#
|
|
87
|
+
# @param value [String, nil] Description text to set
|
|
88
|
+
# @return [String, nil] The current description
|
|
89
|
+
def description(value = nil)
|
|
90
|
+
if value
|
|
91
|
+
self._description = value
|
|
92
|
+
else
|
|
93
|
+
_description
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
81
97
|
# Factory method to instantiate and execute a workflow
|
|
82
98
|
#
|
|
83
99
|
# @param kwargs [Hash] Parameters to pass to the workflow
|