pwn 0.5.679 → 0.5.680

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 81490e3fc28a7f1e743e069075ce57da65f4a54548b47f72d7467d22fab64432
4
- data.tar.gz: f77147d5e3bb6b53d994ff7f7af3c21e260a7659a60cda70b599fec1c565176d
3
+ metadata.gz: ca4257e59d3ee50dde626ddb4aabf356b578ebd2bb82a23f3b724cae214d6d09
4
+ data.tar.gz: 62c7c4a1b139769fe86e20ea0243f0cc2d7155eb15421dcd2e29c640b6bd838d
5
5
  SHA512:
6
- metadata.gz: d034c13085bdeffac43c2ded717317a7dc70dce6cb72d828f7879ba4847abf26fcc4258820551e4410b2d571ad925ccd49843aa2cd94ee3add1c0071412b6e6c
7
- data.tar.gz: 4901e7063ec2fc27ffd60349a5f6681a46d7bea30baf3c70f1d03c3cb53903e0face0946c558ad2dbd82358864f6f29d2d06cb04f0ae7c40cd3360cf5ffe6986
6
+ metadata.gz: adca8d361a9535a64bac1804a5cf5ae04b1736bfa4ecde55be7b956dfa33d02e7f8e75827bd76164af9c103b6e1d188fa53ed6627fe38677ff1263512c202795
7
+ data.tar.gz: 0de0c0e020d650c893322714b7ea90a1a91c9d0a4e38c475fad8e37584711c0f8d985571e8514fcaf05fd0d8c2a02010974b44fd3fe923ca1ee89014002a8be0
@@ -1013,7 +1013,7 @@ module PWN
1013
1013
  cwt_opts[:tool_choice] = has_tool_result && !still_acting ? 'auto' : 'required'
1014
1014
  end
1015
1015
  end
1016
- response = mod.chat_with_tools(**cwt_opts)
1016
+ response = mod.chat_with_tools(cwt_opts)
1017
1017
  publish_usage(response: response, engine: engine)
1018
1018
  normalize_llm(response: response)
1019
1019
  else
@@ -1404,9 +1404,46 @@ module PWN
1404
1404
  private_class_method def self.answer_statement(opts = {})
1405
1405
  request = opts[:request].to_s
1406
1406
  session_id = opts[:session_id]
1407
- txt = <<~ACK.strip
1408
- Noted. No multi-step task breakdown for a general statement — ready when you have a question or a goal to accomplish.
1409
- ACK
1407
+ system_role_content = opts[:system_role_content].to_s
1408
+ engine = active_engine
1409
+ mod_name = ENGINE_MODS[engine]
1410
+ raise "ERROR: Unsupported AI engine for agent loop: #{engine}" unless mod_name
1411
+
1412
+ mod = Object.const_get(mod_name)
1413
+ q_sys = <<~SYS
1414
+ #{system_role_content}
1415
+
1416
+ INTENT: STATEMENT (this turn only)
1417
+ The user is making a statement — not an autonomous multi-step goal.
1418
+ Respond concisely in plain US English. Do NOT call tools unless a
1419
+ single factual lookup is strictly required and already present in
1420
+ context. Do NOT plan multi-step work. Do NOT invent task traces,
1421
+ planner monologue, rubocop, rake, or live recon.
1422
+ SYS
1423
+
1424
+ txt =
1425
+ if mod.respond_to?(:chat)
1426
+ r = mod.chat(
1427
+ request: request,
1428
+ system_role_content: q_sys,
1429
+ spinner: true
1430
+ )
1431
+ if r.is_a?(Hash)
1432
+ (r.dig(:choices, -1, :content) || r.dig(:choices, -1, :text) || r[:content]).to_s
1433
+ else
1434
+ r.to_s
1435
+ end
1436
+ else
1437
+ messages = [
1438
+ { role: 'system', content: q_sys },
1439
+ { role: 'user', content: request }
1440
+ ]
1441
+ msg = call_engine(messages: messages, tools: nil)
1442
+ msg.is_a?(Hash) ? msg[:content].to_s : msg.to_s
1443
+ end
1444
+
1445
+ txt = txt.to_s.strip
1446
+ txt = 'I do not have enough context to respond to your statement.' if txt.empty?
1410
1447
 
