brute 0.4.1 → 1.0.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/lib/brute/agent.rb +14 -0
  3. data/lib/brute/diff.rb +18 -28
  4. data/lib/brute/loop/agent_stream.rb +118 -0
  5. data/lib/brute/loop/agent_turn.rb +520 -0
  6. data/lib/brute/{compactor.rb → loop/compactor.rb} +2 -0
  7. data/lib/brute/{doom_loop.rb → loop/doom_loop.rb} +2 -0
  8. data/lib/brute/loop/step.rb +332 -0
  9. data/lib/brute/loop/tool_call_step.rb +90 -0
  10. data/lib/brute/middleware/compaction_check.rb +60 -146
  11. data/lib/brute/middleware/doom_loop_detection.rb +95 -92
  12. data/lib/brute/middleware/llm_call.rb +78 -80
  13. data/lib/brute/middleware/message_tracking.rb +115 -162
  14. data/lib/brute/middleware/otel/span.rb +25 -106
  15. data/lib/brute/middleware/otel/token_usage.rb +29 -84
  16. data/lib/brute/middleware/otel/tool_calls.rb +23 -107
  17. data/lib/brute/middleware/otel/tool_results.rb +22 -86
  18. data/lib/brute/middleware/reasoning_normalizer.rb +78 -103
  19. data/lib/brute/middleware/retry.rb +95 -76
  20. data/lib/brute/middleware/session_persistence.rb +38 -37
  21. data/lib/brute/middleware/token_tracking.rb +64 -63
  22. data/lib/brute/middleware/tool_error_tracking.rb +108 -82
  23. data/lib/brute/middleware/tool_use_guard.rb +57 -90
  24. data/lib/brute/middleware/tracing.rb +53 -63
  25. data/lib/brute/middleware.rb +18 -0
  26. data/lib/brute/orchestrator/turn.rb +105 -0
  27. data/lib/brute/pipeline.rb +77 -133
  28. data/lib/brute/prompts/build_switch.rb +21 -25
  29. data/lib/brute/prompts/environment.rb +31 -35
  30. data/lib/brute/prompts/identity.rb +22 -29
  31. data/lib/brute/prompts/instructions.rb +15 -18
  32. data/lib/brute/prompts/max_steps.rb +18 -25
  33. data/lib/brute/prompts/plan_reminder.rb +18 -26
  34. data/lib/brute/prompts/skills.rb +8 -30
  35. data/lib/brute/prompts.rb +28 -0
  36. data/lib/brute/providers/ollama.rb +135 -0
  37. data/lib/brute/providers/shell.rb +2 -2
  38. data/lib/brute/providers/shell_response.rb +2 -2
  39. data/lib/brute/providers.rb +62 -0
  40. data/lib/brute/queue/base_queue.rb +222 -0
  41. data/lib/brute/{file_mutation_queue.rb → queue/file_mutation_queue.rb} +28 -26
  42. data/lib/brute/queue/parallel_queue.rb +66 -0
  43. data/lib/brute/queue/sequential_queue.rb +63 -0
  44. data/lib/brute/store/message_store.rb +362 -0
  45. data/lib/brute/store/session.rb +106 -0
  46. data/lib/brute/{snapshot_store.rb → store/snapshot_store.rb} +2 -0
  47. data/lib/brute/{todo_store.rb → store/todo_store.rb} +2 -0
  48. data/lib/brute/system_prompt.rb +81 -194
  49. data/lib/brute/tools/delegate.rb +46 -116
  50. data/lib/brute/tools/fs_patch.rb +36 -37
  51. data/lib/brute/tools/fs_remove.rb +2 -2
  52. data/lib/brute/tools/fs_undo.rb +2 -2
  53. data/lib/brute/tools/fs_write.rb +29 -41
  54. data/lib/brute/tools/todo_read.rb +1 -1
  55. data/lib/brute/tools/todo_write.rb +1 -1
  56. data/lib/brute/tools.rb +31 -0
  57. data/lib/brute/version.rb +1 -1
  58. data/lib/brute.rb +40 -204
  59. metadata +31 -20
  60. data/lib/brute/agent_stream.rb +0 -181
  61. data/lib/brute/hooks.rb +0 -84
  62. data/lib/brute/message_store.rb +0 -463
  63. data/lib/brute/orchestrator.rb +0 -550
  64. data/lib/brute/session.rb +0 -161
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if __FILE__ == $0
4
- require "bundler/setup"
5
- require "brute"
6
- end
7
-
3
+ require "bundler/setup"
4
+ require "brute"
8
5
  require 'fileutils'
