diff --git a/gui/src/api.ts b/gui/src/api.ts index 8cdd45652..1df043791 100644 --- a/gui/src/api.ts +++ b/gui/src/api.ts @@ -16,8 +16,12 @@ let promptCancelled = false; type AdminTokenPrompt = (verifyToken: AdminTokenVerifier) => Promise; let requestAdminToken: AdminTokenPrompt = promptForAdminToken; -/** Document path re-fetched to mint a fresh loopback GUI session (server injects meta tags). */ -const SESSION_REBOOTSTRAP_PATH = "/"; +/** + * Document path re-fetched to mint a fresh loopback GUI session (server injects meta tags). + * Deliberately NOT "/": the Vite dev server owns that route for the app shell, so the dev + * proxy forwards this dedicated extensionless path to the backend with the original host. + */ +const SESSION_REBOOTSTRAP_PATH = "/opencodex-session"; /** Safe authenticated read used to validate a raw admin token before closing the sign-in form. */ const ADMIN_TOKEN_VALIDATION_PATH = "/api/settings"; diff --git a/gui/src/components/CodexAccountPool.tsx b/gui/src/components/CodexAccountPool.tsx index dcbd8d91d..f6b038676 100644 --- a/gui/src/components/CodexAccountPool.tsx +++ b/gui/src/components/CodexAccountPool.tsx @@ -250,6 +250,9 @@ export default function CodexAccountPool({ apiBase, accountModeState = null, ban const switchActionLabel = t(accountModeState === "direct" ? "codexAuth.prepareForPool" : "codexAuth.setAsNext"); const pauseBusy = pauseUpdatingId !== null || pausingExhausted; const autoSwitchThreshold = autoSwitch.threshold ?? 0; + // The standalone Codex Auth page keeps the doctor-copy affordance; the embedded + // Providers workspace account surface does not. + const showDoctorCopy = !embedded; return (
@@ -290,8 +293,8 @@ export default function CodexAccountPool({ apiBase, accountModeState = null, ban pauseUpdatingId={pauseUpdatingId} pauseBusy={pauseBusy} onOpenReset={openResetPopup} - onCopyDoctor={copyDoctor} - doctorCopyOutcomeFor={doctorCopy.outcomeFor} + onCopyDoctor={showDoctorCopy ? copyDoctor : undefined} + doctorCopyOutcomeFor={showDoctorCopy ? doctorCopy.outcomeFor : undefined} />
@@ -322,8 +325,8 @@ export default function CodexAccountPool({ apiBase, accountModeState = null, ban onReauth={openReauth} onEditAlias={editAlias} onRemove={remove} - onCopyDoctor={copyDoctor} - doctorCopyOutcomeFor={doctorCopy.outcomeFor} + onCopyDoctor={showDoctorCopy ? copyDoctor : undefined} + doctorCopyOutcomeFor={showDoctorCopy ? doctorCopy.outcomeFor : undefined} /> )} diff --git a/gui/src/components/combo-workspace-add-modal.tsx b/gui/src/components/combo-workspace-add-modal.tsx index aa8f7fb6a..cff828c5c 100644 --- a/gui/src/components/combo-workspace-add-modal.tsx +++ b/gui/src/components/combo-workspace-add-modal.tsx @@ -102,7 +102,7 @@ export function AddComboModal({
-

{t("cws.addSubtitle")}

+

{t("cws.addSubtitle")}

{error && {error}}
@@ -118,7 +118,7 @@ export function AddComboModal({ model: comboPublicModelId(e.target.value, d.alias), }))} /> -

+

{t("cws.field.idInternalHint")}

@@ -136,10 +136,10 @@ export function AddComboModal({ model: comboPublicModelId(d.id, e.target.value), }))} /> -

+

{t("cws.field.aliasHint")}

-

+

{t("cws.field.idHint", { model: draft.id.trim() ? comboPublicModelId(draft.id, draft.alias) : "…", })} @@ -152,7 +152,7 @@ export function AddComboModal({ disabled={busy} onChange={(strategy) => setDraft((d) => ({ ...d, strategy }))} /> -

+

{draft.strategy === "failover" ? t("cws.strategy.failoverHint") : t("cws.strategy.roundRobinHint")}

@@ -165,7 +165,7 @@ export function AddComboModal({ allowedEfforts={allowedEfforts} onChange={(defaultEffort) => setDraft((d) => ({ ...d, defaultEffort }))} /> -

+

{t("cws.field.defaultEffortHint")}

@@ -186,16 +186,13 @@ export function AddComboModal({ setDraft((d) => ({ ...d, stickyLimit })); }} /> -

+

{t("cws.field.stickyLimitHint")}

)}
{t("cws.targets")} -

- {draft.strategy === "failover" ? t("cws.targets.failoverHint") : t("cws.targets.roundRobinHint")} -

setDraft((d) => ({ ...d, targets }))} /> +

+ {draft.strategy === "failover" ? t("cws.targets.failoverHint") : t("cws.targets.roundRobinHint")} +

diff --git a/gui/src/components/combo-workspace-detail-panel.tsx b/gui/src/components/combo-workspace-detail-panel.tsx index 71d36f0af..caaa05bed 100644 --- a/gui/src/components/combo-workspace-detail-panel.tsx +++ b/gui/src/components/combo-workspace-detail-panel.tsx @@ -187,7 +187,7 @@ export function DetailPanel({ model: comboPublicModelId(e.target.value, d.alias), }))} /> -

+

{isCreate ? t("cws.field.idInternalHint") : t("cws.field.idHintEdit", { model: comboPublicModelId(draft.id, draft.alias) })} @@ -207,7 +207,7 @@ export function DetailPanel({ model: comboPublicModelId(d.id, e.target.value), }))} /> -

