miniswen 1.2.0 → 1.3.1
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/README.md +6 -5
- data/lib/miniswen/agent.rb +23 -5
- data/lib/miniswen/cli.rb +4 -0
- data/lib/miniswen/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4c9e3b53432be806eb3a0822777bafd74b6656e5c3577e2b7a41f70f24f6a97
|
|
4
|
+
data.tar.gz: a533f95356c1b8ba40606a25cc79f6e6da885fe42251daf436dcad62df6a273e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bf213b85fd14ef0ec93b94409361f490b82769f70b6d6fbef8917688a9510c29366f7825c0ecdf951824a42ed19a33a23530679c23108f852996486ffd5d92db
|
|
7
|
+
data.tar.gz: a9328e4313ce9abbe5843368428f4e85752cc9690c00e6bfe8c68321e8c820ce1000996472c76aded6eef0fa988815c9a2a7348bc12bc953ea356f980184bd71
|
data/README.md
CHANGED
|
@@ -88,6 +88,7 @@ agent:
|
|
|
88
88
|
timeout: 30m
|
|
89
89
|
step_limit: 100
|
|
90
90
|
cost_limit: 5.0
|
|
91
|
+
# max_output_tokens: 32768 # [optional] output cap per model call, for hosts that reserve the model's full max output out of the context window (default: the provider's)
|
|
91
92
|
environment:
|
|
92
93
|
network: # the sandbox network while the agent works: just enough to reach the model
|
|
93
94
|
mode: allowlist
|
|
@@ -142,7 +143,7 @@ A minimal task example—checking whether an agent can write "Hello, world" into
|
|
|
142
143
|
+Hello, world
|
|
143
144
|
```
|
|
144
145
|
|
|
145
|
-
- `verification_test.rb`: a Ruby test that grades the solution (pass → 1, fail → 0; for partial credit, write a float in 0.0..1.0 to `$LOGS/reward.txt` instead). A check worth recording but not grading goes into `allow_failure { ... }` (`include LemansReport::Assertions`): a failed assertion inside lands in `checks.json` as `fail (allowed)` with its message and leaves the reward alone, while errors and skips stay hard failures. We use Minitest:
|
|
146
|
+
- `verification_test.rb`: a Ruby test that grades the solution (pass → 1, fail → 0; for partial credit, write a float in 0.0..1.0 to `$LOGS/reward.txt` instead). A check worth recording but not grading goes into `allow_failure { ... }` (`include LemansReport::Assertions`): a failed assertion inside lands in `checks.json` as `fail (allowed)` with its message and leaves the reward alone, while errors and skips stay hard failures (a test may call `allow_failure` once). For fractional credit next to the reward, say what passing the required checks alone is worth (`LemansReport.base_credit = 0.7`) and weight the allowed failures (`allow_failure(points: 2) { ... }`, 1 by default): the trial's `credit` is the base credit plus the remainder scaled by the share of extra points passed, rounded to two digits — 0 whenever the suite fails, and simply the reward when no `base_credit` is set. We use Minitest:
|
|
146
147
|
|
|
147
148
|
```ruby
|
|
148
149
|
require "minitest/autorun"
|
|
@@ -218,11 +219,11 @@ ar-archive-book-access miniswen-installed gpt-5.6-luna 1 completed 0.0
|
|
|
218
219
|
6 trials: 6 scored, 0 invalid, 6 solved (100%) · $0.0801 · pass@2 3/3 tasks (100%)
|
|
219
220
|
```
|
|
220
221
|
|
|
221
|
-
`lemans run` runs all the tasks for the model defined in `bench.yml` and prints the report at the end. You can override the model(s) to use (`--model`), the number of attempts (`--attempts`), or select specific tasks by name (`--task=ac-throttle-search`, may be repeated).
|
|
222
|
+
`lemans run` runs all the tasks for the model defined in `bench.yml` and prints the report at the end. You can override the model(s) to use (`--model`), the agent's output cap per model call (`--max-output-tokens`), the number of attempts (`--attempts`), or select specific tasks by name (`--task=ac-throttle-search`, may be repeated).
|
|
222
223
|
|
|
223
224
|
Each trial writes a flat `runs/<model>/<task>__<id>/` directory:
|
|
224
225
|
|
|
225
|
-
- `result.json`: reward, outcome (completed, error, etc.), usage, timings, tags, digests
|
|
226
|
+
- `result.json`: reward, credit, outcome (completed, error, etc.), usage, timings, tags, digests
|
|
226
227
|
- `trajectory.json`: [ATIF](https://www.harborframework.com/docs/agents/trajectory-format) trajectory of the agent's session
|
|
227
228
|
- `agent.patch`: the agent's work as one diff against the sealed baseline
|
|
228
229
|
- `verifier.log`, `checks.json`, etc.: additional logs captured during the verification phase.
|
|
@@ -253,8 +254,8 @@ gpt-5.6-luna ar-archive-book-access 2/2 2m 23s $0.0132 12.5 156905
|
|
|
253
254
|
| --- | --- |
|
|
254
255
|
| `lemans init` | Scaffold a new bench directory: an annotated `bench.yml` and two example tasks |
|
|
255
256
|
| `lemans tasks` | List the tasks in a bench (`--tag` to filter) |
|
|
256
|
-
| `lemans run` | Run tasks and grade them (`--task`, `--tag`, `--agent`, `--model`, `-k`, `-c`, `--resume`) |
|
|
257
|
-
| `lemans report` | Summarize `runs/` as a table or CSV (`--tag`, `-A [task-agent-model]` to aggregate, `-S <column>` to sort); repeated attempts add pass@k per model × task |
|
|
257
|
+
| `lemans run` | Run tasks and grade them (`--task`, `--tag`, `--agent`, `--model`, `--max-output-tokens`, `-k`, `-c`, `--resume`) |
|
|
258
|
+
| `lemans report` | Summarize `runs/` as a table or CSV (`--task`, `--tag`, `--metadata key:value` to filter, `-A [task-agent-model]` to aggregate, `-S <column>` to sort); repeated attempts add pass@k per model × task, fractional grading a `credit` column |
|
|
258
259
|
| `lemans clobber` | Delete run results (`--task`, `--ttl 10m\|2h\|1d`, `--invalid`, `-f` to skip the confirmation) |
|
|
259
260
|
|
|
260
261
|
## miniswen
|
data/lib/miniswen/agent.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Miniswen
|
|
|
14
14
|
|
|
15
15
|
# Both finish_reason dialects accepted raw: OpenAI-shaped providers say
|
|
16
16
|
# "length"/"tool_calls", Anthropic says "max_tokens"/"tool_use".
|
|
17
|
-
TRUNCATION_FINISH_REASONS = %w[length max_tokens].freeze
|
|
17
|
+
TRUNCATION_FINISH_REASONS = %w[length max_tokens model_context_window_exceeded].freeze
|
|
18
18
|
CLAIMED_TOOL_FINISH_REASONS = %w[tool_calls tool_use].freeze
|
|
19
19
|
# A safety stop, which arrives looking exactly like a model that forgot
|
|
20
20
|
# to call the tool: no content, no tool call, and — since the provider
|
|
@@ -224,19 +224,20 @@ module Miniswen
|
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
CostSource = Data.define(:name, :model, :priced_as, :registry) do
|
|
227
|
-
def to_h = { name
|
|
227
|
+
def to_h = { name:, model:, priced_as:, registry: }.compact
|
|
228
228
|
end
|
|
229
229
|
|
|
230
230
|
attr_reader :messages, :environment
|
|
231
231
|
|
|
232
|
-
private attr_reader :max_steps, :max_time, :max_cost, :exec_timeout,
|
|
232
|
+
private attr_reader :max_steps, :max_time, :max_cost, :exec_timeout, :max_output_tokens,
|
|
233
233
|
:clock, :reporter
|
|
234
234
|
|
|
235
235
|
# `model` is a litellm-style name ("openrouter/z-ai/glm-5.2"), optionally
|
|
236
236
|
# suffixed with a reasoning effort ("openrouter/openai/gpt-5.6-luna#xhigh").
|
|
237
237
|
# Limits of 0 or nil are disabled.
|
|
238
238
|
def initialize(model:, environment:, max_steps: 0, max_time: 0, max_cost: nil,
|
|
239
|
-
exec_timeout: 30,
|
|
239
|
+
exec_timeout: 30, max_output_tokens: 0,
|
|
240
|
+
clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) },
|
|
240
241
|
reporter: nil)
|
|
241
242
|
name, @effort = model.split("#", 2)
|
|
242
243
|
@provider, @id = name.split("/", 2)
|
|
@@ -254,6 +255,7 @@ module Miniswen
|
|
|
254
255
|
@max_time = max_time.to_f
|
|
255
256
|
@max_cost = max_cost
|
|
256
257
|
@exec_timeout = exec_timeout
|
|
258
|
+
@max_output_tokens = max_output_tokens.to_i
|
|
257
259
|
|
|
258
260
|
@clock = clock
|
|
259
261
|
@reporter = reporter
|
|
@@ -503,7 +505,7 @@ module Miniswen
|
|
|
503
505
|
tools: { bash: @bash_tool },
|
|
504
506
|
temperature: nil,
|
|
505
507
|
model: model_info,
|
|
506
|
-
params: routing_params,
|
|
508
|
+
params: routing_params.merge(output_cap_params(model_info)),
|
|
507
509
|
thinking: (RubyLLM::Thinking::Config.new(effort: @effort) if @effort)
|
|
508
510
|
)
|
|
509
511
|
payload(response)
|
|
@@ -543,6 +545,22 @@ module Miniswen
|
|
|
543
545
|
|
|
544
546
|
def provider_order = ENV["LEMANS_PROVIDER_ORDER"] || ENV["OPENROUTER_PROVIDER_ORDER"]
|
|
545
547
|
|
|
548
|
+
# OpenAI itself retired `max_tokens` for its reasoning models; the
|
|
549
|
+
# OpenAI-compatible providers and Anthropic still read it.
|
|
550
|
+
def output_cap_params(model_info)
|
|
551
|
+
return {} if max_output_tokens.zero?
|
|
552
|
+
|
|
553
|
+
cap = [ info&.max_tokens, max_output_tokens ].compact.min
|
|
554
|
+
provider_class = RubyLLM::Provider.providers[model_info.provider.to_sym]
|
|
555
|
+
if [ RubyLLM::Providers::OpenAI, RubyLLM::Providers::Azure ].include?(provider_class)
|
|
556
|
+
{ max_completion_tokens: cap }
|
|
557
|
+
elsif provider_class <= RubyLLM::Providers::OpenAI || provider_class <= RubyLLM::Providers::Anthropic
|
|
558
|
+
{ max_tokens: cap }
|
|
559
|
+
else
|
|
560
|
+
{}
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
546
564
|
def cost_source
|
|
547
565
|
if local?
|
|
548
566
|
return CostSource.new(name: :local_provider, model: @model,
|
data/lib/miniswen/cli.rb
CHANGED
|
@@ -123,6 +123,10 @@ module Miniswen
|
|
|
123
123
|
options[:exec_timeout] = v
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
+
opts.on("--max-output-tokens=TOKENS", Integer, "Output cap per model call (default: the provider's)") do |v|
|
|
127
|
+
options[:max_output_tokens] = v
|
|
128
|
+
end
|
|
129
|
+
|
|
126
130
|
opts.on("-q", "--quiet", "Disable progress output") do
|
|
127
131
|
@quiet = true
|
|
128
132
|
end
|
data/lib/miniswen/version.rb
CHANGED