9
6
 
10
7
  module Brute
@@ -19,9 +16,9 @@ module Brute
19
16
 
20
17
  def call(file_path:, content:)
21
18
  path = File.expand_path(file_path)
22
- Brute::FileMutationQueue.serialize(path) do
19
+ Brute::Queue::FileMutationQueue.serialize(path) do
23
20
  old_content = File.exist?(path) ? File.read(path) : ''
24
- Brute::SnapshotStore.save(path)
21
+ Brute::Store::SnapshotStore.save(path)
25
22
  FileUtils.mkdir_p(File.dirname(path))
26
23
  File.write(path, content)
27
24
  diff = Brute::Diff.unified(old_content, content)
@@ -32,47 +29,38 @@ module Brute
32
29
  end
33
30
  end
34
31
 
35
- if __FILE__ == $0
36
- require_relative "../../../spec/spec_helper"
37
-
38
- RSpec.describe Brute::Tools::FSWrite do
39
- around(:each) { |ex| Dir.mktmpdir { |d| @dir = d; ex.run } }
32
+ test do
33
+ require "tmpdir"
40
34
 
41
- let(:tool) { described_class.new }
42
-
43
- it "writes content to a new file" do
44
- path = File.join(@dir, "new.rb")
45
- result = tool.call(file_path: path, content: "hello\n")
46
- expect(result[:success]).to be true
47
- expect(File.read(path)).to eq("hello\n")
48
- end
49
-
50
- it "returns a diff for new files" do
51
- path = File.join(@dir, "new.rb")
52
- result = tool.call(file_path: path, content: "line1\nline2\n")
53
- expect(result[:diff]).to include("+line1")
54
- expect(result[:diff]).to include("+line2")
35
+ it "writes content to a new file" do
36
+ Dir.mktmpdir do |dir|
37
+ path = File.join(dir, "new.rb")
38
+ Brute::Tools::FSWrite.new.call(file_path: path, content: "hello\n")
39
+ File.read(path).should == "hello\n"
55
40
  end
41
+ end
56
42
 
57
- it "returns a diff for overwritten files" do
58
- path = File.join(@dir, "existing.rb")
59
- File.write(path, "old content\n")
60
- result = tool.call(file_path: path, content: "new content\n")
61
- expect(result[:diff]).to include("-old content")
62
- expect(result[:diff]).to include("+new content")
43
+ it "returns a diff for new files" do
44
+ Dir.mktmpdir do |dir|
45
+ path = File.join(dir, "new.rb")
46
+ result = Brute::Tools::FSWrite.new.call(file_path: path, content: "line1\nline2\n")
47
+ result[:diff].should =~ /\+line1/
63
48
  end
49
+ end
64
50
 
65
- it "creates parent directories" do
66
- path = File.join(@dir, "deep", "nested", "file.rb")
67
- result = tool.call(file_path: path, content: "nested\n")
68
- expect(result[:success]).to be true
69
- expect(File.exist?(path)).to be true
51
+ it "creates parent directories" do
52
+ Dir.mktmpdir do |dir|
53
+ path = File.join(dir, "deep", "nested", "file.rb")
54
+ result = Brute::Tools::FSWrite.new.call(file_path: path, content: "nested\n")
55
+ result[:success].should.be.true
70
56
  end
57
+ end
71
58
 
72
- it "returns byte count" do
73
- path = File.join(@dir, "test.rb")
74
- result = tool.call(file_path: path, content: "hello")
75
- expect(result[:bytes]).to eq(5)
59
+ it "returns byte count" do
60
+ Dir.mktmpdir do |dir|
61
+ path = File.join(dir, "test.rb")
62
+ result = Brute::Tools::FSWrite.new.call(file_path: path, content: "hello")
63
+ result[:bytes].should == 5
76
64
  end
77
65
  end
78
66
  end
@@ -13,7 +13,7 @@ module Brute
13
13
  param :_placeholder, String, "Unused, pass any value"
14
14
 
15
15
  def call(_placeholder: nil)
16
- {todos: Brute::TodoStore.all}
16
+ {todos: Brute::Store::TodoStore.all}
17
17
  end
