modelrig 0.9.0 → 0.11.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.
Files changed (231) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/README.md +51 -27
  3. package/data/PROVENANCE.md +14 -0
  4. package/data/pricing-map.json +26 -0
  5. package/dist/adapters/attempt-meta-map.d.ts +8 -1
  6. package/dist/adapters/attempt-meta-map.d.ts.map +1 -1
  7. package/dist/adapters/attempt-meta-map.js +4 -0
  8. package/dist/adapters/build-adapters.js +2 -2
  9. package/dist/adapters/gemini.d.ts +28 -1
  10. package/dist/adapters/gemini.d.ts.map +1 -1
  11. package/dist/adapters/gemini.js +38 -9
  12. package/dist/adapters/grok.d.ts.map +1 -1
  13. package/dist/adapters/grok.js +53 -4
  14. package/dist/adapters/openai-compat.d.ts +8 -2
  15. package/dist/adapters/openai-compat.d.ts.map +1 -1
  16. package/dist/adapters/openai-compat.js +8 -1
  17. package/dist/adapters/openai-stream.d.ts +10 -2
  18. package/dist/adapters/openai-stream.d.ts.map +1 -1
  19. package/dist/adapters/openai-stream.js +5 -1
  20. package/dist/adapters/openai.d.ts +10 -1
  21. package/dist/adapters/openai.d.ts.map +1 -1
  22. package/dist/adapters/openai.js +57 -7
  23. package/dist/adapters/responses-api.d.ts +61 -0
  24. package/dist/adapters/responses-api.d.ts.map +1 -0
  25. package/dist/adapters/responses-api.js +124 -0
  26. package/dist/artifacts/artifact.d.ts +20 -0
  27. package/dist/artifacts/artifact.d.ts.map +1 -1
  28. package/dist/artifacts/artifact.js +207 -171
  29. package/dist/artifacts/index.d.ts +3 -1
  30. package/dist/artifacts/index.d.ts.map +1 -1
  31. package/dist/artifacts/index.js +8 -1
  32. package/dist/bakeoff/groundedness.d.ts +58 -0
  33. package/dist/bakeoff/groundedness.d.ts.map +1 -0
  34. package/dist/bakeoff/groundedness.js +165 -0
  35. package/dist/bakeoff/quality.d.ts +14 -1
  36. package/dist/bakeoff/quality.d.ts.map +1 -1
  37. package/dist/bakeoff/quality.js +10 -0
  38. package/dist/bakeoff/replay.d.ts.map +1 -1
  39. package/dist/bakeoff/replay.js +4 -0
  40. package/dist/cli.d.ts.map +1 -1
  41. package/dist/cli.js +8 -0
  42. package/dist/config.d.ts +31 -0
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +23 -0
  45. package/dist/doctor-cli.d.ts +7 -0
  46. package/dist/doctor-cli.d.ts.map +1 -0
  47. package/dist/doctor-cli.js +68 -0
  48. package/dist/doctor-preflight.d.ts +64 -0
  49. package/dist/doctor-preflight.d.ts.map +1 -0
  50. package/dist/doctor-preflight.js +167 -0
  51. package/dist/feedback/coverage.d.ts.map +1 -1
  52. package/dist/feedback/coverage.js +9 -2
  53. package/dist/feedback/grade.d.ts +8 -1
  54. package/dist/feedback/grade.d.ts.map +1 -1
  55. package/dist/feedback/grade.js +4 -0
  56. package/dist/gateway/http-protocol.d.ts +19 -0
  57. package/dist/gateway/http-protocol.d.ts.map +1 -1
  58. package/dist/gateway/serve-client.d.ts +99 -0
  59. package/dist/gateway/serve-client.d.ts.map +1 -0
  60. package/dist/gateway/serve-client.js +360 -0
  61. package/dist/index.d.ts +31 -3
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +71 -8
  64. package/dist/prompts/manifest.d.ts +128 -0
  65. package/dist/prompts/manifest.d.ts.map +1 -0
  66. package/dist/prompts/manifest.js +214 -0
  67. package/dist/prompts/prompt-fetch.d.ts +84 -0
  68. package/dist/prompts/prompt-fetch.d.ts.map +1 -0
  69. package/dist/prompts/prompt-fetch.js +120 -0
  70. package/dist/prompts/prompt-resolve.d.ts +76 -0
  71. package/dist/prompts/prompt-resolve.d.ts.map +1 -0
  72. package/dist/prompts/prompt-resolve.js +93 -0
  73. package/dist/prompts/slot-resolver.d.ts +91 -0
  74. package/dist/prompts/slot-resolver.d.ts.map +1 -0
  75. package/dist/prompts/slot-resolver.js +135 -0
  76. package/dist/prompts/tools-register.d.ts +60 -0
  77. package/dist/prompts/tools-register.d.ts.map +1 -0
  78. package/dist/prompts/tools-register.js +48 -0
  79. package/dist/prompts/version-hash.d.ts +29 -0
  80. package/dist/prompts/version-hash.d.ts.map +1 -0
  81. package/dist/prompts/version-hash.js +54 -0
  82. package/dist/prompts-export-cli.d.ts +21 -0
  83. package/dist/prompts-export-cli.d.ts.map +1 -0
  84. package/dist/prompts-export-cli.js +130 -0
  85. package/dist/registry/cache-policy.d.ts.map +1 -1
  86. package/dist/registry/cache-policy.js +22 -0
  87. package/dist/registry/pricing-shape.d.ts +38 -8
  88. package/dist/registry/pricing-shape.d.ts.map +1 -1
  89. package/dist/registry/pricing-shape.js +40 -12
  90. package/dist/registry/pricing.d.ts +6 -5
  91. package/dist/registry/pricing.d.ts.map +1 -1
  92. package/dist/registry/pricing.js +9 -5
  93. package/dist/routes/destination-loader.d.ts +16 -0
  94. package/dist/routes/destination-loader.d.ts.map +1 -0
  95. package/dist/routes/destination-loader.js +29 -0
  96. package/dist/routes/draft.d.ts +7 -0
  97. package/dist/routes/draft.d.ts.map +1 -1
  98. package/dist/routes/draft.js +12 -0
  99. package/dist/routes/loader.d.ts.map +1 -1
  100. package/dist/routes/loader.js +27 -54
  101. package/dist/routes/output-loader.d.ts +42 -0
  102. package/dist/routes/output-loader.d.ts.map +1 -0
  103. package/dist/routes/output-loader.js +112 -0
  104. package/dist/routes/prompt-loader.d.ts +49 -0
  105. package/dist/routes/prompt-loader.d.ts.map +1 -0
  106. package/dist/routes/prompt-loader.js +113 -0
  107. package/dist/routes/resolved-bundle.d.ts +19 -0
  108. package/dist/routes/resolved-bundle.d.ts.map +1 -1
  109. package/dist/routes/resolved-bundle.js +24 -0
  110. package/dist/routes/screen-loader.d.ts +1 -1
  111. package/dist/routes/screen-loader.d.ts.map +1 -1
  112. package/dist/routes/screen-loader.js +8 -1
  113. package/dist/run/accept.d.ts +3 -0
  114. package/dist/run/accept.d.ts.map +1 -1
  115. package/dist/run/accept.js +1 -0
  116. package/dist/run/cost.d.ts +31 -2
  117. package/dist/run/cost.d.ts.map +1 -1
  118. package/dist/run/cost.js +57 -2
  119. package/dist/run/destination.d.ts +39 -0
  120. package/dist/run/destination.d.ts.map +1 -0
  121. package/dist/run/destination.js +45 -0
  122. package/dist/run/dispatch.d.ts +25 -3
  123. package/dist/run/dispatch.d.ts.map +1 -1
  124. package/dist/run/dispatch.js +26 -4
  125. package/dist/run/raw-defaults.d.ts.map +1 -1
  126. package/dist/run/raw-defaults.js +6 -1
  127. package/dist/run/raw-finalize.d.ts +96 -0
  128. package/dist/run/raw-finalize.d.ts.map +1 -0
  129. package/dist/run/raw-finalize.js +283 -0
  130. package/dist/run/raw-knobs.d.ts +36 -0
  131. package/dist/run/raw-knobs.d.ts.map +1 -0
  132. package/dist/run/raw-knobs.js +99 -0
  133. package/dist/run/raw-request.d.ts +24 -0
  134. package/dist/run/raw-request.d.ts.map +1 -0
  135. package/dist/run/raw-request.js +69 -0
  136. package/dist/run/raw-schema.d.ts +76 -0
  137. package/dist/run/raw-schema.d.ts.map +1 -0
  138. package/dist/run/raw-schema.js +166 -0
  139. package/dist/run/raw-search-cost.d.ts +49 -0
  140. package/dist/run/raw-search-cost.d.ts.map +1 -0
  141. package/dist/run/raw-search-cost.js +79 -0
  142. package/dist/run/raw-support.d.ts +64 -6
  143. package/dist/run/raw-support.d.ts.map +1 -1
  144. package/dist/run/raw-support.js +84 -11
  145. package/dist/run/raw.d.ts +25 -26
  146. package/dist/run/raw.d.ts.map +1 -1
  147. package/dist/run/raw.js +30 -351
  148. package/dist/run/record-attempt.d.ts +8 -0
  149. package/dist/run/record-attempt.d.ts.map +1 -1
  150. package/dist/run/record-attempt.js +26 -12
  151. package/dist/run/record-call.d.ts +104 -0
  152. package/dist/run/record-call.d.ts.map +1 -0
  153. package/dist/run/record-call.js +277 -0
  154. package/dist/run/repair-attempt.d.ts +68 -0
  155. package/dist/run/repair-attempt.d.ts.map +1 -0
  156. package/dist/run/repair-attempt.js +180 -0
  157. package/dist/run/resolve-destination.d.ts +49 -0
  158. package/dist/run/resolve-destination.d.ts.map +1 -0
  159. package/dist/run/resolve-destination.js +76 -0
  160. package/dist/run/routing-docs.d.ts.map +1 -1
  161. package/dist/run/routing-docs.js +9 -4
  162. package/dist/run/run.d.ts +30 -1
  163. package/dist/run/run.d.ts.map +1 -1
  164. package/dist/run/run.js +75 -148
  165. package/dist/run/telemetry-row.d.ts +92 -0
  166. package/dist/run/telemetry-row.d.ts.map +1 -0
  167. package/dist/run/telemetry-row.js +81 -0
  168. package/dist/run/validate.d.ts +12 -1
  169. package/dist/run/validate.d.ts.map +1 -1
  170. package/dist/run/validate.js +31 -0
  171. package/dist/run/web-search-pricing.d.ts +43 -0
  172. package/dist/run/web-search-pricing.d.ts.map +1 -0
  173. package/dist/run/web-search-pricing.js +56 -0
  174. package/dist/settings/grading-guide.d.ts +27 -1
  175. package/dist/settings/grading-guide.d.ts.map +1 -1
  176. package/dist/status.d.ts +6 -0
  177. package/dist/status.d.ts.map +1 -1
  178. package/dist/status.js +4 -1
  179. package/dist/telemetry/artifact-store.d.ts.map +1 -1
  180. package/dist/telemetry/artifact-store.js +11 -0
  181. package/dist/telemetry/attempt-meta.d.ts +66 -1
  182. package/dist/telemetry/attempt-meta.d.ts.map +1 -1
  183. package/dist/telemetry/attempt-meta.js +27 -1
  184. package/dist/telemetry/exporter-setup.d.ts +2 -0
  185. package/dist/telemetry/exporter-setup.d.ts.map +1 -1
  186. package/dist/telemetry/exporter-setup.js +6 -1
  187. package/dist/telemetry/grade-mappers.d.ts +5 -2
  188. package/dist/telemetry/grade-mappers.d.ts.map +1 -1
  189. package/dist/telemetry/grade-mappers.js +8 -2
  190. package/dist/telemetry/grades-sql.d.ts +4 -1
  191. package/dist/telemetry/grades-sql.d.ts.map +1 -1
  192. package/dist/telemetry/grades-sql.js +26 -3
  193. package/dist/telemetry/ingest-protocol.d.ts +26 -2
  194. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  195. package/dist/telemetry/ingest-protocol.js +32 -29
  196. package/dist/telemetry/lanes.d.ts +31 -0
  197. package/dist/telemetry/lanes.d.ts.map +1 -0
  198. package/dist/telemetry/lanes.js +41 -0
  199. package/dist/telemetry/org-identity.d.ts +47 -0
  200. package/dist/telemetry/org-identity.d.ts.map +1 -0
  201. package/dist/telemetry/org-identity.js +100 -0
  202. package/dist/telemetry/route-registration.d.ts +48 -0
  203. package/dist/telemetry/route-registration.d.ts.map +1 -0
  204. package/dist/telemetry/route-registration.js +77 -0
  205. package/dist/telemetry/sinks.d.ts +10 -1
  206. package/dist/telemetry/sinks.d.ts.map +1 -1
  207. package/dist/telemetry/sinks.js +52 -6
  208. package/dist/telemetry/store-migrations.d.ts.map +1 -1
  209. package/dist/telemetry/store-migrations.js +13 -0
  210. package/dist/tenancy/api-key-format.d.ts +16 -1
  211. package/dist/tenancy/api-key-format.d.ts.map +1 -1
  212. package/dist/tenancy/api-key-format.js +17 -0
  213. package/dist/types/provider.d.ts +20 -3
  214. package/dist/types/provider.d.ts.map +1 -1
  215. package/dist/types/provider.js +1 -0
  216. package/dist/types/route.d.ts +76 -0
  217. package/dist/types/route.d.ts.map +1 -1
  218. package/dist/types/telemetry.d.ts +30 -2
  219. package/dist/types/telemetry.d.ts.map +1 -1
  220. package/docs/agent-skill/SKILL.md +75 -5
  221. package/docs/instrumentation.md +98 -36
  222. package/docs/llms.txt +96 -16
  223. package/docs/managed-serving.md +150 -0
  224. package/docs/mcp-oracle.md +75 -2
  225. package/docs/migration-playbook.md +5 -4
  226. package/docs/quickstart.md +169 -83
  227. package/package.json +3 -2
  228. package/registry/registry.json +82 -0
  229. package/dist/feedback/feedback.d.ts +0 -35
  230. package/dist/feedback/feedback.d.ts.map +0 -1
  231. package/dist/feedback/feedback.js +0 -39
