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.
- checksums.yaml +7 -0
- data/exe/brute +89 -0
- data/lib/brute_cli.rb +29 -0
- 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: []
|