miniswen 1.3.3 → 1.3.4

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: 9dcf80689f2e298f334350c181a91372967140d43f7f165832c69311226437ea
4
- data.tar.gz: 95460fe301c6e8a112dc27e0d4433a0b43998f74d6930943cc8823adbc3e79cb
3
+ metadata.gz: d3124b6837dc7ec83d7abb8ec1a49da77b96767a0ab0e564d99b1cc639d6bf4f
4
+ data.tar.gz: b16c938ec5c39af746923c5814583e22ff576d357332c579ef8f7c0d9bdc73b1
5
5
  SHA512:
6
- metadata.gz: 3da1895808b25d679099dbf528ec634cdaf81177c70acd959b7be8653288ee862c18314449fc6d343ead5d59bfbb13a703b1ba59e2341b0dcf85b2a3dca8bdfe
7
- data.tar.gz: 975caedb5731b91490fbf6bd1b193103ca438afde7b6cda0f809377a98bfdfd6f76b32d2d2ee1b87696747e13d2600362bcc04d92de8c018969ac6c73ea45ee4
6
+ metadata.gz: 3084347bf1ccf8c6fbcab21af5b1699ee00b30d27dc5f8dfe7610c684bf27709b47e82658ec5a4e00234ce235c27a180f532f1f520ec8613e20f6e02634c96a7
7
+ data.tar.gz: d7a7873f8af98236c23d32809b2361409b0f0d27a310979b93bb705feafab0d26dfac3764c4378ade8de2e56943b54f6746e258e8a675861ec93709dada0542a
data/README.md CHANGED
@@ -15,6 +15,7 @@ lemans is a harness for benchmarking coding agents, the Ruby way:
15
15
  - Ruby 3.4+ is required to run `lemans`
16
16
  - Daytona account (API token) or Docker (for local sandboxes)
17
17
  - Some LLM provider/proxy credentials (e.g., OpenRouter)
18
+ - iproute2 in the sandbox image, so a jailed agent keeps loopback while cut off the internet
18
19
 
19
20
  ## Getting started
20
21
 
data/lib/miniswen/cli.rb CHANGED
@@ -22,6 +22,7 @@ module Miniswen
22
22
  @atif_path = nil
23
23
  @refresh_registry = false
24
24
  @skip_registry_refresh = false
25
+ @jail = false
25
26
  end
26
27
 
27
28
  def run
@@ -42,6 +43,9 @@ module Miniswen
42
43
  if @docker_id
43
44
  require "miniswen/environment/docker"
44
45
  Environment::Docker.new(@docker_id)
46
+ elsif @jail
47
+ require "miniswen/jail"
48
+ Jail.new.start
45
49
  else
46
50
  Local.new
47
51
  end
@@ -53,6 +57,8 @@ module Miniswen
53
57
  rescue StandardError => e
54
58
  write_results(agent.partial_result(error_message(e)))
55
59
  raise
60
+ ensure
61
+ environment.stop
56
62
  end
57
63
 
58
64
  write_results(result)
@@ -151,6 +157,10 @@ module Miniswen
151
157
  @docker_id = v
152
158
  end
153
159
 
160
+ opts.on("--jail", "Run every command in its own namespaces: none of the harness's environment, no network, read-only system, none of its files") do
161
+ @jail = true
162
+ end
163
+
154
164
  opts.on("--refresh-registry", "Refresh the model registry, persist it, and exit") do
155
165
  @refresh_registry = true
