@wendellresearch-ai/benchwarmers 0.2.0 → 0.2.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.
Files changed (96) hide show
  1. package/AGENTS.md +147 -147
  2. package/BENCHMARKS.md +262 -262
  3. package/GATEWAY.md +272 -272
  4. package/NOTICE +28 -28
  5. package/PRIVACY.md +46 -46
  6. package/README.md +368 -314
  7. package/SECURITY.md +83 -83
  8. package/TERMS.md +22 -22
  9. package/USAGE.md +170 -163
  10. package/VERSION +1 -1
  11. package/bin/benchwarmers.js +16 -74
  12. package/cli.py +666 -0
  13. package/examples/config/gateway.json +5 -5
  14. package/examples/config/model-roles.json +11 -11
  15. package/gateway.py +755 -755
  16. package/launcher.py +120 -0
  17. package/mcp_server.py +266 -266
  18. package/metrics/alerts.py +116 -116
  19. package/metrics/aliases.py +41 -41
  20. package/metrics/bench_collections.py +141 -141
  21. package/metrics/catalog.py +295 -295
  22. package/metrics/client.py +394 -394
  23. package/metrics/cliproxy.py +191 -191
  24. package/metrics/connect.py +691 -691
  25. package/metrics/cost.py +152 -152
  26. package/metrics/decide.py +227 -227
  27. package/metrics/discover.py +318 -318
  28. package/metrics/endpoints.py +436 -436
  29. package/metrics/guard.py +617 -592
  30. package/metrics/learn.py +221 -221
  31. package/metrics/litellm_hub.py +206 -206
  32. package/metrics/model_roles.py +84 -84
  33. package/metrics/offload.py +166 -166
  34. package/metrics/owui.py +205 -205
  35. package/metrics/paths.py +60 -60
  36. package/metrics/route.py +579 -579
  37. package/metrics/scheduler.py +275 -275
  38. package/metrics/sources.py +167 -167
  39. package/metrics/wrong.py +144 -144
  40. package/package.json +68 -65
  41. package/perf/README.md +89 -89
  42. package/perf/run.py +261 -261
  43. package/scripts/auto_retire.py +367 -367
  44. package/scripts/check.py +108 -106
  45. package/scripts/check_deprecations.py +378 -378
  46. package/scripts/check_themes.py +103 -103
  47. package/scripts/init.py +124 -124
  48. package/scripts/list_served.py +78 -78
  49. package/scripts/notice.py +78 -78
  50. package/scripts/onboard.py +401 -331
  51. package/scripts/provider_tags.py +129 -129
  52. package/scripts/reprefix.py +136 -136
  53. package/scripts/sync_config.py +105 -105
  54. package/scripts/test_auth.py +255 -255
  55. package/scripts/test_cli.py +189 -0
  56. package/scripts/test_client.py +233 -233
  57. package/scripts/test_connect.py +222 -222
  58. package/scripts/test_first_run.py +180 -180
  59. package/scripts/test_hubs.py +328 -328
  60. package/scripts/test_launcher.py +67 -0
  61. package/scripts/test_llm_log.py +85 -81
  62. package/scripts/test_mcp.py +178 -178
  63. package/scripts/test_merged.py +214 -214
  64. package/scripts/test_no_owui.py +291 -291
  65. package/scripts/test_owui.py +90 -90
  66. package/scripts/test_serve_edit.py +448 -438
  67. package/scripts/test_verdict.py +98 -98
  68. package/scripts/test_vision.py +228 -228
  69. package/serve.py +3904 -3764
  70. package/suite/mine.py +154 -154
  71. package/suite/pace.py +145 -145
  72. package/suite/run.py +1046 -1042
  73. package/suite/seed.py +421 -421
  74. package/suite/tasks/claim-alias-unbound/fixtures/onboard.py +286 -286
  75. package/suite/tasks/claim-error-text-string/fixtures/decide.py +187 -187
  76. package/suite/tasks/claim-list-body/fixtures/gateway.py +235 -235
  77. package/suite/tasks/claim-member-nominated-twice/fixtures/gateway.py +284 -284
  78. package/suite/tasks/claim-nominee-uses-slot/fixtures/gateway.py +284 -284
  79. package/suite/tasks/claim-silent-exit/fixtures/gateway.py +235 -235
  80. package/suite/tasks/claim-sse-hang/fixtures/gateway.py +235 -235
  81. package/suite/tasks/claim-unknown-nominee-crash/fixtures/gateway.py +284 -284
  82. package/suite/tasks/rebench-matchms-809-bug/task.json +23 -23
  83. package/suite/tasks/rebench-matchms-809-control/task.json +27 -27
  84. package/suite/tasks/rebench-more-itertools-1028-bug/task.json +23 -23
  85. package/suite/tasks/rebench-more-itertools-1028-control/task.json +27 -27
  86. package/suite/tasks/rebench-narwhals-2864-bug/task.json +23 -23
  87. package/suite/tasks/rebench-narwhals-2864-control/task.json +27 -27
  88. package/suite/tasks/rebench-quantecon-py-769-bug/task.json +23 -23
  89. package/suite/tasks/rebench-quantecon-py-769-control/task.json +27 -27
  90. package/suite/tasks/rebench-scrapy-6867-bug/task.json +23 -23
  91. package/suite/tasks/rebench-scrapy-6867-control/task.json +27 -27
  92. package/ui/bench.css +430 -425
  93. package/ui/bench.js +1756 -1576
  94. package/ui/themes/dark.css +35 -35
  95. package/ui/themes/hardwood.css +52 -52
  96. package/ui/themes/rainforest.css +32 -32
