Skip to content

feat(agent): funfa auth + subscription-backed web_search - #28

Merged
gustavohariel merged 1 commit into
mainfrom
feat/auth-and-subscription-web-search
Jun 1, 2026
Merged

gustavohariel merged 1 commit into
mainfrom
feat/auth-and-subscription-web-search

Conversation

@gustavohariel

Copy link
Copy Markdown
Owner

What & why

Since funfa embeds pi as a library (not the pi CLI), users had no way to authenticate, and web_search was a no-op without a separate PARALLEL_API_KEY. This PR makes funfa self-sufficient on a single model subscription: sign in, then search through that same sub.

1. funfa auth — in-process OAuth login

  • New agent/auth.ts drives pi's AuthStorage.login(providerId, callbacks) directly (no pi binary required), persisting to the same ~/.pi/agent/auth.json the next run reads.
  • New auth subcommand with an interactive provider picker (anthropic = Claude Pro/Max, openai-codex = ChatGPT, github-copilot) or an explicit arg: funfa auth [provider].
  • The <game> positional became optional (a parent command can't also require a positional alongside subcommands); the parent handler prints its own missing-game usage error.
  • The no-credential error now points at funfa auth instead of "run pi".
  • Interactive I/O (@inquirer select/input + best-effort browser open) is injected, so the orchestration is unit-tested without a real OAuth round-trip.

2. Subscription-backed web_search

  • New agent/tools/web-search-providers.ts: a provider chain that routes through whichever subscription is authed, then a keyed fallback, then a fetch_page degradation hint.
    • Anthropic → one cheap claude-haiku-4-5 call to the public Messages API with the server-side web_search_20250305 tool. OAuth tokens are shaped as Claude Code requests (the form Anthropic accepts for a subscription token).
    • Codex (ChatGPT) → the private chatgpt.com/backend-api/codex/responses endpoint funfa already drives the loop through, with the built-in web_search tool; auth is the OAuth JWT and the ChatGPT account-id is decoded from it (SSE-parsed).
    • Parallel stays as the keyed fallback.
  • Request shapes mirror @earendil-works/pi-ai 0.78.0 internals, so calls are accepted on the same credential. WebSearchResult gained an optional answer to carry the synthesized summary.

Verification

  • Full suite 105 pass / 1 skip / 0 fail; tsc + Ultracite clean; binary compiles.
  • New tests: auth.test.ts (provider resolution, cancel/fail classification, callback wiring) and web-search-providers.test.ts (JWT account-id decode + chain selection, network-free).
  • Live web_search on a ChatGPT/Codex sub returned a synthesized answer (PROTON_PREFER_SDL=1 + GE-Proton) plus source URLs in ~21s, with no Parallel key.

Caveats

  • Both subscription providers ride undocumented/grey-area surfaces (Anthropic's OAuth + server-tool path; ChatGPT's private backend) — the same ones Oh My Pi depends on. If either changes upstream the chain degrades to Parallel-or-fetch_page gracefully, so failures are non-fatal.
  • claude-cli/account-id request shaping is pinned to pi-ai 0.78.0 conventions; revisit on pi upgrades.

Add 'funfa auth': an in-process pi OAuth login (AuthStorage.login) with a provider picker, so users sign in to Claude Pro/Max, ChatGPT, or GitHub Copilot without a separate pi binary. The game positional is now optional (parent + subcommand), and the no-credential error points at 'funfa auth'.

Route web_search through whichever subscription is authed instead of requiring a Parallel key. New provider chain (web-search-providers.ts): Anthropic via the server-side web_search_20250305 tool (OAuth shaped as Claude Code), Codex via the chatgpt.com backend Responses web_search tool (JWT account-id + SSE), then the Parallel fallback, then a fetch_page degradation hint. Request shapes mirror @earendil-works/pi-ai 0.78.0 so the calls are accepted on the same credential.

Verified: full suite 105 pass / 1 skip / 0 fail, typecheck + lint clean, and a live web_search on a ChatGPT/Codex sub returns synthesized answer + sources.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@gustavohariel
gustavohariel merged commit 8d2a376 into main Jun 1, 2026
2 checks passed
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