@wendellresearch-ai/benchwarmers 0.5.5 → 0.6.0

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.
package/README.md CHANGED
@@ -99,7 +99,7 @@ with [AGENTS.md](AGENTS.md).
99
99
 
100
100
  ## Try it
101
101
 
102
- **v0.3, early.** It runs with Python 3.11 or later on Windows, macOS and
102
+ **Pre-1.0, early.** It runs with Python 3.11 or later on Windows, macOS and
103
103
  Linux, from PyPI, npm, a checkout or Docker. Expect rough edges, and read the
104
104
  code where these pages are thin.
105
105
 
@@ -145,6 +145,10 @@ dependencies either way: the app is the Python standard library.
145
145
  its key, which goes to the key file in llm's user folder (`keys.json`,
146
146
  shared with the `llm` CLI if you have it, not needed otherwise), never into
147
147
  the data folder. `BENCHWARMERS_KEY_<NAME>` in the environment works too.
148
+ To move an install to another machine, Settings → Export and import takes
149
+ the folder as one .zip (settings only, or everything; the endpoints' keys
150
+ only if you tick them) and imports it on the other install, saving what it
151
+ replaces to `backups/` first.
148
152
 
149
153
  3. **Start the dashboard.** With no endpoint yet it opens on adding one: sign
150
154
  in with a provider on its own page (OpenRouter, NanoGPT, Hugging Face,
@@ -153,7 +157,10 @@ dependencies either way: the app is the Python standard library.
153
157
  LiteLLM included. Anthropic and Gemini keys can also be called through
154
158
  those providers' own APIs (the API choice in the same dialog). Only providers that publish a sign-in for other apps are
155
159
  offered; adding one is an entry in `metrics/connect.py` (its docstring says
156
- how).
160
+ how). A model server already running on this machine, at its usual port or
161
+ any other its process is listening on (Ollama, LM Studio, Jan, llama.cpp,
162
+ LocalAI, vLLM, LiteLLM, CLI Proxy API, OmniRoute), is offered under "Found
163
+ on this machine", its address and kind filled in.
157
164
 
158
165
  python serve.py # http://localhost:8122
159
166
 
@@ -176,7 +183,11 @@ dependencies either way: the app is the Python standard library.
176
183
  - **Collections and seats.** A collection names the models a panel always
177
184
  includes and the shape of work it is for (review, design, enumeration...).
178
185
  Each call adds explorer seats chosen by how long a model has gone unused, so
179
- the bench keeps learning about models a router would stop asking.
186
+ the bench keeps learning about models a router would stop asking. A member
187
+ that is out of quota or rate-limited keeps its place while an explorer
188
+ stands in for it until it is back. A collection can set its own calls per
189
+ request and explorers, and one marked ad hoc (an expensive one, say) runs
190
+ only when a request names it.
180
191
  - **Verdicts.** Each seat's answer carries a call id. Once you have checked an
181
192
  answer against the real work, record whether it was useful, and which of its
182
193
  claims were real or false. Verdicts, not vibes, decide the next panel; a
@@ -191,6 +202,18 @@ dependencies either way: the app is the Python standard library.
191
202
  that is only out of quota until a stated reset is not counted against. The
192
203
  built-in scheduler runs all of this once Settings switches it on; a fresh
193
204
  install spends no calls until then.
205
+ - **Benchmarks.** One page of reports: bugs found against false alarms, who
206
+ is confidently wrong, real work that helped, each model against its own
207
+ earlier scores (Trend), whether each provider was there when the bench
208
+ called it (Uptime: busy, unreachable and timed out count as down; your own
209
+ quota and pacing are left out), and speed. Each report shares as an image or
210
+ its table. [BENCHMARKS.md](BENCHMARKS.md) says how to read them.
211
+ - **Decision models.** A model that answers typed questions with a
212
+ probability (Mercury Decide, say) labels a request's shape, picks a
213
+ collection for a request that names none (when it is sure, and the reply
214
+ says so), and classes an error no rule knows. Each is measured daily on
215
+ questions the bench's own data answers, and each use asks the one that does
216
+ best.
194
217
  - **Rate limits and usage.** Limits come from providers' rate-limit headers
195
218
  and error messages, and from what you set per connection or model
196
219
  (requests a minute, day or month; tokens a minute or day). They are kept per
