rixie 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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +40 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +69 -0
  5. data/bin/rixie +7 -0
  6. data/lib/rixie/agent/compressor.rb +41 -0
  7. data/lib/rixie/agent/plan.rb +62 -0
  8. data/lib/rixie/agent/re_act.rb +53 -0
  9. data/lib/rixie/agent.rb +122 -0
  10. data/lib/rixie/cli/commands/base.rb +33 -0
  11. data/lib/rixie/cli/commands/compress.rb +49 -0
  12. data/lib/rixie/cli/commands/context.rb +18 -0
  13. data/lib/rixie/cli/commands/help.rb +21 -0
  14. data/lib/rixie/cli/commands/model.rb +25 -0
  15. data/lib/rixie/cli/commands/strategy.rb +50 -0
  16. data/lib/rixie/cli/commands.rb +8 -0
  17. data/lib/rixie/cli/markdown.rb +59 -0
  18. data/lib/rixie/cli/renderer.rb +171 -0
  19. data/lib/rixie/cli/spinner.rb +47 -0
  20. data/lib/rixie/cli/terminal.rb +28 -0
  21. data/lib/rixie/cli.rb +285 -0
  22. data/lib/rixie/configuration.rb +56 -0
  23. data/lib/rixie/context/history.rb +62 -0
  24. data/lib/rixie/context/plan.rb +31 -0
  25. data/lib/rixie/context/summary.rb +25 -0
  26. data/lib/rixie/error.rb +34 -0
  27. data/lib/rixie/event/compression_end.rb +7 -0
  28. data/lib/rixie/event/compression_start.rb +7 -0
  29. data/lib/rixie/event/envelope.rb +7 -0
  30. data/lib/rixie/event/finished.rb +7 -0
  31. data/lib/rixie/event/llm_call_start.rb +7 -0
  32. data/lib/rixie/event/run_end.rb +7 -0
  33. data/lib/rixie/event/run_start.rb +7 -0
  34. data/lib/rixie/event/task_end.rb +7 -0
  35. data/lib/rixie/event/task_start.rb +7 -0
  36. data/lib/rixie/event/thought_completed.rb +7 -0
  37. data/lib/rixie/event/token.rb +7 -0
  38. data/lib/rixie/event/tool_call_end.rb +7 -0
  39. data/lib/rixie/event/tool_call_start.rb +7 -0
  40. data/lib/rixie/event/tool_calls_completed.rb +7 -0
  41. data/lib/rixie/event.rb +16 -0
  42. data/lib/rixie/event_listener.rb +36 -0
  43. data/lib/rixie/http/client.rb +140 -0
  44. data/lib/rixie/llm/adapter/dummy.rb +38 -0
  45. data/lib/rixie/llm/adapter/openai.rb +147 -0
  46. data/lib/rixie/llm/client/resolver.rb +58 -0
  47. data/lib/rixie/llm/client.rb +33 -0
  48. data/lib/rixie/llm/response.rb +19 -0
  49. data/lib/rixie/llm/tool_call.rb +36 -0
  50. data/lib/rixie/mcp/http/client.rb +86 -0
  51. data/lib/rixie/mcp/http.rb +3 -0
  52. data/lib/rixie/mcp.rb +3 -0
  53. data/lib/rixie/message.rb +10 -0
  54. data/lib/rixie/prompt_builder.rb +13 -0
  55. data/lib/rixie/run.rb +60 -0
  56. data/lib/rixie/search/base.rb +13 -0
  57. data/lib/rixie/search/duck_duck_go.rb +66 -0
  58. data/lib/rixie/search/wikipedia.rb +59 -0
  59. data/lib/rixie/session.rb +153 -0
  60. data/lib/rixie/store/base.rb +37 -0
  61. data/lib/rixie/store/memory.rb +30 -0
  62. data/lib/rixie/store/null.rb +19 -0
  63. data/lib/rixie/strategy/plan_execute.rb +65 -0
  64. data/lib/rixie/strategy/re_act.rb +15 -0
  65. data/lib/rixie/strategy/simple.rb +14 -0
  66. data/lib/rixie/subscriber.rb +12 -0
  67. data/lib/rixie/subscribers/event_severity.rb +23 -0
  68. data/lib/rixie/subscribers/json_logger.rb +70 -0
  69. data/lib/rixie/subscribers/logger.rb +65 -0
  70. data/lib/rixie/task.rb +53 -0
  71. data/lib/rixie/token_counter.rb +10 -0
  72. data/lib/rixie/tool/calculator.rb +154 -0
  73. data/lib/rixie/tool/current_time.rb +30 -0
  74. data/lib/rixie/tool/fetch.rb +42 -0
  75. data/lib/rixie/tool/file_list.rb +39 -0
  76. data/lib/rixie/tool/file_read.rb +53 -0
  77. data/lib/rixie/tool/file_sandbox.rb +33 -0
  78. data/lib/rixie/tool/file_search.rb +72 -0
  79. data/lib/rixie/tool/human_input.rb +24 -0
  80. data/lib/rixie/tool/web_search.rb +34 -0
  81. data/lib/rixie/tool/wikipedia_search.rb +38 -0
  82. data/lib/rixie/tool.rb +23 -0
  83. data/lib/rixie/tool_executor.rb +34 -0
  84. data/lib/rixie/version.rb +5 -0
  85. data/lib/rixie.rb +74 -0
  86. data/sig/rixie.rbs +4 -0
  87. metadata +146 -0
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "file_sandbox"
4
+
5
+ module Rixie
6
+ class Tool
7
+ DEFAULT_FILE_SEARCH_RESULTS = 50
8
+ DEFAULT_FILE_SEARCH_GLOB = "**/*"
9
+ private_constant :DEFAULT_FILE_SEARCH_RESULTS, :DEFAULT_FILE_SEARCH_GLOB
10
+
11
+ build = ->(root_dir: nil) {
12
+ Tool.new(
13
+ name: "file_search",
14
+ description: "Search file contents for a regex pattern within the configured root directory. " \
15
+ "Returns matching lines in 'path:lineno:content' format. " \
16
+ "Binary files are skipped.",
17
+ input_schema: {
18
+ type: "object",
19
+ properties: {
20
+ pattern: {
21
+ type: "string",
22
+ description: "Regex pattern to search for"
23
+ },
24
+ glob: {
25
+ type: "string",
26
+ description: "Optional glob filter for files. Defaults to '#{DEFAULT_FILE_SEARCH_GLOB}'."
27
+ },
28
+ max_results: {
29
+ type: "integer",
30
+ description: "Maximum matches to return. Defaults to #{DEFAULT_FILE_SEARCH_RESULTS}."
31
+ }
32
+ },
33
+ required: ["pattern"]
34
+ },
35
+ call: ->(args) {
36
+ begin
37
+ base = FileSandbox.root(root_dir)
38
+ pattern = (args["pattern"] || args[:pattern]).to_s
39
+ glob = (args["glob"] || args[:glob] || DEFAULT_FILE_SEARCH_GLOB).to_s
40
+ max = (args["max_results"] || args[:max_results] || DEFAULT_FILE_SEARCH_RESULTS).to_i
41
+ regex = Regexp.new(pattern)
42
+
43
+ results = []
44
+ catch(:done) do
45
+ Dir.glob(glob, base: base).sort.each do |rel|
46
+ full = begin
47
+ FileSandbox.resolve(base, rel)
48
+ rescue FileSandbox::PathError
49
+ next
50
+ end
51
+ next unless File.file?(full)
52
+ next if FileSandbox.binary?(full)
53
+
54
+ File.foreach(full).with_index(1) do |line, lineno|
55
+ next unless line.match?(regex)
56
+ results << "#{rel}:#{lineno}:#{line.chomp}"
57
+ throw :done if results.size >= max
58
+ end
59
+ end
60
+ end
61
+
62
+ results.empty? ? "No matches found." : results.join("\n")
63
+ rescue RegexpError => e
64
+ "Error: invalid regex: #{e.message}"
65
+ end
66
+ }
67
+ )
68
+ }
69
+ FileSearch = build.call
70
+ FileSearch.define_singleton_method(:with, &build)
71
+ end
72
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rixie
4
+ class Tool
5
+ HumanInput = Tool.new(
6
+ name: "human_input",
7
+ description: "Call this tool when you need input, clarification, or approval from " \
8
+ "the user before proceeding. The user will see your question and reply " \
9
+ "in the next message.",
10
+ input_schema: {
11
+ type: "object",
12
+ properties: {
13
+ question: {
14
+ type: "string",
15
+ description: "The question or prompt to present to the user"
16
+ }
17
+ },
18
+ required: ["question"]
19
+ },
20
+ call: ->(args) { args["question"] },
21
+ return_direct: true
22
+ )
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rixie
4
+ class Tool
5
+ build = ->(provider: Search::DuckDuckGo.new, max_results: 5) {
6
+ Tool.new(
7
+ name: "web_search",
8
+ description: "Search the web for current information. Returns a list of relevant results with titles, snippets, and URLs.",
9
+ input_schema: {
10
+ type: "object",
11
+ properties: {
12
+ query: {
13
+ type: "string",
14
+ description: "The search query"
15
+ }
16
+ },
17
+ required: ["query"]
18
+ },
19
+ call: ->(args) {
20
+ results = provider.search(args["query"], max_results: max_results)
21
+ if results.empty?
22
+ "No results found."
23
+ else
24
+ results.map.with_index(1) { |r, i|
25
+ "#{i}. #{r[:title]}\n #{r[:snippet]}\n URL: #{r[:url]}"
26
+ }.join("\n\n")
27
+ end
28
+ }
29
+ )
30
+ }
31
+ WebSearch = build.call
32
+ WebSearch.define_singleton_method(:with, &build)
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rixie
4
+ class Tool
5
+ build = ->(language: Search::Wikipedia::DEFAULT_LANGUAGE, max_results: Search::Wikipedia::DEFAULT_MAX_RESULTS) {
6
+ provider = Search::Wikipedia.new(language: language)
7
+ Tool.new(
8
+ name: "wikipedia_search",
9
+ description: "Search Wikipedia for encyclopedic information about people, places, " \
10
+ "concepts, or events. Returns titles, snippets, and article URLs. " \
11
+ "Use this when you need authoritative reference information rather " \
12
+ "than general web results.",
13
+ input_schema: {
14
+ type: "object",
15
+ properties: {
16
+ query: {
17
+ type: "string",
18
+ description: "The search query"
19
+ }
20
+ },
21
+ required: ["query"]
22
+ },
23
+ call: ->(args) {
24
+ results = provider.search(args["query"] || args[:query], max_results: max_results)
25
+ if results.empty?
26
+ "No results found."
27
+ else
28
+ results.map.with_index(1) { |r, i|
29
+ "#{i}. #{r[:title]}\n #{r[:snippet]}\n URL: #{r[:url]}"
30
+ }.join("\n\n")
31
+ end
32
+ }
33
+ )
34
+ }
35
+ WikipediaSearch = build.call
36
+ WikipediaSearch.define_singleton_method(:with, &build)
37
+ end
38
+ end
data/lib/rixie/tool.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rixie
4
+ class Tool
5
+ attr_reader :name, :description, :input_schema
6
+
7
+ def initialize(name:, description:, input_schema:, call:, return_direct: false)
8
+ @name = name
9
+ @description = description
10
+ @input_schema = input_schema
11
+ @call = call
12
+ @return_direct = return_direct
13
+ end
14
+
15
+ def return_direct?
16
+ @return_direct
17
+ end
18
+
19
+ def call(arguments)
20
+ @call.call(arguments)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rixie
4
+ class ToolExecutor
5
+ Result = Data.define(:tool_call_id, :content, :error) do
6
+ def success? = error.nil?
7
+ def error? = !error.nil?
8
+ end
9
+
10
+ def initialize(tools: [])
11
+ @tools = tools.each_with_object({}) { |t, h| h[t.name] = t }
12
+ end
13
+
14
+ def execute(tool_call)
15
+ tool = @tools[tool_call.name]
16
+ raise Rixie::ToolNotFoundError, "Tool not found: #{tool_call.name.inspect}" if tool.nil?
17
+
18
+ content = tool.call(tool_call.arguments)
19
+ Result.new(tool_call_id: tool_call.id, content: content.to_s, error: nil)
20
+ rescue ToolNotFoundError
21
+ raise # configuration bug, not a tool runtime error — let it propagate
22
+ rescue => e
23
+ Result.new(tool_call_id: tool_call.id, content: "Error: #{e.message}", error: e)
24
+ end
25
+
26
+ def return_direct?(tool_calls)
27
+ tool_calls.any? { |tc| @tools[tc.name]&.return_direct? }
28
+ end
29
+
30
+ def definitions
31
+ @tools.values
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rixie
4
+ VERSION = "0.1.0"
5
+ end
data/lib/rixie.rb ADDED
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rixie/version"
4
+ require_relative "rixie/error"
5
+ require_relative "rixie/http/client"
6
+ require_relative "rixie/configuration"
7
+ require_relative "rixie/event"
8
+ require_relative "rixie/event_listener"
9
+ require_relative "rixie/subscriber"
10
+ require_relative "rixie/subscribers/event_severity"
11
+ require_relative "rixie/subscribers/logger"
12
+ require_relative "rixie/subscribers/json_logger"
13
+ require_relative "rixie/llm/tool_call"
14
+ require_relative "rixie/message"
15
+ require_relative "rixie/llm/response"
16
+ require_relative "rixie/llm/client"
17
+ require_relative "rixie/llm/adapter/dummy"
18
+ require_relative "rixie/tool"
19
+ require_relative "rixie/tool/human_input"
20
+ require_relative "rixie/tool/fetch"
21
+ require_relative "rixie/tool/current_time"
22
+ require_relative "rixie/tool/calculator"
23
+ require_relative "rixie/tool/file_read"
24
+ require_relative "rixie/tool/file_list"
25
+ require_relative "rixie/tool/file_search"
26
+ require_relative "rixie/tool_executor"
27
+ require_relative "rixie/prompt_builder"
28
+ require_relative "rixie/token_counter"
29
+ require_relative "rixie/context/history"
30
+ require_relative "rixie/context/plan"
31
+ require_relative "rixie/context/summary"
32
+ require_relative "rixie/agent"
33
+ require_relative "rixie/agent/plan"
34
+ require_relative "rixie/agent/re_act"
35
+ require_relative "rixie/agent/compressor"
36
+ require_relative "rixie/store/base"
37
+ require_relative "rixie/store/memory"
38
+ require_relative "rixie/store/null"
39
+ require_relative "rixie/run"
40
+ require_relative "rixie/strategy/simple"
41
+ require_relative "rixie/strategy/plan_execute"
42
+ require_relative "rixie/strategy/re_act"
43
+ require_relative "rixie/task"
44
+ require_relative "rixie/session"
45
+ require_relative "rixie/mcp"
46
+ require_relative "rixie/search/base"
47
+ require_relative "rixie/search/duck_duck_go"
48
+ require_relative "rixie/search/wikipedia"
49
+ require_relative "rixie/tool/web_search"
50
+ require_relative "rixie/tool/wikipedia_search"
51
+
52
+ module Rixie
53
+ module LLM
54
+ module Adapter; end
55
+ end
56
+
57
+ class << self
58
+ def configure
59
+ yield config
60
+ end
61
+
62
+ def config
63
+ @config ||= Configuration.new
64
+ end
65
+
66
+ def reset!
67
+ @config = Configuration.new
68
+ end
69
+
70
+ def logger
71
+ config.logger
72
+ end
73
+ end
74
+ end
data/sig/rixie.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Rixie
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rixie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - madogiwa0124
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: logger
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: Rixie is a standalone Ruby gem for orchestrating AI agents. It provides
27
+ a clean abstraction for LLM communication, tool execution, and multi-step reasoning
28
+ strategies.
29
+ email:
30
+ - madogiwa0124@gmail.com
31
+ executables:
32
+ - rixie
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - CHANGELOG.md
37
+ - LICENSE.txt
38
+ - README.md
39
+ - bin/rixie
40
+ - lib/rixie.rb
41
+ - lib/rixie/agent.rb
42
+ - lib/rixie/agent/compressor.rb
43
+ - lib/rixie/agent/plan.rb
44
+ - lib/rixie/agent/re_act.rb
45
+ - lib/rixie/cli.rb
46
+ - lib/rixie/cli/commands.rb
47
+ - lib/rixie/cli/commands/base.rb
48
+ - lib/rixie/cli/commands/compress.rb
49
+ - lib/rixie/cli/commands/context.rb
50
+ - lib/rixie/cli/commands/help.rb
51
+ - lib/rixie/cli/commands/model.rb
52
+ - lib/rixie/cli/commands/strategy.rb
53
+ - lib/rixie/cli/markdown.rb
54
+ - lib/rixie/cli/renderer.rb
55
+ - lib/rixie/cli/spinner.rb
56
+ - lib/rixie/cli/terminal.rb
57
+ - lib/rixie/configuration.rb
58
+ - lib/rixie/context/history.rb
59
+ - lib/rixie/context/plan.rb
60
+ - lib/rixie/context/summary.rb
61
+ - lib/rixie/error.rb
62
+ - lib/rixie/event.rb
63
+ - lib/rixie/event/compression_end.rb
64
+ - lib/rixie/event/compression_start.rb
65
+ - lib/rixie/event/envelope.rb
66
+ - lib/rixie/event/finished.rb
67
+ - lib/rixie/event/llm_call_start.rb
68
+ - lib/rixie/event/run_end.rb
69
+ - lib/rixie/event/run_start.rb
70
+ - lib/rixie/event/task_end.rb
71
+ - lib/rixie/event/task_start.rb
72
+ - lib/rixie/event/thought_completed.rb
73
+ - lib/rixie/event/token.rb
74
+ - lib/rixie/event/tool_call_end.rb
75
+ - lib/rixie/event/tool_call_start.rb
76
+ - lib/rixie/event/tool_calls_completed.rb
77
+ - lib/rixie/event_listener.rb
78
+ - lib/rixie/http/client.rb
79
+ - lib/rixie/llm/adapter/dummy.rb
80
+ - lib/rixie/llm/adapter/openai.rb
81
+ - lib/rixie/llm/client.rb
82
+ - lib/rixie/llm/client/resolver.rb
83
+ - lib/rixie/llm/response.rb
84
+ - lib/rixie/llm/tool_call.rb
85
+ - lib/rixie/mcp.rb
86
+ - lib/rixie/mcp/http.rb
87
+ - lib/rixie/mcp/http/client.rb
88
+ - lib/rixie/message.rb
89
+ - lib/rixie/prompt_builder.rb
90
+ - lib/rixie/run.rb
91
+ - lib/rixie/search/base.rb
92
+ - lib/rixie/search/duck_duck_go.rb
93
+ - lib/rixie/search/wikipedia.rb
94
+ - lib/rixie/session.rb
95
+ - lib/rixie/store/base.rb
96
+ - lib/rixie/store/memory.rb
97
+ - lib/rixie/store/null.rb
98
+ - lib/rixie/strategy/plan_execute.rb
99
+ - lib/rixie/strategy/re_act.rb
100
+ - lib/rixie/strategy/simple.rb
101
+ - lib/rixie/subscriber.rb
102
+ - lib/rixie/subscribers/event_severity.rb
103
+ - lib/rixie/subscribers/json_logger.rb
104
+ - lib/rixie/subscribers/logger.rb
105
+ - lib/rixie/task.rb
106
+ - lib/rixie/token_counter.rb
107
+ - lib/rixie/tool.rb
108
+ - lib/rixie/tool/calculator.rb
109
+ - lib/rixie/tool/current_time.rb
110
+ - lib/rixie/tool/fetch.rb
111
+ - lib/rixie/tool/file_list.rb
112
+ - lib/rixie/tool/file_read.rb
113
+ - lib/rixie/tool/file_sandbox.rb
114
+ - lib/rixie/tool/file_search.rb
115
+ - lib/rixie/tool/human_input.rb
116
+ - lib/rixie/tool/web_search.rb
117
+ - lib/rixie/tool/wikipedia_search.rb
118
+ - lib/rixie/tool_executor.rb
119
+ - lib/rixie/version.rb
120
+ - sig/rixie.rbs
121
+ homepage: https://github.com/madogiwa0124/rixie
122
+ licenses:
123
+ - MIT
124
+ metadata:
125
+ homepage_uri: https://github.com/madogiwa0124/rixie
126
+ source_code_uri: https://github.com/madogiwa0124/rixie/tree/main
127
+ changelog_uri: https://github.com/madogiwa0124/rixie/blob/main/CHANGELOG.md
128
+ bug_tracker_uri: https://github.com/madogiwa0124/rixie/issues
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '3.4'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 4.0.6
144
+ specification_version: 4
145
+ summary: AI agent orchestration for Ruby
146
+ test_files: []