18
18
  end
19
19
  end
@@ -29,7 +29,7 @@ module Brute
29
29
  t = t.transform_keys(&:to_sym) if t.is_a?(Hash)
30
30
  {id: t[:id], content: t[:content], status: t[:status]}
31
31
  end
32
- Brute::TodoStore.replace(items)
32
+ Brute::Store::TodoStore.replace(items)
33
33
  {success: true, count: items.size}
34
34
  end
35
35
  end
@@ -0,0 +1,31 @@
1
+ require_relative 'tools/fs_read'
2
+ require_relative 'tools/fs_write'
3
+ require_relative 'tools/fs_patch'
4
+ require_relative 'tools/fs_remove'
5
+ require_relative 'tools/fs_search'
6
+ require_relative 'tools/fs_undo'
7
+ require_relative 'tools/shell'
8
+ require_relative 'tools/net_fetch'
9
+ require_relative 'tools/todo_write'
10
+ require_relative 'tools/todo_read'
11
+ require_relative 'tools/delegate'
12
+ require_relative 'tools/question'
13
+
14
+ module Brute
15
+ module Tools
16
+ ALL = [
17
+ Tools::FSRead,
18
+ Tools::FSWrite,
19
+ Tools::FSPatch,
20
+ Tools::FSRemove,
21
+ Tools::FSSearch,
22
+ Tools::FSUndo,
23
+ Tools::Shell,
24
+ Tools::NetFetch,
25
+ Tools::TodoWrite,
26
+ Tools::TodoRead,
27
+ Tools::Delegate,
28
+ Tools::Question
29
+ ].freeze
30
+ end
31
+ end
data/lib/brute/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Brute
4
- VERSION = "0.4.1"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/brute.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'llm'
4
4
  require 'timeout'
5
5
  require 'logger'
6
+ require 'scampi/kernel_ext'
6
7
 
7
8
  # Brute — a coding agent built on llm.rb
8
9
  #
@@ -11,220 +12,55 @@ require 'logger'
11
12
  #
12
13
  # Tracing → Retry → Session → Tokens → Compaction → ToolErrors → DoomLoop → Reasoning → [LLM Call]
13
14
  #
15
+ # Entry point:
16
+ #
17
+ # agent = Brute::Agent.new(provider:, model:, tools:, system_prompt:)
18
+ # step = Brute::Loop::AgentTurn.perform(agent:, session:, pipeline:, input:)
19
+ #
14
20
  require_relative 'brute/version'
15
21
 
16
22
  module Brute
17
- module Tools; end
18
- module Hooks; end
19
- module Middleware; end
23
+ def self.provider
24
+ @provider ||= Brute::Providers.guess_from_env
25
+ end
26
+
27
+ def self.provider=(p)
28
+ @provider = p
29
+ end
20
30
  end
21
31
 
22
- # Infrastructure
23
32
  require_relative 'brute/diff'
24
- require_relative 'brute/snapshot_store'
25
- require_relative 'brute/todo_store'
26
- require_relative 'brute/file_mutation_queue'
27
- require_relative 'brute/doom_loop'
28
- require_relative 'brute/hooks'
29
- require_relative 'brute/compactor'
30
- require_relative 'brute/prompts/base'
31
- require_relative 'brute/prompts/identity'
32
- require_relative 'brute/prompts/tone_and_style'
33
- require_relative 'brute/prompts/objectivity'
34
- require_relative 'brute/prompts/task_management'
35
- require_relative 'brute/prompts/doing_tasks'
36
- require_relative 'brute/prompts/tool_usage'
37
- require_relative 'brute/prompts/conventions'
38
- require_relative 'brute/prompts/git_safety'
39
- require_relative 'brute/prompts/code_references'
40
- require_relative 'brute/prompts/environment'
41
- require_relative 'brute/prompts/instructions'
42
- require_relative 'brute/prompts/editing_approach'
43
- require_relative 'brute/prompts/autonomy'
44
- require_relative 'brute/prompts/editing_constraints'
45
- require_relative 'brute/prompts/frontend_tasks'
46
- require_relative 'brute/prompts/proactiveness'
47
- require_relative 'brute/prompts/code_style'
48
- require_relative 'brute/prompts/security_and_safety'
49
- require_relative 'brute/prompts/skills'
50
- require_relative 'brute/prompts/plan_reminder'
51
- require_relative 'brute/prompts/max_steps'
52
- require_relative 'brute/prompts/build_switch'
53
33
  require_relative 'brute/skill'