@@ -58,7 +58,7 @@ on purpose.
58
58
  | Tool | Does | Never does |
59
59
  |---|---|---|
60
60
  | `get_proposals` | Lists open proposals for your routes — each carries an `evidence.change_spec` (the machine-readable diff + `apply_instructions` a coding agent applies) plus its evidence and savings. | Change anything. |
61
- | `create_route` | Writes a **draft** route bundle — YAML, schema, prompt — into your drafts directory, candidates seeded from the registry, your current model first. | Edit your source, register a route, overwrite an existing draft. |
61
+ | `create_route` | Writes a **draft** route bundle — YAML, schema, prompt — into your drafts directory, candidates seeded from the registry, your current model first. `output_kind: text` drafts a prose route (`output: text`, no schema); `user_prompt` adds a `prompt.user` per-call user turn. | Edit your source, register a route, overwrite an existing draft. |
62
62
  | `test_route` | Makes **one** real billed call through a route, under a fresh budget envelope (default $1). | Run unbounded. |
63
63
  | `run_bakeoff` | Replays captured inputs through challenger variants, each arm under its own envelope (default $2). | Switch what serves your route. |
64
64
  | `run_optimizer` | Runs **one** explicit optimizer cycle for a route — reflect, score candidates on your golden eval cases, file a proposal carrying a `change_spec`. Pass `{ estimate: true }` first for the cost preview. Needs the `oracle-act` scope. | Apply anything; run on a schedule (there is none). |
