pwn 0.5.779 → 0.5.780

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: 7dd747b247b7c7039df9bba24c9542ecd37b65df6c650b09730ce6b9803d599b
4
- data.tar.gz: b355d2d146e6b26c833319ac265b76e8fa3fe85892ff53e7c78e1f0238daf067
3
+ metadata.gz: 3207a135c108d0af20cc351965b217a3235abb0eaf67a31d244e3779ed6b72e5
4
+ data.tar.gz: 750df1371f8eb0fbab32b66e88b7568dbac4a49de7dc4020fc018a9957053acc
5
5
  SHA512:
6
- metadata.gz: 6f594c419c8095b788c397b64dcaa417a8efbc3992007b40079f121d93a8dc6ee67b3b41bb5bf48526e55720d99f2fe7cad5ae1fb5a563d71421a866240c4f04
7
- data.tar.gz: 87e8e462103a8954fd94e9859fbde5e528d1f6803e3dda5abdadbe0e58524a56125fc084747edf0171289b99f84bfcc75d65d5ff4ac10d95d2d44cfe9d002205
6
+ metadata.gz: b10627e1329fa50ac482a49b1013ab455f52eac1a943d92ef7f9144bb93625e742935e0ad2caa1294f3d10a3c46d758b0de50695463e138af76ed7f61871438b
7
+ data.tar.gz: 3f55e834e447b8d51b8a28bd0c71d97498e577d49d7dadfea2a5ceda5e5bfa3876225d27f0c238b02dce690ea82d48612d29fd8a45130cea8213fc4a5650ce0a
data/Gemfile CHANGED
@@ -49,7 +49,7 @@ gem 'jwt', '3.3.0'
49
49
  gem 'libusb', '0.8.0'
50
50
  gem 'luhn', '3.0.0'
51
51
  gem 'mail', '2.9.1'
52
- gem 'mcp', '1.8.0'
52
+ gem 'mcp', '1.8.1'
53
53
  gem 'meshtastic', '0.0.188'
54
54
  gem 'metasm', '1.0.6'
55
55
  gem 'mongo', '2.26.0'
@@ -2195,7 +2195,8 @@ module PWN
2195
2195
  pairs.each do |pair|
2196
2196
  tool = pair.find { |m| m[:role].to_s == 'tool' }
2197
2197
  prev = collapsed.last&.find { |m| m[:role].to_s == 'tool' }
2198
- next if tool && prev && tool[:content].to_s.strip == prev[:content].to_s.strip
2198
+ # Compare raw bytes: existing history may contain malformed tool output.
2199
+ next if tool && prev && tool[:content].to_s.b.strip == prev[:content].to_s.b.strip
2199
2200
 
2200
2201
  collapsed << pair
2201
2202
  end
@@ -2241,8 +2242,10 @@ module PWN
2241
2242
  FileUtils.mkdir_p(dir)
2242
2243
  path = File.join(dir, "#{digest[0, 12]}.txt")
2243
2244
  File.binwrite(path, text) unless File.file?(path)
2244
- head = text.byteslice(0, 2_048).to_s
2245
- tail = text.bytesize > 3_072 ? text.byteslice(-1_024, 1_024).to_s : ''
2245
+ # Keep the artifact/digest byte-exact; only the displayed excerpt is text.
2246
+ # Byte slicing can bisect a multibyte character at either boundary.
2247
+ head = text.byteslice(0, 2_048).to_s.dup.force_encoding(Encoding::UTF_8).scrub
2248
+ tail = text.bytesize > 3_072 ? text.byteslice(-1_024, 1_024).to_s.dup.force_encoding(Encoding::UTF_8).scrub : ''
2246
2249
  mid = tail.empty? ? '' : "\n...\n#{tail}"
2247
2250
  "#{head}#{mid}\n[compacted path=#{path} sha256=#{digest} bytes=#{text.bytesize} ref=#{path}]"
2248
2251
  rescue StandardError
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.779'
4
+ VERSION = '0.5.780'
5
5
  end
@@ -1304,6 +1304,45 @@ describe PWN::AI::Agent::Loop do # rubocop:disable Metrics/BlockLength
1304
1304
  expect(src).not_to match(/compact_history!\(messages: messages\) if local/)
1305
1305
  end
1306
1306
 
1307
+ it 'keeps UTF-8 previews valid across repeated history compaction' do
1308
+ Dir.mktmpdir('pwn-history-encoding') do |dir|
1309
+ allow(Dir).to receive(:home).and_return(dir)
1310
+ messages = [{ role: 'system', content: 'sys' }, { role: 'user', content: 'goal' }]
1311
+ 8.times do |n|
1312
+ messages << { role: 'assistant', content: '', tool_calls: [{ id: "c#{n}" }] }
1313
+ messages << { role: 'tool', tool_call_id: "c#{n}", content: "a#{'é' * 3000}#{n}" }
1314
+ end
1315
+ 2.times do
1316
+ expect { described_class.send(:compact_history!, messages: messages) }.not_to output(/compact_history swallowed/).to_stderr
1317
+ expect(messages.all? { |msg| msg[:content].valid_encoding? }).to be(true)
1318
+ end
1319
+ end
1320
+ end
1321
+
1322
+ it 'preserves raw spilled bytes while rendering malformed and binary-tagged text safely' do
1323
+ Dir.mktmpdir('pwn-history-binary') do |dir|
1324
+ allow(Dir).to receive(:home).and_return(dir)
1325
+ ["a#{'é' * 3000}".b, "a\xff#{'é' * 3000}"].each do |text|
1326
+ preview = described_class.send(:spill_tool_body, text: text)
1327
+ expect(preview.encoding).to eq(Encoding::UTF_8)
1328
+ expect(preview.valid_encoding?).to be(true)
1329
+ expect(preview).to include('é', '[compacted path=')
1330
+ path = preview[/\[compacted path=(.*?) sha256=/, 1]
1331
+ expect(File.binread(path)).to eq(text.b)
1332
+ end
1333
+ end
1334
+ end
1335
+
1336
+ it 'compacts existing malformed tool history without swallowing encoding errors' do
1337
+ messages = [{ role: 'system', content: 'sys' }, { role: 'user', content: 'goal' }]
1338
+ 8.times do |n|
1339
+ messages << { role: 'assistant', tool_calls: [{ id: "c#{n}" }] }
1340
+ messages << { role: 'tool', tool_call_id: "c#{n}", content: "invalid\xff#{n}" }
1341
+ end
1342
+ expect { described_class.send(:compact_history!, messages: messages) }.not_to output(/compact_history swallowed/).to_stderr
1343
+ expect(messages.count { |msg| msg[:role] == 'tool' }).to eq(6)
1344
+ end
1345
+
1307
1346
  it 'shrinks tool bodies when history is fat' do
1308
1347
  msgs = [
1309
1348
  { role: 'system', content: 'sys' },
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.779
4
+ version: 0.5.780
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -505,14 +505,14 @@ dependencies:
505
505
  requirements:
506
506
  - - '='
507
507
  - !ruby/object:Gem::Version
508
- version: 1.8.0
508
+ version: 1.8.1
509
509
  type: :runtime
510
510
  prerelease: false
511
511
  version_requirements: !ruby/object:Gem::Requirement
512
512
  requirements:
513
513
  - - '='
514
514
  - !ruby/object:Gem::Version
515
- version: 1.8.0
515
+ version: 1.8.1
516
516
  - !ruby/object:Gem::Dependency
517
517
  name: meshtastic
518
518
  requirement: !ruby/object:Gem::Requirement