@@ -203,7 +226,10 @@ dependencies either way: the app is the Python standard library.
203
226
  are read from its site and watched for changes.
204
227
  - **Discover.** FreeLLMAPI's free catalog, with models.dev for the details
205
228
  and paid models it lacks, merged into one list of models worth adding,
206
- smartest first, each with the routes this install has to it.
229
+ smartest first, each with the routes this install has to it and links to
230
+ its pages on both. Each Open WebUI connection's own model list adds what a
231
+ provider serves before either catalog lists it; **Refresh lists** fetches
232
+ them all now rather than at the daily fetch.
207
233
 
208
234
  ## Asking a panel
209
235
 
@@ -266,6 +292,7 @@ running server, so the same commands work against one on another machine.
266
292
  bench model retire <alias> --reason "..." and back: bench model restore <alias>
267
293
  bench collection save reviewers --members a,b,c --description "adversarial review"
268
294
  bench collection save reviewers --add d --remove a
295
+ bench collection save heavy-hitters --ad-hoc --max-calls 4 --max-explorers 0
269
296
  bench endpoint add openrouter --base https://openrouter.ai/api/v1 (asks for the key, hidden)
270
297
  bench key create my-app --collections core --rpm 30
271
298
  bench settings scheduler run --off perf
@@ -296,8 +323,9 @@ no server at `BENCHWARMERS_URL`.
296
323
 
297
324
  A running Benchwarmers is an MCP server at `/mcp` on its own port
298
325
  (`http://127.0.0.1:8122/mcp`; `/v1/mcp` works too), over streamable HTTP,
299
- with three tools: `list_collections`, `ask` (a collection, a prompt,
300
- optionally `merged`, `with` and `system`) and `verdict`. Nothing to start per
326
+ with four tools: `list_collections`, `ask` (a collection, a prompt,
327
+ optionally `merged`, `with` and `system`), `verdict` and `pending_verdicts`
328
+ (the seats still unjudged). Nothing to start per
301
329
  client: every agent session shares the one server, behind the same Host,
302
330
  Origin and gateway-key checks as `/v1`. The tool descriptions carry the
303
331
  rules: ask a collection, not a favourite model; verify before acting; name
@@ -385,6 +413,13 @@ points at it with `ANTHROPIC_BASE_URL=http://127.0.0.1:8122` and
385
413
  OpenAI-, Responses- or Ollama-speaking agents with the same base URL.
386
414
  [GATEWAY.md](GATEWAY.md), "Route mode", has the set-up and the limits.
387
415
 
416
+ **Ready set-ups.** The dashboard's **Clients** page (Gateway) gives each
417
+ popular app's configuration, filled in from your install's address,
418
+ collections and MCP server, with a Copy button: opencode, VS Code chat, Codex
419
+ CLI, Zed, Continue, Cline and Kilo Code, Claude Code, goose, and chat apps
420
+ (LobeHub, AnythingLLM, Cherry Studio, Chatbox, LibreChat). Where keys are
421
+ asked for, it makes one and fills it in, never into a file that may sync.
422
+
388
423
  <!-- The MCP Registry's proof that the PyPI package is this server (server.json):
389
424
  mcp-name: io.github.WendellResearch-AI/benchwarmers -->
390
425
 
@@ -437,12 +472,17 @@ reaches Wendell Research. What it sends, and where:
437
472
 
438
473
  - **Your prompts**, only to the endpoints you add: a provider, an aggregator,
439
474
  a hub such as Open WebUI, or a local runtime. That includes the probes, the