@@ -66,7 +66,7 @@ on purpose.
66
66
  | `execute_swap` | Records an approved swap and **returns** the route-YAML diff to apply via a PR. Needs the `decision` scope. | Write any file; commit to your repo. |
67
67
  | `record_grade` | Attaches a 0–1 grade (with an optional comment) to one inference or a whole run — the signal the next cycle learns from. Needs the `grade` scope on the HTTP path. | Spend a billed call; guess attribution for an unknown subject. |
68
68
  | `get_task_settings` / `set_task_settings` | Reads / writes a task's governance settings and its **grading guide** (the rubric the task's grader is taught from). `set` needs the `task-settings` scope. | Change route config (the pass threshold lives in the route, and is refused here). |
69
- | `get_call_config` | Reads a route's **current live** call-config — its version, mode, and the model(s) it serves. Read-only. | Change anything. |
69
+ | `get_call_config` | Reads a route's **current live** call-config — its version, mode, the model(s) it serves, the `effective` model + why (pin / YAML default), and any `drift`. Read-only. | Change anything. |
70
70
  | `set_call_config` | **Sets what serves a route right now** — pins a model or starts a live A/B — on the human's behalf. A real, versioned control-plane change. | Bypass the eligibility gate or the `route-config` scope; imply it is a draft. |
71
71
  | `rollback_call_config` | Restores a prior call-config version (re-appended as a new version — history is never deleted). | Delete history; escape the scope check. |
72
72
 
@@ -84,6 +84,55 @@ This is the half of the pivot where the agent sets routes *for the human*.
84
84
  call-config tools deliberately **do**: they change what serves live traffic right
85
85
  now, on the human's behalf, and say so unmistakably.
86
86
 