34
+ require_relative 'brute/prompts'
54
35
  require_relative 'brute/system_prompt'
55
- require_relative 'brute/message_store'
56
- require_relative 'brute/session'
57
36
  require_relative 'brute/pipeline'
58
- require_relative 'brute/agent_stream'
37
+ require_relative 'brute/agent'
38
+
39
+ # Brute::Store
40
+ require_relative 'brute/store/snapshot_store'
41
+ require_relative 'brute/store/todo_store'
42
+ require_relative 'brute/store/message_store'
43
+ require_relative 'brute/store/session'
44
+
45
+ # Brute::Loop (before Queue — queue tests reference Loop::Step)
46
+ require_relative 'brute/loop/doom_loop'
47
+ require_relative 'brute/loop/compactor'
48
+ require_relative 'brute/loop/agent_stream'
49
+ require_relative 'brute/loop/step'
50
+ require_relative 'brute/loop/tool_call_step'
51
+
52
+ # Brute::Queue
53
+ require_relative 'brute/queue/file_mutation_queue'
54
+ require_relative 'brute/queue/base_queue'
55
+ require_relative 'brute/queue/sequential_queue'
56
+ require_relative 'brute/queue/parallel_queue'
57
+
58
+ # Brute::Loop (agent_turn depends on Queue)
59
+ require_relative 'brute/loop/agent_turn'
59
60
 
60
- # Provider patches
61
61
  require_relative 'brute/patches/anthropic_tool_role'
62
62
  require_relative 'brute/patches/buffer_nil_guard'
63
63
 
64
- # Middleware (Rack-style)
65
- require_relative 'brute/middleware/base'
66
- require_relative 'brute/middleware/llm_call'
67
- require_relative 'brute/middleware/retry'
68
- require_relative 'brute/middleware/doom_loop_detection'
69
- require_relative 'brute/middleware/token_tracking'
70
- require_relative 'brute/middleware/compaction_check'
71
- require_relative 'brute/middleware/session_persistence'
72
- require_relative 'brute/middleware/message_tracking'
73
- require_relative 'brute/middleware/tracing'
74
- require_relative 'brute/middleware/tool_error_tracking'
75
- require_relative 'brute/middleware/reasoning_normalizer'
76
- require_relative "brute/middleware/tool_use_guard"
77
- require_relative "brute/middleware/otel"
78
-
79
- # Tools
80
- require_relative 'brute/tools/fs_read'
81
- require_relative 'brute/tools/fs_write'
82
- require_relative 'brute/tools/fs_patch'
83
- require_relative 'brute/tools/fs_remove'
84
- require_relative 'brute/tools/fs_search'
85
- require_relative 'brute/tools/fs_undo'
86
- require_relative 'brute/tools/shell'
87
- require_relative 'brute/tools/net_fetch'
88
- require_relative 'brute/tools/todo_write'
89
- require_relative 'brute/tools/todo_read'
90
- require_relative 'brute/tools/delegate'
91
- require_relative 'brute/tools/question'
92
-
93
- # Providers
94
- require_relative 'brute/providers/shell_response'
95
- require_relative 'brute/providers/shell'
96
- require_relative 'brute/providers/models_dev'
97
- require_relative 'brute/providers/opencode_zen'
98
- require_relative 'brute/providers/opencode_go'
99
-
100
- # Orchestrator (depends on tools, middleware, and infrastructure)
101
- require_relative 'brute/orchestrator'
102
-
103
- module Brute
104
- # The complete set of tools available to the agent.
105
- TOOLS = [
106
- Tools::FSRead,
107
- Tools::FSWrite,
108
- Tools::FSPatch,
109
- Tools::FSRemove,
110
- Tools::FSSearch,
111
- Tools::FSUndo,
112
- Tools::Shell,
113
- Tools::NetFetch,
114
- Tools::TodoWrite,
115
- Tools::TodoRead,
116
- Tools::Delegate,
117
- Tools::Question
118
- ].freeze
119
-
120
- # Default provider, resolved from environment.
121
- def self.provider
122
- @provider ||= resolve_provider
123
- end
124
-
125
- def self.provider=(p)
126
- @provider = p
127
- end
128
-
129
- # Create a new orchestrator with sensible defaults.
130
- def self.agent(cwd: Dir.pwd, model: nil, tools: TOOLS, session: nil, reasoning: {}, agent_name: nil, **callbacks)
131
- Orchestrator.new(
132
- provider: provider,
133
- model: model,
134
- tools: tools,
135
- cwd: cwd,
136
- session: session,
137
- reasoning: reasoning,
138
- agent_name: agent_name,
139
- **callbacks
140
- )
141
- end
142
-
143
- PROVIDERS = {
144
- 'anthropic' => ->(key) { LLM.anthropic(key: key).tap { Patches::AnthropicToolRole.apply! } },
145
- 'openai' => ->(key) { LLM.openai(key: key) },
146
- 'google' => ->(key) { LLM.google(key: key) },
147
- 'deepseek' => ->(key) { LLM.deepseek(key: key) },
148
- 'ollama' => ->(key) { LLM.ollama(key: key) },
149
- 'xai' => ->(key) { LLM.xai(key: key) },
150
- 'opencode_zen' => ->(key) { LLM::OpencodeZen.new(key: key) },
151
- 'opencode_go' => ->(key) { LLM::OpencodeGo.new(key: key) },
152
- 'shell' => ->(_key) { Providers::Shell.new },
153
- }.freeze
154
-
155
- # List provider names that have API keys configured in the environment.
156
- # The shell provider is always available (no key needed).
157
- def self.configured_providers
158
- PROVIDERS.keys.select { |name| api_key_for(name) }
159
- end
160
-
161
- # Build a provider instance for the given name using available API keys.
162
- # Returns nil if no key is found.
163
- def self.provider_for(name)
164
- key = api_key_for(name)
165
- return nil unless key
166
-
167
- factory = PROVIDERS[name]
168
- return nil unless factory
169
-
170
- factory.call(key)
171
- end
172
-
173
- # Look up the API key for a given provider name.
174
- def self.api_key_for(name)
175
- # Shell provider needs no key.
176
- return "none" if name == "shell"
177
-
178
- # OpenCode providers: check OPENCODE_API_KEY, fall back to "public" for anonymous access.
179
- if name == "opencode_zen" || name == "opencode_go"
180
- return ENV["OPENCODE_API_KEY"] || "public"
181
- end
182
-
183
- # Explicit generic key always works
184
- return ENV["LLM_API_KEY"] if ENV["LLM_API_KEY"]
185
-
186
- case name
187
- when "anthropic" then ENV["ANTHROPIC_API_KEY"]
188
- when "openai" then ENV["OPENAI_API_KEY"]
189
- when "google" then ENV["GOOGLE_API_KEY"]
190
- end
191
- end
192
-
193
- # Resolve the LLM provider from environment variables.
194
- #
195
- # Checks in order:
196
- # 1. LLM_API_KEY + LLM_PROVIDER (explicit)
197
- # 2. OPENCODE_API_KEY (implicit: provider = opencode_zen)
198
- # 3. ANTHROPIC_API_KEY (implicit: provider = anthropic)
199
- # 4. OPENAI_API_KEY (implicit: provider = openai)
200
- # 5. GOOGLE_API_KEY (implicit: provider = google)
201
- #
202
- # Returns nil if no key is found. Error is deferred to Orchestrator#run.
203
- def self.resolve_provider
204
- if ENV['LLM_API_KEY']
205
- key = ENV['LLM_API_KEY']
206
- name = ENV.fetch('LLM_PROVIDER', 'opencode_zen').downcase
207
- elsif ENV['OPENCODE_API_KEY']
208
- key = ENV['OPENCODE_API_KEY']
209
- name = 'opencode_zen'
210
- elsif ENV['ANTHROPIC_API_KEY']
211
- key = ENV['ANTHROPIC_API_KEY']
212
- name = 'anthropic'
213
- elsif ENV['OPENAI_API_KEY']
214
- key = ENV['OPENAI_API_KEY']
215
- name = 'openai'
216
- elsif ENV['GOOGLE_API_KEY']
217
- key = ENV['GOOGLE_API_KEY']
218
- name = 'google'
219
- else
220
- return nil
221
- end
222
-
223
- factory = PROVIDERS[name]
224
- raise "Unknown LLM provider: #{name}. Available: #{PROVIDERS.keys.join(', ')}" unless factory
225
-
226
- factory.call(key)
227
- end
228
-
229
- private_class_method :resolve_provider
230
- end
64
+ require_relative 'brute/middleware'
65
+ require_relative 'brute/tools'
66
+ require_relative 'brute/providers'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brute
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brute Contributors
@@ -52,33 +52,33 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: '4.11'
54
54
  - !ruby/object:Gem::Dependency
55
- name: rake
55
+ name: scampi
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '13.0'
61
- type: :development
60
+ version: '0'
61
+ type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '13.0'
67
+ version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
- name: rspec
69
+ name: rake
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '3.13'
74
+ version: '13.0'
75
75
  type: :development
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '3.13'
81
+ version: '13.0'
82
82
  description: Production-grade coding agent with tool execution, middleware pipeline,
83
83
  context compaction, session persistence, and multi-provider LLM support.
84
84
  executables: []
@@ -86,13 +86,15 @@ extensions: []
86
86
  extra_rdoc_files: []
87
87
  files:
88
88
  - lib/brute.rb
89
- - lib/brute/agent_stream.rb
90
- - lib/brute/compactor.rb
89
+ - lib/brute/agent.rb
91
90
  - lib/brute/diff.rb
92
- - lib/brute/doom_loop.rb
93
- - lib/brute/file_mutation_queue.rb
94
- - lib/brute/hooks.rb
95
- - lib/brute/message_store.rb
91
+ - lib/brute/loop/agent_stream.rb
92
+ - lib/brute/loop/agent_turn.rb
93
+ - lib/brute/loop/compactor.rb
94
+ - lib/brute/loop/doom_loop.rb
95
+ - lib/brute/loop/step.rb
96
+ - lib/brute/loop/tool_call_step.rb
97
+ - lib/brute/middleware.rb
96
98
  - lib/brute/middleware/base.rb
97
99
  - lib/brute/middleware/compaction_check.rb
98
100
  - lib/brute/middleware/doom_loop_detection.rb
@@ -110,10 +112,11 @@ files:
110
112
  - lib/brute/middleware/tool_error_tracking.rb
111
113
  - lib/brute/middleware/tool_use_guard.rb
112
114
  - lib/brute/middleware/tracing.rb
113
- - lib/brute/orchestrator.rb
115
+ - lib/brute/orchestrator/turn.rb
114
116
  - lib/brute/patches/anthropic_tool_role.rb
115
117
  - lib/brute/patches/buffer_nil_guard.rb
116
118
  - lib/brute/pipeline.rb
119
+ - lib/brute/prompts.rb
117
120
  - lib/brute/prompts/autonomy.rb
118
121
  - lib/brute/prompts/base.rb
119
122
  - lib/brute/prompts/build_switch.rb
@@ -155,16 +158,24 @@ files:
155
158
  - lib/brute/prompts/text/tool_usage/google.txt
156
159
  - lib/brute/prompts/tone_and_style.rb
157
160
  - lib/brute/prompts/tool_usage.rb
161
+ - lib/brute/providers.rb
158
162
  - lib/brute/providers/models_dev.rb
163
+ - lib/brute/providers/ollama.rb
159
164
  - lib/brute/providers/opencode_go.rb
160
165
  - lib/brute/providers/opencode_zen.rb
161
166
  - lib/brute/providers/shell.rb
162
167
  - lib/brute/providers/shell_response.rb
163
- - lib/brute/session.rb
168
+ - lib/brute/queue/base_queue.rb
169
+ - lib/brute/queue/file_mutation_queue.rb
170
+ - lib/brute/queue/parallel_queue.rb
171
+ - lib/brute/queue/sequential_queue.rb
164
172
  - lib/brute/skill.rb
165
- - lib/brute/snapshot_store.rb
173
+ - lib/brute/store/message_store.rb
174
+ - lib/brute/store/session.rb
175
+ - lib/brute/store/snapshot_store.rb
176
+ - lib/brute/store/todo_store.rb
166
177
  - lib/brute/system_prompt.rb
167
- - lib/brute/todo_store.rb
178
+ - lib/brute/tools.rb
168
179
  - lib/brute/tools/delegate.rb
169
180
  - lib/brute/tools/fs_patch.rb
170
181
  - lib/brute/tools/fs_read.rb