Skip to content

feat: Codex CLI subprocess provider + web-fetch & Steam Deck-aware research - #24

Merged
gustavohariel merged 4 commits into
mainfrom
feat/codex-subprocess-provider
May 31, 2026
Merged

gustavohariel merged 4 commits into
mainfrom
feat/codex-subprocess-provider

Conversation

@gustavohariel

Copy link
Copy Markdown
Owner

Summary

Adds a zero-setup, zero-cost provider for users logged in to the OpenAI Codex CLI (ChatGPT subscription), plus research-quality improvements (page fetching, recency, Steam Deck awareness) that benefit both the codex and API-key paths.

1. Codex subprocess provider (43ce7e2)

When no API key is set (or FUNFA_PROVIDER=codex forces it) and codex is installed + logged in, funfa delegates investigate→propose to codex exec — codex runs the hardware probes via its own shell and researches via its own web search, returning the plan as --output-schema JSON. funfa keeps the consent gate, on-disk write, and verbatim render client-side.

  • Precedence (resolveProviderIntent): forced codex → API key wins → codex fallback → missing-keys.
  • A spike on codex 0.135.0 found the app-server protocol exposes no client-tool registration, so funfa's ToolLoopAgent can't drive codex with its own tools — codex owns the loop on this path. The API-key path is unchanged.
  • codex-cli.ts: CodexCli, makeBunCodexCli (Bun.spawn, detect via Bun.which + auth.json, model from config.toml/FUNFA_CODEX_MODEL), proposeViaCodex, buildCodexInstructions/Prompt, CodexUnavailableError.

2. fetch_page tool + Steam Deck-aware research (a1f14af)

  • New fetch_page tool (5th Vercel-path tool): reads a cited URL past search snippets — the accepted answer and the latest comments. The old "do not fetch" rule was self-defeating and is gone.
  • Recency guidance: paginate threads (?ctp=N), weight recent comments, a newer "no-longer-works" comment overrides the popular one.
  • Steam Deck awareness across skills: detect the Deck (ID=steamos/VARIANT_ID=steamdeck/Van Gogh), read ProtonDB's Deck reports, treat controller/input as a first-class fix (Steam Input community layouts), allow a Steam Input layout as a high-tier item.

3. fetch_page domain allowlist (7d2fd6f)

Limits fetch_page to trusted gaming domains (ProtonDB, PCGamingWiki, GitHub, Steam, SteamDB; subdomains ok), re-checks the post-redirect host, and is overridable via FUNFA_FETCH_ALLOWLIST. Scope: gates funfa's tool only — the codex path browses through its own sandbox and isn't constrained by this list.

4. Clean cited URLs (72267dd)

Plan skill strips locale/tracking params (l=, utm_*, …) while keeping functional ones (?ctp=N). Enforced in the skill (the CLI never parses the plan body).

Verification

  • 79 tests + check-types + ultracite green.
  • No-key e2e: funfa "Assassin's Creed Revelations" used codex and produced a PCGamingWiki-sourced plan.
  • Steam Deck e2e (mocked OLED via FUNFA_FAKE_HARDWARE): headlines the Dankaishin keyboard-mapped Steam Input layout (the current working fix), cites the thread at ?ctp=2, flags GE-Proton 10-21 as broken, marks Proton 8.0-5 stale.

New env vars

FUNFA_PROVIDER/FUNFA_USE_CODEX (force codex), FUNFA_CODEX_MODEL, FUNFA_CODEX_BINARY, CODEX_HOME, FUNFA_FETCH_ALLOWLIST, FUNFA_FAKE_HARDWARE (dev/test affordance for running off-Linux). All documented in CLAUDE.md.

Security note

fetch_page ingests untrusted HTML; the no-fetch rule was lifted intentionally. Guardrails: domain allowlist (BYOK path), skill instructions to treat fetched text as data / ignore embedded instructions / never recommend a forum-only download, and codex runs -s read-only. The codex path's network is governed by codex itself, not funfa's allowlist.

🤖 Generated with Claude Code

