ruboty-ai_agent 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4358837ce9305dcb0965a67c957b75e8320aad2988647a9e6ae751a98e7b7009
4
- data.tar.gz: 3b1ad1c43bc443c5d86b1ea80bd8d9a45263056bc91ade861058e600493cb1b7
3
+ metadata.gz: ab07f82523eaf799691d9b03457bfa01751d0b0d1864e69bbbfc8661d34a0fef
4
+ data.tar.gz: 9e51ee2e35c00010df295626b8749019feefc67eab4d5fe396913eb1f468e433
5
5
  SHA512:
6
- metadata.gz: fb0b30fad316d595d3e088d9262b46b32af67467c23b28494a7214f83093bb2a939953005c19b84e907eae81c4d1ba00a2dd84ca96e8cc85fdffe016d687e036
7
- data.tar.gz: 586e425b1c2f806d663e861d18fa57579649b6d29135576a1677f825f637fc017d5cb910e6b1edc1bc2e1a7d5c8eb4e40d6c7795c170e69f418434b84750c0f8
6
+ metadata.gz: beda5fe21c74e2def519c4e7d9bef74144fffb5daa7ea2334debc065218ab319eead0be9db7a36fda3ed4909bd16b54dab8f289dfd94da77b971c20b20f5a40e
7
+ data.tar.gz: 1b7a5ff752355974c23a807c6360d2a8454d19e0afc7e0546e253c99e9ed79a2731aa32a02963471449052c81f7e1635babf7e16d093cc8708ba71889638ae4c
data/CHANGELOG.md CHANGED
@@ -1,4 +1,11 @@
1
1
  ## Unreleased
2
+ ## 0.4.0
3
+
4
+ - Add `bot_help` builtin tool to retrieve Ruboty's help information.
5
+ - Add `fetch` builtin tool for fetching web content.
6
+ - Fix `/usage` command to show token usage of last message.
7
+ - Format tool call logs for better readability.
8
+
2
9
  ## 0.3.0
3
10
 
4
11
  - Add think tool.
data/Gemfile CHANGED
@@ -19,3 +19,5 @@ gem 'rubocop-rake', '~> 0.7.0'
19
19
  gem 'rubocop-rbs_inline', '~> 1.4.0'
20
20
  gem 'rubocop-rspec', '~> 3.7.0'
21
21
  gem 'steep', require: false
22
+
23
+ gem 'ruby-readability'
data/bin/ruboty CHANGED
@@ -17,6 +17,8 @@ gemfile do
17
17
  gem 'ruboty'
18
18
  gem 'ruboty-ai_agent', path: '../'
19
19
 
20
+ gem 'ruby-readability'
21
+
20
22
  # You can add other ruboty plugins here for testing.
21
23
  # gem 'ruboty-echo'
22
24
  # gem 'ruboty-alias'
@@ -82,10 +82,10 @@ module Ruboty
82
82
 
83
83
  chat_thread.messages.compact(llm:) if chat_thread.messages.over_auto_compact_threshold?
84
84
  when :tool_call
85
- message.reply("Calling tool #{event[:tool].name} with arguments #{event[:tool_arguments]&.to_json}") unless event[:tool].silent?
85
+ message.reply(indent_with_quotation("Calling tool #{event[:tool].name} with arguments #{truncate(event[:tool_arguments]&.to_json, max: 100)}")) unless event[:tool].silent?
86
86
  when :tool_response
87
87
  chat_thread.messages << event[:message]
88
- message.reply("Tool response: #{event[:tool_response].slice(0..100)}") unless event[:tool].silent?
88
+ message.reply(indent_with_quotation("Tool response: #{truncate(event[:tool_response], max: 100)}")) unless event[:tool].silent?
89
89
  end
90
90
  end
91
91
  rescue StandardError => e
@@ -95,6 +95,18 @@ module Ruboty
95
95
  message.reply("エラーが発生しました: #{e.message}")
96
96
  end
97
97
  end