package/SECURITY.md CHANGED
@@ -1,83 +1,83 @@
1
- # Security
2
-
3
- ## Supported versions
4
-
5
- Fixes ship on `main` and in the next release. Use the latest of either.
6
-
7
- | Version | Supported |
8
- | --- | --- |
9
- | latest release, `main` | ✅ |
10
- | older releases | ❌ |
11
-
12
- ## Reporting a vulnerability
13
-
14
- Report it privately through
15
- [GitHub Security Advisories](https://github.com/WendellResearch-AI/benchwarmers/security/advisories/new).
16
- Please don't open a public issue for a vulnerability.
17
-
18
- Include what you can: the version or commit, how it is run (from source or
19
- Docker, bound to 127.0.0.1 or wider, with or without an admin token), steps to
20
- reproduce, and what an attacker gains.
21
-
22
- ## The model
23
-
24
- **On this machine by default.** The dashboard (`serve.py`, port 8122) and the
25
- gateway (on the same port at `/v1`, or alone with `gateway.py` on 8123) listen
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
29
- there is no login and the gateway asks for no key.
30
-
31
- **Anywhere else, only with a login.** To listen beyond this machine
32
- (`BENCH_BIND`, and `BENCH_PORT` / `BENCH_GATEWAY_PORT` for the ports), set
33
- `BENCHWARMERS_ADMIN_TOKEN` (16 or more characters) first; without it both
34
- servers refuse to start. With a token:
35
-
36
- - the dashboard asks for it once, then keeps an `HttpOnly; SameSite=Strict`
37
- session cookie for a week (changing the token signs everyone out);
38
- - the gateway's routes (`/v1/...`, `/bench/verdict`) take a **gateway key** as
39
- `Authorization: Bearer <key>`. Make named keys on Settings: each is shown
40
- once, kept only as a hash, revocable, and never opens the dashboard;
41
- - `BENCHWARMERS_PUBLIC_URL` (e.g. `https://bench.example.com`) is the address
42
- browsers use behind a proxy or on a LAN address; its host and origin are
43
- accepted, and the cookie is `Secure` when it is https;
44
- - every request is logged to stderr: route, status, and who (a key's name or
45
- admin), never a secret.
46
-
47
- `BENCHWARMERS_REQUIRE_KEYS=1` asks for gateway keys on this machine too, with
48
- the dashboard left open, so each local app has its own. A key can be limited
49
- to some collections and to a number of requests a minute, and its name is on
50
- every call it makes. A browser app on another origin is let in by
51
- `BENCH_ALLOWED_ORIGINS` (CORS on the gateway's routes only; never `*`).
52
-
53
- Settings, under Server and access, shows how all of this stands right now
54
- (whether a secret is set, never its value). It is changed only in the
55
- environment, then a restart: a page that could change its own login could
56
- open itself to anyone.
57
-
58
- ## What Benchwarmers touches
59
-
60
- - **Keys.** Endpoint keys come from `BENCHWARMERS_KEY_<NAME>` (the key name
61
- upper-cased, `-` as `_`) first, then from the `llm` CLI's key store. They are
62
- never written to the data folder, never shown back, and never put in a log.
63
- Sign-ins through a provider's page store their token the same way.
64
- - **The network.** Your prompts go only to the endpoints you add; the probes,
65
- the suite and onboarding spend calls there too. Otherwise: public catalog
66
- reads (models.dev, FreeLLMAPI, OpenRouter's model list), a provider's
67
- sign-in page when you choose one, Observable Plot from jsDelivr in the
68
- dashboard's page, and Hugging Face and GitHub only when you run
69
- `suite/rebench.py`. [PRIVACY.md](PRIVACY.md) lists them.
70
- - **Files.** It writes inside its data folder (`BENCHWARMERS_HOME`, or the
71
- folder `.benchwarmers-home` names) and, in the `llm` CLI's own folder, its
72
- key store (when you paste a key or sign in) and its model list (when it
73
- registers a model). Images sent to the gateway are never written to a log.
74
- - **Processes.** Onboarding, the probes and the suite run this repository's
75
- own scripts with the same Python. Model ids that reach a command line are
76
- checked against a strict pattern first.
77
-
78
- ## Endpoints you add
79
-
80
- An endpoint receives everything sent to the models on it, including any code
81
- or document in a prompt. Benchwarmers cannot vouch for a provider; the
82
- Endpoints page says the same. Some providers' free tiers keep prompts or train
83
- on them: check each one's terms before you send it private work.
1
+ # Security
2
+
3
+ ## Supported versions
4
+
5
+ Fixes ship on `main` and in the next release. Use the latest of either.
6
+
7
+ | Version | Supported |
8
+ | --- | --- |
9
+ | latest release, `main` | ✅ |
10
+ | older releases | ❌ |
11
+
12
+ ## Reporting a vulnerability
13
+
14
+ Report it privately through
15
+ [GitHub Security Advisories](https://github.com/WendellResearch-AI/benchwarmers/security/advisories/new).
16
+ Please don't open a public issue for a vulnerability.
17
+
18
+ Include what you can: the version or commit, how it is run (from source or
19
+ Docker, bound to 127.0.0.1 or wider, with or without an admin token), steps to
20
+ reproduce, and what an attacker gains.
21
+
22
+ ## The model
23
+
24
+ **On this machine by default.** The dashboard (`serve.py`, port 8122) and the
25
+ gateway (on the same port at `/v1`, or alone with `gateway.py` on 8123) listen
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
29
+ there is no login and the gateway asks for no key.
30
+
31
+ **Anywhere else, only with a login.** To listen beyond this machine
32
+ (`BENCH_BIND`, and `BENCH_PORT` / `BENCH_GATEWAY_PORT` for the ports), set
33
+ `BENCHWARMERS_ADMIN_TOKEN` (16 or more characters) first; without it both
34
+ servers refuse to start. With a token:
35
+
36
+ - the dashboard asks for it once, then keeps an `HttpOnly; SameSite=Strict`
37
+ session cookie for a week (changing the token signs everyone out);
38
+ - the gateway's routes (`/v1/...`, `/bench/verdict`) take a **gateway key** as
39
+ `Authorization: Bearer <key>`. Make named keys on Settings: each is shown
40
+ once, kept only as a hash, revocable, and never opens the dashboard;
41
+ - `BENCHWARMERS_PUBLIC_URL` (e.g. `https://bench.example.com`) is the address
42
+ browsers use behind a proxy or on a LAN address; its host and origin are
43
+ accepted, and the cookie is `Secure` when it is https;
44
+ - every request is logged to stderr: route, status, and who (a key's name or
45
+ admin), never a secret.
46
+
47
+ `BENCHWARMERS_REQUIRE_KEYS=1` asks for gateway keys on this machine too, with
48
+ the dashboard left open, so each local app has its own. A key can be limited
49
+ to some collections and to a number of requests a minute, and its name is on
50
+ every call it makes. A browser app on another origin is let in by
51
+ `BENCH_ALLOWED_ORIGINS` (CORS on the gateway's routes only; never `*`).
52
+
53
+ Settings, under Server and access, shows how all of this stands right now
54
+ (whether a secret is set, never its value). It is changed only in the
55
+ environment, then a restart: a page that could change its own login could
56
+ open itself to anyone.
57
+
58
+ ## What Benchwarmers touches
59
+
60
+ - **Keys.** Endpoint keys come from `BENCHWARMERS_KEY_<NAME>` (the key name
61
+ upper-cased, `-` as `_`) first, then from the `llm` CLI's key store. They are
62
+ never written to the data folder, never shown back, and never put in a log.
63
+ Sign-ins through a provider's page store their token the same way.
64
+ - **The network.** Your prompts go only to the endpoints you add; the probes,
65
+ the suite and onboarding spend calls there too. Otherwise: public catalog
66
+ reads (models.dev, FreeLLMAPI, OpenRouter's model list), a provider's
67
+ sign-in page when you choose one, Observable Plot from jsDelivr in the
68
+ dashboard's page, and Hugging Face and GitHub only when you run
69
+ `suite/rebench.py`. [PRIVACY.md](PRIVACY.md) lists them.
70
+ - **Files.** It writes inside its data folder (`BENCHWARMERS_HOME`, or the
71
+ folder `.benchwarmers-home` names) and, in the `llm` CLI's own folder, its
72
+ key store (when you paste a key or sign in) and its model list (when it
73
+ registers a model). Images sent to the gateway are never written to a log.
74
+ - **Processes.** Onboarding, the probes and the suite run this repository's
75
+ own scripts with the same Python. Model ids that reach a command line are
76
+ checked against a strict pattern first.
77
+
78
+ ## Endpoints you add
79
+
80
+ An endpoint receives everything sent to the models on it, including any code
81
+ or document in a prompt. Benchwarmers cannot vouch for a provider; the
82
+ Endpoints page says the same. Some providers' free tiers keep prompts or train
83
+ on them: check each one's terms before you send it private work.
package/TERMS.md CHANGED
@@ -1,22 +1,22 @@
1
- # Terms of use
2
-
3
- *Effective 22 October 2026.*
4
-
5
- Benchwarmers is free to use under its [license](LICENSE) (MIT). These terms
6
- add only the following.
7
-
8
- - **Provided as is.** It comes with no warranty of any kind. Its panels,
9
- scores and verdicts are evidence to weigh, not advice: models agree with each
10
- other and are still wrong, so check what they say before you act on it.
11
- - **Your responsibility.** You are responsible for the endpoints you add, for
12
- what you send to them, for the calls it makes on your keys, and for following
13
- each provider's terms, rate limits and usage policies.
14
- - **No liability.** To the extent the law allows, Wendell Research is not
15
- liable for any loss or damage arising from its use, including the cost of
16
- model calls.
17
- - **Not affiliated.** It isn't made or endorsed by any model provider,
18
- aggregator or hub it works with. Names belong to their owners.
19
- - **Changes.** These terms may change; the current version is always this
20
- file, with its history in the repository's commits.
21
-
22
- Questions: [open an issue](https://github.com/WendellResearch-AI/benchwarmers/issues).
1
+ # Terms of use
2
+
3
+ *Effective 22 October 2026.*
4
+
5
+ Benchwarmers is free to use under its [license](LICENSE) (MIT). These terms
6
+ add only the following.
7
+
8
+ - **Provided as is.** It comes with no warranty of any kind. Its panels,
9
+ scores and verdicts are evidence to weigh, not advice: models agree with each
10
+ other and are still wrong, so check what they say before you act on it.
11
+ - **Your responsibility.** You are responsible for the endpoints you add, for
12
+ what you send to them, for the calls it makes on your keys, and for following
13
+ each provider's terms, rate limits and usage policies.
14
+ - **No liability.** To the extent the law allows, Wendell Research is not
15
+ liable for any loss or damage arising from its use, including the cost of
16
+ model calls.
17
+ - **Not affiliated.** It isn't made or endorsed by any model provider,
18
+ aggregator or hub it works with. Names belong to their owners.
19
+ - **Changes.** These terms may change; the current version is always this
20
+ file, with its history in the repository's commits.
21
+
22
+ Questions: [open an issue](https://github.com/WendellResearch-AI/benchwarmers/issues).
package/USAGE.md CHANGED
@@ -1,163 +1,170 @@
1
- # Using Benchwarmers
2
-
3
- Day-to-day use, once it runs: the dashboard's pages, onboarding models,
4
- collections, connecting your apps and recording verdicts. Setting it up is in
5
- the README's [Try it](README.md#try-it) (or [AGENTS.md](AGENTS.md), for a
6
- coding agent doing it with you); the gateway's whole contract is in
7
- [GATEWAY.md](GATEWAY.md).
8
-
9
- ## Contents
10
-
11
- - [The dashboard](#the-dashboard)
12
- - [Onboarding models](#onboarding-models)
13
- - [Collections](#collections)
14
- - [Connecting an app](#connecting-an-app)
15
- - [Recording verdicts](#recording-verdicts)
16
- - [Discover: finding models to add](#discover-finding-models-to-add)
17
- - [The scheduler](#the-scheduler)
18
- - [Your data folder](#your-data-folder)
19
-
20
- ## The dashboard
21
-
22
- `python serve.py`, then http://localhost:8122. The sidebar groups its pages:
23
-
24
- | Group | Page | What it is for |
25
- | --- | --- | --- |
26
- | 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. |
27
- | | **Benchmarks** | How models do on the suite and on real work: bugs found against false alarms, who is confidently wrong, and speed. |
28
- | | **Quota management** | What limits each connection, and which models are resting after hitting one. |
29
- | | **Logs** | Gateway calls (who sat and how it went, never the prompt), changes made from the dashboard, the scheduler, and onboarding runs. |
30
- | 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. |
31
- | | **Models** | Every model on the bench, by the connection it comes from. |
32
- | | **Collections** | The named panels your apps ask for, and the gateway's settings. |
33
- | | **Discover** | Models worth adding, from public catalogs, with the ways this install can reach each one. |
34
- | Control | **Settings** | Theme, gateway keys, the scheduler, the model client, providers whose free models work only in their own app, and how the install is reached (shown only). |
35
- | | **Info** | Version, Python, data folder and counts. |
36
-
37
- "Action needed", above the pages, lists what will not fix itself, such as a
38
- model about to be retired, with Retry, Open and Retire now beside it. Hide
39
- folds it away until something new turns up.
40
-
41
- ## Onboarding models
42
-
43
- **Onboard a model**, top right, lists everything your endpoints serve that is
44
- not on the bench yet. Search, and tick one or several: the ticks survive a new
45
- search, so you can gather models from different connections in one go.
46
- Dismiss hides one you never want offered (an image model, say); the dismissed
47
- list brings it back.
48
-
49
- Each model is registered, probed with four short calls, and, if it answers,
50
- run through the suite. That takes minutes and spends calls, so they run **one
51
- at a time**, in a queue the dashboard keeps:
52
-
53
- - One model with nothing ahead of it is followed step by step in the popup.
54
- - Otherwise the popup shows the queue, and a chip beside the button shows the
55
- progress ("Onboarding 2 of 5: ..."), filling as models finish. It turns green
56
- when every model is on the bench, and red when one failed or did not answer.
57
- - Closing the popup or reloading the page stops nothing. **Details** reopens
58
- the queue: each model's state, its alias, why it stopped, and its log.
59
- - **Stop** lets the model running now finish and skips the rest. **Clear**
60
- forgets a finished batch's results; the logs stay in `runs/`.
61
-
62
- A model that registered but did not answer stays on the bench as
63
- unavailable, so the daily probe keeps watching it.
64
-
65
- ## Collections
66
-
67
- A collection is a named panel: the models it always includes, the shape of
68
- work it is for (review, design, enumeration, ...), and how its reply comes
69
- back. On the **Collections** page, **New collection**, then pick the members.
70
- Each call also seats explorers, the models unused longest, up to the gateway's
71
- limits (Gateway settings, on the same page: how many calls a request may make,
72
- and how many of them explore).
73
-
74
- ## Connecting an app
75
-
76
- Any OpenAI-compatible client works. Point it at the dashboard's port and ask
77
- for the model `bench/<collection>`:
78
-
79
- | Setting | Value |
80
- | --- | --- |
81
- | Base URL | `http://127.0.0.1:8122/v1` (or `gateway.py` alone: `http://127.0.0.1:8123/v1`) |
82
- | API key | any text on this machine; a **gateway key** from Settings when keys are required |
83
- | Model | `bench/<collection>`, or `bench/<collection>:merged` for one merged answer |
84
-
85
- With the OpenAI Python SDK:
86
-
87
- ```python
88
- from openai import OpenAI
89
-
90
- bench = OpenAI(base_url="http://127.0.0.1:8122/v1", api_key="local")
91
- reply = bench.chat.completions.create(
92
- model="bench/<collection>",
93
- messages=[{"role": "user", "content": "Where can this function return a stale value? ..."}],
94
- )
95
- print(reply.choices[0].message.content) # every seat's answer, labelled
96
- ```
97
-
98
- In a chat app such as Open WebUI, add the base URL as an OpenAI connection;
99
- the collections appear as models. For a chat window, the `:merged` form reads
100
- best: a merger model writes one answer saying where the seats agreed and
101
- disagreed, and every seat is still in the reply's `bench` field.
102
-
103
- Images go in as OpenAI `image_url` parts; only models that take images sit,
104
- and the rest are listed in `bench.skipped`. [GATEWAY.md](GATEWAY.md) has the
105
- limits and the reply's full shape.
106
-
107
- **A coding agent** connects over MCP instead: the Claude Code plugin
108
- (`/plugin marketplace add WendellResearch-AI/benchwarmers`, then
109
- `/plugin install benchwarmers@benchwarmers`), or `benchwarmers mcp` in any MCP
110
- client, with `BENCHWARMERS_URL` and, where keys are required, a gateway key in
111
- `BENCHWARMERS_KEY`. Its `ask` tool returns every seat with its call id and its
112
- `verdict` tool records the verdicts; README, "From Claude Code and other
113
- agents", has the set-up.
114
-
115
- ## Recording verdicts
116
-
117
- A panel's answers are worth something only once someone has checked them
118
- against the real work. Every seat has a call id; record a verdict per call on
119
- the Collections page (the Gateway card lists recent requests: click a seat),
120
- or:
121
-
122
- curl http://127.0.0.1:8122/bench/verdict -H "Content-Type: application/json" \
123
- -d '{"call": "<call id>", "useful": true, "note": "found the real bug", "real": ["..."], "false": ["..."]}'
124
-
125
- `real` and `false` list the specific claims you verified either way. False
126
- claims feed **Confidently wrong** on Benchmarks, and verdicts together decide
127
- who sits on the next panel. Agreement between models is not evidence: they
128
- are often wrong together.
129
-
130
- ## Discover: finding models to add
131
-
132
- **Discover** merges models.dev and FreeLLMAPI into one list, free models
133
- first, with what is new this week badged. A row opens its popup: what the
134
- model takes and does, its price, and every route this install has to it, each
135
- with an **Add via this**. Adding through a hub (Open WebUI, LiteLLM, CLI Proxy
136
- API) puts it in that hub too; adding direct registers it on its own endpoint
137
- only. Either way the onboarding joins the same queue.
138
-
139
- Some providers' free models work only inside their own app; Discover leaves
140
- those out and keeps their paid models. Settings, **Free only in their own
141
- app**, switches a provider either way or adds one.
142
-
143
- ## The scheduler
144
-
145
- The recurring jobs (the morning availability probe, the catalog refresh, the
146
- deprecation check and auto-retire, suite passes, the weekly speed and
147
- capability tests) run inside the dashboard. Settings, **Scheduler**:
148
-
149
- - **Off**: nothing runs; a fresh install spends no calls until you opt in.
150
- - **Log only**: writes "would run" to `runs/scheduler.log` at each due time,
151
- to check the times before anything spends calls.
152
- - **Run**: runs each job at its time, one at a time per job.
153
-
154
- If something else already runs these jobs (cron, Windows Task Scheduler),
155
- turn it off in the same step, or every job runs twice.
156
-
157
- ## Your data folder
158
-
159
- Everything that is yours (endpoints, registrations, collections, verdicts,
160
- call logs, probe history, task answers) lives in the data folder: the one
161
- `BENCHWARMERS_HOME` names, else the one in `.benchwarmers-home` at the top of
162
- the checkout. Back it up by copying it; move it by copying it and pointing one
163
- of those two at the new place. Info shows which folder is in use.
1
+ # Using Benchwarmers
2
+
3
+ Day-to-day use, once it runs: the dashboard's pages, onboarding models,
4
+ collections, connecting your apps and recording verdicts. Setting it up is in
5
+ the README's [Try it](README.md#try-it) (or [AGENTS.md](AGENTS.md), for a
6
+ coding agent doing it with you); the gateway's whole contract is in
7
+ [GATEWAY.md](GATEWAY.md).
8
+
9
+ ## Contents
10
+
11
+ - [The dashboard](#the-dashboard)
12
+ - [Onboarding models](#onboarding-models)
13
+ - [Collections](#collections)
14
+ - [Connecting an app](#connecting-an-app)
15
+ - [Recording verdicts](#recording-verdicts)
16
+ - [Discover: finding models to add](#discover-finding-models-to-add)
17
+ - [The scheduler](#the-scheduler)
18
+ - [Your data folder](#your-data-folder)
19
+
20
+ ## The dashboard
21
+
22
+ `python serve.py`, then http://localhost:8122. The sidebar groups its pages:
23
+
24
+ | Group | Page | What it is for |
25
+ | --- | --- | --- |
26
+ | 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. |
27
+ | | **Benchmarks** | How models do on the suite and on real work: bugs found against false alarms, who is confidently wrong, and speed. |
28
+ | | **Quota management** | What limits each connection, and which models are resting after hitting one. |
29
+ | | **Logs** | Gateway calls (who sat and how it went, never the prompt), changes made from the dashboard, the scheduler, and onboarding runs. |
30
+ | 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. |
31
+ | | **Models** | Every model on the bench, by the connection it comes from. |
32
+ | | **Collections** | The named panels your apps ask for, and the gateway's settings. |
33
+ | | **Discover** | Models worth adding, from public catalogs, with the ways this install can reach each one. |
34
+ | Control | **Settings** | Theme, gateway keys, the scheduler, the model client, providers whose free models work only in their own app, and how the install is reached (shown only). |
35
+ | | **Info** | Version, Python, data folder and counts. |
36
+
37
+ "Action needed", above the pages, lists what will not fix itself, such as a
38
+ model about to be retired, with Retry, Open and Retire now beside it. Hide
39
+ folds it away until something new turns up.
40
+
41
+ ## Onboarding models
42
+
43
+ **Onboard a model**, top right, lists everything your endpoints serve that is
44
+ not on the bench yet. Search, and tick one or several: the ticks survive a new
45
+ search, so you can gather models from different connections in one go.
46
+ Dismiss hides one you never want offered (an image model, say); the dismissed
47
+ list brings it back.
48
+
49
+ Each model is registered, probed with four short calls, and, if it answers,
50
+ run through the suite. That takes minutes and spends calls, so they run **one
51
+ at a time**, in a queue the dashboard keeps:
52
+
53
+ - One model with nothing ahead of it is followed step by step in the popup.
54
+ - Otherwise the popup shows the queue, and a chip beside the button shows the
55
+ progress ("Onboarding 2 of 5: ..."), filling as models finish. It turns green
56
+ when every model is on the bench, and red when one failed or did not answer.
57
+ - Closing the popup or reloading the page stops nothing. **Details** reopens
58
+ the queue: each model's state, its alias, why it stopped, and its log.
59
+ - **Stop** lets the model running now finish and skips the rest. **Clear**
60
+ forgets a finished batch's results; the logs stay in `runs/`.
61
+
62
+ A model that registered but did not answer stays on the bench as
63
+ unavailable, so the daily probe keeps watching it.
64
+
65
+ ## Collections
66
+
67
+ A collection is a named panel: the models it always includes, the shape of
68
+ work it is for (review, design, enumeration, ...), and how its reply comes
69
+ back. On the **Collections** page, **New collection**, then pick the members.
70
+ Each call also seats explorers, the models unused longest, up to the gateway's
71
+ limits (Gateway settings, on the same page: how many calls a request may make,
72
+ and how many of them explore).
73
+
74
+ ## Connecting an app
75
+
76
+ Any OpenAI-compatible client works. Point it at the dashboard's port and ask
77
+ for the model `bench/<collection>`:
78
+
79
+ | Setting | Value |
80
+ | --- | --- |
81
+ | Base URL | `http://127.0.0.1:8122/v1` (or `gateway.py` alone: `http://127.0.0.1:8123/v1`) |
82
+ | API key | any text on this machine; a **gateway key** from Settings when keys are required |
83
+ | Model | `bench/<collection>`, or `bench/<collection>:merged` for one merged answer |
84
+
85
+ With the OpenAI Python SDK:
86
+
87
+ ```python
88
+ from openai import OpenAI
89
+
90
+ bench = OpenAI(base_url="http://127.0.0.1:8122/v1", api_key="local")
91
+ reply = bench.chat.completions.create(
92
+ model="bench/<collection>",
93
+ messages=[{"role": "user", "content": "Where can this function return a stale value? ..."}],
94
+ )
95
+ print(reply.choices[0].message.content) # every seat's answer, labelled
96
+ ```
97
+
98
+ In a chat app such as Open WebUI, add the base URL as an OpenAI connection;
99
+ the collections appear as models. For a chat window, the `:merged` form reads
100
+ best: a merger model writes one answer saying where the seats agreed and
101
+ disagreed, and every seat is still in the reply's `bench` field.
102
+
103
+ Images go in as OpenAI `image_url` parts; only models that take images sit,
104
+ and the rest are listed in `bench.skipped`. [GATEWAY.md](GATEWAY.md) has the
105
+ limits and the reply's full shape.
106
+
107
+ **A coding agent** connects over MCP instead: the Claude Code plugin
108
+ (`/plugin marketplace add WendellResearch-AI/benchwarmers`, then
109
+ `/plugin install benchwarmers@benchwarmers`), or `benchwarmers mcp` in any MCP
110
+ client, with `BENCHWARMERS_URL` and, where keys are required, a gateway key in
111
+ `BENCHWARMERS_KEY`. Its `ask` tool returns every seat with its call id and its
112
+ `verdict` tool records the verdicts; README, "From Claude Code and other
113
+ agents", has the set-up.
114
+
115
+ **From a terminal or a script**, `bench ask <collection> "..."` (a pipe or
116
+ `-f FILE` adds the text to review) prints every seat's answer and a table of
117
+ call ids, and `bench verdict <call id> --useful|--not-useful` judges one. The
118
+ rest of this guide's pages have commands too (`bench models`, `bench onboard`,
119
+ `bench collection save`, `bench endpoint add`, `bench key create`, `bench
120
+ settings`); README, "From the command line", lists them.
121
+
122
+ ## Recording verdicts
123
+
124
+ A panel's answers are worth something only once someone has checked them
125
+ against the real work. Every seat has a call id; record a verdict per call on
126
+ the Collections page (the Gateway card lists recent requests: click a seat),
127
+ or:
128
+
129
+ curl http://127.0.0.1:8122/bench/verdict -H "Content-Type: application/json" \
130
+ -d '{"call": "<call id>", "useful": true, "note": "found the real bug", "real": ["..."], "false": ["..."]}'
131
+
132
+ `real` and `false` list the specific claims you verified either way. False
133
+ claims feed **Confidently wrong** on Benchmarks, and verdicts together decide
134
+ who sits on the next panel. Agreement between models is not evidence: they
135
+ are often wrong together.
136
+
137
+ ## Discover: finding models to add
138
+
139
+ **Discover** merges models.dev and FreeLLMAPI into one list, free models
140
+ first, with what is new this week badged. A row opens its popup: what the
141
+ model takes and does, its price, and every route this install has to it, each
142
+ with an **Add via this**. Adding through a hub (Open WebUI, LiteLLM, CLI Proxy
143
+ API) puts it in that hub too; adding direct registers it on its own endpoint
144
+ only. Either way the onboarding joins the same queue.
145
+
146
+ Some providers' free models work only inside their own app; Discover leaves
147
+ those out and keeps their paid models. Settings, **Free only in their own
148
+ app**, switches a provider either way or adds one.
149
+
150
+ ## The scheduler
151
+
152
+ The recurring jobs (the morning availability probe, the catalog refresh, the
153
+ deprecation check and auto-retire, suite passes, the weekly speed and
154
+ capability tests) run inside the dashboard. Settings, **Scheduler**:
155
+
156
+ - **Off**: nothing runs; a fresh install spends no calls until you opt in.
157
+ - **Log only**: writes "would run" to `runs/scheduler.log` at each due time,
158
+ to check the times before anything spends calls.
159
+ - **Run**: runs each job at its time, one at a time per job.
160
+
161
+ If something else already runs these jobs (cron, Windows Task Scheduler),
162
+ turn it off in the same step, or every job runs twice.
163
+
164
+ ## Your data folder
165
+
166
+ Everything that is yours (endpoints, registrations, collections, verdicts,
167
+ call logs, probe history, task answers) lives in the data folder: the one
168
+ `BENCHWARMERS_HOME` names, else the one in `.benchwarmers-home` at the top of
169
+ the checkout. Back it up by copying it; move it by copying it and pointing one
170
+ of those two at the new place. Info shows which folder is in use.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1