440
- suite and onboarding, which spend calls on your keys. Add only endpoints you
441
- are content to send that work to.
475
+ suite and onboarding, which spend calls on your keys, and the decision
476
+ models' daily benchmark, which puts past requests, judged answers and
477
+ redacted error text to them again. Add only endpoints you are content to
478
+ send that work to.
442
479
  - **Catalog reads**, no key and nothing of yours: FreeLLMAPI (its feed and
443
480
  its site's sitemap) and models.dev once a day, and OpenRouter's public
444
481
  model list. With an NVIDIA connection, the public file of rate limits
445
482
  build.nvidia.com states, once a day and on Refresh.
483
+ - **Model lists**, with no prompt: each Open WebUI connection's list of the
484
+ models its provider serves, asked through Open WebUI with the key it
485
+ already holds, once a day and on Discover's Refresh lists.
446
486
  - **Sign-ins**, only when you choose one: the provider's own sign-in page.
447
487
  - **Quota reads**, only when you press Refresh on Quota management, with no
448
488
  prompt: OpenRouter's key status, and xKiro's and Requesty's usage, each with
@@ -450,12 +490,18 @@ reaches Wendell Research. What it sends, and where:
450
490
  API asks each sign-in's own provider for its quota.
451
491
  - **Charts**: the dashboard's browser page loads Observable Plot from jsDelivr
452
492
  at a pinned version.
493
+ - **Posts**, only when you click Post on X, Bluesky, LinkedIn or Reddit in a
494
+ report's Share menu: that site opens in your browser with the report's name
495
+ and the project's link. The image goes only to your clipboard, a file, or
496
+ the app you pick in your system's share sheet.
453
497
  - **Seeding real-bug tasks**, only when you run `suite/rebench.py`: the
454
498
  SWE-rebench-V2 rows from Hugging Face and the files from GitHub.
455
499
 
456
500
  Keys stay in the environment or llm's key file (`keys.json` in its user
457
- folder), never in the data folder. [PRIVACY.md](PRIVACY.md) and [SECURITY.md](SECURITY.md) have the
458
- detail.
501
+ folder), not in the data folder. An export (Settings, Export and import)
502
+ carries them only if you tick them, and an import that carries keys first
503
+ backs up the ones it replaces, in the data folder's `backups/`.
504
+ [PRIVACY.md](PRIVACY.md) and [SECURITY.md](SECURITY.md) have the detail.
459
505
 
460
506
  ## Limits
461
507
 
@@ -463,8 +509,8 @@ detail.
463
509
  with tools is refused there, not trimmed. Route mode passes turns only to
464
510
  members on chat-completions endpoints, keeps its sticky conversations in
465
511
  memory (a restart starts each on a fresh pick), and has been run end to end
466
- with Claude Code; the Codex, opencode and Cline set-ups are written from
467
- their docs. Shadow seats (other members answering an agent's turn for
512
+ with Claude Code; the other set-ups on the Clients page are written from
513
+ each app's docs, not run. Shadow seats (other members answering an agent's turn for
468
514
  evaluation) are planned, not built.
469
515
  - **Some parts are checked against fakes only.** The native Anthropic and
470
516
  Gemini endpoints, and the LiteLLM and CLI Proxy API hub adapters, are built
@@ -474,9 +520,10 @@ detail.
474
520
  seats before it stream as they finish.
475
521
  - **Pacing and the ledger cover the built-in client.** Calls made through the
476
522
  `llm` CLI, when you choose it, are neither paced nor counted.
477
- - **Calls cost.** Probes, onboarding and the suite run on your keys and free
478
- tiers. Onboarding runs one model at a time for that reason (Quick spreads
479
- the suite over the scheduled passes); a suite pass is paced, not burst.
523
+ - **Calls cost.** Probes, onboarding, the suite and the decision benchmark
524
+ run on your keys and free tiers. Onboarding runs one model at a time for
525
+ that reason (Quick spreads the suite over the scheduled passes); a suite
526
+ pass is paced, not burst.
480
527
  - **The scheduler lives in the server.** Its jobs run while the dashboard (or
481
528
  the container, or the service) is up; a missed run is made up once, within
482
529
  seven days, when it comes back.
package/SECURITY.md CHANGED
@@ -24,8 +24,9 @@ reproduce, and what an attacker gains.
24
24
  **On this machine by default.** The dashboard (`serve.py`, port 8122) and the
25
25
  gateway (on the same port at `/v1`, or alone with `gateway.py` on 8123) listen
26
26
  on 127.0.0.1. Every request is checked for the server's own host name (against
27
- DNS rebinding), and every write must be a same-origin JSON request, so a web
28
- page open in your browser cannot drive either server. With no admin token
27
+ DNS rebinding), and every write must be a same-origin request with a JSON
28
+ body (a zip, for an import), a type no plain form can send, so a web page
29
+ open in your browser cannot drive either server. With no admin token
29
30
  there is no login and the gateway asks for no key.
30
31
 
31
32
  **Anywhere else, only with a login.** To listen beyond this machine
