ruboty-ai_agent 0.2.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +8 -0
  3. data/CHANGELOG.md +21 -2
  4. data/Gemfile +2 -0
  5. data/README.md +2 -0
  6. data/Rakefile +2 -0
  7. data/bin/ruboty +2 -0
  8. data/lib/ruboty/ai_agent/actions/add_mcp.rb +7 -2
  9. data/lib/ruboty/ai_agent/actions/base.rb +11 -1
  10. data/lib/ruboty/ai_agent/actions/chat.rb +27 -6
  11. data/lib/ruboty/ai_agent/actions/list_ai_commands.rb +1 -1
  12. data/lib/ruboty/ai_agent/actions/list_mcp.rb +50 -3
  13. data/lib/ruboty/ai_agent/agent.rb +3 -3
  14. data/lib/ruboty/ai_agent/chat_thread_messages.rb +6 -3
  15. data/lib/ruboty/ai_agent/commands/base.rb +12 -7
  16. data/lib/ruboty/ai_agent/commands/prompt_command.rb +3 -4
  17. data/lib/ruboty/ai_agent/commands/usage.rb +1 -3
  18. data/lib/ruboty/ai_agent/commands.rb +6 -16
  19. data/lib/ruboty/ai_agent/database/query_methods.rb +1 -1
  20. data/lib/ruboty/ai_agent/llm/openai/model.rb +1 -1
  21. data/lib/ruboty/ai_agent/llm/openai.rb +1 -1
  22. data/lib/ruboty/ai_agent/mcp_clients.rb +2 -15
  23. data/lib/ruboty/ai_agent/request.rb +17 -0
  24. data/lib/ruboty/ai_agent/settings.rb +28 -0
  25. data/lib/ruboty/ai_agent/tool.rb +11 -3
  26. data/lib/ruboty/ai_agent/tool_definitions/base.rb +88 -0
  27. data/lib/ruboty/ai_agent/tool_definitions/bot_help.rb +89 -0
  28. data/lib/ruboty/ai_agent/tool_definitions/fetch.rb +142 -0
  29. data/lib/ruboty/ai_agent/tool_definitions/think.rb +41 -0
  30. data/lib/ruboty/ai_agent/tool_definitions.rb +23 -0
  31. data/lib/ruboty/ai_agent/user_mcp_client.rb +3 -2
  32. data/lib/ruboty/ai_agent/version.rb +1 -1
  33. data/lib/ruboty/ai_agent.rb +5 -0
  34. data/lib/ruboty/handlers/ai_agent.rb +4 -1
  35. data/script/generate-memorized-ivar-rbs.rb +27 -4
  36. data/sig/generated/ruboty/ai_agent/actions/base.rbs +4 -0
  37. data/sig/generated/ruboty/ai_agent/actions/chat.rbs +8 -0
  38. data/sig/generated/ruboty/ai_agent/actions/list_mcp.rbs +11 -0
  39. data/sig/generated/ruboty/ai_agent/agent.rbs +1 -1
  40. data/sig/generated/ruboty/ai_agent/chat_thread_messages.rbs +3 -2
  41. data/sig/generated/ruboty/ai_agent/commands/base.rbs +6 -5
  42. data/sig/generated/ruboty/ai_agent/commands/prompt_command.rbs +2 -3
  43. data/sig/generated/ruboty/ai_agent/commands.rbs +2 -3
  44. data/sig/generated/ruboty/ai_agent/mcp_clients.rbs +0 -5
  45. data/sig/generated/ruboty/ai_agent/request.rbs +23 -0
  46. data/sig/generated/ruboty/ai_agent/settings.rbs +21 -0
  47. data/sig/generated/ruboty/ai_agent/tool.rbs +9 -3
  48. data/sig/generated/ruboty/ai_agent/tool_definitions/base.rbs +54 -0
  49. data/sig/generated/ruboty/ai_agent/tool_definitions/bot_help.rbs +23 -0
  50. data/sig/generated/ruboty/ai_agent/tool_definitions/fetch.rbs +43 -0
  51. data/sig/generated/ruboty/ai_agent/tool_definitions/think.rbs +17 -0
  52. data/sig/generated/ruboty/ai_agent/tool_definitions.rbs +12 -0
  53. data/sig/generated/ruboty/ai_agent/user_mcp_client.rbs +4 -2
  54. data/sig/generated/ruboty/ai_agent.rbs +2 -0
  55. data/sig/generated-by-scripts/memorized_ivars.rbs +18 -0
  56. metadata +15 -1