98
+
99
+ def truncate(text, max:)
100
+ if text.length > max
101
+ "#{text.slice(0..max)}..."
102
+ else
103
+ text
104
+ end
105
+ end
106
+
107
+ def indent_with_quotation(text, quota = '> ')
108
+ text.lines.map { |line| "#{quota}#{line}" }.join
109
+ end
98
110
  end
99
111
  end
100
112
  end
@@ -11,12 +11,15 @@ module Ruboty
11
11
  store(message, key: (keys.last.to_s.to_i || -1) + 1)
12
12
  end
13
13
 
14
+ def token_usage #: TokenUsage?
15
+ all_values.reverse_each.find(&:token_usage)&.token_usage
16
+ end
17
+
14
18
  alias << add
15
19
 
16
20
  # Check if any message's token usage exceeds auto compact threshold
17
- # @rbs return: bool
18
- def over_auto_compact_threshold?
19
- all_values.any? { |message| message.token_usage&.over_auto_compact_threshold? }
21
+ def over_auto_compact_threshold? #: boolish
22
+ token_usage&.over_auto_compact_threshold?
20
23
  end
21
24
 
22
25
  # Compact chat messages by summarizing them
@@ -8,9 +8,7 @@ module Ruboty
8
8
  on(%r{/usage}, name: 'show_usage', description: 'Show token usage information for the latest AI response')
9
9
 
10
10
  def call(*) #: void
11
- latest_message = chat_thread.messages.all_values.find(&:token_usage)
12
-
13
- token_usage = latest_message&.token_usage
11
+ token_usage = chat_thread.messages.token_usage
14
12
 
15
13
  if token_usage
16
14
  usage_text = "Token usage: #{format_number(token_usage.prompt_tokens)} (prompt) + #{format_number(token_usage.completion_tokens)} (completion) = #{format_number(token_usage.total_tokens)} (total)"
@@ -18,7 +18,7 @@ module Ruboty
18
18
  Commands::Clear,
19
19
  Commands::Compact,
20
20
  Commands::Usage
21
- ].map { |cmd_class| cmd_class.new(request: request) }
21
+ ].map { |cmd_class| cmd_class.new(request:) }
22
22
  end
23
23
  end
24
24
  end
@@ -19,7 +19,7 @@ module Ruboty
19
19
  if name.include?('gpt-5')
20
20
  400_000
21
21
  else
22
- 128_000
22
+ AiAgent.settings.max_tokens || 128_000
23
23
  end
24
24
  end
25
25
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ # Provide library-wide settings.
6
+ class Settings
7
+ # Provide access to settings instance.
8
+ module Accessor
9
+ def settings #: Ruboty::AiAgent::Settings
10
+ Settings.instance
11
+ end
12
+ end
13
+
14
+ # @rbs %a{memorized}
15
+ def self.instance #: Ruboty::AiAgent::Settings
16
+ @instance ||= Settings.new
17
+ end
18
+
19
+ def max_tokens #: Integer?
20
+ ENV['AI_AGENT_MAX_TOKENS']&.to_i
21
+ end
22
+
23
+ def auto_compact_threshold #: Float
24
+ ENV.fetch('AI_AGENT_AUTO_COMPACT_THRESHOLD', '80').to_f
25
+ end
26
+ end
27
+ end
28
+ end
@@ -20,6 +20,10 @@ module Ruboty
20
20
  # def self.tool_input_schema=: (input_schema) -> input_schema
21
21
 
22
22
  class << self
23
+ def available? #: boolish
24
+ true
25
+ end
26
+
23
27
  # @rbs skip
24
28
  attr_accessor :tool_name
