fix(coding-agent,ai): show env auth source in /login

This commit is contained in:
Armin Ronacher
2026-04-23 21:01:55 +02:00
parent 05e2e9d170
commit e97051313d
10 changed files with 352 additions and 48 deletions

View File

@@ -0,0 +1,44 @@
import type { AuthCredential, AuthStatus } from "../../../core/auth-storage.js";
export type SelectorAuthType = "oauth" | "api_key";
export type AuthSelectorIndicator =
| { kind: "configured"; label: string }
| { kind: "configured-other"; label: string }
| { kind: "runtime" }
| { kind: "environment"; label: string }
| { kind: "fallback" }
| { kind: "unconfigured" };
function getConfiguredLabel(authType: SelectorAuthType): string {
return authType === "oauth" ? "subscription configured" : "api key configured";
}
export function getAuthSelectorIndicator(
authType: SelectorAuthType,
credential: AuthCredential | undefined,
authStatus?: AuthStatus,
): AuthSelectorIndicator {
if (credential) {
const label = getConfiguredLabel(credential.type);
return credential.type === authType ? { kind: "configured", label } : { kind: "configured-other", label };
}
if (authType === "oauth") {
return { kind: "unconfigured" };
}
if (authStatus?.source === "runtime") {
return { kind: "runtime" };
}
if (authStatus?.source === "environment") {
return { kind: "environment", label: authStatus.label ?? "API key" };
}
if (authStatus?.source === "fallback") {
return { kind: "fallback" };
}
return { kind: "unconfigured" };
}

View File

@@ -9,6 +9,7 @@ import {
} from "@mariozechner/pi-tui";
import type { AuthStorage } from "../../../core/auth-storage.js";
import { theme } from "../theme/theme.js";
import { getAuthSelectorIndicator } from "./auth-selector-status.js";
import { DynamicBorder } from "./dynamic-border.js";
export type AuthSelectorProvider = {
@@ -114,11 +115,7 @@ export class OAuthSelectorComponent extends Container implements Focusable {
const isSelected = i === this.selectedIndex;
// Check if user is configured for this provider
const credentials = this.authStorage.get(provider.id);
const statusIndicator = credentials
? theme.fg("success", " ✓ configured")
: theme.fg("muted", " • unconfigured");
const statusIndicator = this.formatStatusIndicator(provider);
let line = "";
if (isSelected) {
const prefix = theme.fg("accent", "→ ");
@@ -149,6 +146,32 @@ export class OAuthSelectorComponent extends Container implements Focusable {
}
}
private formatStatusIndicator(provider: AuthSelectorProvider): string {
const status = provider.authType === "api_key" ? this.authStorage.getAuthStatus(provider.id) : undefined;
const indicator = getAuthSelectorIndicator(provider.authType, this.authStorage.get(provider.id), status);
if (indicator.kind === "configured") {
return theme.fg("success", `${indicator.label}`);
}
if (indicator.kind === "configured-other") {
return theme.fg("muted", " • ") + theme.fg("warning", indicator.label);
}
const base = theme.fg("muted", " • unconfigured");
if (indicator.kind === "environment") {
return base + theme.fg("success", ` · env: ${indicator.label}`);
}
if (indicator.kind === "runtime") {
return base + theme.fg("success", " · runtime API key");
}
if (indicator.kind === "fallback") {
return base + theme.fg("success", " · custom API key");
}
return base;
}
handleInput(keyData: string): void {
const kb = getKeybindings();
// Up arrow