mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-06 05:12:03 +08:00
feat: add model connectivity tests and harden cursor heartbeats
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import type { ModelConnectivityResult } from "../../api";
|
||||
import { Icon } from "../ui/Icon";
|
||||
import { TooltipTrigger } from "../ui/TooltipTrigger";
|
||||
import { informationOutlineIcon } from "../ui/icons";
|
||||
import styles from "./CursorSettings.module.scss";
|
||||
|
||||
export type CursorModelTestState =
|
||||
| { status: "success"; result: ModelConnectivityResult }
|
||||
| { status: "error"; error: string };
|
||||
|
||||
export function CursorModelTestResult({ state }: { state: CursorModelTestState }) {
|
||||
const success = state.status === "success";
|
||||
const summary = success
|
||||
? t("速度:{speed} tokens/s", { speed: formatSpeed(state.result.tokens_per_second) })
|
||||
: t("错误:{error}", { error: state.error });
|
||||
const detail = success
|
||||
? t("速度 {speed} tokens/s · 首字 {firstText} ms · 总耗时 {duration} ms · 输出 {tokens} tokens{estimated} · 返回:{output}", {
|
||||
speed: formatSpeed(state.result.tokens_per_second),
|
||||
firstText: state.result.first_text_ms ?? "--",
|
||||
duration: state.result.duration_ms,
|
||||
tokens: state.result.output_tokens,
|
||||
estimated: state.result.tokens_estimated ? t("(估算)") : "",
|
||||
output: state.result.output || "--",
|
||||
})
|
||||
: t("测试失败:{error}", { error: state.error });
|
||||
|
||||
return <div className={`${styles.testResult} ${success ? styles.testSuccess : styles.testError}`}>
|
||||
<span className={styles.testResultText}>{summary}</span>
|
||||
<TooltipTrigger label={detail}><span className={styles.testResultHint} tabIndex={0}><Icon icon={informationOutlineIcon} size="1.1em" /></span></TooltipTrigger>
|
||||
</div>;
|
||||
}
|
||||
|
||||
function formatSpeed(value: number) {
|
||||
return Number.isFinite(value) ? value.toFixed(1) : "0.0";
|
||||
}
|
||||
@@ -86,11 +86,46 @@
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
.testResult {
|
||||
min-width: 0;
|
||||
max-width: 220px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: type.$font-size-xs;
|
||||
}
|
||||
.testSuccess {
|
||||
color: var(--vscode-testing-iconPassed, #73c991);
|
||||
}
|
||||
.testError {
|
||||
color: var(--vscode-errorForeground, #f48771);
|
||||
}
|
||||
.testResultText {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.testResultHint {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: currentColor;
|
||||
cursor: help;
|
||||
&:focus-visible {
|
||||
outline: 1px solid var(--vscode-focusBorder);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
.editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
.editorTestResult {
|
||||
margin-top: 14px;
|
||||
}
|
||||
.command {
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
.region {
|
||||
position: fixed;
|
||||
z-index: 11000;
|
||||
z-index: 16000;
|
||||
top: calc(48px + env(safe-area-inset-top));
|
||||
right: 0;
|
||||
left: 0;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ScrollableContent } from "../virtual/ScrollableContent";
|
||||
import controls from "./Controls.module.scss";
|
||||
import styles from "./Modal.module.scss";
|
||||
|
||||
export function Modal({ id, open, title, children, busy, wide, onClose, onSubmit, closeLabel = t("取消"), submitLabel = t("保存") }: { id?: string; open: boolean; title: string; children: ReactNode; busy?: boolean; wide?: boolean; onClose: () => void; onSubmit?: () => void; closeLabel?: string; submitLabel?: string }) {
|
||||
export function Modal({ id, open, title, children, busy, wide, onClose, onSubmit, secondaryAction, closeLabel = t("取消"), submitLabel = t("保存") }: { id?: string; open: boolean; title: string; children: ReactNode; busy?: boolean; wide?: boolean; onClose: () => void; onSubmit?: () => void; secondaryAction?: ReactNode; closeLabel?: string; submitLabel?: string }) {
|
||||
const dialog = useRef<HTMLDivElement>(null);
|
||||
const closeRef = useRef(onClose);
|
||||
const busyRef = useRef(Boolean(busy));
|
||||
@@ -29,6 +29,7 @@ export function Modal({ id, open, title, children, busy, wide, onClose, onSubmit
|
||||
<ScrollableContent alwaysShowVertical className={styles.body} viewportClassName={styles.bodyViewport} contentClassName={styles.bodyContent}>{children}</ScrollableContent>
|
||||
<footer>
|
||||
<button type="button" className={controls.primary} disabled={busy} onClick={onClose}>{closeLabel}</button>
|
||||
{secondaryAction}
|
||||
{onSubmit && <button type="button" className={controls.primary} disabled={busy} onClick={onSubmit}>{busy ? t("处理中…") : submitLabel}</button>}
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user