@@ -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
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ module ToolDefinitions
6
+ # Tool
7
+ class Think < Base
8
+ self.tool_name = 'think'
9
+ self.tool_title = 'Think'
10
+
11
+ self.tool_description = <<~TEXT
12
+ Use this tool to think abount something. It will not obtain new information or make any changes, but just log the thought.
13
+ Use it when completx reasoing or brainstorming is needed.
14
+ TEXT
15
+
16
+ self.tool_input_schema = {
17
+ type: 'object',
18
+ properties: {
19
+ thought: { type: 'string', description: 'Your thought.' }
20
+ },
21
+ required: ['thought']
22
+ }
23
+
24
+ # @rbs arguments: Hash[String, untyped]
25
+ # @rbs return: String?
26
+ def call(arguments)
27
+ thought = arguments['thought']
28
+
29
+ request.message.reply("Thought:\n#{thought}")
30
+
31
+ thought
32
+ end
33
+
34
+ # @rbs override
35
+ def silent?
36
+ true
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ # Tool Definitions for AI Agent
6
+ module ToolDefinitions
7
+ autoload :Base, 'ruboty/ai_agent/tool_definitions/base'
8
+ autoload :Fetch, 'ruboty/ai_agent/tool_definitions/fetch'
9
+ autoload :Think, 'ruboty/ai_agent/tool_definitions/think'
10
+ autoload :BotHelp, 'ruboty/ai_agent/tool_definitions/bot_help'
11
+
12
+ # @rbs request: Request
13
+ # @rbs return: Array[Base]
14
+ def self.builtins(request:)
15
+ [
16
+ Think,
17
+ BotHelp,
18
+ Fetch
19
+ ].select(&:available?).map { |tool_def| tool_def.new(request:) }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -68,14 +68,15 @@ module Ruboty
68
68
  mcp_client.cleanup_session
69
69
  end
70
70
 
71
- private
72
-
73
71
  # @rbs return: McpConfiguration
74
72
  def configuration
75
73
  user.mcp_configurations.all_values.find { |config| config.name == mcp_name } ||
76
74
  raise("MCP configuration not found: #{mcp_name}")
77
75
  end
78
76
 
77
+ private
78
+
79
+ # @rbs %a{memorized}
79
80
  # @rbs return: HttpMcpClient
80
81
  def mcp_client
81
82
  @mcp_client ||= case configuration.transport
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ruboty
4
4
  module AiAgent
5
- VERSION = '0.2.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -28,8 +28,11 @@ module Ruboty
28
28
  autoload :PromptCommandDefinition, 'ruboty/ai_agent/prompt_command_definition'
29
29
  autoload :Recordable, 'ruboty/ai_agent/recordable'
30
30
  autoload :RecordSet, 'ruboty/ai_agent/record_set'
31
+ autoload :Request, 'ruboty/ai_agent/request'
32
+ autoload :Settings, 'ruboty/ai_agent/settings'
31
33
  autoload :TokenUsage, 'ruboty/ai_agent/token_usage'
32
34
  autoload :Tool, 'ruboty/ai_agent/tool'
35
+ autoload :ToolDefinitions, 'ruboty/ai_agent/tool_definitions'
33
36
  autoload :User, 'ruboty/ai_agent/user'
34
37
  autoload :UserAiMemories, 'ruboty/ai_agent/user_ai_memories'
35
38
  autoload :UserAssociations, 'ruboty/ai_agent/user_associations'
@@ -39,6 +42,8 @@ module Ruboty
39
42
  autoload :UserMcpToolsCaches, 'ruboty/ai_agent/user_mcp_tools_caches'
40
43
  autoload :UserPromptCommandDefinitions, 'ruboty/ai_agent/user_prompt_command_definitions'
41
44
 
