feat(agent): free DeepSeek Codex path via control plane (ENG-4785)#264
Merged
Conversation
Wire the box side of the 'no Codex sub' option. The cloud PR adds the setup choice + the codex_use_free WS command; this makes the box honor it. - bootstrap.sh: write an INERT [model_providers.browser-use-free] + [profiles.browser-use-free] block in ~/.codex/config.toml (base_url at the control plane, wire_api=chat, auth.command=bu-cp-token), plus the bu-cp-token helper that hands codex the box token. Not the default — codex exec reads the default provider and ignores --profile, so making it default would route own-sub users through us. Idempotent. - box_agent.py: handle the codex_use_free WS command — set the top-level profile line so the free profile becomes this box's default, then nudge the auth poll loop. check_codex_authed() now treats an active browser-use-free profile as authed (the free path has no codex login; the control plane holds the credential), so codex_authed flips and the setup wizard completes. Pairs with cloud PR #4551.
Contributor
There was a problem hiding this comment.
2 issues found across 2 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
- P0 (bootstrap.sh): don't source /etc/bux/env as root — sourcing executes the file as shell, so a tampered line would run as root. grep only the BUX_CLOUD_URL / BUX_BOX_TOKEN values we need (URL/token, no shell metachars). Applied to both the provider-config block and the bu-cp-token helper. - P2 (box_agent.py): the grep gate matched any 'profile =' (incl. inside a table) but the awk only rewrote a top-level one, so codex_use_free could report success without setting the default profile. Replace with a single awk pass that always sets the top-level key (replace-in-place or insert above the first table), plus a verify step that fails if it isn't set.
…ublic host (ENG-4785) The CP is internal-only and reachable from the box VPC only over PrivateLink; the public BUX_CLOUD_URL host has no /api/codex route. So bootstrap now reads BUX_CP_CODEX_URL (the PrivateLink endpoint DNS the provisioner writes into /etc/bux/env) as Codex's base_url, instead of deriving it from BUX_CLOUD_URL. Empty (not set / not staging) -> skip writing the free-Codex provider block. Also: tighten _codex_free_profile_active() to match the top-level 'profile' key exactly (not startswith), so 'profile_dir'/'profiles' can't be mistaken for the default-profile selector. Pairs with cloud #4561 (writes BUX_CP_CODEX_URL, staging-gated).
Contributor
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
…l (Cubic, ENG-4785) Coerce the value to an absolute https:// base_url: tolerate a bare host or a stray ws/wss value rather than emitting a scheme-less base_url that silently breaks Codex routing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Box side of the "no Codex subscription → free DeepSeek" option. Pairs with cloud PR
browser-use/cloud#4551(the setup choice +codex_use_freeWS command) andbrowser-use/cloud#4542(the control-plane proxy).How
bootstrap.sh— writes, on every box, an inert Codex provider/profile:[model_providers.browser-use-free]:base_urlat the control plane (derived fromBUX_CLOUD_URL,wss://→https://, +/api/codex/v1),wire_api = "chat",auth.command = /usr/local/bin/bu-cp-token.[profiles.browser-use-free]:model = "deepseek/deepseek-v4-flash".bu-cp-tokenhelper: prints$BUX_BOX_TOKENfrom/etc/bux/envso Codex authenticates to the CP with the box token (read at call time → token rotation just works). The CP holds the OpenRouter key; the box never sees it.[features] goalswriter right above it.Why inert, not default:
codex exec(how the box runs Codex) reads the default provider inconfig.tomland ignores--profile. Making the free provider the global default would silently route own-sub users through us. So bootstrap only ships the block; selecting it is per-box and explicit.box_agent.py— handles thecodex_use_freeWS command:profile = "browser-use-free"line (idempotent awk/prepend), making the free profile this box's default.check_codex_authed()now treats an activebrowser-use-freeprofile as authed — the free path has nocodex login(the CP holds the credential), so this is what flipscodex_authedand completes the setup wizard. Nudges the auth poll loop so it reports immediately.Gates
ruff check agent/(what CI runs) — clean.bash -n agent/bootstrap.sh— valid.ruff formatsince the repo isn't formatted with it and CI doesn't gate on it.🤖 Generated with Claude Code
Summary by cubic
Adds an opt-in free DeepSeek path for Codex via the control plane for boxes without a Codex subscription (ENG-4785). Uses the CP PrivateLink endpoint (
BUX_CP_CODEX_URL) and treats the active free profile as authed with no login.New Features
bootstrap.sh: writes inert[model_providers.browser-use-free]and[profiles.browser-use-free]to~/.codex/config.tomlwith base"$BUX_CP_CODEX_URL/api/codex/v1",wire_api = "chat", auth.command/usr/local/bin/bu-cp-token, modeldeepseek/deepseek-v4-flash; not default; idempotent; skip ifBUX_CP_CODEX_URLis unset./usr/local/bin/bu-cp-tokento emit$BUX_BOX_TOKENfrom/etc/bux/env; CP holds the OpenRouter key.box_agent.py: handlescodex_use_freeto set the top‑levelprofile = "browser-use-free"forbux; treats an active free profile as authed and wakes the auth poll loop.Bug Fixes
bootstrap.shandbu-cp-token: do not source/etc/bux/envas root; grep onlyBUX_CP_CODEX_URLandBUX_BOX_TOKEN.box_agent.py: ensurecodex_use_freealways sets the top‑levelprofile(single awk pass + verify). Tighten_codex_free_profile_active()to match the exact top‑levelprofilekey.bootstrap.sh: normalizeBUX_CP_CODEX_URLto an absolutehttps://base_url (handle bare host andws/wss) to prevent invalid routing.Written for commit c12e854. Summary will update on new commits. Review in cubic