Commit 2deb6fa
* Work on openapi spec for services
* Improve 402 html page
* Update storefronts
* feat(buy-x402): add --set-default so the agent self-adopts paid/<model> as primary
After a persistent inference buy publishes paid/<remote-model> in LiteLLM, the
agent adopts it as its own primary chat model in-pod via native
'hermes config set model.default' (atomic write, per-request re-read, no restart,
no host CLI, no new RBAC). Includes a LiteLLM /v1/models existence guard, an
auto-refill safety warning, and a PyYAML fallback writer.
Validated by a design+adversarial workflow and a live CLI smoke against a running
obol-agent: buy --set-default flips config.yaml model.default to paid/AEON-7/... and
the next agent chat settled via the x402-buyer pool (spent 0->1) with no restart;
rollback verified.
* Have agent stream responses to keep the tunnel alive
* security(x402): SRI-pin the Scalar bundle on the public /api page
The /api OpenAPI reference is served over the public tunnel and pulls the
@scalar/api-reference bundle from jsdelivr. The integrity hash was left empty
in phase 1, so the browser executed whatever the CDN returned, unverified.
Populate scalarBundleSRI with the sha384 of the pinned 1.34.0 bundle so a
tampered CDN response is blocked. Comment updated to stress the hash must be
re-derived in lockstep with every scalarBundleVersion bump.
* fix(buy-x402): run --set-default existence guard before auto-refill warning
The 'paid/<model> not selectable in LiteLLM' guard ran *after* the
no-auto-refill WARNING. A model that LiteLLM would refuse still printed a
scary 'every chat turn fails when the pool empties' warning describing a
primary-model failure mode that cannot occur when the default was never
switched. Reorder so we refuse first and only warn when we are actually
about to adopt the model.
* security(x402): sanitize ServiceOffer-sourced tokens in 402 copy-paste commands
spec.model.name and metadata.name flow from the ServiceOffer CR into
copy-pasteable 'obol buy inference ...' commands rendered on the public 402
page. A hostile or fat-fingered offer could smuggle shell metacharacters into
a command a reader might paste. Add sanitizeDisplayToken at the render
boundary: CR-sourced tokens must match the model-id/k8s-name charset
(^[A-Za-z0-9._:/-]+$) or collapse to the existing safe placeholder. Real ids
like qwen3.5:9b and anthropic/claude-3-5-sonnet-latest pass through unchanged.
* docs(claude): compress and correct CLAUDE.md; fold in #597 streaming/sell-agent facts
Terse rewrite of project CLAUDE.md (42725 -> 41797 bytes) corrected against the live codebase. Preserves all invariants, the 14 pitfalls, and flag warnings; adds #597's stream:true / statusRecorder.Flush guidance and agent-backed-offer (port 8642) facts so the compressed doc loses nothing rc12 ships.
---------
Co-authored-by: Oisín Kyne <oisin@obol.tech>
Co-authored-by: bussyjd <jd@obol.tech>
Co-authored-by: bussyjd <bussyjd@users.noreply.github.com>
1 parent 8fb1553 commit 2deb6fa
27 files changed
Lines changed: 3204 additions & 266 deletions
File tree
- cmd/obol
- internal
- embed/skills/buy-x402
- scripts
- schemas
- serviceoffercontroller
- x402
- templates
- plans
- web/public-storefront
- src
- components
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
195 | 195 | | |
196 | 196 | | |
197 | 197 | | |
198 | | - | |
199 | | - | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
200 | 201 | | |
201 | 202 | | |
202 | 203 | | |
| |||
296 | 297 | | |
297 | 298 | | |
298 | 299 | | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
299 | 312 | | |
300 | 313 | | |
301 | 314 | | |
| |||
345 | 358 | | |
346 | 359 | | |
347 | 360 | | |
348 | | - | |
| 361 | + | |
349 | 362 | | |
350 | 363 | | |
351 | 364 | | |
| |||
601 | 614 | | |
602 | 615 | | |
603 | 616 | | |
604 | | - | |
605 | | - | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
606 | 620 | | |
607 | 621 | | |
608 | 622 | | |
| |||
799 | 813 | | |
800 | 814 | | |
801 | 815 | | |
802 | | - | |
| 816 | + | |
803 | 817 | | |
804 | 818 | | |
805 | 819 | | |
| |||
1362 | 1376 | | |
1363 | 1377 | | |
1364 | 1378 | | |
1365 | | - | |
| 1379 | + | |
1366 | 1380 | | |
1367 | 1381 | | |
1368 | 1382 | | |
| |||
3861 | 3875 | | |
3862 | 3876 | | |
3863 | 3877 | | |
3864 | | - | |
| 3878 | + | |
3865 | 3879 | | |
3866 | 3880 | | |
3867 | 3881 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
79 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
80 | 81 | | |
81 | 82 | | |
82 | 83 | | |
| |||
173 | 174 | | |
174 | 175 | | |
175 | 176 | | |
176 | | - | |
| 177 | + | |
177 | 178 | | |
178 | 179 | | |
179 | 180 | | |
| |||
418 | 419 | | |
419 | 420 | | |
420 | 421 | | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
421 | 432 | | |
422 | 433 | | |
423 | 434 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1396 | 1396 | | |
1397 | 1397 | | |
1398 | 1398 | | |
1399 | | - | |
| 1399 | + | |
1400 | 1400 | | |
1401 | 1401 | | |
1402 | 1402 | | |
| |||
1419 | 1419 | | |
1420 | 1420 | | |
1421 | 1421 | | |
1422 | | - | |
| 1422 | + | |
1423 | 1423 | | |
1424 | 1424 | | |
1425 | 1425 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
71 | 72 | | |
72 | 73 | | |
73 | 74 | | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
74 | 87 | | |
75 | 88 | | |
76 | 89 | | |
| |||
150 | 163 | | |
151 | 164 | | |
152 | 165 | | |
| 166 | + | |
153 | 167 | | |
154 | 168 | | |
155 | 169 | | |
| |||
0 commit comments