87
+ ### Point a scoped key at the control plane (once)
88
+
89
+ The four read tools work with no account. The call-config tools do **not**: a
90
+ read needs a valid `rig_sk_` key, and a **write** (`set_call_config` /
91
+ `rollback_call_config`) needs that key to carry the **`route-config`** scope. Give
92
+ the MCP server both the key and the host so the tools can reach `/v1`:
93
+
94
+ ```jsonc
95
+ {
96
+ "mcpServers": {
97
+ "modelrig": {
98
+ "command": "npx",
99
+ "args": ["modelrig-oracle"],
100
+ "env": {
101
+ // A rig_sk_ key minted at app.modelrig.ai (/keys). To FLIP a route it
102
+ // must carry the `route-config` scope; a read-only key still reads.
103
+ "MODELRIG_API_KEY": "rig_sk_…",
104
+ // The control plane the oracle's tools call. Omit to use the hosted
105
+ // default (https://api.modelrig.ai). The oracle reads MODELRIG_INGEST_URL
106
+ // ONLY — MODELRIG_SERVER_URL is an app-side var and is NOT honored here.
107
+ "MODELRIG_INGEST_URL": "https://api.modelrig.ai"
108
+ }
109
+ }
110
+ }
111
+ }
112
+ ```
113
+
114
+ A key without `route-config` authenticates fine and reads, then a write returns a
115
+ teaching **403** naming the missing scope — mint or rotate a key with it, or set
116
+ the config in the console.
117
+
118
+ ### The flip, end to end
119
+
120
+ 1. **Read the current config.** `get_call_config(route)` → the live `version`,
121
+ `mode`, and model(s) serving the route this instant. `version: 0` means no
122
+ override (the route resolves to its deployed bundle default).
123
+ 2. **Set the new model.** `set_call_config({ route, mode: "pin", provider, model })`
124
+ (shape below). The response names the new **version** and a rollback hint.
125
+ 3. **It takes effect at serve time — no redeploy.** The SDK reads the route's
126
+ config **just-before-call**, merges the pin over the deployed bundle, and
127
+ serves it. It is **fail-open**: on any control-plane error the last-known-good
128
+ (else the deployed bundle) serves, and a route with **no override resolves
129
+ byte-identical** to today. The change lands on the route's *next* request once
130
+ the resolver's short cache refreshes (TTL ~30–60s). (Serving requires the app
131
+ to overlay call-config on the route — see
132
+ [Change your route's model live](quickstart.md#change-your-routes-model-live-no-redeploy).)
133
+ 4. **Undo when you want.** `rollback_call_config({ route, toVersion })` re-appends a
134
+ prior version as a new one (history is never deleted).
135
+
87
136
  | Tool | Endpoint | Scope |
88
137
  |---|---|---|
89
138
  | `get_call_config` | `GET /v1/routes/:route/call-config` | any org-scoped key — a read needs none special |
@@ -96,6 +145,30 @@ Version `0` means there is no override yet — the route resolves to its deploye
96
145
  (mirrored) bundle default. History (audit + rollback targets) is at
97
146
  `GET /v1/routes/:route/call-config/history`.
98
147
 
148
+ **It also answers "what will this route serve, and why?"** (RV-1). The tool reads
149
+ `GET /v1/routes/:route/call-config?include=effective` and returns:
150
+
151
+ - `effective` — `{ source, provider, model, version, since }`, where `source` is
152
+ `pin` (a call-config pin serves; `version` = the call-config version),
153
+ `experiment` (a live A/B — no single model), `deployed_default` (no override; the
154
+ app's YAML default = the registered route's first candidate; `version` = the YAML
155
+ route version), or `unknown` (no deployment has registered the route in your org).
156
+ `serving` phrases it in one line.
157
+ - `drift` — non-null only when a pin is set but recent calls on the route (last 24h,
158
+ from 5 minutes after the pin, ≤500 sampled) served a **different** model:
159
+ `{ servedProvider, servedModel, calls, lastSeen, pinnedCalls, windowStart }`, plus a
160
+ `drift_warning` sentence. It means the app's resolver is failing open — check its SDK
161
+ version, its `MODELRIG_API_KEY`, and that the call path resolves call-config at
162
+ serve time. Setting the pin again will not fix drift; the app has to honor it.
163
+
164
+ Routes appear here before their first call: a rig created with routes and a
165
+ control-plane key registers them on startup — metadata plus the declared bundle
166
+ (prompt template, schema, policy), `ingest` scope only. That registered bundle is
167
+ what `set_call_config` checks a pin against, so **pins work for api-mode apps once
168
+ their routes register**; before that, a pin is refused with a teaching 422 ("no
169
+ servable bundle in your organization") — start the app (with an SDK that has
170
+ RV-1) and retry.
171
+
99
172
  **Pin a model:**
100
173
 
101
174
  ```jsonc
@@ -213,8 +213,9 @@ regression). Silent is the only forbidden outcome.
213
213
  `dimensions[].key` in `rig.yaml` (tag-safe `[A-Za-z0-9_]{1,64}`) so the
214
214
  console can attribute cost by it. A `required: true` dimension missing from a
215
215
  run's tags **warns once per process** (and under-attributes that run) — it
216
- is never rejected. An example that shows `tags: { run_id }` assumes a
217
- `run_id` dimension exists.
216
+ is never rejected. Don't put `run_id` in your tags: inside a run the SDK stamps
217
+ it (it is reserved — see the
218
+ [reserved tag keys](instrumentation.md#reserved-tag-keys-the-one-list)).
218
219
  - **`result.output` is already parsed and schema-validated** — delete the old
219
220
  call site's `JSON.parse` and fence-stripping rather than keeping both.
220
221
  - **Routes resolve from `./modelrig/routes` relative to the process CWD.** In a
@@ -391,7 +392,7 @@ through `rig.runRaw` without a `run.start` around it records inferences but no
391
392
  run — `/runs` stays empty and `/projects` shows "(no run)". Open the run context
392
393
  around each pipeline execution (`rig.artifacts.run.start({ pipeline, episodeKey })`
393
394
  … `run.end()`); inside it the SDK names the step and stamps the `run_id` tag —
394
- and the `step` tag too (a value you pass always wins) — you tag `subject` /
395
+ and the `step` tag too (`run_id` is reserved: never set it yourself) — you tag `subject` /
395
396
  `feature` yourself. Do not declare a
396
397
  migration done until one real execution shows a run with steps on `/runs`.
397
398
 
@@ -434,7 +435,7 @@ Because this is behaviour-affecting, the agent **proposes, never applies**:
434
435
  keeps the diff inside the customer's codebase legible — a product surface.
435
436
  5. **A human merges.** The skill's autonomy ends at a green report and an open PR.
436
437
 
437
- ### Replaced-call disposition (RULED, Matt 2026-08-16): DELETE the original, never comment it out
438
+ ### Replaced-call disposition: DELETE the original, never comment it out
438
439
 
439
440
  Rollback is git-native and the skill makes it explicit:
440
441
 
@@ -1,5 +1,7 @@
1
1
  # ModelRig quickstart — see, prove, and save on every model call
2
2
 
3
+ **The question this page answers: how do I get from nothing to my first run on `/runs`, with its steps and artifacts, in about ten minutes?**
4
+
3
5
  ModelRig is the operating layer for your AI workstream. Each LLM task becomes a
4
6
  **versioned route file** (prompt template + JSON schema + candidate models +
5
7
  policy) that you call with one line — `rig.run("task.name", {input, tags})` —
@@ -15,22 +17,33 @@ and three things happen at once:
15
17
  - **Save** — a winning candidate is a change to your YAML you review; nothing
16
18
  swaps a model on its own, and your routes are always YAML in your git.
17
19
 
18
- The rest of this page is Step 0 (two minutes, once), then the two ways to
19
- instrument your project — point your coding agent at it, or do it by hand.
20
+ The path is the same whoever does the work: **mint a key → install → confirm the
21
+ org → define a route → wrap one pipeline execution in a run → see it on `/runs`.**
22
+ Step 0 is yours (two minutes, once); after that, point your coding agent at this
23
+ page or follow the steps by hand. Already have LLM calls you only want to *watch*
24
+ first? [Choosing a lane](https://modelrig.dev/choosing-a-lane.html) shows the observe path, which skips
25
+ the route.
20
26
 
21
27
  ## Step 0 — create your org and key (two minutes, human-only)
22
28
 
23
29
  Account setup stays human: your coding agent never creates accounts, signs in,
24
- or holds credentials. Once, up front:
30
+ or holds credentials. Once, up front, sign up and create your organization at
31
+ [app.modelrig.ai](https://app.modelrig.ai) (email and an org name is the whole
32
+ form). Then:
33
+
34
+ <!-- BLOCK:KEY -->
35
+ **Mint a key in the org you want the data in.** Sign in at https://app.modelrig.ai, check the organization name in the header badge, and create a key on the API keys page. The `rig_sk_` secret is shown once. One key = one org: every row the key exports lands in the organization it was minted in, whichever organization you happen to be viewing in the console. Set it on every service, worker and cron that creates a rig; your provider keys stay where they are.
25
36
 
26
- 1. Sign up and create your organization at
27
- [app.modelrig.ai](https://app.modelrig.ai) — email and an org name is the
28
- whole form.
29
- 2. Issue an API key in the console (the `rig_sk_…` value is shown once — copy it).
30
- 3. Export it beside your provider keys: `MODELRIG_API_KEY=rig_sk_…`.
37
+ ```bash
38
+ # Wherever your app reads configuration: .env.local, your platform's env vars, a secret manager. Never in code.
39
+ MODELRIG_API_KEY=rig_sk_…
40
+ ```
41
+ <!-- /BLOCK:KEY -->
31
42
 
32
43
  That key is the only ModelRig credential your app ever holds — never a database
33
- URL, never a service-role key. Provider keys never leave your process.
44
+ URL, never a service-role key. Provider keys never leave your process. Which org
45
+ a key belongs to, and how the console chooses the org it shows you, is
46
+ [Orgs and keys](https://modelrig.dev/orgs-and-keys.html).
34
47
 
35
48
  **No account needed for the open lane:** with only your provider keys set,
36
49
  routes, probes and telemetry run entirely on your machine — the hosted console
@@ -51,33 +64,18 @@ Same flat 2% margin either way; your negotiated provider discounts stay yours.
51
64
 
52
65
  ## Point your coding agent at it
53
66
 
54
- The fastest migration is the one your agent performs. From inside your project,
55
- paste this into Claude Code, Codex, or Cursor:
67
+ The fastest migration is the one your agent performs. Paste the migration prompt
68
+ from [modelrig.ai/get-started](https://modelrig.ai/get-started) (the console's
69
+ `/setup` page carries the same prompt) into Claude Code, Codex, or Cursor from
70
+ inside your project. It is the maintained version: it starts the agent at the
71
+ bottom of the [autonomy ladder](migration-playbook.md), has it confirm the org
72
+ your key exports to, wrap each pipeline execution in a run, and stop for your
73
+ approval at every checkpoint.
56
74
 
57
- ```
58
- Migrate this project to ModelRig routes (https://modelrig.dev).
59
-
60
- 0. If MODELRIG_API_KEY is not set and I want hosted telemetry, STOP and ask me
61
- to create an org and issue a rig_sk_ key at https://app.modelrig.ai. Never
62
- create accounts, sign in, or handle credentials yourself. Without the key,
63
- proceed in local-only mode — that is fully supported.
64
- 1. Read https://modelrig.dev/quickstart.html and
65
- https://modelrig.dev/route-bundles.html.
66
- 2. Find every place this codebase calls an LLM API directly.
67
- 3. For each call site, define a route bundle YAML (schema, candidate models,
68
- policy, prompt template) and replace the direct call with
69
- rig.run("<route.name>"). Keep prompt and schema semantics unchanged.
70
- 4. Before naming any model capability, check the probed registry — declared
71
- flags and probed behavior differ; trust the probed layer.
72
- 5. Run the project's existing tests and report every file you changed.
73
- ```
74
-
75
- Your agent reads the docs, finds your LLM call sites, and turns them into
76
- routes. It **won't** create accounts, sign in, or touch your API keys (those
77
- stay in the environment you set in Step 0), and it swaps call sites to
78
- `rig.run()` without changing prompt or schema semantics — same model, human-
79
- reviewed. The full autonomy ladder and same-model guarantees are in the
80
- [migration playbook](migration-playbook.md).
75
+ Your agent reads the docs, finds your LLM call sites, and wires them in. It
76
+ **won't** create accounts, sign in, or touch your API keys (those stay in the
77
+ environment you set in Step 0), and when it replaces a call site with `rig.run()`
78
+ it keeps prompt and schema semantics unchanged — same model, human-reviewed.
81
79
 
82
80
  ## Or set it up by hand
83
81
 
@@ -87,14 +85,15 @@ reviewed. The full autonomy ladder and same-model guarantees are in the
87
85
  pnpm add modelrig # or npm i modelrig — Node >= 20
88
86
  ```
89
87
 
90
- It installs a native module (`better-sqlite3`) — prebuilt for macOS/Linux on
91
- x64/arm64; an unusual platform compiles it and needs a C++ toolchain.
88
+ It installs a native module (`better-sqlite3`) from a prebuilt binary on
89
+ macOS and Linux (x64/arm64); any other platform compiles it at install time and
90
+ needs a C++ toolchain.
92
91
 
93
- **Deploying:** `modelrig` installs prebuilt (no separate build step), but it
94
- needs a **Node** runtime (not Edge/Workers), and if your deploy bundles server
95
- code you must mark it external — Next.js `serverExternalPackages: ['modelrig']`,
96
- esbuild `--external:better-sqlite3`, webpack `externals`. Set `MODELRIG_API_KEY`
97
- on every service, worker, and cron that runs a rig.
92
+ **Deploying:** `modelrig` needs a **Node** runtime (not Edge/Workers), and if
93
+ your deploy bundles server code you must mark it external — Next.js
94
+ `serverExternalPackages: ['modelrig']`, esbuild `--external:better-sqlite3`,
95
+ webpack `externals`. Set `MODELRIG_API_KEY` on every service, worker, and cron
96
+ that runs a rig; hosted-platform specifics are in [Deploying](https://modelrig.dev/deploying.html).
98
97
 
99
98
  ```ts
100
99
  import { createRig, loadConfigFromEnv } from "modelrig";
@@ -117,12 +116,21 @@ MODELRIG_TELEMETRY_DB=./.modelrig/telemetry.db # default
117
116
  MODELRIG_ENVELOPE_BUDGET_USD=25 # default envelope budget
118
117
  ```
119
118
 
120
- Provider keys never leave your process on either lane. A `rig_sk_` key is issued
121
- in the console at [app.modelrig.ai](https://app.modelrig.ai) and is the only
122
- ModelRig credential your app ever holds — never a database URL, never a
123
- service-role key.
119
+ ### 2. Confirm the org
124
120
 
125
- ### 2. Define a route bundle
121
+ <!-- BLOCK:CONFIRM_ORG -->
122
+ **Confirm the org before you trust an empty console.** Run `modelrig doctor` from the same environment your app runs in. It asks GET /v1/whoami which organization the key belongs to, and the name it prints must match the org badge in the console header. If it names a different organization, your data is landing there: switch the console to that organization, or mint a key in the one you meant (https://modelrig.dev/orgs-and-keys.html).
123
+
124
+ ```bash
125
+ npx modelrig doctor
126
+ # [modelrig] key rig_sk_…AbCd → org «Your Org» ✓ (ingest https://api.modelrig.ai, …)
127
+
128
+ # No CLI in that environment? Ask the API directly:
129
+ curl -H "Authorization: Bearer $MODELRIG_API_KEY" https://api.modelrig.ai/v1/whoami
130
+ ```
131
+ <!-- /BLOCK:CONFIRM_ORG -->
132
+
133
+ ### 3. Define a route bundle
126
134
 
127
135
  One YAML file per route under `modelrig/routes/`:
128
136
 
@@ -175,15 +183,15 @@ types allowed, and `format` is annotation-only — it is not asserted (an
175
183
  `email`/`date-time` format is documentation, not a constraint). Author 2020-12
176
184
  unless you have a draft-07 schema already; both work.
177
185
 
178
- ### 3. Call it
186
+ ### 4. Call it
179
187
 
180
188
  ```ts
181
189
  const rig = createRig(loadConfigFromEnv());
182
190
 
183
191
  const result = await rig.run("example.support_summarize", {
184
192
  input: { ticket: rawTicket, product: "Acme Cloud", priorContext: history },
185
- tags: { run_id: "run-123", step: "summarize", customer: "acme" },
186
- budget: { envelope: "run-123" }, // hard-stop cost envelope for the run
193
+ tags: { subject: "acme", feature: "summarize" },
194
+ budget: { envelope: "ticket-123" }, // hard-stop cost envelope for the run
187
195
  });
188
196
 
189
197
  result.output; // JSON, already validated against your schema
@@ -195,51 +203,70 @@ result.meta.attemptsByClass; // retries consumed, per failure class
195
203
  rig.close();
196
204
  ```
197
205
 
198
- ### 4. Wrap it in a run — the standard path
206
+ ### 5. Wrap it in a run — the standard path
199
207
 
200
208
  **Every pipeline execution is a run.** A run is the standard way ModelRig records
201
- what your workstream did — not an appendix. Wrap the execution in a run context,
202
- name one **step** per model-call family, and **save the work products** as
203
- artifacts; then the console's **Runs** tab shows the run → step → artifact chain
204
- you can click through, and `/projects` groups it by tag.
209
+ what your workstream did — not an appendix. The console's **Runs** tab then shows
210
+ the run → step → artifact chain you can click through, and `/projects` groups it
211
+ by tag.
212
+
213
+ <!-- BLOCK:RUN_WRAP -->
214
+ **Wrap one pipeline execution in a run.** Every pipeline execution is a run. Wrap each execution in `run.scope` (or `run.start` / `run.end`), name one step per model call with `stepKey`, `artifact.save` the work products, and pass `environment` so the Env column on /runs is filled. Inside the run the SDK stamps `run_id` and `step` on every call. `run_id` is reserved: don't set it yourself.
205
215
 
206
216
  ```ts
217
+ import { createRig, loadConfigFromEnv } from "modelrig";
218
+
207
219
  const rig = createRig(loadConfigFromEnv());
208
220
 
209
- // One run per pipeline execution. run.scope isolates concurrent runs; use
210
- // run.start()/run.end() for one run at a time on a request path.
221
+ // Every pipeline execution is a run. Inside the scope the SDK records each
222
+ // rig.run / rig.runRaw call as a step and stamps run_id and step on every row.
223
+ // run_id is reserved: don't set it yourself (put your own attempt id in a tag of
224
+ // your own, such as pipeline_attempt_id).
211
225
  await rig.artifacts.run.scope(
212
- { pipeline: "support", episodeKey: ticketId },
226
+ { pipeline: "support", episodeKey: ticketId, environment: process.env.NODE_ENV ?? "development" },
213
227
  async () => {
214
228
  const result = await rig.run("example.support_summarize", {
215
229
  input: { ticket, product, priorContext },
216
- tags: { subject: customer, feature: "summarize" }, // run_id auto-stamped
217
- stepKey: "summarize", // names this step on /runs
230
+ tags: { subject: customer, feature: "summarize" },
231
+ stepKey: "summarize", // names this step on /runs
218
232
  });
219
- // Save the work product — prompt/raw/parsed all save the same way.
220
- rig.artifacts.artifact.save(result.output, { name: "summary", type: "step_output" });
233
+ rig.artifacts.artifact.save(result.output, { name: "summary", type: "step_output", stepKey: "summarize" });
221
234
  },
222
235
  );
223
- rig.close();
236
+
237
+ await rig.close(); // flushes the exporter — call once at shutdown
224
238
  ```
239
+ <!-- /BLOCK:RUN_WRAP -->
225
240
 
226
- - **Tags:** carry `subject` (what the run is *about*) and `feature`. You no longer
227
- hand-write `run_id` — **inside a run context the SDK stamps `tags.run_id`** (the
228
- run's `episodeKey`, else its id) on every attempt row of both lanes; a value you
229
- pass always wins, and outside a run context nothing is stamped. It also stamps
230
- `tags.step` (the current step key) the same way; a value you pass always wins,
231
- so name the step yourself with `stepKey` (or `tags.step`) when you want a
232
- specific label.
233
241
  - **Raw lane:** a `rig.runRaw` call inside a run context records a ground-truth
234
242
  step too (since 0.5.0), so grounded/cached pipelines fill the same graph.
235
- - **See it:** open `/runs` — the run, its steps, its artifacts. `modelrig status`
236
- prints `runs recorded: N (last: …)` as the local mirror, and `modelrig validate`
237
- warns if a rig records calls but never starts a run.
238
-
239
- The full artifact API — lineage (`link`), evaluations (`evaluate`), the reusable
240
- per-step seam, and `run.scope` vs `run.start` — is the
241
- [instrumentation guide](instrumentation.md); this section is the standard path
242
- that links to it.
243
+ - **Reserved tags:** `run_id` and `step` are stamped by the SDK; the full list of
244
+ reserved keys is in the
245
+ [instrumentation guide](instrumentation.md#reserved-tag-keys-the-one-list).
246
+
247
+ The full artifact API — lineage (`link`), grades, the reusable per-step seam, and
248
+ `run.scope` vs `run.start` — is the [instrumentation guide](instrumentation.md).
249
+
250
+ ### 6. See it on /runs
251
+
252
+ Open `/runs` in the console, with the org badge showing the org `doctor` named:
253
+ the run, its steps in order, and the artifacts you saved. `modelrig status`
254
+ prints `runs recorded: N (last: …)` as the local mirror, and `modelrig validate`
255
+ warns if a rig records calls but never starts a run. If the page is empty:
256
+
257
+ <!-- BLOCK:EMPTY_CONSOLE -->
258
+ **The console is empty: five checks, in order.** If /runs (or /inferences) is empty for the org in the header badge, work these checks in order. The full tree is https://modelrig.dev/troubleshooting.html.
259
+
260
+ ```text
261
+ 1. npx modelrig doctor, from the environment your app runs in.
262
+ no export sink configured → this process does not see MODELRIG_API_KEY: set it, redeploy, open a new shell.
263
+ AUTH FAILED (401 / 403) → the key is mistyped, revoked or not accepted: mint a key, set it, redeploy, open a new shell.
264
+ 2. The org doctor prints is not the org in the badge → wrong org: switch the console, or mint a key in the org you meant.
265
+ 3. /inferences has rows but /runs is empty → the calls are not inside run.scope / run.start.
266
+ 4. A run is missing a step or a cost → that call is not on a ModelRig lane (see not-captured).
267
+ 5. A doc describes something your install lacks → compare `npm ls modelrig` with the version stamp in modelrig.dev/llms.txt.
268
+ ```
269
+ <!-- /BLOCK:EMPTY_CONSOLE -->
243
270
 
244
271
  ## Change your route's model live (no redeploy)
245
272
 
@@ -253,6 +280,52 @@ merges it over your bundle. Two modes:
253
280
  - **`experiment`** — a weighted live A/B across arms, with the chosen arm recorded on
254
281
  every row so the console can score it.
255
282
 
283
+ **See what a route serves — before its first call.** Your YAML stays the deploy-time
284
+ default and the fail-open safety net; ModelRig is where you *see* and *change* it. A rig
285
+ created with a `routesDir` **and** a control-plane key registers each route the moment
286
+ `createRig()` runs — its metadata (route, version, candidates) **and its declared bundle**
287
+ (the prompt *template* with its `{{placeholders}}`, schema, policy, plus a content hash):
288
+ fire-and-forget, fail-open, through the same `/v1/ingest` call telemetry uses (the
289
+ `ingest` scope is enough). The bundle is stored as **route configuration**, not captured
290
+ content — it holds the authored template, never per-call values — so it is stored even when
291
+ your org's capture posture is `off` (telemetry rows are still dropped then). Registering
292
+ the bundle is what lets the control plane **validate and accept a pin** for the route: a
293
+ pin is checked against the route's `require` before it is written, so a route with no
294
+ registered bundle refuses pins with a teaching 422. If you promote a prompt version in
295
+ ModelRig (Prompt System of Record), the promoted template wins over the one in your YAML
296
+ on every later registration; everything else (candidates, schema, policy) follows your
297
+ deploy. So every route shows up in the console and over MCP right away, and one read
298
+ answers *"what will this route serve, and why?"*:
299
+
300
+ ```bash
301
+ curl -H "authorization: Bearer $MODELRIG_API_KEY" \
302
+ "${MODELRIG_INGEST_URL:-https://api.modelrig.ai}/v1/routes/example.support_summarize/call-config?include=effective"
303
+ ```
304
+
305
+ ```jsonc
306
+ {
307
+ "version": 0, "mode": null, "config": null, // no override yet
308
+ "effective": {
309
+ "source": "deployed_default", // pin | experiment | deployed_default | unknown
310
+ "provider": "openai", "model": "gpt-5.4-mini", // your YAML's first candidate
311
+ "version": 1, // the YAML route version
312
+ "since": "2026-10-10T12:00:00Z" // when the deployment last declared it
313
+ },
314
+ "drift": null
315
+ }
316
+ ```
317
+
318
+ `source: "pin"` means a call-config pin is serving (its `version` is the call-config
319
+ version); `unknown` means no deployment has registered the route in your org yet. When a
320
+ pin is set but recent calls on the route served a **different** model, `drift` says so —
321
+ `{ servedProvider, servedModel, calls, lastSeen, pinnedCalls, windowStart }` (last 24h,
322
+ starting 5 minutes after the pin, ≤500 calls sampled). Drift means your app is not
323
+ honoring the pin: its resolver is failing open (an older SDK, a wrong `MODELRIG_API_KEY`,
324
+ or a call path that never resolves call-config — see below). The console's call-config
325
+ card shows the same thing as **Serving: \<model\> — \<pin vN | YAML default\>** plus a
326
+ drift warning; `get_call_config` over MCP returns it too. Without `?include=effective`
327
+ the response is unchanged (that is what the SDK's serve-time poll reads).
328
+
256
329
  **Read call-config just-before-call.** Build a resolver once (it caches with a short TTL
257
330
  and revalidates by ETag — no per-call network cost when fresh), then overlay the current
258
331
  config onto a bundle and serve it through `rig.runBundle()`:
@@ -381,14 +454,26 @@ from the SDK or over HTTP for a non-SDK surface (see the
381
454
  `run-outcome@v1` grade, with an explicit, bounded model judge available when
382
455
  you want one (see the [grade protocol](grade-protocol.md#native-run-grades)).
383
456
 
457
+ ## Serve without holding the provider key (optional)
458
+
459
+ Everything above runs on **your** provider key — `destination: direct`, the
460
+ default, and nothing here changes it. If you would rather ModelRig serve a
461
+ route's model on its own credentials and bill it from a prepaid balance, declare
462
+ `destination: modelrig-served` on the route, set `managedServing: true` in the
463
+ rig config, mint a key with the `serve` scope, and turn managed serving on in
464
+ Account settings. The walk-through, including what each refusal teaches, is
465
+ [Managed serving](managed-serving.md).
466
+
384
467
  ## Runtime requirements
385
468
 
386
469
  ModelRig assumes a **long-lived Node process with a writable disk**, and a few
387
470
  things follow from that. Check them before you deploy:
388
471
 
389
- - **Node ≥ 20**, and a native build toolchain at install time — it compiles
390
- `better-sqlite3` (a C/C++ addon) for the local telemetry buffer. On a slim
391
- container add the build essentials (`python3`, `make`, a C++ compiler).
472
+ - **Node ≥ 20.** The local telemetry buffer is `better-sqlite3` (a C/C++
473
+ addon): it installs from a prebuilt binary on macOS and Linux (x64/arm64), and
474
+ compiles at install time anywhere else — on such a platform, or a slim
475
+ container without the prebuilt, add the build essentials (`python3`, `make`, a
476
+ C++ compiler).
392
477
  - **A writable disk.** Telemetry and captures go to a local SQLite file
393
478
  (`MODELRIG_TELEMETRY_DB`, default `./.modelrig/telemetry.db`); the background
394
479
  exporter batches from it. A read-only filesystem breaks this.
@@ -417,8 +502,9 @@ loader's own words, is in [route-bundles.md](./route-bundles.md#when-it-doesnt-w
417
502
  - **The bundle won't load, naming an undeclared variable.** A `{{name}}` in the
418
503
  template isn't in `prompt.variables`. Add it (or fix the typo).
419
504
  - **The first call succeeds locally but nothing appears in the console.**
420
- `MODELRIG_API_KEY` isn't set in that environment. Everything runs without it;
421
- it only decides where telemetry lands.
505
+ Usually `MODELRIG_API_KEY` isn't set in that environment, or it belongs to a
506
+ different org than the one the console is showing. Run `npx modelrig doctor`
507
+ there and work through [Troubleshooting an empty console](https://modelrig.dev/troubleshooting.html).
422
508
  - **The call runs but the output isn't what the old code produced.** Usually a
423
509
  wrong `json: native` — a claim about the model, valid only for one whose
424
510
  registry entry shows probed `structured_native`. Check the probed registry,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modelrig",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
5
  "description": "ModelRig — capability-aware AI gateway: routes-as-code, provider adapters, typed failures, budget envelopes, and local-first telemetry.",
6
6
  "license": "Apache-2.0",
@@ -52,6 +52,7 @@
52
52
  "docs/how-it-fits.md",
53
53
  "docs/migration-playbook.md",
54
54
  "docs/mcp-oracle.md",
55
+ "docs/managed-serving.md",
55
56
  "docs/agent-skill/SKILL.md",
56
57
  "docs/llms.txt",
57
58
  "templates/ticket-triage.json",
@@ -75,7 +76,7 @@
75
76
  "@google/genai": "^2.4.0",
76
77
  "ajv": "^8.17.0",
77
78
  "better-sqlite3": "^11.10.0",
78
- "openai": "^4.77.0",
79
+ "openai": "^7.13.0",
79
80
  "yaml": "^2.6.0"
80
81
  },
81
82
  "devDependencies": {
@@ -7296,6 +7296,88 @@
7296
7296
  "NOT flex-eligible (mini/nano, Pro, and older families) — flex requests are silently served at default tier"
7297
7297
  ],
7298
7298
  "facts": null
7299
+ },
7300
+ {
7301
+ "model_key": "zai/glm-5p2",
7302
+ "declared": {
7303
+ "as_of": "2026-09-08T00:00:00.000Z",
7304
+ "source": "z.ai-price-list(2026-09-08)+adapter-static",
7305
+ "pricing": {
7306
+ "input_usd_per_mtok": 1.4,
7307
+ "output_usd_per_mtok": 4.4,
7308
+ "cached_input_usd_per_mtok": null
7309
+ },
7310
+ "pricing_v2": {
7311
+ "base": {
7312
+ "input": 0.0000014,
7313
+ "output": 0.0000044,
7314
+ "cache_read": null
7315
+ },
7316
+ "tiers": null,
7317
+ "context_bands": null,
7318
+ "batch_discount": null,
7319
+ "modality": null,
7320
+ "source": "z.ai-website",
7321
+ "as_of": "2026-09-08T00:00:00.000Z",
7322
+ "basis": "base · standard tier · text"
7323
+ },
7324
+ "flags": {
7325
+ "supports_response_schema": true,
7326
+ "supports_web_search": true,
7327
+ "supports_prompt_caching": null,
7328
+ "adapter_structured_native": null,
7329
+ "adapter_grounded_native": false,
7330
+ "supports_image_input": false
7331
+ }
7332
+ },
7333
+ "probed": null,
7334
+ "observed": null,
7335
+ "discrepancies": [],
7336
+ "callNotes": [
7337
+ "B4a: reachable via the OpenAI-compat adapter on the Z.ai international endpoint (https://api.z.ai/api/paas/v4) keyed by ZAI_API_KEY; model id passes through verbatim (no wire prefix). Native GLM web_search (supports_web_search declared) is NOT wired on the ModelRig adapter until B4b — adapter_grounded_native is pinned false (so the derived grounded_native capability matches the fail-closed raw-lane grounding knob; B4b flips it true and wires the tool)."
7338
+ ],
7339
+ "facts": null
7340
+ },
7341
+ {
7342
+ "model_key": "zai/glm-5p2-flash",
7343
+ "declared": {
7344
+ "as_of": "2026-09-08T00:00:00.000Z",
7345
+ "source": "z.ai-price-list(2026-09-08)+adapter-static",
7346
+ "pricing": {
7347
+ "input_usd_per_mtok": 0.08,
7348
+ "output_usd_per_mtok": 0.25,
7349
+ "cached_input_usd_per_mtok": null
7350
+ },
7351
+ "pricing_v2": {
7352
+ "base": {
7353
+ "input": 0.00000008,
7354
+ "output": 0.00000025,
7355
+ "cache_read": null
7356
+ },
7357
+ "tiers": null,
7358
+ "context_bands": null,
7359
+ "batch_discount": null,
7360
+ "modality": null,
7361
+ "source": "z.ai-website",
7362
+ "as_of": "2026-09-08T00:00:00.000Z",
7363
+ "basis": "base · standard tier · text"
7364
+ },
7365
+ "flags": {
7366
+ "supports_response_schema": true,
7367
+ "supports_web_search": true,
7368
+ "supports_prompt_caching": null,
7369
+ "adapter_structured_native": null,
7370
+ "adapter_grounded_native": false,
7371
+ "supports_image_input": false
7372
+ }
7373
+ },
7374
+ "probed": null,
7375
+ "observed": null,
7376
+ "discrepancies": [],
7377
+ "callNotes": [
7378
+ "B4a: budget GLM sibling reached via the OpenAI-compat adapter on the Z.ai international endpoint keyed by ZAI_API_KEY; model id passes through verbatim. Native web_search is B4b (adapter_grounded_native pinned false so the derived grounded_native capability matches the fail-closed raw-lane grounding knob)."
7379
+ ],
7380
+ "facts": null
7299
7381
  }
7300
7382
  ]
7301
7383
  }
@@ -1,35 +0,0 @@
1
- /**
2
- * rig.feedback() — Phase 4 WS2 (spec: judgment starts accumulating).
3
- * The SDK surface normalizes a target (inference id or {episode}) + opts
4
- * into a FeedbackRow; the write is a synchronous local SQLite insert
5
- * (fire-and-forget from the caller's view — no network, never throws for
6
- * sink reasons). The Supabase mirror rides the exporter, dual-store style.
7
- */
8
- import type { FeedbackRow } from "../types/telemetry";
9
- export type FeedbackTarget = string | {
10
- readonly episode: string;
11
- };
12
- export interface FeedbackOpts {
13
- readonly verdict: "up" | "down";
14
- /** Optional graded signal in [0, 1]; verdict remains the primary axis. */
15
- readonly score?: number;
16
- readonly note?: string;
17
- /** Who judged: "sdk" (default), a review-agent name, "human", … */
18
- readonly source?: string;
19
- /**
20
- * The org this verdict belongs to (Phase 6 WS2). Omit from application code
21
- * — a rig has one org and the exporter knows it.
22
- *
23
- * Supplied by modelrig-server, and only ever with an org it has ALREADY
24
- * authorized the caller into: a value that arrived in a request body and was
25
- * passed through here would be a tenant chosen by the client (T3). Setting
26
- * it is what lets one hosted server hold verdicts for many orgs without
27
- * misfiling any of them (QA-P6-010).
28
- */
29
- readonly orgId?: string;
30
- /** Authenticated user who recorded it. Same provenance rule as `orgId`:
31
- * resolved from a session, never read off a request body. */
32
- readonly createdBy?: string | null;
33
- }
34
- export declare function buildFeedbackRow(target: FeedbackTarget, opts: FeedbackOpts): FeedbackRow;
35
- //# sourceMappingURL=feedback.d.ts.map