156
166
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "miniswen/local"
4
+
5
+ module Miniswen
6
+ # Runs every command in its own namespaces: none of the harness's environment,
7
+ # no network, read-only system, none of its files.
8
+ class Jail < Local
9
+ SETUP = <<~SH
10
+ set -eu
11
+ ip link set lo up
12
+ for dir in /usr /etc /opt; do mount -o bind,ro "$dir" "$dir"; done
13
+ for dir in /tmp /run /root; do mkdir -p "/var/lib/miniswen$dir" && mount --bind "/var/lib/miniswen$dir" "$dir"; done
14
+ echo ready
15
+ exec sleep infinity
16
+ SH
17
+
18
+ def initialize(workdir: Dir.pwd)
19
+ @workdir = workdir
20
+ end
21
+
22
+ def start
23
+ _, @stdout, @stderr, @holder = Open3.popen3(
24
+ "unshare", "--net", "--mount", "--pid", "--fork", "--kill-child", "--mount-proc", "sh", "-c", SETUP, pgroup: true
25
+ )
26
+ return self if @stdout.gets == "ready\n"
27
+
28
+ raise InfrastructureError, "jail did not start: #{@stderr.read}"
29
+ end
30
+
31
+ def stop
32
+ Process.kill(:KILL, -@holder.pid) if @holder.alive?
33
+ end
34
+
35
+ private
36
+
37
+ def spawn_arguments(command, env)
38
+ [ ENV.to_h.merge(env.to_h).slice(*container_variables),
39
+ "nsenter", "--target", @holder.pid.to_s, "--net", "--mount", "--pid=/proc/#{@holder.pid}/ns/pid_for_children", "--wd=#{@workdir}",
40
+ "--", "setpriv", "--bounding-set=-all", "--inh-caps=-all", "--no-new-privs", "--", "sh", "-c", command ]
41
+ end
42
+
43
+ def spawn_options = super.merge(unsetenv_others: true)
44
+
45
+ def container_variables
46
+ @container_variables ||= File.read("/proc/1/environ").split("\0").map { it.split("=").first } | Agent::EXEC_ENV.keys
47
+ end
48
+ end
49
+ end
@@ -12,7 +12,7 @@ module Miniswen
12
12
  # Always through a shell: Ruby execs a metacharacter-free string directly,
13
13
  # and a missing binary would then raise ENOENT here instead of exiting 127.
14
14
  def exec(command, timeout: nil, env: nil)
15
- Open3.popen2e(env || {}, "sh", "-c", command, pgroup: true) do |stdin, io, wait_thr|
15
+ Open3.popen2e(*spawn_arguments(command, env), **spawn_options) do |stdin, io, wait_thr|
16
16
  stdin.close
17
17
  reader = Thread.new { io.read }
18
18
 
@@ -27,8 +27,14 @@ module Miniswen
27
27
  end
28
28
  end
29
29
 
30
+ def stop = nil
31
+
30
32
  private
31
33
 
34
+ def spawn_arguments(command, env) = [ env || {}, "sh", "-c", command ]
35
+
36
+ def spawn_options = { pgroup: true }
37
+
32
38
  def kill_group(pid)
33
39
  Process.kill(:KILL, -pid)
34
40
  rescue Errno::ESRCH, Errno::EPERM
@@ -8,10 +8,10 @@ RubyLLM.configure do |config|
8
8
  config.logger = Logger.new(IO::NULL) unless ENV["MINISWEN_DEBUG"] == "1"
9
9
  end
10
10
 
11
- # About five minutes of retries (1, 2, 4, ... 128s plus jitter): provider
11
+ # About ten minutes of retries (1, 2, 4, ... 256s plus jitter): provider
12
12
  # outages and rate-limit windows outlast the minute this used to allow.
13
13
  RubyLLM.configure do |config|
14
- config.max_retries = 8
14
+ config.max_retries = 9
15
15
  config.retry_interval = 1
16
16
  end
17
17
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Miniswen
4
- VERSION = "1.3.3"
4
+ VERSION = "1.3.4"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miniswen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.3
4
+ version: 1.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Svyatoslav Kryukov
@@ -58,6 +58,7 @@ files:
58
58
  - lib/miniswen/cli/reporter.rb
59
59
  - lib/miniswen/environment.rb
60
60
  - lib/miniswen/environment/docker.rb
61
+ - lib/miniswen/jail.rb
61
62
  - lib/miniswen/local.rb
62
63
  - lib/miniswen/ruby_llm.rb
63
64
  - lib/miniswen/testing.rb