Skip to content

AX improvements - #784

Merged
fretchen merged 9 commits into
mainfrom
agent_further
Nov 12, 2026
Merged

fretchen merged 9 commits into
mainfrom
agent_further

Conversation

@fretchen

Copy link
Copy Markdown
Owner

No description provided.

fretchen and others added 9 commits November 11, 2026 07:49
…SEARCH_SERVICE_URL

A leftover trial-deploy env value advertised the *.bunny.run origin as the
payment scope on the direct routes, making #97600 unattributable to
web-agent.fretchen.eu for indexers (cdp-sdk#835). resource.url is the payment
scope, not the serving origin, so it now always names the production identity
from openapi.search.json's servers[0].url — the same pattern as the llm twin.
The stale env var was removed from script 97472 (verified live: search and
fetch both quote https://web-agent.fretchen.eu now).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Each origin now serves a generated agent README at GET /, unconditionally
(agents send Accept: */*, so the old text/html gate hid it): spec title and
description, the well-known contracts (openapi.json, agent-registration,
oasf.json, MCP), prices from the spec's x-payment-info / the live price
ceiling, the x402 payment flow, a no-wallet curl that returns the honest
402, and the error semantics. The <link rel="icon"> x402scan parses stays
the first head element; nothing on the page is hand-restated.

- discovery.ts (bunny + scw twins): FAVICON_DISCOVERY_HTML + wantsHtml
  replaced by buildRootPage(RootPageInput); no callers of wantsHtml remain.
- searchapi_routes: page generated from the committed spec (prices per
  route from x-payment-info); serviceName -> "Fretchen Web Retrieval";
  spec title -> "Fretchen Web Retrieval - pay-per-call web access for agents".
- llm_routes: page with the live MAX_PRICE_ATOMIC ceiling, the testnet mock
  note, and the MCP link; serviceName -> "Fretchen LLM Inference"; spec
  title -> "Fretchen LLM Inference - pay-per-call chat completions for agents".
- mcp_routes: hand-composed gateway page (the origin relays, holds no spec
  of its own): links to both seller origins, its registration document,
  free initialize/tools/list curl, and the isError/structuredContent 402
  shape of an unpaid tools/call.
- genimg (scw): same scheme, generated from openapi.genimg.json (title and
  description unchanged - already capability-first, decided).
- tests: root serving is now unconditional and asserted with favicon-first,
  href, price and curl checks; the llm "non-POST" rejection moved from GET
  (now the root page) to PUT; pinned serviceNames and titles updated.
- READMEs: one entry each describing the root page.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
The 402 challenge now lists two schemes: the batch-settlement channel
entries first (unchanged prices and behavior), plus ONE appended exact
alternative — a single EIP-3009 signature per call, flat 10000 atomic
($0.01) in USDC on Base mainnet — so stock x402 clients without channel
wiring can pay per call. Batch prices are untouched; the two schemes
price independently (which is why /fetch quotes $0.01 under exact
despite its $0.001 channel price: the flat price equals the
facilitator's per-settle fee, so a settled exact call nets zero minus
upstream cost — accepted break-even for the simplicity).

- x402_server.ts: createExactAlternative (the single accepts entry, also
  the per-call verify/settle requirements; USDC-on-Base resolved from
  the chain-utils registry) + withExactAlternative (appends the entry
  after the batch accepts — the order is the contract).
- searchapi_routes/llm_routes: challenge wrapped; paid path forks on
  accepted.scheme. The exact flow verifies/settles through the plain
  exact resource server with no channel machinery (no enhance, no
  locks, no releaseLock), answers invalid payments with a plain 402
  instead of the SDK corrective, keeps upstream-failure-free semantics
  (settle only after a successful run), and settles the same flat amount
  it verified (no usage metering on the llm side).
- MCP inherits both schemes unchanged (it relays headers to these
  handlers); tests pin the exact entry's shape and appended-last
  position, the channel-free call path, the flat settle, the
  never-offered-terms rejection, and the untouched batch behavior.

Generated docs follow: both root pages' payment lines and both specs'
x-guidance name the alternative (generated-where-possible); README
describes the dual-scheme challenge.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Three agent complaints, one KISS rule: a page always states the schemes
it accepts and prices EVERY accepted token, generated from the same
PriceList constants the challenge quotes (formatParallelPrices in both
x402_server twins — EURe, EURC, USDC in the seller's preference order,
EUR leading where the euro tokens are accepted, decimals from the token
registry). Nothing token-ish appears on one page and not another.

- web-agent + llm-agent price lines now carry €/$ per token per route
  (plus the flat exact alternative), and one standardized Payment
  paragraph on both: both schemes — channels first, exact appended —
  networks/tokens, retry-same-request.
- openapi.search.json's description said "USDC (or EURC on Base)" —
  stale from before EURe; now names all three tokens and both schemes
  (it is the page's summary). openapi.llm.json's description gets the
  same skeleton.
- genimg's page showed only the $0.07 figure although its EUR price is
  €0.06 — now ßper-token via the same twin helper (. price and page
  share PRICE_ATOMIC).
- The MCP gateway page never mentioned /fetch — the web seller's
  most-called route is REST-only (not an MCP tool): its seller link,
  a price bullet, and the payment paragraph now name it, say where it
  lives, and note the two schemes so an MCP-only agent can find it.

Tests: root-page pins updated to the generated per-token strings
(EURe-first, exact flat price), the gateway page pins GET /fetch; both
suites and the twins' x402_server stay in sync.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
A paid request on Base Sepolia now runs the full x402 machinery (402
challenge, payment validation, channel verify, settle-on-success, the
Payment-Response header) but is answered by deterministic, loudly marked
stand-ins (src/search_stand_in.ts) instead of the metered upstreams —
matching the llm-agent's testnet behavior. Testnet money (free tokens)
never buys Brave queries or /fetch egress; mainnet payments always get
the real thing, and the exact scheme remains Base mainnet only.

- searchapi_routes: OFFERED_NETWORKS from getBatchSettlementNetworks()
  (adds the testnet mock path), run() takes useMock=isTestnet(network),
  root page carries a Base Sepolia test note.
- search_stand_in: standInSearch()/standInFetch() returning the services'
  own answer shapes, echoing the input and carrying the marker.
- openapi.search: guidance flipped — Base Sepolia settles free test
  tokens for stand-in answers; metered upstreams run for mainnet only.
- tests: routes + mcp pin the invariant in both directions (testnet
  settles without touching fetch; mainnet still calls Brave).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
The /favicon.png served on every ERC-8004 origin (and linked first in
each root page, where x402scan reads it) was a stale JPEG. Regenerate
favicon.ts in both seller packages from the live website logo
(website/public/fretchen.png, 512x512 PNG); the /favicon.png path and
the base64-embed mechanism stay as they are.

- bunny_js + scw_js: favicon.ts re-encoded, Content-Type image/png.
- discovery.ts twins: <link rel=icon> type updated.
- tests: content-type pins flipped, magic bytes pin the PNG signature
  (0x8950) instead of the JPEG SOI marker.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
@fretchen
fretchen merged commit 36a8109 into main Nov 12, 2026
5 checks passed
@fretchen
fretchen deleted the agent_further branch November 12, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant