brute 5.1.0 → 6.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.
- checksums.yaml +4 -4
- data/lib/brute/compaction/middleware/sliding_window.rb +1 -1
- data/lib/brute/compaction/middleware/strategy.rb +0 -2
- data/lib/brute/compaction/summarize.rb +30 -21
- data/lib/brute/completion/lang_chain.rb +34 -31
- data/lib/brute/completion/llmrb.rb +31 -29
- data/lib/brute/completion/open_router.rb +43 -40
- data/lib/brute/completion/ruby_llm.rb +28 -27
- data/lib/brute/contrib/otel.rb +81 -49
- data/lib/brute/eval/case.rb +7 -2
- data/lib/brute/eval/suite.rb +10 -5
- data/lib/brute/eval/transcript.rb +3 -3
- data/lib/brute/eval/world.rb +2 -2
- data/lib/brute/eval.rb +1 -1
- data/lib/brute/events/handler.rb +3 -1
- data/lib/brute/events/prefixed_terminal_output.rb +3 -1
- data/lib/brute/events/terminal_output_handler.rb +1 -1
- data/lib/brute/hooks.rb +88 -112
- data/lib/brute/message_transport/anthropic.rb +13 -3
- data/lib/brute/message_transport/llm.rb +8 -4
- data/lib/brute/message_transport/open_router.rb +30 -16
- data/lib/brute/message_transport/openai.rb +14 -7
- data/lib/brute/message_transport/ruby_llm.rb +21 -17
- data/lib/brute/message_transport/ruby_open_ai.rb +59 -57
- data/lib/brute/messages.rb +15 -8
- data/lib/brute/middleware/000_base.rb +5 -5
- data/lib/brute/middleware/002_session_log.rb +12 -4
- data/lib/brute/middleware/008_checkpoint.rb +26 -18
- data/lib/brute/middleware/010_max_iterations.rb +1 -1
- data/lib/brute/middleware/020_system_prompt.rb +1 -1
- data/lib/brute/middleware/040_default_compaction_pipeline.rb +49 -45
- data/lib/brute/middleware/070_default_tool_pipeline.rb +44 -53
- data/lib/brute/prompt_template.rb +19 -15
- data/lib/brute/prompts/base.rb +19 -10
- data/lib/brute/prompts/environment.rb +3 -1
- data/lib/brute/prompts/instructions.rb +9 -7
- data/lib/brute/prompts/skills.rb +5 -3
- data/lib/brute/rack/adapter.rb +40 -23
- data/lib/brute/skill.rb +136 -89
- data/lib/brute/system_prompt.rb +9 -9
- data/lib/brute/token_counter.rb +3 -1
- data/lib/brute/tool.rb +10 -6
- data/lib/brute/tools/adapter.rb +53 -43
- data/lib/brute/tools/fs/snapshot_store.rb +5 -1
- data/lib/brute/tools/fs_patch.rb +16 -8
- data/lib/brute/tools/fs_read.rb +107 -80
- data/lib/brute/tools/fs_remove.rb +6 -2
- data/lib/brute/tools/fs_search.rb +14 -4
- data/lib/brute/tools/fs_undo.rb +6 -2
- data/lib/brute/tools/fs_write.rb +5 -1
- data/lib/brute/tools/net_fetch.rb +6 -2
- data/lib/brute/tools/question.rb +42 -39
- data/lib/brute/tools/shell.rb +20 -5
- data/lib/brute/tools/skill_load.rb +44 -39
- data/lib/brute/tools/todo_write.rb +19 -15
- data/lib/brute/truncation.rb +68 -43
- data/lib/brute/turn/agent_pipeline.rb +23 -13
- data/lib/brute/turn/compaction_pipeline.rb +4 -3
- data/lib/brute/turn/pipeline.rb +87 -96
- data/lib/brute/turn/tool_pipeline.rb +4 -3
- data/lib/brute/usage_detection/llmrb.rb +18 -14
- data/lib/brute/usage_detection/open_router.rb +20 -17
- data/lib/brute/usage_detection/ruby_llm.rb +18 -14
- data/lib/brute/usage_detection/usage.rb +10 -1
- data/lib/brute/utils/diff.rb +18 -10
- data/lib/brute/version.rb +1 -1
- data/lib/brute.rb +10 -11
- data/lib/brute_cli/providers/shell.rb +32 -29
- data/lib/brute_cli/providers/shell_response.rb +20 -18
- metadata +30 -5
- data/lib/brute/middleware/040_compaction_check.rb +0 -73
- data/lib/brute/middleware/070_tool_pipeline.rb +0 -61
- data/lib/brute/middleware/event_handler.rb +0 -27
data/lib/brute/utils/diff.rb
CHANGED
|
@@ -12,17 +12,25 @@ module Brute
|
|
|
12
12
|
old_lines = old_text.lines
|
|
13
13
|
new_lines = new_text.lines
|
|
14
14
|
diffs = ::Diff::LCS.diff(old_lines, new_lines)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
if diffs.empty?
|
|
16
|
+
''
|
|
17
|
+
else
|
|
18
|
+
output = +''
|
|
19
|
+
file_length_difference = 0
|
|
20
|
+
diffs.each do |piece|
|
|
21
|
+
hunk = ::Diff::LCS::Hunk.new(
|
|
22
|
+
old_lines,
|
|
23
|
+
new_lines,
|
|
24
|
+
piece,
|
|
25
|
+
context,
|
|
26
|
+
file_length_difference,
|
|
27
|
+
)
|
|
28
|
+
file_length_difference = hunk.file_length_difference
|
|
29
|
+
output << hunk.diff(:unified)
|
|
30
|
+
output << "\n"
|
|
31
|
+
end
|
|
32
|
+
output
|
|
24
33
|
end
|
|
25
|
-
output
|
|
26
34
|
end
|
|
27
35
|
end
|
|
28
36
|
end
|
data/lib/brute/version.rb
CHANGED
data/lib/brute.rb
CHANGED
|
@@ -12,13 +12,13 @@ require_relative 'brute/version'
|
|
|
12
12
|
|
|
13
13
|
module Brute
|
|
14
14
|
LOGO = <<-LOGO
|
|
15
|
-
.o8 .
|
|
16
|
-
"888 .o8
|
|
17
|
-
888oooo. oooo d8b oooo oooo .o888oo .ooooo.
|
|
18
|
-
d88' `88b `888""8P `888 `888 888 d88' `88b
|
|
19
|
-
888 888 888 888 888 888 888ooo888
|
|
20
|
-
888 888 888 888 888 888 . 888 .o
|
|
21
|
-
`Y8bod8P' d888b `V88V"V8P' "888" `Y8bod8P'
|
|
15
|
+
.o8 .
|
|
16
|
+
"888 .o8
|
|
17
|
+
888oooo. oooo d8b oooo oooo .o888oo .ooooo.
|
|
18
|
+
d88' `88b `888""8P `888 `888 888 d88' `88b
|
|
19
|
+
888 888 888 888 888 888 888ooo888
|
|
20
|
+
888 888 888 888 888 888 . 888 .o
|
|
21
|
+
`Y8bod8P' d888b `V88V"V8P' "888" `Y8bod8P'
|
|
22
22
|
LOGO
|
|
23
23
|
|
|
24
24
|
# NOTE: Brute owns no LLM configuration and no LLM library. All
|
|
@@ -68,7 +68,9 @@ module Brute
|
|
|
68
68
|
#
|
|
69
69
|
def self.load_agent(path = "agent.ru")
|
|
70
70
|
path = File.expand_path(path)
|
|
71
|
-
|
|
71
|
+
unless File.file?(path)
|
|
72
|
+
raise ArgumentError, "no such agent file: #{path}"
|
|
73
|
+
end
|
|
72
74
|
|
|
73
75
|
Brute::Turn::AgentPipeline.parse_file(path)
|
|
74
76
|
end
|
|
@@ -132,11 +134,8 @@ require_relative "brute/middleware/010_max_iterations"
|
|
|
132
134
|
require_relative "brute/middleware/020_system_prompt"
|
|
133
135
|
require_relative "brute/middleware/025_skills"
|
|
134
136
|
require_relative "brute/middleware/040_default_compaction_pipeline"
|
|
135
|
-
require_relative "brute/middleware/040_compaction_check"
|
|
136
137
|
require_relative "brute/middleware/060_questions"
|
|
137
138
|
require_relative "brute/middleware/070_default_tool_pipeline"
|
|
138
|
-
require_relative "brute/middleware/070_tool_pipeline"
|
|
139
|
-
require_relative "brute/middleware/event_handler"
|
|
140
139
|
require_relative "brute/middleware/user_queue"
|
|
141
140
|
require_relative "brute/prompt_template"
|
|
142
141
|
require_relative "brute/prompts"
|
|
@@ -44,12 +44,13 @@ module BruteCLI
|
|
|
44
44
|
|
|
45
45
|
# nil text means we received tool results (second call) —
|
|
46
46
|
# return an empty assistant response so the agent loop exits.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
if text.nil?
|
|
48
|
+
ShellResponse.new(model: model, tools: tools)
|
|
49
|
+
else
|
|
50
|
+
wrap = INTERPRETERS.fetch(model, INTERPRETERS["bash"])
|
|
51
|
+
command = wrap.call(text)
|
|
52
|
+
ShellResponse.new(command: command, model: model, tools: tools)
|
|
53
|
+
end
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
# For the REPL model picker: provider.models.all.select(&:chat?)
|
|
@@ -61,38 +62,40 @@ module BruteCLI
|
|
|
61
62
|
|
|
62
63
|
private
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
# Extract the user's text from the messages array.
|
|
66
|
+
# Returns nil when the messages contain tool results (the second
|
|
67
|
+
# round-trip) so #complete knows to return an empty response.
|
|
68
|
+
def extract_text(prompt)
|
|
69
|
+
case prompt
|
|
70
|
+
when String
|
|
71
|
+
prompt
|
|
72
|
+
when ::Array
|
|
73
|
+
if prompt.any? { |m| m.respond_to?(:role) && m.role == :tool }
|
|
74
|
+
nil
|
|
75
|
+
else
|
|
76
|
+
user_msg = prompt.reverse_each.find { |m| m.respond_to?(:role) && m.role == :user }
|
|
77
|
+
user_msg&.content.to_s
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
prompt.to_s
|
|
81
|
+
end
|
|
78
82
|
end
|
|
79
|
-
end
|
|
80
83
|
|
|
81
84
|
# ── ModelList ──────────────────────────────────────────────────
|
|
82
85
|
|
|
83
86
|
# Minimal object that quacks like provider.models so the REPL's
|
|
84
87
|
# fetch_models can call provider.models.all.select(&:chat?).
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
class ModelList
|
|
89
|
+
ModelEntry = Struct.new(:id, :chat?, keyword_init: true)
|
|
87
90
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
def initialize(names)
|
|
92
|
+
@entries = names.map { |n| ModelEntry.new(id: n, chat?: true) }
|
|
93
|
+
end
|
|
91
94
|
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
def all
|
|
96
|
+
@entries
|
|
97
|
+
end
|
|
94
98
|
end
|
|
95
|
-
end
|
|
96
99
|
end
|
|
97
100
|
end
|
|
98
101
|
end
|
|
@@ -25,22 +25,24 @@ module BruteCLI
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def messages
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
if @command.nil?
|
|
29
|
+
[empty_assistant]
|
|
30
|
+
else
|
|
31
|
+
call_id = "shell_#{SecureRandom.hex(8)}"
|
|
32
|
+
tool_calls = [
|
|
33
|
+
Brute::ToolCall.new(
|
|
34
|
+
id: call_id,
|
|
35
|
+
name: "shell",
|
|
36
|
+
arguments: { "command" => @command },
|
|
37
|
+
)
|
|
38
|
+
]
|
|
39
|
+
[Brute::Message.new(
|
|
40
|
+
role: :assistant,
|
|
41
|
+
content: "",
|
|
42
|
+
tool_calls: tool_calls,
|
|
36
43
|
)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
[Brute::Message.new(
|
|
40
|
-
role: :assistant,
|
|
41
|
-
content: "",
|
|
42
|
-
tool_calls: tool_calls,
|
|
43
|
-
)]
|
|
44
|
+
]
|
|
45
|
+
end
|
|
44
46
|
end
|
|
45
47
|
alias_method :choices, :messages
|
|
46
48
|
|
|
@@ -83,9 +85,9 @@ module BruteCLI
|
|
|
83
85
|
|
|
84
86
|
private
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
def empty_assistant
|
|
89
|
+
Brute::Message.new(role: :assistant, content: "")
|
|
90
|
+
end
|
|
89
91
|
end
|
|
90
92
|
end
|
|
91
93
|
end
|
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:
|
|
4
|
+
version: 6.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brute Contributors
|
|
@@ -219,6 +219,20 @@ dependencies:
|
|
|
219
219
|
- - ">="
|
|
220
220
|
- !ruby/object:Gem::Version
|
|
221
221
|
version: '0'
|
|
222
|
+
- !ruby/object:Gem::Dependency
|
|
223
|
+
name: rubocop
|
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
|
225
|
+
requirements:
|
|
226
|
+
- - ">="
|
|
227
|
+
- !ruby/object:Gem::Version
|
|
228
|
+
version: '0'
|
|
229
|
+
type: :development
|
|
230
|
+
prerelease: false
|
|
231
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
232
|
+
requirements:
|
|
233
|
+
- - ">="
|
|
234
|
+
- !ruby/object:Gem::Version
|
|
235
|
+
version: '0'
|
|
222
236
|
- !ruby/object:Gem::Dependency
|
|
223
237
|
name: rake
|
|
224
238
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -233,6 +247,20 @@ dependencies:
|
|
|
233
247
|
- - "~>"
|
|
234
248
|
- !ruby/object:Gem::Version
|
|
235
249
|
version: '13.0'
|
|
250
|
+
- !ruby/object:Gem::Dependency
|
|
251
|
+
name: rdoc
|
|
252
|
+
requirement: !ruby/object:Gem::Requirement
|
|
253
|
+
requirements:
|
|
254
|
+
- - "~>"
|
|
255
|
+
- !ruby/object:Gem::Version
|
|
256
|
+
version: '8.0'
|
|
257
|
+
type: :development
|
|
258
|
+
prerelease: false
|
|
259
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
260
|
+
requirements:
|
|
261
|
+
- - "~>"
|
|
262
|
+
- !ruby/object:Gem::Version
|
|
263
|
+
version: '8.0'
|
|
236
264
|
- !ruby/object:Gem::Dependency
|
|
237
265
|
name: scampi
|
|
238
266
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -322,12 +350,9 @@ files:
|
|
|
322
350
|
- lib/brute/middleware/010_max_iterations.rb
|
|
323
351
|
- lib/brute/middleware/020_system_prompt.rb
|
|
324
352
|
- lib/brute/middleware/025_skills.rb
|
|
325
|
-
- lib/brute/middleware/040_compaction_check.rb
|
|
326
353
|
- lib/brute/middleware/040_default_compaction_pipeline.rb
|
|
327
354
|
- lib/brute/middleware/060_questions.rb
|
|
328
355
|
- lib/brute/middleware/070_default_tool_pipeline.rb
|
|
329
|
-
- lib/brute/middleware/070_tool_pipeline.rb
|
|
330
|
-
- lib/brute/middleware/event_handler.rb
|
|
331
356
|
- lib/brute/middleware/user_queue.rb
|
|
332
357
|
- lib/brute/prompt_template.rb
|
|
333
358
|
- lib/brute/prompts.rb
|
|
@@ -415,7 +440,7 @@ files:
|
|
|
415
440
|
- lib/brute_cli/providers/shell_response.rb
|
|
416
441
|
homepage: https://github.com/general-intelligence-systems/brute
|
|
417
442
|
licenses:
|
|
418
|
-
-
|
|
443
|
+
- Apache-2.0
|
|
419
444
|
metadata:
|
|
420
445
|
documentation_uri: https://general-intelligence-systems.github.io/brute/
|
|
421
446
|
rdoc_options: []
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "brute"
|
|
5
|
-
require "gem_kit"
|
|
6
|
-
|
|
7
|
-
module Brute
|
|
8
|
-
module Middleware
|
|
9
|
-
# The old compaction trigger, kept working while it is deprecated.
|
|
10
|
-
# DefaultCompactionPipeline is the layer that does the job.
|
|
11
|
-
#
|
|
12
|
-
# It passes the turn through and compacts nothing, which is what it always
|
|
13
|
-
# did -- and it is deliberately not a subclass of its replacement, because
|
|
14
|
-
# inheriting would make a layer that did nothing suddenly start giving up
|
|
15
|
-
# context. A deprecation warns about a name; it does not change what the
|
|
16
|
-
# code under that name does.
|
|
17
|
-
#
|
|
18
|
-
# Whatever it was configured with is accepted and ignored, so existing
|
|
19
|
-
# `use` lines keep parsing until they are moved over:
|
|
20
|
-
#
|
|
21
|
-
# use Brute::Middleware::DefaultCompactionPipeline,
|
|
22
|
-
# window: 200_000,
|
|
23
|
-
# summariser: Brute::Completion::OpenRouter.new(config: { access_token: key })
|
|
24
|
-
#
|
|
25
|
-
class CompactionCheck < Brute::Middleware::Base
|
|
26
|
-
extend GemKit::Deprecate
|
|
27
|
-
superseded_by "Brute::Middleware::DefaultCompactionPipeline", "6.0"
|
|
28
|
-
|
|
29
|
-
def initialize(app, **_options)
|
|
30
|
-
@app = app
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def call(env) = @app.call(env)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
__END__
|
|
39
|
-
|
|
40
|
-
describe "brute/middleware/040_compaction_check" do
|
|
41
|
-
it "passes the turn through as it always did, and says what to use instead" do
|
|
42
|
-
warned = []
|
|
43
|
-
original = GemKit::Deprecate.method(:warn)
|
|
44
|
-
GemKit::Deprecate.define_singleton_method(:warn) { |message| warned << message }
|
|
45
|
-
|
|
46
|
-
begin
|
|
47
|
-
# Whatever it was configured with is taken and ignored, so an existing
|
|
48
|
-
# `use` line keeps parsing.
|
|
49
|
-
layer = Brute::Middleware::CompactionCheck.new(
|
|
50
|
-
->(env) { env[:messages].assistant("answered") },
|
|
51
|
-
system_prompt: "you are helpful",
|
|
52
|
-
token_threshold: 100
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
env = { messages: Brute.log }
|
|
56
|
-
layer.call(env)
|
|
57
|
-
env[:messages].last.content.should == "answered"
|
|
58
|
-
ensure
|
|
59
|
-
GemKit::Deprecate.define_singleton_method(:warn, original)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Not a subclass of its replacement: a layer that compacted nothing must
|
|
63
|
-
# not start compacting because its name was deprecated.
|
|
64
|
-
Brute::Middleware::CompactionCheck.ancestors
|
|
65
|
-
.should.not.include Brute::Middleware::DefaultCompactionPipeline
|
|
66
|
-
|
|
67
|
-
warned.first.should.include "Brute::Middleware::DefaultCompactionPipeline"
|
|
68
|
-
|
|
69
|
-
declared = GemKit::Deprecate.registry.find { |entry| entry.name == "Brute::Middleware::CompactionCheck" }
|
|
70
|
-
declared.replacement.should == "Brute::Middleware::DefaultCompactionPipeline"
|
|
71
|
-
declared.removed_in.should == Gem::Version.new("6.0")
|
|
72
|
-
end
|
|
73
|
-
end
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "brute"
|
|
5
|
-
require "gem_kit"
|
|
6
|
-
|
|
7
|
-
module Brute
|
|
8
|
-
module Middleware
|
|
9
|
-
# The old name for DefaultToolPipeline, kept working while it is
|
|
10
|
-
# deprecated. The middleware is one particular wiring of tool dispatch and
|
|
11
|
-
# the name now says so, leaving Brute::Turn::ToolPipeline as the mechanism
|
|
12
|
-
# to compose when that wiring is not what you want.
|
|
13
|
-
#
|
|
14
|
-
# use Brute::Middleware::DefaultToolPipeline, tools: tools
|
|
15
|
-
#
|
|
16
|
-
class ToolPipeline < DefaultToolPipeline
|
|
17
|
-
extend GemKit::Deprecate
|
|
18
|
-
superseded_by "Brute::Middleware::DefaultToolPipeline", "6.0"
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
__END__
|
|
24
|
-
|
|
25
|
-
describe "brute/middleware/070_tool_pipeline" do
|
|
26
|
-
it "still dispatches tools under the old name, and says what to use instead" do
|
|
27
|
-
warned = []
|
|
28
|
-
original = GemKit::Deprecate.method(:warn)
|
|
29
|
-
GemKit::Deprecate.define_singleton_method(:warn) { |message| warned << message }
|
|
30
|
-
|
|
31
|
-
begin
|
|
32
|
-
tool = Brute::Turn::ToolPipeline.new(name: "echo", description: "echo") do
|
|
33
|
-
run ->(env) { env[:result] = "echoed" }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
agent = Brute.agent
|
|
37
|
-
.use(Brute::Middleware::ToolPipeline, tools: [tool])
|
|
38
|
-
.run(
|
|
39
|
-
->(env) {
|
|
40
|
-
env[:messages] << Brute::Message.new(
|
|
41
|
-
role: :assistant,
|
|
42
|
-
content: "",
|
|
43
|
-
tool_calls: [{ id: "1", name: "echo", arguments: {} }]
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
agent.start("go")[:messages].last.content.should == "echoed"
|
|
49
|
-
ensure
|
|
50
|
-
GemKit::Deprecate.define_singleton_method(:warn, original)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
Brute::Middleware::ToolPipeline.ancestors.should.include Brute::Middleware::DefaultToolPipeline
|
|
54
|
-
warned.first.should.include "Brute::Middleware::DefaultToolPipeline"
|
|
55
|
-
warned.first.should.include "6.0"
|
|
56
|
-
|
|
57
|
-
declared = GemKit::Deprecate.registry.find { |entry| entry.name == "Brute::Middleware::ToolPipeline" }
|
|
58
|
-
declared.replacement.should == "Brute::Middleware::DefaultToolPipeline"
|
|
59
|
-
declared.removed_in.should == Gem::Version.new("6.0")
|
|
60
|
-
end
|
|
61
|
-
end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'bundler/setup'
|
|
4
|
-
require 'brute'
|
|
5
|
-
|
|
6
|
-
module Brute
|
|
7
|
-
module Middleware
|
|
8
|
-
class EventHandler < Brute::Middleware::Base
|
|
9
|
-
def initialize(app, handler_class:, **opts)
|
|
10
|
-
@app = app
|
|
11
|
-
@handler_class = handler_class
|
|
12
|
-
@opts = opts
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def call(env)
|
|
16
|
-
env[:events] = @handler_class.new(env[:events], **@opts)
|
|
17
|
-
@app.call(env)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
__END__
|
|
24
|
-
|
|
25
|
-
describe "brute/middleware/event_handler" do
|
|
26
|
-
# not implemented
|
|
27
|
-
end
|