45
+ extend Settings::Accessor
46
+
42
47
  # Ensure all recordables are loaded
43
48
  [
44
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',
@@ -18,7 +21,7 @@ module Ruboty
18
21
 
19
22
  on(/add mcp (?<name>\S+)\s+(?<config>.+)\z/, name: 'add_mcp', description: 'Add a new MCP server')
20
23
  on(/remove mcp (?<name>\S+)/, name: 'remove_mcp', description: 'Remove the specified MCP server')
21
- on(/list mcps?/, name: 'list_mcp', description: 'List configured MCP servers')
24
+ on(/list mcps?(?<with_headers>\s+with\s+headers)?/, name: 'list_mcp', description: 'List configured MCP servers')
22
25
 
23
26
  on(/set (?:(?<scope>user|global) )?system prompt "(?<prompt>.+?)"/, name: 'set_system_prompt', description: 'Set system prompt')
24
27
  on(/show system prompt/, name: 'show_system_prompt', description: 'Show system prompt')
@@ -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
@@ -28,6 +28,10 @@ module Ruboty
28
28
  # @rbs %a{memorized}
29
29
  %a{memorized}
30
30
  def chat_thread: () -> Ruboty::AiAgent::ChatThread
31
+
32
+ private
33
+
34
+ def thread_id: () -> String
31
35
  end
32
36
  end
33
37
  end
@@ -12,11 +12,19 @@ module Ruboty
12
12
 
13
13
  def body_param: () -> String
14
14
 
15
+ # @rbs %a{memorized}
16
+ %a{memorized}
17
+ def request: () -> Request
18
+
15
19
  private
16
20
 
17
21
  # @rbs body: String
18
22
  # @rbs return: void
19
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
20
28
  end
21
29
  end
22
30
  end
@@ -6,6 +6,17 @@ module Ruboty
6
6
  # ListMcp action for Ruboty::AiAgent
7
7
  class ListMcp < Base
8
8
  def call: () -> untyped
9
+
10
+ private
11
+
12
+ # @rbs client: UserMcpClient
13
+ # @rbs show_headers: bool
14
+ # @rbs return: String
15
+ def format_mcp_client: (UserMcpClient client, ?show_headers: bool) -> String
16
+
17
+ # @rbs client: UserMcpClient
18
+ # @rbs return: String
19
+ def format_tools: (UserMcpClient client) -> String
9
20
  end
10
21
  end
11
22
  end
@@ -21,7 +21,7 @@ module Ruboty
21
21
 
22
22
  def on_tool_call: (tool: untyped, tool_arguments: untyped) ?{ (?) -> untyped } -> untyped
23
23
 
24
- def on_tool_response: (tool_response: untyped, message: untyped) ?{ (?) -> untyped } -> untyped
24
+ def on_tool_response: (tool: untyped, tool_response: untyped, message: untyped) ?{ (?) -> untyped } -> untyped
25
25
 
26
26
  def on_response: (untyped response) ?{ (?) -> untyped } -> untyped
27
27
  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
@@ -6,13 +6,14 @@ module Ruboty
6
6
  # Base class for commands.
7
7
  # @abstract
8
8
  class Base
9
- attr_reader message: Ruboty::Message
9
+ attr_reader request: Request
10
10
 
11
- attr_reader chat_thread: Ruboty::AiAgent::ChatThread
11
+ # @rbs request: Request
12
+ def initialize: (request: Request) -> untyped
12
13
 
13
- # @rbs message: Ruboty::Message
14
- # @rbs chat_thread: Ruboty::AiAgent::ChatThread
15
- def initialize: (message: Ruboty::Message, chat_thread: Ruboty::AiAgent::ChatThread) -> untyped
14
+ def message: () -> Ruboty::Message
15
+
16
+ def chat_thread: () -> Ruboty::AiAgent::ChatThread
16
17
 
17
18
  # @rbs *args: untyped
18
19
  # @rbs return: untyped
@@ -8,9 +8,8 @@ module Ruboty
8
8
  attr_reader definition: Ruboty::AiAgent::PromptCommandDefinition
9
9
 
10
10
  # @rbs definition: Ruboty::AiAgent::PromptCommandDefinition
11
- # @rbs message: Ruboty::Message
12
- # @rbs chat_thread: Ruboty::AiAgent::ChatThread
13
- def initialize: (definition: Ruboty::AiAgent::PromptCommandDefinition, message: Ruboty::Message, chat_thread: Ruboty::AiAgent::ChatThread) -> untyped
11
+ # @rbs request: Ruboty::AiAgent::Request
12
+ def initialize: (definition: Ruboty::AiAgent::PromptCommandDefinition, request: Ruboty::AiAgent::Request) -> untyped
14
13
 
15
14
  # @rbs commandline: String
16
15
  # @rbs return: boolish
@@ -4,10 +4,9 @@ module Ruboty
4
4
  module AiAgent
5
5
  # Interaction commands (a.k.a. Slash commands, Prompts, etc)
6
6
  module Commands
7
- # @rbs message: Ruboty::Message
8
- # @rbs chat_thread: ChatThread
7
+ # @rbs request: Request
9
8
  # @rbs return: Array[Commands::BuiltinBase]
10
- def self.builtins: (message: Ruboty::Message, chat_thread: ChatThread) -> Array[Commands::BuiltinBase]
9
+ def self.builtins: (request: Request) -> Array[Commands::BuiltinBase]
11
10
  end
12
11
  end
13
12
  end
@@ -12,11 +12,6 @@ module Ruboty
12
12
  # @rbs return: Array[Tool]
13
13
  def available_tools: () -> Array[Tool]
14
14
 
15
- # @rbs function_name: String
16
- # @rbs arguments: Hash[String, untyped]
17
- # @rbs return: untyped
18
- def execute_tool: (String function_name, Hash[String, untyped] arguments) -> untyped
19
-
20
15
  # @rbs return: bool
21
16
  def any?: () -> bool
22
17
  end
@@ -0,0 +1,23 @@
1
+ # Generated from lib/ruboty/ai_agent/request.rb with RBS::Inline
2
+
3
+ module Ruboty
4
+ module AiAgent
5
+ class Request < Data
6
+ attr_reader message(): Ruboty::Message
7
+
8
+ attr_reader chat_thread(): Ruboty::AiAgent::ChatThread
9
+
10
+ def self.new: (Ruboty::Message message, Ruboty::AiAgent::ChatThread chat_thread) -> instance
11
+ | (message: Ruboty::Message, chat_thread: Ruboty::AiAgent::ChatThread) -> instance
12
+
13
+ def self.members: () -> [ :message, :chat_thread ]
14
+
15
+ def members: () -> [ :message, :chat_thread ]
16
+ end
17
+
18
+ # Request for chat action from user.
19
+ class Request
20
+ def message_body: () -> String
21
+ end
22
+ end
23
+ end
@@ -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
@@ -12,14 +12,20 @@ module Ruboty
12
12
 
13
13
  attr_reader input_schema: Hash[untyped, untyped]?
14
14
 
15
- attr_reader on_call: (^(Hash[String, untyped]) -> String)?
15
+ attr_reader silent: boolish
16
+
17
+ attr_reader on_call: (^(Hash[String, untyped]) -> String?)?
16
18
 
17
19
  # @rbs name: String
18
20
  # @rbs title: String
19
21
  # @rbs description: String
20
22
  # @rbs input_schema: Hash[untyped, untyped]?
21
- # @rbs &on_call: ? (Hash[String, untyped]) -> String
22
- def initialize: (name: String, title: String, description: String, input_schema: Hash[untyped, untyped]?) ?{ (Hash[String, untyped]) -> String } -> void
23
+ # @rbs ?silent: boolish?
24
+ # @rbs &on_call: ? (Hash[String, untyped]) -> String?
25
+ def initialize: (name: String, title: String, description: String, input_schema: Hash[untyped, untyped]?, ?silent: untyped) ?{ (Hash[String, untyped]) -> String? } -> void
26
+
27
+ # Returns true if the tool should be called silently (without notifying the user).
28
+ def silent?: () -> boolish
23
29
 
24
30
  def call: (untyped params) -> String?
25
31
  end