gustavohariel and others added 4 commits May 30, 2026 21:09
Let users on an OpenAI Codex CLI ChatGPT subscription run funfa with no
API key and no metered cost. When no provider key is set (or
FUNFA_PROVIDER=codex is forced) and codex is installed + logged in,
funfa delegates investigate->propose to `codex exec`: codex runs the
hardware probes via its own shell and researches via its own web search,
returning the plan as `--output-schema` JSON. funfa keeps the consent
gate, the on-disk write, and the verbatim render client-side.

Spike (codex 0.135.0) showed the app-server protocol exposes no
client-tool registration, so funfa's ToolLoopAgent cannot drive codex
with its own tools; codex owns the loop on this path. The API-key Vercel
path is unchanged. Precedence: forced codex -> API key wins -> codex
fallback -> missing-keys.

- codex-cli.ts: CodexCli, makeBunCodexCli (Bun.spawn, detect via
  Bun.which + auth.json, model from config.toml/FUNFA_CODEX_MODEL),
  proposeViaCodex, buildCodexInstructions/Prompt (inlines the 4 skills +
  a no-tools/JSON-output override), CODEX_OUTPUT_SCHEMA,
  CodexUnavailableError.
- provider.ts: findApiKey, isCodexForced, resolveProviderIntent.
- submit-plan.ts: extract shared applySubmitPlan (consent-gate parity).
- registry.ts: export skillBodyByName. deps.ts: new error kinds.
- index.ts: branch on provider intent.
- FUNFA_FAKE_HARDWARE: env-gated dev affordance to run the loop off-Linux
  by injecting hardware facts (skips probes). Off by default.
- compile.test guarded so the no-key path still hits missing-keys when a
  real codex is present on the dev/CI machine.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two linked improvements driven by a Steam Deck dogfood (AC Revelations,
controller broken): the loop must (a) know it's on a Deck and (b) read
the latest community fix, not the stale popular one.

- New fetch_page tool (Vercel/BYOK path): fetches a cited URL and
  returns stripped readable text so the agent reads past search
  snippets to the accepted answer AND the most recent comments.
  makeBunFetchPage is the production impl (http(s) only, size/time
  capped, light HTML->text). Threaded via experimental_context like the
  other tools; codex path uses its own browsing instead.
- Lift the old "do not fetch" rule in game-research (it blocked finding
  the real fix) and add "Read the source, and read the latest":
  paginate threads (?ctp=N), weight recent comments, a newer
  "no longer works / new fix" comment wins over the popular one. Keep
  the untrusted-data stance: ignore embedded instructions, never
  recommend a forum-only download.
- Steam Deck awareness across skills: hardware detects the Deck
  (ID=steamos / VARIANT_ID=steamdeck / Van Gogh GPU); game-research
  reads ProtonDB's Deck reports and treats controller/input as a
  first-class fix (Steam Input, community keyboard-mapped layouts);
  funfa PHASE 1 pursues the input fix; plan allows a Steam Input layout
  as a high-tier item.
- Tools count 4 -> 5; CLAUDE.md updated (tool list + security note).

Verified: Deck mock for AC Revelations now headlines the Dankaishin
keyboard-mapped Steam Input layout (Arrax's current fix), cites the
thread at ?ctp=2, flags GE-Proton 10-21 as broken, and marks the old
Proton 8.0-5 path stale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gate the fetch_page tool to a default set of trusted gaming domains
(ProtonDB, PCGamingWiki, GitHub, Steam community/store, SteamDB);
subdomains allowed. Other hosts return an error without a request, and
the post-redirect host is re-checked so an allowed domain can't bounce
the fetch off-list. Override via FUNFA_FETCH_ALLOWLIST (comma-separated)
— this is a starting point, meant to be tuned.

Scope note: this gates funfa's own fetch_page only. On the codex path,
codex browses through its own sandbox and is NOT constrained by this
list — funfa only runs codex with `-s read-only` + `--ignore-user-config`.
Documented in CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The plan skill now tells the model to clean source URLs before citing
them — drop locale/tracking query params (l=, lang=, utm_*, fbclid,
gclid, snr=, curator_*) and #comment fragments, but KEEP params that
change what the reader sees (forum page ?ctp=N, wiki anchors, GitHub
line ranges). Fixes plans citing e.g. `?ctp=2&l=greek`.

Enforced in the skill, not code: the CLI writes the plan markdown
verbatim and never parses the body.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@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 2d07bc8 into main May 31, 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