* feat(server): add MiniMax quota fetcher Mirror the live multi-provider quota panel (#1278) for MiniMax. Resolves the bearer token from $MINIMAX_API_KEY or the MiniMax CLI config at ~/.mmx/config.json (api_key, oauth.access_token) and credentials at ~/.mmx/credentials.json, then queries the /v1/token_plan/remains endpoint on the configured region (global by default, cn when region='cn'). The response is normalized into ProviderUsage windows per model_remains entry, surfacing the interval and weekly limits with their reset times and a danger tone when the server reports status=2. * feat(app): add MiniMax brand icon for usage page The quota panel resolves the icon via resolveProviderIconName, which falls back to a generic Bot for any provider not in BUILTIN_PROVIDER_ICON_NAMES. Register 'minimax' as a built-in icon and vendor the official 24×24 brand mark (single Path, currentColor) as MiniMaxIcon so the usage card stops showing the generic robot. * refactor(server): flatten nested ternaries in MiniMax quota fetcher Greptile review on #1662 called out two nested ternaries in toIntervalWindow and toWeeklyWindow. Extract a toneForStatus helper that uses an explicit if/else chain so the same status-to-tone mapping is shared between the interval and weekly windows, and add the missing trailing newline. * fix: format
74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
import { Bot, PackagePlus } from "lucide-react-native";
|
|
import { createElement, type ComponentType } from "react";
|
|
import { SvgXml } from "react-native-svg";
|
|
import { ClaudeIcon } from "@/components/icons/claude-icon";
|
|
import { CodexIcon } from "@/components/icons/codex-icon";
|
|
import { CopilotIcon } from "@/components/icons/copilot-icon";
|
|
import { MiniMaxIcon } from "@/components/icons/minimax-icon";
|
|
import { OpenCodeIcon } from "@/components/icons/opencode-icon";
|
|
import { OmpIcon } from "@/components/icons/omp-icon";
|
|
import { PiIcon } from "@/components/icons/pi-icon";
|
|
import { ACP_PROVIDER_CATALOG } from "@/data/acp-provider-catalog";
|
|
import { resolveProviderIconName } from "@/components/provider-icon-name";
|
|
|
|
export interface ProviderIconProps {
|
|
size: number;
|
|
color: string;
|
|
}
|
|
|
|
export type ProviderIconComponent = ComponentType<ProviderIconProps>;
|
|
|
|
const BUILTIN_PROVIDER_ICONS: Record<string, ProviderIconComponent> = {
|
|
claude: ClaudeIcon as unknown as ProviderIconComponent,
|
|
codex: CodexIcon as unknown as ProviderIconComponent,
|
|
copilot: CopilotIcon as unknown as ProviderIconComponent,
|
|
kiro: PackagePlus,
|
|
minimax: MiniMaxIcon as unknown as ProviderIconComponent,
|
|
omp: OmpIcon as unknown as ProviderIconComponent,
|
|
opencode: OpenCodeIcon as unknown as ProviderIconComponent,
|
|
pi: PiIcon as unknown as ProviderIconComponent,
|
|
};
|
|
|
|
const CATALOG_ICON_SVGS = new Map(
|
|
ACP_PROVIDER_CATALOG.flatMap((entry) => (entry.iconSvg ? [[entry.id, entry.iconSvg]] : [])),
|
|
);
|
|
|
|
const catalogIconComponents = new Map<string, ProviderIconComponent>();
|
|
|
|
function createCatalogIcon(provider: string, iconSvg: string): ProviderIconComponent {
|
|
const CatalogProviderIcon: ProviderIconComponent = ({ size, color }) =>
|
|
createElement(SvgXml, {
|
|
xml: iconSvg,
|
|
width: size,
|
|
height: size,
|
|
color,
|
|
});
|
|
CatalogProviderIcon.displayName = `CatalogProviderIcon(${provider})`;
|
|
return CatalogProviderIcon;
|
|
}
|
|
|
|
function getCatalogProviderIcon(provider: string): ProviderIconComponent {
|
|
const cached = catalogIconComponents.get(provider);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
const iconSvg = CATALOG_ICON_SVGS.get(provider);
|
|
if (!iconSvg) {
|
|
return Bot;
|
|
}
|
|
const icon = createCatalogIcon(provider, iconSvg);
|
|
catalogIconComponents.set(provider, icon);
|
|
return icon;
|
|
}
|
|
|
|
export function getProviderIcon(provider: string): ProviderIconComponent {
|
|
const name = resolveProviderIconName(provider);
|
|
if (name.kind === "builtin") {
|
|
return BUILTIN_PROVIDER_ICONS[name.id];
|
|
}
|
|
if (name.kind === "catalog") {
|
|
return getCatalogProviderIcon(name.id);
|
|
}
|
|
return Bot;
|
|
}
|