"use client";
import { ExternalLink, Link2Off, PlugZap } from "lucide-react";
import { Button } from "@/components/ui/Button";
import { SectionHeader } from "@/components/ui/SectionHeader";
import { StatusNote } from "@/components/ui/StatusNote";
import { authOpenUrl, formatExpiresAt } from "@/lib/settings/kimiOauth";
import { useKimiOauth } from "@/lib/settings/useKimiOauth";
interface KimiCodeOauthProps {
initialConnected: boolean;
initialExpiresAt: string | null;
}
// Kimi Code(OAuth 订阅 plan)连接区(K1.4)。
// 与 API-key 凭据行分离:无 key 输入,连接经 device flow(显示 user_code + 开授权页 + 轮询 job)。
export function KimiCodeOauth({
initialConnected,
initialExpiresAt,
}: KimiCodeOauthProps) {
const oauth = useKimiOauth({ initialConnected, initialExpiresAt });
const { phase, device, expiresAt, busy, error } = oauth;
const expiresLabel = formatExpiresAt(expiresAt);
return (
订阅 plan 经 OAuth 设备授权连接(无需 API Key)。连接后可在上方档位路由里选用
kimi-code · kimi-for-coding。
>
}
className="mb-3"
/>
{phase === "connected" ? "已连接" : "未连接"}
{phase === "connected" && expiresLabel ? (
凭据有效至 {expiresLabel}(到期自动刷新)
) : null}
{phase === "connected" ? (
) : (
)}
{phase === "awaiting" && device ? (
) : null}
{phase !== "awaiting" ? (
OAuth 连接只保存加密后的访问凭据;模型选择仍在“档位路由”里统一配置。
) : null}
{phase === "error" && error ? (
{error}
) : null}
);
}
interface DeviceInstructionsProps {
userCode: string;
openUrl: string;
}
// 设备授权指引:突出展示 user_code(可读、可选、可聚焦)+ 打开授权页按钮。
function DeviceInstructions({ userCode, openUrl }: DeviceInstructionsProps) {
const openAuth = (): void => {
if (typeof window !== "undefined") {
window.open(openUrl, "_blank", "noopener,noreferrer");
}
};
return (
请在浏览器中打开授权页,并确认页面显示的设备码与下方一致。
授权完成后本页会自动检测连接状态(设备码过期后请重新连接)。
);
}