Module: PWN::AI::Agent::TaskSummarizer

Defined in:
lib/pwn/ai/agent/task_summarizer.rb

Overview

Coalesce a burst of tool calls into periodic "summary_of_current_task" UI lines without stopping the loop.

Constant Summary collapse

DEFAULT_EVERY =
5
DEFAULT_INTERVAL_S =
8.0
MAX_BUFFER =
64

Class Method Summary collapse

Class Method Details

.authorsObject

Author(s)

0day Inc. support@0dayinc.com



96
97
98
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 96

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <support@0dayinc.com>\n"
end

.emit!(state, final: false) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 74

def emit!(state, final: false)
  return nil if state.nil? || state[:events].empty?

  counts = state[:counts].sort_by { |_, c| -c }.map { |n, c| "#{n}×#{c}" }
  recent = state[:events].last(every_n)
  focus = recent.map { |e| e[:name] }.uniq.first(4).join(', ')
  fails = state[:events].count { |e| !e[:ok] }
  tail = recent.map { |e| e[:preview] }.compact.reject(&:empty?).last
  bit = tail && !tail.empty? ? "; e.g. #{tail}" : ''
  fail_bit = fails.positive? ? "; failures=#{fails}" : ''
  phase = final ? 'done' : 'in progress'
  state[:since_emit] = 0
  state[:last_emit_at] = Time.now
  "#{phase}: #{focus}#{state[:total]} tools (#{counts.first(6).join(', ')})#{fail_bit}#{bit}"
end

.enabled?Boolean

Returns:

  • (Boolean)


15
16
17
18
19
20
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 15

def enabled?
  v = PWN::Env.dig(:ai, :agent, :task_summary)
  v.nil? || !!v
rescue StandardError
  true
end

.every_nObject



28
29
30
31
32
33
34
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 28

def every_n
  n = PWN::Env.dig(:ai, :agent, :task_summary_every)
  n = DEFAULT_EVERY if n.nil?
  [n.to_i, 1].max
rescue StandardError
  DEFAULT_EVERY
end

.flush!(state) ⇒ Object



90
91
92
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 90

def flush!(state)
  emit!(state, final: true)
end

.fresh(opts = {}) ⇒ Object

Per-run state (also safe for nested/swarm if callers keep their own hash)



45
46
47
48
49
50
51
52
53
54
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 45

def fresh(opts = {})
  {
    request: opts[:request].to_s,
    events: [],
    since_emit: 0,
    last_emit_at: Time.now,
    total: 0,
    counts: Hash.new(0)
  }
end

.helpObject

Display Usage for this Module



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 102

public_class_method def self.help
  puts <<~USAGE
    USAGE:
      state = PWN::AI::Agent::TaskSummarizer.fresh(request: 'do the thing')
      line  = PWN::AI::Agent::TaskSummarizer.record!(state, 'shell', 'ls', '{success:true}')
      line  = PWN::AI::Agent::TaskSummarizer.flush!(state)
      PWN::AI::Agent::TaskSummarizer.enabled?
      PWN::AI::Agent::TaskSummarizer.verbose?
      PWN::AI::Agent::TaskSummarizer.every_n
      PWN::AI::Agent::TaskSummarizer.interval_s

      #{self}.authors
  USAGE
end

.interval_sObject



36
37
38
39
40
41
42
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 36

def interval_s
  t = PWN::Env.dig(:ai, :agent, :task_summary_interval_s)
  t = DEFAULT_INTERVAL_S if t.nil?
  [t.to_f, 1.0].max
rescue StandardError
  DEFAULT_INTERVAL_S
end

.record!(state, name, args, result) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 56

def record!(state, name, args, result)
  return nil unless state

  preview = args.is_a?(String) ? args.to_s[0, 60] : args.inspect[0, 60]
  rs = result.to_s
  ok = !rs.match?(/\A\s*\{?\s*"?(success|ok)"?\s*=>\s*false/i) &&
       !rs.match?(/ERROR:|Traceback|NoMethodError|StandardError/i)
  state[:events] << { name: name.to_s, preview: preview, ok: ok, t: Time.now }
  state[:events].shift while state[:events].size > MAX_BUFFER
  state[:counts][name.to_s] += 1
  state[:total] += 1
  state[:since_emit] += 1

  due = state[:since_emit] >= every_n ||
        (Time.now - state[:last_emit_at]) >= interval_s
  due ? emit!(state) : nil
end

.verbose?Boolean

Returns:

  • (Boolean)


22
23
24
25
26
# File 'lib/pwn/ai/agent/task_summarizer.rb', line 22

def verbose?
  !!PWN::Env.dig(:ai, :agent, :task_summary_verbose)
rescue StandardError
  false
end