pwn 0.5.659 → 0.5.660
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/pwn/ai/agent/task_summarizer.rb +119 -0
- data/lib/pwn/ai/agent.rb +1 -0
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/task_summarizer_spec.rb +53 -0
- data/third_party/pwn_rdoc.jsonl +10 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '06678f228c6acc69d9fb173f01f3825af6a7a8dcffcb8ed24c865bf281e0c65c'
|
|
4
|
+
data.tar.gz: 9967223f974d122e30cbb4be7aea369108e28b951ace091a1ed90d54825a4720
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6feb604302f7e6fd428e8dcd2d1c6a888ed2e6d4c96f3e7b75b6537a5694c3053da6a69da751275c8c168f627f6b71b031ed502cf02b1b0eb8bb2dfd72e2e354
|
|
7
|
+
data.tar.gz: 26f65f4e16312694c1163b0de7fe0545ca8ad7b8e1cdea647d931f131de6aaef89f0fe8b39be72509932295c1ad1521066c88722d5654cb6a856891c1c19e860
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PWN
|
|
4
|
+
module AI
|
|
5
|
+
module Agent
|
|
6
|
+
# Coalesce a burst of tool calls into periodic
|
|
7
|
+
# "summary_of_current_task" UI lines without stopping the loop.
|
|
8
|
+
module TaskSummarizer
|
|
9
|
+
DEFAULT_EVERY = 5
|
|
10
|
+
DEFAULT_INTERVAL_S = 8.0
|
|
11
|
+
MAX_BUFFER = 64
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def enabled?
|
|
16
|
+
v = PWN::Env.dig(:ai, :agent, :task_summary)
|
|
17
|
+
v.nil? || !!v
|
|
18
|
+
rescue StandardError
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def verbose?
|
|
23
|
+
!!PWN::Env.dig(:ai, :agent, :task_summary_verbose)
|
|
24
|
+
rescue StandardError
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def every_n
|
|
29
|
+
n = PWN::Env.dig(:ai, :agent, :task_summary_every)
|
|
30
|
+
n = DEFAULT_EVERY if n.nil?
|
|
31
|
+
[n.to_i, 1].max
|
|
32
|
+
rescue StandardError
|
|
33
|
+
DEFAULT_EVERY
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def interval_s
|
|
37
|
+
t = PWN::Env.dig(:ai, :agent, :task_summary_interval_s)
|
|
38
|
+
t = DEFAULT_INTERVAL_S if t.nil?
|
|
39
|
+
[t.to_f, 1.0].max
|
|
40
|
+
rescue StandardError
|
|
41
|
+
DEFAULT_INTERVAL_S
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Per-run state (also safe for nested/swarm if callers keep their own hash)
|
|
45
|
+
def fresh(opts = {})
|
|
46
|
+
{
|
|
47
|
+
request: opts[:request].to_s,
|
|
48
|
+
events: [],
|
|
49
|
+
since_emit: 0,
|
|
50
|
+
last_emit_at: Time.now,
|
|
51
|
+
total: 0,
|
|
52
|
+
counts: Hash.new(0)
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def record!(state, name, args, result)
|
|
57
|
+
return nil unless state
|
|
58
|
+
|
|
59
|
+
preview = args.is_a?(String) ? args.to_s[0, 60] : args.inspect[0, 60]
|
|
60
|
+
rs = result.to_s
|
|
61
|
+
ok = !rs.match?(/\A\s*\{?\s*"?(success|ok)"?\s*=>\s*false/i) &&
|
|
62
|
+
!rs.match?(/ERROR:|Traceback|NoMethodError|StandardError/i)
|
|
63
|
+
state[:events] << { name: name.to_s, preview: preview, ok: ok, t: Time.now }
|
|
64
|
+
state[:events].shift while state[:events].size > MAX_BUFFER
|
|
65
|
+
state[:counts][name.to_s] += 1
|
|
66
|
+
state[:total] += 1
|
|
67
|
+
state[:since_emit] += 1
|
|
68
|
+
|
|
69
|
+
due = state[:since_emit] >= every_n ||
|
|
70
|
+
(Time.now - state[:last_emit_at]) >= interval_s
|
|
71
|
+
due ? emit!(state) : nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def emit!(state, final: false)
|
|
75
|
+
return nil if state.nil? || state[:events].empty?
|
|
76
|
+
|
|
77
|
+
counts = state[:counts].sort_by { |_, c| -c }.map { |n, c| "#{n}×#{c}" }
|
|
78
|
+
recent = state[:events].last(every_n)
|
|
79
|
+
focus = recent.map { |e| e[:name] }.uniq.first(4).join(', ')
|
|
80
|
+
fails = state[:events].count { |e| !e[:ok] }
|
|
81
|
+
tail = recent.map { |e| e[:preview] }.compact.reject(&:empty?).last
|
|
82
|
+
bit = tail && !tail.empty? ? "; e.g. #{tail}" : ''
|
|
83
|
+
fail_bit = fails.positive? ? "; failures=#{fails}" : ''
|
|
84
|
+
phase = final ? 'done' : 'in progress'
|
|
85
|
+
state[:since_emit] = 0
|
|
86
|
+
state[:last_emit_at] = Time.now
|
|
87
|
+
"#{phase}: #{focus} — #{state[:total]} tools (#{counts.first(6).join(', ')})#{fail_bit}#{bit}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def flush!(state)
|
|
91
|
+
emit!(state, final: true)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Author(s):: 0day Inc. <support@0dayinc.com>
|
|
95
|
+
|
|
96
|
+
public_class_method def self.authors
|
|
97
|
+
"AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Display Usage for this Module
|
|
101
|
+
|
|
102
|
+
public_class_method def self.help
|
|
103
|
+
puts <<~USAGE
|
|
104
|
+
USAGE:
|
|
105
|
+
state = PWN::AI::Agent::TaskSummarizer.fresh(request: 'do the thing')
|
|
106
|
+
line = PWN::AI::Agent::TaskSummarizer.record!(state, 'shell', 'ls', '{success:true}')
|
|
107
|
+
line = PWN::AI::Agent::TaskSummarizer.flush!(state)
|
|
108
|
+
PWN::AI::Agent::TaskSummarizer.enabled?
|
|
109
|
+
PWN::AI::Agent::TaskSummarizer.verbose?
|
|
110
|
+
PWN::AI::Agent::TaskSummarizer.every_n
|
|
111
|
+
PWN::AI::Agent::TaskSummarizer.interval_s
|
|
112
|
+
|
|
113
|
+
#{self}.authors
|
|
114
|
+
USAGE
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
data/lib/pwn/ai/agent.rb
CHANGED
data/lib/pwn/version.rb
CHANGED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe PWN::AI::Agent::TaskSummarizer do
|
|
6
|
+
it 'fresh method should exist' do
|
|
7
|
+
expect(described_class).to respond_to :fresh
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'record! method should exist' do
|
|
11
|
+
expect(described_class).to respond_to :record!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'emit! method should exist' do
|
|
15
|
+
expect(described_class).to respond_to :emit!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'flush! method should exist' do
|
|
19
|
+
expect(described_class).to respond_to :flush!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'enabled? method should exist' do
|
|
23
|
+
expect(described_class).to respond_to :enabled?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'should display information for authors' do
|
|
27
|
+
expect(described_class).to respond_to :authors
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'should display information for existing help method' do
|
|
31
|
+
expect(described_class).to respond_to :help
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'coalesces tool bursts into a summary line' do
|
|
35
|
+
allow(PWN::Env).to receive(:dig).and_call_original
|
|
36
|
+
allow(PWN::Env).to receive(:dig).with(:ai, :agent, :task_summary_every).and_return(2)
|
|
37
|
+
allow(PWN::Env).to receive(:dig).with(:ai, :agent, :task_summary_interval_s).and_return(9_999)
|
|
38
|
+
allow(PWN::Env).to receive(:dig).with(:ai, :agent, :task_summary).and_return(true)
|
|
39
|
+
allow(PWN::Env).to receive(:dig).with(:ai, :agent, :task_summary_verbose).and_return(false)
|
|
40
|
+
|
|
41
|
+
state = described_class.fresh(request: 'fix rake')
|
|
42
|
+
expect(described_class.record!(state, 'shell', 'rake', '{success:true}')).to be_nil
|
|
43
|
+
line = described_class.record!(state, 'shell', 'rake 2>&1', '{success:true}')
|
|
44
|
+
expect(line).to be_a(String)
|
|
45
|
+
expect(line).to include('in progress')
|
|
46
|
+
expect(line).to include('shell')
|
|
47
|
+
expect(state[:total]).to eq 2
|
|
48
|
+
|
|
49
|
+
fin = described_class.flush!(state)
|
|
50
|
+
expect(fin).to include('done')
|
|
51
|
+
expect(fin).to include('2 tools')
|
|
52
|
+
end
|
|
53
|
+
end
|
data/third_party/pwn_rdoc.jsonl
CHANGED
|
@@ -460,6 +460,16 @@
|
|
|
460
460
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Swarm.retire Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Swarm.retire`: Supported Method Parameters\n\nPWN::AI::Agent::Swarm.retire(name: ‘required - persona name’)\n"}]}
|
|
461
461
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Swarm.spawn Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Swarm.spawn`: Supported Method Parameters\n\nPWN::AI::Agent::Swarm.spawn(\n\nname: 'required - persona name (snake_case)',\nrole: 'required - system_role_content overlay for this persona',\ntoolsets: 'optional - Array of Registry toolset names',\nengine: 'optional - :openai / :anthropic / :grok / :gemini / :ollama',\nmax_iters: 'optional - per-turn iteration cap for this persona'\n\n)\n"}]}
|
|
462
462
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::Swarm.with_persona_env Usage"},{"role":"assistant","content":"`PWN::AI::Agent::Swarm.with_persona_env`: "}]}
|
|
463
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
464
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.help`: "}]}
|
|
465
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.emit! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.emit!`: "}]}
|
|
466
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.enabled? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.enabled?`: "}]}
|
|
467
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.every_n Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.every_n`: "}]}
|
|
468
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.flush! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.flush!`: "}]}
|
|
469
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.fresh Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.fresh`: "}]}
|
|
470
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.interval_s Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.interval_s`: "}]}
|
|
471
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.record! Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.record!`: "}]}
|
|
472
|
+
{"messages":[{"role":"user","content":"PWN::AI::Agent::TaskSummarizer.verbose? Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TaskSummarizer.verbose?`: "}]}
|
|
463
473
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TransparentBrowser.analyze Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TransparentBrowser.analyze`: Supported Method Parameters\n\nai_analysis = PWN::AI::Agent::TransparentBrowser.analyze(\n\nrequest: 'required - current step in the JavaScript debugging session to analyze',\nsource_to_review: 'required - the block of JavaScript code in which the current step resides'\n\n)\n"}]}
|
|
464
474
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TransparentBrowser.authors Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TransparentBrowser.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
|
|
465
475
|
{"messages":[{"role":"user","content":"PWN::AI::Agent::TransparentBrowser.help Usage"},{"role":"assistant","content":"`PWN::AI::Agent::TransparentBrowser.help`: "}]}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pwn
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.660
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 0day Inc.
|
|
@@ -1856,6 +1856,7 @@ files:
|
|
|
1856
1856
|
- lib/pwn/ai/agent/reward.rb
|
|
1857
1857
|
- lib/pwn/ai/agent/sast.rb
|
|
1858
1858
|
- lib/pwn/ai/agent/swarm.rb
|
|
1859
|
+
- lib/pwn/ai/agent/task_summarizer.rb
|
|
1859
1860
|
- lib/pwn/ai/agent/tools/cron.rb
|
|
1860
1861
|
- lib/pwn/ai/agent/tools/curriculum.rb
|
|
1861
1862
|
- lib/pwn/ai/agent/tools/extrospection.rb
|
|
@@ -2317,6 +2318,7 @@ files:
|
|
|
2317
2318
|
- spec/lib/pwn/ai/agent/reward_spec.rb
|
|
2318
2319
|
- spec/lib/pwn/ai/agent/sast_spec.rb
|
|
2319
2320
|
- spec/lib/pwn/ai/agent/swarm_spec.rb
|
|
2321
|
+
- spec/lib/pwn/ai/agent/task_summarizer_spec.rb
|
|
2320
2322
|
- spec/lib/pwn/ai/agent/tools/cron_spec.rb
|
|
2321
2323
|
- spec/lib/pwn/ai/agent/tools/curriculum_spec.rb
|
|
2322
2324
|
- spec/lib/pwn/ai/agent/tools/extrospection_spec.rb
|