25
29
 
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ module ToolDefinitions
6
+ # Tool for retrieving Ruboty help information
7
+ class BotHelp < Base
8
+ self.tool_name = 'bot_help'
9
+ self.tool_title = 'Show help information about this bot (you)'
10
+
11
+ self.tool_description = <<~TEXT
12
+ Get help information about available patterns of this bot (you).
13
+ This returns the same information as the 'help' command in Ruboty.
14
+
15
+ # Hint
16
+
17
+ - You are a Ruboty bot. You can find available commands by using this tool.
18
+ - If user asks for what you can do or usage (e.g. "Tell me the usage", "How do I use it?"), use this tool to respond.
19
+ - If user asks for specific commands, use the 'filter' argument to search for them.
20
+ - If user typed a command that you don't know, use this tool to find out the correct command.
21
+ TEXT
22
+
23
+ self.tool_input_schema = {
24
+ type: 'object',
25
+ properties: {
26
+ filter: {
27
+ type: 'string',
28
+ description: 'Optional filter to search for specific commands (e.g., "mcp", "ai", "ping")'
29
+ }
30
+ },
31
+ required: []
32
+ }
33
+
34
+ # @rbs arguments: Hash[String, untyped]
35
+ # @rbs return: String?
36
+ def call(arguments)
37
+ filter = arguments['filter']
38
+
39
+ descriptions = filtered_descriptions(filter)
40
+
41
+ if descriptions.empty?
42
+ if filter
43
+ "No description matched to '#{filter}'"
44
+ else
45
+ 'No commands available'
46
+ end
47
+ else
48
+ descriptions.join("\n")
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # @rbs filter: String?
55
+ # @rbs return: Array[String]
56
+ def filtered_descriptions(filter)
57
+ descriptions = all_descriptions
58
+
59
+ if filter
60
+ descriptions.select! do |description|
61
+ description.include?(filter)
62
+ end
63
+ end
64
+
65
+ descriptions
66
+ end
67
+
68
+ # @rbs return: Array[String]
69
+ def all_descriptions
70
+ actions = Ruboty.actions.reject(&:hidden?)
71
+
72
+ # Sort by description for consistent ordering
73
+ sorted_actions = begin
74
+ actions.sort_by(&:description)
75
+ rescue ArgumentError
76
+ # Fallback if sorting fails (e.g., in tests with mocks)
77
+ actions
78
+ end
79
+
80
+ sorted_actions.map do |action|
81
+ prefix = ''
82
+ prefix += "#{request.message.robot.name} " unless action.all?
83
+ "#{prefix}#{action.pattern.inspect} - #{action.description}"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'net/https'
6
+
7
+ module Ruboty
8
+ module AiAgent
9
+ module ToolDefinitions
10
+ # Fetch and extract readable content from web pages using ruby-readability
11
+ class Fetch < Base
12
+ class FetchError < StandardError; end
13
+
14
+ self.tool_name = 'fetch'
15
+ self.tool_title = 'Fetch Web Page Content'
16
+
17
+ self.tool_description = <<~TEXT
18
+ Fetch and extract readable content from a web page using ruby-readability.
19
+ This tool downloads the HTML from a URL and extracts the main readable text,
20
+ filtering out navigation, ads, and other boilerplate content.
21
+ TEXT
22
+
23
+ self.tool_input_schema = {
24
+ type: 'object',
25
+ properties: {
26
+ url: {
27
+ type: 'string',
28
+ description: 'The URL of the web page to fetch.'
29
+ }
30
+ },
31
+ required: ['url']
32
+ }
33
+
34
+ class << self
35
+ # @rbs @available: bool
36
+
37
+ def avaliable!
38
+ @available = true
39
+ end
40
+
41
+ def not_avaliable!
42
+ @available = false
43
+ end
44
+
45
+ def available? #: boolish
46
+ @available
47
+ end
48
+ end
49
+
50
+ # @rbs arguments: Hash[String, untyped]
51
+ # @rbs return: String?
52
+ def call(arguments)
53
+ url = arguments['url']
54
+
55
+ return 'Error: Please provide a URL parameter.' unless url
56
+
57
+ url = normalize_url(url.to_s)
58
+ return 'Error: Invalid URL format.' unless valid_url?(url)
59
+
60
+ content = begin
61
+ fetch_content(url)
62
+ rescue StandardError => e
63
+ raise FetchError, e.message
64
+ end
65
+
66
+ readable_content = extract_readable_content(content)
67
+
68
+ if readable_content.strip.empty?
69
+ "No readable content found on the page: #{url}"
70
+ else
71
+ "Content from #{url}:\n\n#{readable_content}"
72
+ end
73
+ rescue FetchError => e
74
+ "Failed to fetch content from #{url}: #{e.message}"
75
+ end
76
+
77
+ private
78
+
79
+ # @rbs url: String
80
+ # @rbs return: String
81
+ def normalize_url(url)
82
+ url = url.strip
83
+ url = "https://#{url}" unless url.match?(%r{\Ahttps?://})
84
+ url
85
+ end
86
+
87
+ # @rbs url: String
88
+ # @rbs return: bool
89
+ def valid_url?(url)
90
+ uri = URI.parse(url)
91
+ return false unless uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
92
+ return false if uri.host.nil?
93
+
94
+ true
95
+ rescue URI::InvalidURIError
96
+ false
97
+ end
98
+
99
+ # @rbs url: String
100
+ # @rbs return: String
101
+ def fetch_content(url)
102
+ uri = URI.parse(url)
103
+ host = uri.host
104
+ port = uri.port
105
+ raise 'Invalid URL: missing host' if host.nil?
106
+
107
+ http = Net::HTTP.new(host, port)
108
+ http.use_ssl = true if uri.scheme == 'https'
109
+ http.open_timeout = 10
110
+ http.read_timeout = 30
111
+
112
+ path = uri.path
113
+ path = '/' if path.nil? || path.empty?
114
+ request = Net::HTTP::Get.new(path)
115
+ request['User-Agent'] = 'Mozilla/5.0 (compatible; RubotyAI/1.0)'
116
+
117
+ response = http.request(request)
118
+
119
+ raise "HTTP error: #{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
120
+
121
+ response.body
122
+ end
123
+
124
+ # @rbs content: String
125
+ # @rbs return: String
126
+ def extract_readable_content(content)
127
+ document = Readability::Document.new(content)
128
+ document.content
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ # Add Fetch tool only if ruby-readability is available
136
+ begin
137
+ require 'ruby-readability'
138
+ Ruboty::AiAgent::ToolDefinitions::Fetch.avaliable!
139
+ rescue LoadError
140
+ # ruby-readability not available, skip Fetch tool
141
+ Ruboty::AiAgent::ToolDefinitions::Fetch.not_avaliable!
142
+ end
@@ -5,14 +5,18 @@ module Ruboty
5
5
  # Tool Definitions for AI Agent
6
6
  module ToolDefinitions
7
7
  autoload :Base, 'ruboty/ai_agent/tool_definitions/base'
8
+ autoload :Fetch, 'ruboty/ai_agent/tool_definitions/fetch'
8
9
  autoload :Think, 'ruboty/ai_agent/tool_definitions/think'
10
+ autoload :BotHelp, 'ruboty/ai_agent/tool_definitions/bot_help'
9
11
 
10
12
  # @rbs request: Request
11
13
  # @rbs return: Array[Base]
12
14
  def self.builtins(request:)
13
15
  [
14
- Think
15
- ].map { |tool_def| tool_def.new(request:) }
16
+ Think,
17
+ BotHelp,
18
+ Fetch
19
+ ].select(&:available?).map { |tool_def| tool_def.new(request:) }
16
20
  end
17
21
  end
18
22
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ruboty
4
4
  module AiAgent
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -29,6 +29,7 @@ module Ruboty
29
29
  autoload :Recordable, 'ruboty/ai_agent/recordable'
30
30
  autoload :RecordSet, 'ruboty/ai_agent/record_set'
31
31
  autoload :Request, 'ruboty/ai_agent/request'
32
+ autoload :Settings, 'ruboty/ai_agent/settings'
32
33
  autoload :TokenUsage, 'ruboty/ai_agent/token_usage'
33
34
  autoload :Tool, 'ruboty/ai_agent/tool'
34
35
  autoload :ToolDefinitions, 'ruboty/ai_agent/tool_definitions'
@@ -41,6 +42,8 @@ module Ruboty
41
42
  autoload :UserMcpToolsCaches, 'ruboty/ai_agent/user_mcp_tools_caches'
42
43
  autoload :UserPromptCommandDefinitions, 'ruboty/ai_agent/user_prompt_command_definitions'
43
44
 
45
+ extend Settings::Accessor
46
+
44
47
  # Ensure all recordables are loaded
45
48
  [
46
49
  CachedValue,
@@ -9,6 +9,9 @@ module Ruboty
9
9
  env :OPENAI_API_KEY, 'Pass your OpenAI API Key'
10
10
  env :OPENAI_MODEL, 'OpenAI model to use', optional: true
11
11
 
12
+ env :AI_AGENT_MAX_TOKENS, 'Max tokens for AI requests (For OpenAI Models, the default value is automatically decided)', optional: true
13
+ env :AI_AGENT_AUTO_COMPACT_THRESHOLD, 'Threshold of token usage in percentage to auto compact AI memory (default: 90)', optional: true
14
+
12
15
  on(
13
16
  /(?<body>.+)/m,
14
17
  description: 'AI responds to your message if given message did not match any other handlers',
@@ -40,7 +40,7 @@ require 'fileutils'
40
40
  # Generate RBS instance variable definitions for memorized methods
41
41
  class MemorizedIvarRbsGenerator
42
42
  Source = Data.define(:file, :content, :prism_node)
43
- MemorizedMethod = Data.define(:class_name, :method_name, :ivar_name, :return_type, :file)
43
+ MemorizedMethod = Data.define(:class_name, :method_name, :ivar_name, :return_type, :file, :is_class_ivar)
44
44
 
45
45
  def initialize(lib_path: 'lib', output_path: 'sig/generated-by-scripts', namespace_filter: nil)
46
46
  @lib_path = Pathname(lib_path)
@@ -58,7 +58,8 @@ class MemorizedIvarRbsGenerator
58
58
 
59
59
  puts "Found #{memorized_methods.size} memorized methods:"
60
60
  memorized_methods.each do |method|
61
- puts " - #{method.class_name}##{method.method_name} -> @#{method.ivar_name}: #{method.return_type}"
61
+ prefix = method.is_class_ivar ? '.' : '#'
62
+ puts " - #{method.class_name}#{prefix}#{method.method_name} -> @#{method.ivar_name}: #{method.return_type}"
62
63
  end
63
64
 
64
65
  generate_rbs_files(memorized_methods)
@@ -108,10 +109,20 @@ class MemorizedIvarRbsGenerator
108
109
  # Class declaration with instance variables
109
110
  content << ((' ' * indent_level) + "class #{parts.last}")
110
111
 
111
- methods.each do |method|
112
+ # Separate instance variables and class instance variables
113
+ instance_methods = methods.reject(&:is_class_ivar)
114
+ class_methods = methods.select(&:is_class_ivar)
115
+
116
+ # Add instance variables
117
+ instance_methods.each do |method|
112
118
  content << ((' ' * (indent_level + 1)) + "@#{method.ivar_name}: #{method.return_type}")
113
119
  end
114
120
 
121
+ # Add class instance variables (using self.@variable_name notation)
122
+ class_methods.each do |method|
123
+ content << ((' ' * (indent_level + 1)) + "self.@#{method.ivar_name}: #{method.return_type}")
124
+ end
125
+
115
126
  content << "#{' ' * indent_level}end"
116
127
 
117
128
  # Close namespaces
@@ -138,6 +149,7 @@ class MemorizedIvarRbsGenerator
138
149
  @memorized_methods = []
139
150
  @namespace = []
140
151
  @current_class = nil
152
+ @in_singleton_class = false
141
153
  super()
142
154
  end
143
155
 
@@ -157,12 +169,22 @@ class MemorizedIvarRbsGenerator
157
169
  end
158
170
  end
159
171
 
172
+ def visit_singleton_class_node(node)
173
+ old_singleton = @in_singleton_class
174
+ @in_singleton_class = true
175
+ super
176
+ @in_singleton_class = old_singleton
177
+ end
178
+
160
179
  def visit_def_node(node)
161
180
  return unless @current_class
162
181
 
163
182
  # Skip if namespace filter is set and doesn't match
164
183
  return if @namespace_filter && !@current_class.start_with?(@namespace_filter)
165
184
 
185
+ # Check if it's a class method (def self.method_name)
186
+ is_class_method = node.receiver&.is_a?(Prism::SelfNode)
187
+
166
188
  # Check for memorized annotation
167
189
  if memorized_annotated?(node)
168
190
  method_name = node.name.to_s
@@ -176,7 +198,8 @@ class MemorizedIvarRbsGenerator
176
198
  method_name: method_name,
177
199
  ivar_name: ivar_info[:ivar_name],
178
200
  return_type: ivar_info[:return_type],
179
- file: source.file
201
+ file: source.file,
202
+ is_class_ivar: @in_singleton_class || is_class_method
180
203
  )
181
204
  end
182
205
  end
@@ -21,6 +21,10 @@ module Ruboty
21
21
  # @rbs body: String
22
22
  # @rbs return: void
23
23
  def complete_chat: (String body) -> void
24
+
25
+ def truncate: (untyped text, max: untyped) -> untyped
26
+
27
+ def indent_with_quotation: (untyped text, ?untyped quota) -> untyped
24
28
  end
25
29
  end
26
30
  end
@@ -7,11 +7,12 @@ module Ruboty
7
7
  # @rbs message: ChatMessage
8
8
  def add: (ChatMessage message) -> void
9
9
 
10
+ def token_usage: () -> TokenUsage?
11
+
10
12
  alias << add
11
13
 
12
14
  # Check if any message's token usage exceeds auto compact threshold
13
- # @rbs return: bool
14
- def over_auto_compact_threshold?: () -> bool
15
+ def over_auto_compact_threshold?: () -> boolish
15
16
 
16
17
  # Compact chat messages by summarizing them
17
18
  # @rbs llm: LLM::OpenAI
@@ -0,0 +1,21 @@
1
+ # Generated from lib/ruboty/ai_agent/settings.rb with RBS::Inline
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ # Provide library-wide settings.
6
+ class Settings
7
+ # Provide access to settings instance.
8
+ module Accessor
9
+ def settings: () -> Ruboty::AiAgent::Settings
10
+ end
11
+
12
+ # @rbs %a{memorized}
13
+ %a{memorized}
14
+ def self.instance: () -> Ruboty::AiAgent::Settings
15
+
16
+ def max_tokens: () -> Integer?
17
+
18
+ def auto_compact_threshold: () -> Float
19
+ end
20
+ end
21
+ end
@@ -24,6 +24,8 @@ module Ruboty
24
24
 
25
25
  def self.tool_input_schema=: (input_schema) -> input_schema
26
26
 
27
+ def self.available?: () -> boolish
28
+
27
29
  def tool_name: () -> String
28
30
 
29
31
  def tool_title: () -> String
@@ -0,0 +1,23 @@
1
+ # Generated from lib/ruboty/ai_agent/tool_definitions/bot_help.rb with RBS::Inline
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ module ToolDefinitions
6
+ # Tool for retrieving Ruboty help information
7
+ class BotHelp < Base
8
+ # @rbs arguments: Hash[String, untyped]
9
+ # @rbs return: String?
10
+ def call: (Hash[String, untyped] arguments) -> String?
11
+
12
+ private
13
+
14
+ # @rbs filter: String?
15
+ # @rbs return: Array[String]
16
+ def filtered_descriptions: (String? filter) -> Array[String]
17
+
18
+ # @rbs return: Array[String]
19
+ def all_descriptions: () -> Array[String]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ # Generated from lib/ruboty/ai_agent/tool_definitions/fetch.rb with RBS::Inline
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ module ToolDefinitions
6
+ # Fetch and extract readable content from web pages using ruby-readability
7
+ class Fetch < Base
8
+ class FetchError < StandardError
9
+ end
10
+
11
+ @available: bool
12
+
13
+ def self.avaliable!: () -> untyped
14
+
15
+ def self.not_avaliable!: () -> untyped
16
+
17
+ def self.available?: () -> boolish
18
+
19
+ # @rbs arguments: Hash[String, untyped]
20
+ # @rbs return: String?
21
+ def call: (Hash[String, untyped] arguments) -> String?
22
+
23
+ private
24
+
25
+ # @rbs url: String
26
+ # @rbs return: String
27
+ def normalize_url: (String url) -> String
28
+
29
+ # @rbs url: String
30
+ # @rbs return: bool
31
+ def valid_url?: (String url) -> bool
32
+
33
+ # @rbs url: String
34
+ # @rbs return: String
35
+ def fetch_content: (String url) -> String
36
+
37
+ # @rbs content: String
38
+ # @rbs return: String
39
+ def extract_readable_content: (String content) -> String
40
+ end
41
+ end
42
+ end
43
+ end
@@ -5,5 +5,7 @@ module Ruboty
5
5
  module AiAgent
6
6
  class Error < StandardError
7
7
  end
8
+
9
+ extend Settings::Accessor
8
10
  end
9
11
  end
@@ -49,6 +49,14 @@ module Ruboty
49
49
  end
50
50
  end
51
51
 
52
+ module Ruboty
53
+ module AiAgent
54
+ class Settings
55
+ self.@instance: Ruboty::AiAgent::Settings
56
+ end
57
+ end
58
+ end
59
+
52
60
  module Ruboty
53
61
  module AiAgent
54
62
  class User
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruboty-ai_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomoya Chiba
@@ -114,10 +114,13 @@ files:
114
114
  - lib/ruboty/ai_agent/record_set.rb
115
115
  - lib/ruboty/ai_agent/recordable.rb
116
116
  - lib/ruboty/ai_agent/request.rb
117
+ - lib/ruboty/ai_agent/settings.rb
117
118
  - lib/ruboty/ai_agent/token_usage.rb
118
119
  - lib/ruboty/ai_agent/tool.rb
119
120
  - lib/ruboty/ai_agent/tool_definitions.rb
120
121
  - lib/ruboty/ai_agent/tool_definitions/base.rb
122
+ - lib/ruboty/ai_agent/tool_definitions/bot_help.rb
123
+ - lib/ruboty/ai_agent/tool_definitions/fetch.rb
121
124
  - lib/ruboty/ai_agent/tool_definitions/think.rb
122
125
  - lib/ruboty/ai_agent/user.rb
123
126
  - lib/ruboty/ai_agent/user_ai_memories.rb
@@ -182,10 +185,13 @@ files:
182
185
  - sig/generated/ruboty/ai_agent/record_set.rbs
183
186
  - sig/generated/ruboty/ai_agent/recordable.rbs
184
187
  - sig/generated/ruboty/ai_agent/request.rbs
188
+ - sig/generated/ruboty/ai_agent/settings.rbs
185
189
  - sig/generated/ruboty/ai_agent/token_usage.rbs
186
190
  - sig/generated/ruboty/ai_agent/tool.rbs
187
191
  - sig/generated/ruboty/ai_agent/tool_definitions.rbs
188
192
  - sig/generated/ruboty/ai_agent/tool_definitions/base.rbs
193
+ - sig/generated/ruboty/ai_agent/tool_definitions/bot_help.rbs
194
+ - sig/generated/ruboty/ai_agent/tool_definitions/fetch.rbs
189
195
  - sig/generated/ruboty/ai_agent/tool_definitions/think.rbs
190
196
  - sig/generated/ruboty/ai_agent/user.rbs
191
197
  - sig/generated/ruboty/ai_agent/user_ai_memories.rbs