mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 20:32:25 +03:00
fix(oauth): expose manual Codex callback entry (#9944)
Merged after batch validation on a combined worktree cut from `release/v3.8.51` with #9908 and #7138.
**Evidence**
- Focused tests: 36/36 pass on the combined tree (`oauth-modal-codex-lan-ip-8046`, `antigravity-image-credential-retry`, `antigravity-usage-service`, `generic-quota-fetcher`), including the 2 pre-existing anchor tests that assert `codex` stays in `PKCE_CALLBACK_SERVER_PROVIDERS` and that the `localhost:1455` redirect URI is untouched.
- Gates on the combined tree: `check-complexity` PASS, `check-cognitive-complexity` PASS, `typecheck:core` PASS, `check-changelog-integrity` PASS.
- `check-file-size` is red, but reproduces byte-identical on the pure `release/v3.8.51` tip (`imageGeneration.ts`, `roundRobinCombo.ts`, `stream.ts`) — inherited base-red, not from this PR.
**Reconciled**
- `changelog.d/fixes/codex-manual-loopback-action.md` did not start with a markdown bullet, which is the one thing `check-changelog-integrity` failed on. Fixed in your branch (d3dbb5b) so the fragment convention holds; nothing else in your diff was touched.
Thanks for this one, @Ardem2025 — exposing the manual callback entry that already existed in the code instead of adding a new flow is exactly the right shape for the LAN/remote case, and keeping every PKCE/state check untouched made it easy to verify.
This commit is contained in:
1
changelog.d/fixes/codex-manual-loopback-action.md
Normal file
1
changelog.d/fixes/codex-manual-loopback-action.md
Normal file
@@ -0,0 +1 @@
|
||||
- Add a visible manual callback-entry action to the Codex loopback warning so remote users can paste the authorization result instead of setting up an SSH tunnel.
|
||||
@@ -374,11 +374,10 @@ export default function OAuthModal({
|
||||
[provider, onSuccess, reauthConnection, t]
|
||||
);
|
||||
|
||||
// Start OAuth flow. `opts.grokBrowser` lets the grok-cli method tabs force a
|
||||
// specific branch synchronously (avoids reading a just-set state value through
|
||||
// a stale closure); when omitted, falls back to the grokBrowserMode state.
|
||||
// Start OAuth flow. Options let method buttons select a branch synchronously
|
||||
// instead of reading a just-set state value through a stale closure.
|
||||
const startOAuthFlow = useCallback(
|
||||
async (opts?: { grokBrowser?: boolean }) => {
|
||||
async (opts?: { grokBrowser?: boolean; manualLoopback?: boolean }) => {
|
||||
if (!provider) return;
|
||||
try {
|
||||
setError(null);
|
||||
@@ -533,7 +532,7 @@ export default function OAuthModal({
|
||||
setPolling(false);
|
||||
forceManual = true;
|
||||
}
|
||||
} else if (isLocalhost) {
|
||||
} else if (isLocalhost && !opts?.manualLoopback) {
|
||||
setLoopbackHint(buildPkceLoopbackMismatchHint(provider, loopbackLocation));
|
||||
setStep("loopback-mismatch");
|
||||
return;
|
||||
@@ -1160,6 +1159,7 @@ export default function OAuthModal({
|
||||
<OAuthLoopbackMismatchPanel
|
||||
providerName={providerInfo.name}
|
||||
hint={loopbackHint}
|
||||
onManualInput={() => void startOAuthFlow({ manualLoopback: true })}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -89,6 +89,7 @@ export function OAuthDeviceCodePanel({
|
||||
type OAuthLoopbackMismatchPanelProps = {
|
||||
providerName: string;
|
||||
hint: PkceLoopbackMismatchHint;
|
||||
onManualInput: () => void;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
@@ -103,6 +104,7 @@ type OAuthLoopbackMismatchPanelProps = {
|
||||
export function OAuthLoopbackMismatchPanel({
|
||||
providerName,
|
||||
hint,
|
||||
onManualInput,
|
||||
onClose,
|
||||
}: OAuthLoopbackMismatchPanelProps) {
|
||||
const t = useTranslations("oauthModal");
|
||||
@@ -194,6 +196,9 @@ export function OAuthLoopbackMismatchPanel({
|
||||
<p className="text-xs text-text-muted">{t("loopbackMismatchAlternative")}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={onManualInput} fullWidth>
|
||||
{t("popupBlocked")}
|
||||
</Button>
|
||||
<Button onClick={onClose} variant="secondary" fullWidth>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
|
||||
@@ -41,7 +41,7 @@ test("PKCE callback-server providers now warn (not window.open) on a LAN-IP orig
|
||||
// that surfaces the loopback mismatch instead of falling through silently.
|
||||
// The follow-up swapped the flat warning string for the structured hint that feeds
|
||||
// the dedicated panel (buildPkceLoopbackMismatchHint) — the guard itself is unchanged.
|
||||
const arm = modal.match(/else if \(isLocalhost\) \{[\s\S]{0,300}?\n {10}\}/);
|
||||
const arm = modal.match(/else if \(isLocalhost(?: && [^)]+)?\) \{[\s\S]{0,300}?\n {10}\}/);
|
||||
assert.ok(arm, "expected an `else if (isLocalhost)` arm inside the callback-server branch");
|
||||
assert.match(
|
||||
arm![0],
|
||||
@@ -57,6 +57,29 @@ test("PKCE callback-server providers now warn (not window.open) on a LAN-IP orig
|
||||
);
|
||||
});
|
||||
|
||||
test("loopback warning offers the existing manual callback flow", () => {
|
||||
const panels = readFileSync(
|
||||
resolve(here, "../../src/shared/components/OAuthModalPanels.tsx"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
assert.match(
|
||||
modal,
|
||||
/isLocalhost && !opts\?\.manualLoopback/,
|
||||
"the warning guard must be bypassable only through an explicit manual-flow action"
|
||||
);
|
||||
assert.match(
|
||||
modal,
|
||||
/onManualInput=\{\(\) => void startOAuthFlow\(\{ manualLoopback: true \}\)\}/,
|
||||
"the mismatch panel action must initialize the existing authorization-code flow"
|
||||
);
|
||||
assert.match(
|
||||
panels,
|
||||
/<Button onClick=\{onManualInput\} fullWidth>/,
|
||||
"the mismatch panel must render a visible manual-entry action next to Cancel"
|
||||
);
|
||||
});
|
||||
|
||||
test("buildPkceLoopbackMismatchWarning mentions the fixed redirect and a way forward", () => {
|
||||
const msg = buildPkceLoopbackMismatchWarning("codex");
|
||||
assert.match(msg, /localhost:1455/);
|
||||
|
||||
Reference in New Issue
Block a user