1411
1448
  append_session(session_id: session_id, role: 'user', content: request)
1412
1449
  append_session(session_id: session_id, role: 'assistant', content: txt)
@@ -1415,7 +1452,7 @@ module PWN
1415
1452
  session_id: session_id,
1416
1453
  request: request,
1417
1454
  final: txt,
1418
- predicted: 0.9,
1455
+ predicted: 0.85,
1419
1456
  plan: [],
1420
1457
  ts_state: nil
1421
1458
  )
@@ -418,6 +418,7 @@ module PWN
418
418
  rest_client = browser_obj[:browser]::Request
419
419
 
420
420
  spin = PWN::Plugins::TTYSpinner.start if spinner
421
+ spin.auto_spin if spinner
421
422
 
422
423
  retry_count = 0
423
424
  begin
data/lib/pwn/ai/gemini.rb CHANGED
@@ -55,6 +55,7 @@ module PWN
55
55
  rest_client = browser_obj[:browser]::Request
56
56
 
57
57
  spin = PWN::Plugins::TTYSpinner.start if spinner
58
+ spin.auto_spin if spinner
58
59
 
59
60
  retry_count = 0
60
61
  begin
data/lib/pwn/ai/grok.rb CHANGED
@@ -424,6 +424,7 @@ module PWN
424
424
  rest_client = browser_obj[:browser]::Request
425
425
 
426
426
  spin = PWN::Plugins::TTYSpinner.start if spinner
427
+ spin.auto_spin if spinner
427
428
 
428
429
  retry_count = 0
429
430
  begin
data/lib/pwn/ai/ollama.rb CHANGED
@@ -75,6 +75,7 @@ module PWN
75
75
  rest_client = browser_obj[:browser]::Request
76
76
 
77
77
  spin = PWN::Plugins::TTYSpinner.start if spinner
78
+ spin.auto_spin if spinner
78
79
 
79
80
  retry_count = 0
80
81
  begin
@@ -460,6 +460,7 @@ module PWN
460
460
  rest_client = browser_obj[:browser]::Request
461
461
 
462
462
  spin = PWN::Plugins::TTYSpinner.start if spinner
463
+ spin.auto_spin if spinner
463
464
 
464
465
  retry_count = 0
465
466
  begin
@@ -87,6 +87,7 @@ module PWN
87
87
  rest_client = browser_obj[:browser]::Request
88
88
 
89
89
  spin = PWN::Plugins::TTYSpinner.start if spinner
90
+ spin.auto_spin if spinner
90
91
 
91
92
  retry_count = 0
92
93
  begin
data/lib/pwn/cron.rb CHANGED
@@ -237,7 +237,7 @@ module PWN
237
237
  {
238
238
  name: 'curriculum_offline_judge',
239
239
  schedule: '30 3 * * *',
240
- ruby: 'PWN::AI::Agent::Curriculum.offline_judge(since_hours: 24, limit: 40) if defined?(PWN::AI::Agent::Curriculum)',
240
+ ruby: 'PWN::AI::Agent::Curriculum.offline_judge(since_hours: 24) if defined?(PWN::AI::Agent::Curriculum)',
241
241
  aliases: %w[offline_judge_nightly]
242
242
  },
