Merge main into beta — reconverge history after the v3.1.11 promotion - #282
Open
yalexx wants to merge 4 commits into
Open
Merge main into beta — reconverge history after the v3.1.11 promotion#282yalexx wants to merge 4 commits into
yalexx wants to merge 4 commits into
Conversation
* Harden gateway recovery after updates (#263) * fix: migrate legacy openai/<gpt> model+fallbacks to codex on startup (#266) ChatGPT-subscription boxes (Codex OAuth, no OpenAI API key) that stored their active model or a fallback as `openai/gpt-5.5` (etc.) before the setup UI routed ChatGPT picks through Codex hit `401 Missing bearer or basic authentication in header` on api.openai.com/v1/responses — often only as a FailoverError days into use, once the OAuth token first refreshes and the failover chain reaches the keyless `openai/*` fallback. The chat-model pick route already rewrites openai/<gpt> -> codex/<gpt>, but only when the user re-picks the model; existing configs never re-pick, so an updated box stays broken until manually re-selected. Migrate primary + fallbacks in gateway-pre-start.sh on gateway start, guarded on "codex OAuth present AND no OpenAI API key" so keyed / dual-auth boxes (where openai/* is a valid route) are left untouched. Mirrors CODEX_SUPPORTED_MODEL_RE / hasOpenAiApiKeyProfile / hasCodexOauthProfile in src/app/setup-api/chat/model/route.ts. Verified against 6 fixtures: openai->codex primary+fallback migrate; keyed box untouched; non-supported (gpt-4o) primary left as-is; already-codex no-op; no-codex-auth untouched; composes with the retired-Sonnet migration. bash -n and py_compile pass. Co-authored-by: Mike (IDRobots) <mike@idrobots.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * fix(3.1.10): responsive chat header pills (wrap instead of overlap on narrow chat) (#267) * fix: chat header pills squeeze + truncate cleanly on narrow panels On a narrow chat the provider / model / thinking selector pills overlapped into an unreadable strip. Two parts: 1. .header-dropdown-trigger gets width:100% so the button fills its flex-shrinking .header-dropdown parent. Previously the button kept its content width and spilled past the shrunk parent, so overflow:hidden on .chat-header-pills clipped / overlapped the pills instead of the labels truncating. Now every pill gives ground evenly and its label ellipsizes (the chevron stays — it's reserved in the 24px right padding). 2. Single row (no wrap) + overflow:hidden, and the chat window clamps to MIN_CHAT_WIDTH (340px) on both resize paths + the rendered width, so the window stops shrinking once the pills reach a readable minimum instead of smashing them. The open menu is portaled to <body> (HeaderDropdown), so clipping the row can't hide it. Verified at 320-420px: even truncation, carets visible, zero overlap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: open chat from mascot with a macOS-style animation, no corner flash - Stop streaming the frozen mascot's position into mascotX while the chat is open (page.tsx). That nudged mascotX for a frame right after opening, so the popup flashed to the wrong corner before settling. mascotX is now captured once from the tap. - Grow the popup OUT of the mascot: transform-origin pinned to the popup's bottom edge, aligned horizontally with the mascot, and scale 0.82 -> 1 on an easeOutExpo curve (cubic-bezier(0.16,1,0.3,1)) over 0.36s. Smooth, premium, emanates from where you tapped instead of scaling from the popup centre. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: bump SW cache clawbox-v3 -> v4 to invalidate stale assets on the 3.1.10 chat-UI changes Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: keep chat popup header on-screen on short/zoomed viewports The un-dragged popup anchors from the bottom (bottom:170 above the mascot, bottom:65 in tray mode) but its maxHeight budget was a flat 100vh-60px, so on viewports shorter than ~680px (small windows, browser zoom) a 500px-tall popup shoved its whole header — pills, status dot, close button — off the TOP of the screen (rect.y = -76 measured on a 594px viewport). Subtract the bottom anchor from the height budget per mode (+12px top margin) so the header is always visible and the popup just gets shorter instead. Found by driving the real desktop over CDP and sampling the popup rect during open; the same probe confirmed the mascot-open animation runs and there is no left-corner flash. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Mike (IDRobots) <mike@idrobots.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Mike (IDRobots) <mike@idrobots.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Merges beta into main for the 3.1.11 release. The conflicts came from #264 (the 3.1.10 gateway-recovery squash landing on main) diverging from the same work as it evolved on beta; every one resolved to the beta side. The resulting tree is byte-identical to origin/beta -- the exact code verified on hardware today. What ships: - codex: route codex turns through the app-server harness (#280). Without agentRuntime, core posts to /backend-api/responses -- a browser endpoint Cloudflare challenges -- and every turn dies with an HTML error page. - codex: restore the credential #278 broke, and migrate legacy auth profiles into the sqlite store core actually reads (#279). - codex: stop mirroring the rotating refresh token into every codex-home, so a single-use refresh token cannot be spent twice (#278). - codex: default ChatGPT auth to gpt-5.5; unblock GPT-5.6 for entitled accounts (#275, #276). - gateway: stop update/boot from bricking the box; parameterised health and recovery waits. - memory: local embeddings so semantic memory works without an API key. - docs/site: point references at clawbox.com; measured Wi-Fi and local-model performance figures. Hardware verification (2026-07-28, boxes .52 and todor): - HTML/Cloudflare failure reproduced on the old build, fixed by the update - 401 profile=- auth failure reproduced, fixed by the update - forced OAuth token rotation x2 on both boxes -- codex survived both - 3.1.10 -> 3.1.11 through the shipped updater: pass - 3.1.5 -> 3.1.11 through the shipped updater incl. reboot: pass, ~4 min - CI: 1499 unit tests, E2E, E2E-install in a real systemd container Known, not a regression (present in 3.1.10, fix queued for 3.1.12): the Codex model picker offers gpt-5.4/gpt-5.4-mini, which free-tier ChatGPT accounts cannot run -- upstream 400s with no failover. The default is gpt-5.5, which every tier runs, so this only bites a user who picks an older model by hand.
Release v3.1.11 — promote beta to main
The v3.1.11 promotion (#281) landed on main as a single-parent commit -- MERGE_HEAD was dropped while creating the promotion branch -- so beta is not recorded as an ancestor of main even though the trees are identical. Left alone, the next beta -> main promotion would re-conflict on the same files for the same reason #264 caused today's conflicts. This merge is content-neutral: main and beta already have identical trees, so beta's tree does not change. It only records the ancestry.
🦀 ClawReviewPoked my eyestalks out for this one. Quick tour: A content-neutral merge commit that reconnects beta as an ancestor of main after the v3.1.11 promotion (#281) was committed with only one parent. No files change — the tree on beta is byte-identical before and after. This is purely a history repair to prevent the next beta→main promotion from re-conflicting on the same files. At a glance
Good to know
— ClawReview 🦀, your resident reef crab. Just orientation — CodeRabbit does the line-by-line, humans do the merge. Conventions: docs. |
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.
Content-neutral.
mainandbetaalready have identical trees, so beta's tree does not change — this only records the ancestry.Why
The v3.1.11 promotion (#281) landed on
mainas a single-parent commit:MERGE_HEADwas dropped while creating the promotion branch, so the merge was committed without beta as a second parent. My mistake, caught right after tagging.The release itself is unaffected —
v3.1.11points at a tree byte-identical tobeta, and the updater has no ancestry guard, so every box resolves the tag correctly.What it would break is the next promotion: with beta not an ancestor of main,
beta → mainwould re-conflict on the same files, for exactly the reason #264 caused today's conflicts. This merge stops that from recurring.Verification
git diff origin/betaafter the merge: empty