feat: enable Contributor max via Muse User-Agent fingerprint - #20
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
BlockedPath
left a comment
There was a problem hiding this comment.
Thanks for the thorough PR — the endpoint guard, setdefault semantics, and test coverage are clean. I checked it out locally: typecheck and hermetic tests pass on Pi 0.85.1, and the hook behaves the same on Pi 0.87.1 (tests pass; the one 0.87 typecheck failure is pre-existing on main and fixed in #21).
I can't merge it as-is, though, mainly for a policy reason:
1. Default-on client impersonation. This makes every Meta request from this package identify as the first-party Muse CLI in order to get past a server-side gate Meta only documents for standard-tier 1.3. For a published package that puts users' keys/accounts at risk if Meta treats it as abuse, and it's not something I want enabled silently.
If you'd like to keep going, I'd accept it with these changes:
- Opt-in only, e.g.
META_MUSE_USER_AGENT=1(or a provider setting). Off by default, with a README note that it spoofs the Muse CLIUser-Agent, is unsupported by Meta, and may stop working or violate Meta's terms. - Scope it to
muse-spark-1.3-contributor, not every Meta request. Today the header is applied to all Meta traffic, including models that don't need it. - Gate the
maxmapping on the same opt-in. Withmax: "max"unconditionally in the Contributor fallback map, users without the fingerprint (e.g. behind a proxybaseUrl) are offered a level that 400s. - Fix the hardcoded platform.
linux-x86_64is sent from every OS.
2. Hook uses the session model, not the request model. before_provider_headers gets ctx.model from the session (createContext() → getModel()), so the check follows the active session model rather than the model the request is for. A non-Meta request made while the session model is Meta (or the reverse) gets the wrong result. That's worth a comment at least, and it's another reason to keep the blast radius small via opt-in plus model scoping.
3. Smaller items
- The live probe asserts the bare request returns 400, so it breaks if Meta ever opens
maxup. Please assert only the fingerprinted 200 (or make the bare check informational). - The "accepts both API-key and Muse Code login credentials" test is unrelated to this change. Please drop it or move it to a separate PR.
- Please add a
CHANGELOG.mdentry under Unreleased. - Please rebase on
mainonce #21 (Pi 0.87 support) lands.
Happy to re-review once it's opt-in and scoped.
Live-probed 2026-09-25 against POST /v1/responses: muse-spark-1.3-contributor accepts reasoning.effort "max" only when the request carries the Muse CLI User-Agent (400 without it, 200 with it, identical payload). Standard 1.3 accepts max with any User-Agent, as before. - fallback map for muse-spark-1.3-contributor gains max -> "max" (toProviderModels already inherits fallback max for bare catalog IDs) - new before_provider_headers hook setdefaults the captured Muse User-Agent on direct api.meta.ai requests only; explicit headers (any casing, incl. null suppression) and non-Meta endpoints untouched - applies to both credential types: static API key and Muse Code login (minted) keys hit the same direct wire - hermetic wire-contract tests + gated live probe (400 bare / 200 fingerprinted); README updated
First-hand live verification used login-minted credentials; the API-key leg comes from the OMP report. Keep the comment honest.
5c6fc42 to
601f3ab
Compare
|
Maintainer update:
The rest of the requested changes still stand: opt-in, Contributor-only scoping, |
…or-only Maintainer follow-up to the review on this PR. - Gate the fingerprint behind META_MUSE_USER_AGENT=1|true|yes (off by default), since it identifies Pi as Meta's first-party Muse client. - Scope the before_provider_headers hook to muse-spark-1.3-contributor; all other Meta traffic keeps Pi's own User-Agent. - Gate Contributor max on the same opt-in across fallback, catalog, and cached-restore model lists (gateMuseMaxEffort), so users who have not opted in are never offered a level that 400s. Server-advertised or custom max mappings still pass through. - Keep the captured UA byte-for-byte (documented), since variants for other platforms are unverified. - Live probe: assert only the fingerprinted 200 and log the bare status, so the suite survives Meta opening max up. - Drop the unrelated credential-type test; add hermetic env helper, opt-in parsing, hook scoping, gating, and cached re-gate tests. - README opt-in section with a warning, CHANGELOG, and AGENTS.md notes.
BlockedPath
left a comment
There was a problem hiding this comment.
Requested changes addressed in f4a6330: the fingerprint is opt-in (META_MUSE_USER_AGENT), sent only for muse-spark-1.3-contributor, and Contributor max is gated on the same flag. CI is green. Thanks @AdityaVG13!
What
muse-spark-1.3-contributornow exposes themaxreasoning effort, and the extension sends the captured Muse CLIUser-Agenton direct Meta Model API requests so the server accepts it. Works the same on both credential types: a static API key (META_API_KEY/MODEL_API_KEY) and Muse Code login (/login meta, minted key).Why
Live-probed 2026-09-25 against
POST /v1/responseson login-minted credentials: Contributor +reasoning.effort "max"returns HTTP 400 with a generic client UA and HTTP 200 with the Muse UA — identical payload, only the header changed (API-key parity reported in the OMP PR below). Standard 1.3 acceptsmaxwith any UA (unchanged). This mirrors the oh-my-pi #12199 finding for OMP.Meta documents
maxfor standard-tier 1.3 only, so Contributormaxis treated as observed wire behavior throughout (code comments, README, tests) — not a permission claim, and it may be gated differently later.How
extensions/meta.tsMUSE_USER_AGENT: captured fingerprint (muse-build/1.3.0 ..., from the Muse CLI inference entrypoint)isDirectMetaModelApiUrl(): strict direct-endpoint check (https,api.meta.aicase-insensitive, default port, bare/v1); proxies, lookalike hosts, subpaths, and non-default ports never matchapplyMetaUserAgentFingerprint(): setdefault — explicitUser-Agentheaders (any casing, including null suppression) always winbefore_provider_headershook (available on the full>=0.83 <0.86peer range, verified per version): Meta provider only, endpoint verified from the composed model, no fingerprint when the endpoint cannot be verifiedmuse-spark-1.3-contributorgainsmax -> "max";toProviderModelsalready inherits fallbackmaxfor bare catalog IDs, so no change needed there. Older revisions stay clamped.Verification
Also mutation-checked the endpoint guard (flipped comparison fails the test, then reverted).