@@ -60,14 +61,24 @@ open itself to anyone.
60
61
  - **Keys.** Endpoint keys come from `BENCHWARMERS_KEY_<NAME>` (the key name
61
62
  upper-cased, `-` as `_`) first, then from llm's key file (`keys.json` in
62
63
  its user folder, used whether or not the `llm` CLI is installed). They are
63
- never written to the data folder, never shown back, and never put in a log.
64
- Sign-ins through a provider's page store their token the same way.
64
+ never shown back and never put in a log. Sign-ins through a provider's page
65
+ store their token the same way.
66
+ - **Exports.** Settings, Export and import, puts the endpoints' stored keys
67
+ (key, admin key, refresh token; never one from the environment) in an
68
+ export only when you tick them, in plain text in its `keys.json`: keep that
69
+ file like a password and delete it once imported. Importing one puts its
70
+ keys in the key store, and first backs up this install's own, with its files,
71
+ to the data folder's `backups/before-import-<time>.zip`. An import is
72
+ refused whole if any file in it would land outside its scope's folders.
65
73
  - **The network.** Your prompts go only to the endpoints you add; the probes,
66
- the suite and onboarding spend calls there too. Otherwise: public catalog
67
- reads (models.dev, FreeLLMAPI, OpenRouter's model list), a provider's
68
- sign-in page when you choose one, Observable Plot from jsDelivr in the
69
- dashboard's page, and Hugging Face and GitHub only when you run
70
- `suite/rebench.py`. [PRIVACY.md](PRIVACY.md) lists them.
74
+ the suite, onboarding and the decision benchmark spend calls there too.
75
+ Otherwise: public catalog reads (models.dev, FreeLLMAPI, OpenRouter's model
76
+ list), each Open WebUI connection's model list (through Open WebUI, with its
77
+ key), a provider's sign-in page when you choose one, Observable Plot from
78
+ jsDelivr in the dashboard's page, the site a report's Share menu posts to
79
+ when you choose one (opened with the report's name and the project's link
80
+ only), and Hugging Face and GitHub only when you run `suite/rebench.py`.
81
+ [PRIVACY.md](PRIVACY.md) lists them.
71
82
  - **Files.** It writes inside its data folder (`BENCHWARMERS_HOME`, or the
72
83
  folder `.benchwarmers-home` names) and, in llm's user folder, the key file
73
84
  (when you paste a key or sign in) and the model list (when it registers a
package/USAGE.md CHANGED
@@ -13,6 +13,7 @@ coding agent doing it with you); the gateway's whole contract is in
13
13
  - [Collections](#collections)
14
14
  - [Connecting an app](#connecting-an-app)
15
15
  - [Recording verdicts](#recording-verdicts)
16
+ - [Benchmarks, and sharing a report](#benchmarks-and-sharing-a-report)
16
17
  - [Discover: finding models to add](#discover-finding-models-to-add)
17
18
  - [Quota management](#quota-management)
18
19
  - [The scheduler](#the-scheduler)
@@ -24,17 +25,24 @@ coding agent doing it with you); the gateway's whole contract is in
24
25
 
25
26
  | Group | Page | What it is for |
26
27
  | --- | --- | --- |
27
- | Observe | **At a glance** | Every model on the bench: whether it works right now, its role, and its connection. Click a name for its popup: role, alias, facts, options, retire. |
28
+ | Observe | **At a glance** | Every model on the bench: whether it works right now, its uptime over 7 days, its role, and its connection. Click a name for its popup: role, alias, facts, options, retire. |
28
29
  | | **Action needed** | What will not fix itself, by the connection it comes from, with Retry and Retire on each model. |
29
- | | **Benchmarks** | How models do on the suite and on real work: bugs found against false alarms, who is confidently wrong, and speed. |
30
+ | | **Benchmarks** | How models do on the suite and on real work: bugs found against false alarms, who is confidently wrong, each model against its own earlier scores, uptime, speed, and the decision models. Each report shares as an image or its table. |
30
31
  | | **Quota management** | A tile per provider: what is left, when it resets, and which of its models are resting. Then the week's resets, and what the bench sent. |
31
32
  | | **Logs** | Gateway calls (who sat and how it went, never the prompt), changes made from the dashboard, the scheduler, and onboarding runs. |
32
- | Gateway | **Endpoints** | Where models are served from. Add an endpoint (a provider's sign-in, or any OpenAI-compatible API key), change a key, and see what each one serves. Also your own app registrations and rate limits per connection. |
33
+ | Gateway | **Endpoints** | Where models are served from. Add an endpoint (a provider's sign-in, or any OpenAI-compatible API key), change a key, and see what each one serves. A model server running on this machine, at its usual port or any other its process is listening on (LM Studio, Jan, llama.cpp, vLLM and the like), is offered under Found on this machine: Add opens the dialog with it filled in, to test and save. Also your own app registrations and rate limits per connection. |
33
34
  | | **Models** | Every model on the bench, by the connection it comes from. |
34
35
  | | **Collections** | The named panels your apps ask for, and the gateway's settings. |
36
+ | | **Clients** | Each popular app's set-up (opencode, VS Code, Codex, Zed, Continue, Cline, Kilo Code, Claude Code, goose, chat apps), filled in from this install, with Copy and a gateway key made on the spot. |
35
37
  | | **Discover** | Models worth adding, from public catalogs, with the ways this install can reach each one. |
36
- | Control | **Settings** | Theme, gateway keys, the scheduler, the model client, providers whose free models work only in their own app, how the install is reached (shown only), and Restart. |
37
- | | **Info** | Version, Python, data folder and counts. |
38
+ | Control | **Settings** | Theme, gateway keys, the scheduler, the model client, providers whose free models work only in their own app, export and import, how the install is reached (shown only), and Restart. |
39
+ | | **Info** | The source repository, the version (linking its release), Python, data folder and counts. |
40
+
41
+ The page shown follows the data: while it is in view it checks every 10
42
+ seconds, and when something has changed it swaps in the new page in place,
43
+ keeping open sections, sorting and filters. It waits while you are at work on
44
+ it (a popup open, a form not saved or in use, text selected, a chart hovered),
45
+ and **New results · Show**, top right, offers the change instead.
38
46
 
39
47
  **Action needed** lists what will not fix itself, such as a model about to be
40
48
  retired, grouped by the connection it comes from, since one cause usually
@@ -108,7 +116,9 @@ unavailable, so the daily probe keeps watching it.
108
116
  `code`, `light` (small and fast), `vision` (reads images well, weak at text:
109
117
  OCR and document models; seated only when a request carries images) or
110
118
  `image` (makes images; never seated). A model that reads images and does
111
- everything else well stays `general`.
119
+ everything else well stays `general`. Where a decision model is onboarded,
120
+ onboarding asks it to suggest a new chat model's role; the popup shows the
121
+ suggestion, and nothing applies it.
112
122
 
113
123
  ## Collections
114
124
 
@@ -123,16 +133,30 @@ per model with its context, vision and tools, and price. A model served by
123
133
  several providers is still one row, with a chip per provider: tick the chip
124
134
  of the route you want. Ticking two is allowed, and the count says so. The
125
135
  search matches a model, provider or served name, and the select beside it
126
- shows one provider's models; ticked ones always stay in view. A seat's ×
127
- takes that member off, as unticking it does. The tags grey out the models that
136
+ shows one provider's models. The seats above the list always show who is
137
+ ticked, filtered out or not, and a seat's × takes that member off, as unticking
138
+ it does. The tags grey out the models that
128
139
  do not fit them.
129
140
 
130
141
  Each call also seats explorers, the models unused longest, up to the gateway's
131
142
  limits (Gateway settings, on the same page: how many calls a request may make,
132
- and how many of them explore).
143
+ and how many of them explore). A collection can set its own in its popup; left
144
+ empty, it follows those settings. A member out of quota stays on the collection
145
+ and an explorer sits in for it, named `stand-in for <member>`, until the quota
146
+ is back. Max explorers 0 means only the members ever run, stand-ins included.
147
+
148
+ Gateway settings also says whether a request that names no collection is given
149
+ one by a decision model, and how sure that model must be (GATEWAY.md, "No
150
+ default collection").
133
151
 
134
152
  ## Connecting an app
135
153
 
154
+ The dashboard's **Clients** page has a ready set-up for each popular app,
155
+ filled in from this install (its address, collections and MCP server): copy it
156
+ into the file or screen it names. When keys are asked for, it makes one on the
157
+ spot and fills it in where a key goes, never into a file that may sync. What
158
+ follows is the same by hand.
159
+
136
160
  Any OpenAI-compatible client works. Point it at the dashboard's port and ask
137
161
  for the model `bench/<collection>`:
138
162
 
@@ -193,7 +217,8 @@ claude
193
217
 
194
218
  Each conversation is one offload per model that answered it; a verdict is
195
219
  optional, and the Gateway card lists route conversations apart from the
196
- panels. GATEWAY.md, "Route mode", has the other clients and the limits.
220
+ panels. The Clients page has the other agents' set-ups; GATEWAY.md, "Route
221
+ mode", has the limits.
197
222
 
198
223
  **A coding agent** connects over MCP instead: the Claude Code plugin
199
224
  (`/plugin marketplace add WendellResearch-AI/benchwarmers`, then
@@ -225,15 +250,49 @@ claims feed **Confidently wrong** on Benchmarks, and verdicts together decide
225
250
  who sits on the next panel. Agreement between models is not evidence: they
226
251
  are often wrong together.
227
252
 
253
+ ## Benchmarks, and sharing a report
254
+
255
+ **Benchmarks** is one report after another: who to trust with a review, bug
256
+ hunt, real work, confidently wrong, our code, vision, trend, uptime,
257
+ performance and the decision models, then links to public leaderboards. Most
258
+ have a chart, the table folded under it (with a filter, and **Show
259
+ retired**), and **How to read this**;
260
+ [BENCHMARKS.md](BENCHMARKS.md) has the same explanations in one place.
261
+ **Trend** (30 or 60 days) and **Uptime** (7 or 30) have a window to choose.
262
+
263
+ **Share**, top right of each report:
264
+
265
+ - **Copy image** / **Download image**: the report's charts, title and the line
266
+ under it, with a band at the foot holding the logo, the project's link and
267
+ the date, as a PNG at twice the size shown. The table, the key and the
268
+ controls stay out; a window you chose shows as its words.
269
+ - **Copy table as Markdown** / **Download table as CSV**: the table as shown
270
+ (its window, filter and Show retired), a model's connection in brackets.
271
+ - **Share…**: your system's share sheet, with the image.
272
+ - **Post on** X, Bluesky, LinkedIn or Reddit: the image goes on the clipboard
273
+ (or is saved, where there is no clipboard), then the site opens with the
274
+ report's name and the project's link, for you to paste the image into.
275
+
276
+ What your browser cannot do is not offered: copying needs a secure page
277
+ (`localhost` is one; a LAN address over plain http is not), and Share… needs
278
+ a share sheet.
279
+
228
280
  ## Discover: finding models to add
229
281
 
230
282
  **Discover** leads with FreeLLMAPI's catalog of free tiers and fills in from
231
- models.dev, which alone has prices, paid models and providers' base URLs. One
283
+ models.dev, which alone has prices, paid models and providers' base URLs.
284
+ The catalogs trail the providers by days, so it also reads each Open WebUI
285
+ connection's own model list (through Open WebUI, with the keys it already
286
+ has): a model a provider serves that neither catalog lists yet is a row of its
287
+ own, its price unknown where the provider's list does not say. All of them
288
+ are fetched daily; **Refresh lists** fetches them now. A provider is matched
289
+ to your Open WebUI connection by its API host, or by its name in the
290
+ connection's host (FreeLLMAPI's xKiro is `api.xkiro.com`). One
232
291
  list: free models first, then by reach, and within each reach FreeLLMAPI's
233
292
  smartest first (the **Rank** column), then what it does not rank, what is new
234
293
  this week first and badged. A row opens its popup: what
235
294
  the model takes and does, its limits and monthly budget, FreeLLMAPI's known
236
- quirks for it, links to its freellmapi.co page and models.dev, and every route
295
+ quirks for it, links to its own pages on freellmapi.co and models.dev, and every route
237
296
  this install has to it, each with an **Add via this**. Adding through a hub (Open WebUI, LiteLLM, CLI Proxy
238
297
  API) puts it in that hub too; adding direct registers it on its own endpoint
239
298
  only. Either way the onboarding joins the same queue, with the same
@@ -308,8 +367,9 @@ Under the tiles are:
308
367
  ## The scheduler
309
368
 
310
369
  The recurring jobs (the morning availability probe, the catalog refresh, the
311
- deprecation check and auto-retire, suite passes, the weekly speed and
312
- capability tests) run inside the dashboard. Settings, **Scheduler**:
370
+ deprecation check and auto-retire, suite passes, the decision models' daily
371
+ benchmark, the weekly speed and capability tests) run inside the dashboard.
372
+ Settings, **Scheduler**:
313
373
 
314
374
  - **Off**: nothing runs; a fresh install spends no calls until you opt in.
315
375
  - **Log only**: writes "would run" to `runs/scheduler.log` at each due time,
@@ -326,3 +386,16 @@ call logs, probe history, task answers) lives in the data folder: the one
326
386
  `BENCHWARMERS_HOME` names, else the one in `.benchwarmers-home` at the top of
327
387
  the checkout. Back it up by copying it; move it by copying it and pointing one
328
388
  of those two at the new place. Info shows which folder is in use.
389
+
390
+ **Export and import**, on Settings, does the same through the dashboard, for
391
+ another machine or a copy to keep: one .zip of **Settings only**
392
+ (`config/`: endpoints, collections, roles, model options, the schedule,
393
+ gateway keys, the theme) or **Everything** (also every result, history, log
394
+ and saved answer). The endpoints' API keys go in only if you tick them; the
395
+ file then holds them, so keep it like a password and delete it once
396
+ imported. On the other install, choose the file: it says what is in it
397
+ (scope, release, date, files, how many it replaces, keys) before **Import**.
398
+ Its files replace the ones of the same name, after this install's own in that
399
+ scope are saved to `backups/before-import-<time>.zip`; files it does not have
400
+ are left. Restart afterwards (Settings, Server and access), so every part
401
+ reads them.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.5
1
+ 0.6.0
package/cli.py CHANGED
@@ -328,7 +328,10 @@ def cmd_collection(args) -> None:
328
328
  "description": args.description if args.description is not None else old.get("description") or "",
329
329
  "tags": csv(args.tags) if args.tags is not None else old.get("tags") or [],
330
330
  "reply": args.reply or old.get("reply") or "all",
331
- "merger": args.merger if args.merger is not None else old.get("merger") or ""}
331
+ "merger": args.merger if args.merger is not None else old.get("merger") or "",
332
+ "ad_hoc": args.ad_hoc if args.ad_hoc is not None else bool(old.get("ad_hoc"))}
333
+ for key, given in (("max_calls", args.max_calls), ("max_explorers", args.max_explorers)):
334
+ body[key] = old.get(key) if given is None else None if given == "default" else given
332
335
  reply = call("POST", "/api/collection", body)
333
336
  out(args, reply, lambda r: done(r, f"saved collection {name}: {', '.join(members)}"))
334
337
 
@@ -497,6 +500,8 @@ keeps only the answers. Then judge each seat you checked:
497
500
  bench collection save reviewers --members a,b,c --description "adversarial review" --tags review
498
501
  bench collection save reviewers --add d --remove a (the rest stays as it was)
499
502
  bench collection save reviewers --reply merged --merger a
503
+ bench collection save heavy --ad-hoc (runs only when called by name; --no-ad-hoc undoes it)
504
+ bench collection save heavy --max-calls 4 --max-explorers 0 (its own limits; "default" follows the gateway's)
500
505
  bench collection show reviewers
501
506
  bench collection rm reviewers --yes""",
502
507
  "endpoint": """examples:
@@ -629,6 +634,12 @@ def parser() -> argparse.ArgumentParser:
629
634
  c.add_argument("--tags", help="comma-separated")
630
635
  c.add_argument("--reply", choices=["all", "merged", "route"])
631
636
  c.add_argument("--merger", help="the alias that merges, for --reply merged")
637
+ c.add_argument("--ad-hoc", action=argparse.BooleanOptionalAction, default=None,
638
+ help="only when called by name: left off what callers choose from")
639
+ own_limit = lambda v: v if v == "default" else int(v) # noqa: E731
640
+ c.add_argument("--max-calls", type=own_limit, help="its own max calls per request, or default for the gateway's")
641
+ c.add_argument("--max-explorers", type=own_limit,
642
+ help="its own max explorers, or default for the gateway's; 0 means only the members ever run")
632
643
 
633
644
  cmd("endpoints", cmd_endpoints, "where models are served from")
634
645