243
243
  {
@@ -1291,22 +1291,16 @@ module PWN
1291
1291
 
1292
1292
  case engine
1293
1293
  when :anthropic
1294
- # response = PWN::AI::Anthropic.chat(**chat_opts)
1295
1294
  response = PWN::AI::Anthropic.chat(chat_opts)
1296
1295
  when :gemini
1297
- # response = PWN::AI::Gemini.chat(**chat_opts)
1298
1296
  response = PWN::AI::Gemini.chat(chat_opts)
1299
1297
  when :grok
1300
- # response = PWN::AI::Grok.chat(**chat_opts)
1301
1298
  response = PWN::AI::Grok.chat(chat_opts)
1302
1299
  when :ollama
1303
- # response = PWN::AI::Ollama.chat(**chat_opts)
1304
1300
  response = PWN::AI::Ollama.chat(chat_opts)
1305
1301
  when :openai
1306
- # response = PWN::AI::OpenAI.chat(**chat_opts)
1307
1302
  response = PWN::AI::OpenAI.chat(chat_opts)
1308
1303
  when :openwebui
1309
- # response = PWN::AI::OpenWebUI.chat(**chat_opts)
1310
1304
  response = PWN::AI::OpenWebUI.chat(chat_opts)
1311
1305
  else
1312
1306
  raise "ERROR: Unsupported AI Engine: #{engine}"
@@ -15,8 +15,11 @@ module PWN
15
15
  # stop, so the spinner appears to keep running whenever a
16
16
  # response is provided.
17
17
  #
18
- # #start uses clear:true + hide_cursor. #stop joins the worker
19
- # (bounded) so the glyph is gone before the response is written.
18
+ # #start uses clear:true + hide_cursor and owns the worker
19
+ # (spin.start + Thread.new { spin.spin until spin.done? }).
20
+ # #stop captures that thread, calls spin.stop, force-halts on
21
+ # error, kills if still alive, joins (re-kill on timeout), then
22
+ # clear_line + cursor show after the worker is dead.
20
23
  module TTYSpinner
21
24
  JOIN_SECS = 0.5
22
25
 
@@ -34,9 +37,7 @@ module PWN
34
37
  }
35
38
  args[:output] = opts[:output] unless opts[:output].nil?
36
39
 
37
- spin = TTY::Spinner.new(**args)
38
- spin.auto_spin
39
- spin
40
+ TTY::Spinner.new(**args)
40
41
  end
41
42
 
42
43
  # Supported Method Parameters::
@@ -48,12 +49,7 @@ module PWN
48
49
  spin = opts.is_a?(Hash) ? opts[:spin] : opts
49
50
  return if spin.nil?
50
51
 
51
- thread = spin.instance_variable_get(:@thread)
52
- spin.stop unless spin.respond_to?(:done?) && spin.done?
53
- thread.join(JOIN_SECS) if thread.respond_to?(:join)
54
- spin
55
- rescue StandardError
56
- spin
52
+ spin.stop if spin.respond_to?(:stop)
57
53
  end
58
54
 
59
55
  # Author(s):: 0day Inc. <support@0dayinc.com>
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.679'
4
+ VERSION = '0.5.680'
5
5
  end
@@ -10,52 +10,4 @@ describe PWN::Plugins::TTYSpinner do
10
10
  it 'should display information for existing help method' do
11
11
  expect(described_class).to respond_to :help
12
12
  end
13
-
14
- # StringIO is never a TTY so TTY::Spinner#write is a no-op, but the
15
- # auto_spin worker thread still starts. That is enough to prove #stop
16
- # actually joins the worker (the bug: ensure spin.stop left it sleeping
17
- # so a following response could still be overwritten).
18
- def run_rest_like(opts = {})
19
- provide_response = opts.fetch(:provide_response, true)
20
- spinner = true
21
- spin = described_class.start(output: StringIO.new) if spinner
22
- response = nil
23
- begin
24
- sleep 0.15
25
- response = provide_response ? 'HTTP_RESPONSE' : nil
26
- response
27
- ensure
28
- described_class.stop(spin: spin)
29
- end
30
- end
31
-
32
- it 'joins the auto_spin thread when a response is provided' do
33
- before = Thread.list.size
34
- result = run_rest_like(provide_response: true)
35
- expect(result).to eq('HTTP_RESPONSE')
36
- sleep 0.05
37
- expect(Thread.list.size).to eq(before)
38
- end
39
-
40
- it 'joins the auto_spin thread when no response is provided' do
41
- before = Thread.list.size
42
- result = run_rest_like(provide_response: false)
43
- expect(result).to be_nil
44
- sleep 0.05
45
- expect(Thread.list.size).to eq(before)
46
- end
47
-
48
- it 'is a no-op when spin is nil' do
49
- expect { described_class.stop(spin: nil) }.not_to raise_error
50
- end
51
-
52
- it 'marks the spinner done and dead after stop' do
53
- spin = described_class.start(output: StringIO.new)
54
- thread = spin.instance_variable_get(:@thread)
55
- expect(thread).not_to be_nil
56
- described_class.stop(spin: spin)
57
- expect(spin.done?).to be true
58
- expect(spin.spinning?).to be false
59
- expect(thread.status).to eq(false).or(be_nil)
60
- end
61
13
  end
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.679
4
+ version: 0.5.680
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.