brute_cli 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 (4) hide show
  1. checksums.yaml +7 -0
  2. data/exe/brute +89 -0
  3. data/lib/brute_cli.rb +29 -0
  4. metadata +97 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fb2f42dc6aa2c08fb4b1e58f59f34a76c5acd4f279a952a7c660ab1291433267
4
+ data.tar.gz: 34775d35a5b84820359eb5c4757670b26c96abf49128cc3d28c00c4566b048c5
5
+ SHA512:
6
+ metadata.gz: 3cfa605892029140963a04f2728a08f233321436b34c3f940f47eb127628a20d08193ba1b540d52ce224f20a834131e7e9ae9d9849dec7c65b842ef5321cb155
7
+ data.tar.gz: 3008b477c0a57e911fe95ef19d23ef3a4a26b489ceed6b857c334376285c492aa6e6605aa77b3e79a44f580c62601795a92e47109f4cc7a278e1bc4dfc84e964
data/exe/brute ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "brute_cli"
5
+ require "optparse"
6
+
7
+ options = { cwd: Dir.pwd, session_id: nil }
8
+
9
+ OptionParser.new do |opts|
10
+ opts.banner = "Usage: brute [options] [prompt]"
11
+ opts.on("-d", "--directory DIR", "Working directory") { |d| options[:cwd] = File.expand_path(d) }
12
+ opts.on("-s", "--session ID", "Resume a session") { |id| options[:session_id] = id }
13
+ opts.on("--list-sessions", "List saved sessions") { options[:list] = true }
14
+ opts.on("-v", "--version", "Show version") { puts "brute #{Brute::VERSION}"; exit }
15
+ opts.on("-h", "--help", "Show help") { puts opts; exit }
16
+ end.parse!
17
+
18
+ if options[:list]
19
+ sessions = Brute::Session.list
20
+ if sessions.empty?
21
+ puts "No saved sessions."
22
+ else
23
+ sessions.each { |s| puts " #{s[:id]} #{s[:title] || "(untitled)"} #{s[:saved_at]}" }
24
+ end
25
+ exit
26
+ end
27
+
28
+ begin
29
+ session = Brute::Session.new(id: options[:session_id])
30
+
31
+ orch = Brute.agent(
32
+ cwd: options[:cwd],
33
+ session: session,
34
+ on_content: ->(text) { print text },
35
+ on_reasoning: ->(_text) { },
36
+ on_tool_call: ->(name, args) {
37
+ $stderr.puts "\n--- [tool] #{name} ---"
38
+ if args.is_a?(Hash)
39
+ args.each { |k, v| $stderr.puts " #{k}: #{v.to_s[0..100]}" }
40
+ end
41
+ },
42
+ on_tool_result: ->(name, result) {
43
+ if result.is_a?(Hash) && result[:error]
44
+ $stderr.puts " [FAILED] #{result[:error]}"
45
+ else
46
+ $stderr.puts " [ok]"
47
+ end
48
+ },
49
+ )
50
+
51
+ session.restore(orch.context) if options[:session_id]
52
+ rescue RuntimeError => e
53
+ BruteCLI.error(e.message.strip)
54
+ exit 1
55
+ end
56
+
57
+ prompt = ARGV.join(" ")
58
+ prompt = $stdin.read.strip if prompt.empty? && !$stdin.tty?
59
+
60
+ begin
61
+ if prompt.empty?
62
+ $stderr.puts "brute> (interactive mode, Ctrl-D to exit)\n\n"
63
+ loop do
64
+ $stderr.print "brute> "
65
+ input = $stdin.gets&.chomp
66
+ break if input.nil? || input.strip == "exit"
67
+ next if input.strip.empty?
68
+ puts
69
+ orch.run(input)
70
+ puts "\n\n"
71
+ end
72
+ else
73
+ orch.run(prompt)
74
+ puts
75
+ end
76
+ rescue Interrupt
77
+ $stderr.puts "\nAborted."
78
+ exit 130
79
+ rescue LLM::RateLimitError => e
80
+ BruteCLI.error("Rate limited by provider. #{e.message}")
81
+ exit 1
82
+ rescue LLM::ServerError => e
83
+ BruteCLI.error("Provider returned a server error. #{e.message}")
84
+ exit 1
85
+ rescue => e
86
+ BruteCLI.error(e.message)
87
+ $stderr.puts " #{e.backtrace.first}".red if ENV["BRUTE_DEBUG"]
88
+ exit 1
89
+ end
data/lib/brute_cli.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "brute"
4
+ require "colorize"
5
+ require "emoji"
6
+
7
+ # Optionally load brute_flow if available.
8
+ begin
9
+ require "brute_flow"
10
+ rescue LoadError
11
+ # brute_flow is optional for CLI usage
12
+ end
13
+
14
+ module BruteCLI
15
+ VERSION = "0.1.0"
16
+
17
+ CROSS_MARK = Emoji.find_by_alias("x").raw
18
+ WARNING_SIGN = Emoji.find_by_alias("warning").raw
19
+
20
+ # Print a red error message with a cross mark prefix to stderr.
21
+ def self.error(message)
22
+ $stderr.puts "#{CROSS_MARK} #{message}".red
23
+ end
24
+
25
+ # Print a yellow warning to stderr.
26
+ def self.warn(message)
27
+ $stderr.puts "#{WARNING_SIGN} #{message}".yellow
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brute_cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brute Contributors
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: brute
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: brute_flow
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: colorize
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.1'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.1'
54
+ - !ruby/object:Gem::Dependency
55
+ name: gemoji
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '4.1'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '4.1'
68
+ description: Interactive command-line interface for the Brute coding agent. Supports
69
+ single-prompt, interactive, piped, and session modes.
70
+ executables:
71
+ - brute
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - exe/brute
76
+ - lib/brute_cli.rb
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '3.2'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubygems_version: 3.7.2
95
+ specification_version: 4
96
+ summary: CLI for the Brute coding agent
97
+ test_files: []