+

{t("cws.field.aliasHint")}

@@ -218,7 +218,7 @@ export function DetailPanel({ disabled={busy} onChange={(strategy) => updateDraft((d) => ({ ...d, strategy }))} /> -

+

{draft.strategy === "failover" ? t("cws.strategy.failoverHint") : t("cws.strategy.roundRobinHint")}

@@ -231,7 +231,7 @@ export function DetailPanel({ allowedEfforts={allowedEfforts} onChange={(defaultEffort) => updateDraft((d) => ({ ...d, defaultEffort }))} /> -

+

{t("cws.field.defaultEffortHint")}

@@ -256,9 +256,6 @@ export function DetailPanel({ )}
{t("cws.targets")} -

- {draft.strategy === "failover" ? t("cws.targets.failoverHint") : t("cws.targets.roundRobinHint")} -

updateDraft((d) => ({ ...d, targets }))} /> +

+ {draft.strategy === "failover" ? t("cws.targets.failoverHint") : t("cws.targets.roundRobinHint")} +

) : (

{t("cws.aboutTitle")}

-

{t("cws.aboutBody")}

+

{t("cws.aboutBody")}

)} diff --git a/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx b/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx index 243395fec..735660f2a 100644 --- a/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx +++ b/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx @@ -159,23 +159,24 @@ export default function AnthropicAccountPoolSettings({ : t("anthropicPool.disabledDesc")} - +
(); - const doctorCopy = useCopyFeedback(); // Soft "a=1 enrichment lands after the local account list. Reserve stacked // bar height briefly so bars don't shove rows when WHAM returns. @@ -206,12 +202,10 @@ export default function ProviderAuthPanel({ const switching = switchingAccountId === account.id; const healthStatus = account.health?.status; const showReauth = Boolean(account.needsReauth) || oauthHealthShowsReauth(healthStatus); - const showDoctor = oauthHealthShowsDoctor(healthStatus); const inCooldown = oauthHealthIsCooldown(healthStatus); const maskedId = displayAccountId(account.id); const healthLabel = formatOAuthHealthLabel(t, account.health); const healthSummary = formatOAuthHealthSummary(t, item.name, account.id, account.health); - const copyDoctor = () => { doctorCopy.copy(DOCTOR_CMD, account.id); }; return (
  • @@ -248,11 +242,6 @@ export default function ProviderAuthPanel({ {t("pws.reauthenticate")} )} - {showDoctor && ( - - )} - )} - {reauthBusy && onCancelLogin && ( - - )} -
    -
  • - ) : ( -
    - + )} + +
    +

    {t("pws.authSummary")}

    + {needsAttention ? ( +
    +
    - )} +
    + ) : ( +
    + + + {item.authMode === "forward" + ? t("pws.passthrough") + : item.authMode === "oauth" + ? (oauthEmail + ? t("pws.loggedInAs", { email: oauthEmail }) + : oauth?.loggedIn + ? t("pws.loggedInTitle") + : t("pws.notLoggedIn")) + : item.hasApiKey + ? t("pws.apiKeyConfigured") + : authModeLabel(item, t)} + +
    + )} +