import { useMemo, useState } from "react"; import { Braces, CheckCircle2, CircleAlert, Eye, Image, MessageSquareMore, Monitor, Network, Save, ShieldCheck, Sparkles, Terminal, } from "lucide-react"; import type { LucideIcon } from "lucide-react"; import { useConfigStore } from "@/store/config-store"; import type { PiSettings, PiThinkingLevel } from "@/types"; type SettingsPatch = Partial; interface Choice { value: string | number; label: string; } function Section({ icon: Icon, title, description, children, }: { icon: LucideIcon; title: string; description: string; children: React.ReactNode; }) { return (

{title}

{description}

{children}
); } function Row({ label, description, children, }: { label: string; description: string; children: React.ReactNode; }) { return (

{label}

{description}

{children}
); } function Toggle({ checked, disabled, onChange, label, }: { checked: boolean; disabled?: boolean; onChange: (checked: boolean) => void; label: string; }) { return ( ); } function Select({ value, choices, disabled, label, onChange, }: { value: string | number; choices: Choice[]; disabled?: boolean; label: string; onChange: (value: string) => void; }) { return ( ); } const BOOLEAN_CHOICES = [ { value: "true", label: "开启" }, { value: "false", label: "关闭" }, ]; const THINKING_LEVELS: PiThinkingLevel[] = [ "off", "minimal", "low", "medium", "high", "xhigh", "max", ]; export function PiCliSettingsPage() { const { settings, allModels, updateSettings } = useConfigStore(); const [savingKey, setSavingKey] = useState(null); const [saveState, setSaveState] = useState<"idle" | "saved" | "error">("idle"); const [selectedModel, setSelectedModel] = useState(""); const [modelQuery, setModelQuery] = useState(""); const save = async (key: string, patch: SettingsPatch) => { setSavingKey(key); setSaveState("idle"); const ok = await updateSettings(patch); setSavingKey(null); setSaveState(ok ? "saved" : "error"); }; const modelOptions = useMemo( () => allModels .map((model) => ({ key: `${model.providerId}/${model.id}`, label: `${model.name || model.id} · ${model.providerName}`, reasoning: model.reasoning ?? false, })) .sort((a, b) => a.label.localeCompare(b.label)), [allModels] ); const selectedModelInfo = modelOptions.find((model) => model.key === selectedModel); const visibleModelOptions = useMemo(() => { const query = modelQuery.trim().toLocaleLowerCase(); const pinnedKeys = new Set([ selectedModel, ...Object.keys(settings?.modelThinkingLevels ?? {}), ].filter(Boolean)); const pinned = modelOptions.filter((model) => pinnedKeys.has(model.key)); const matched = modelOptions.filter((model) => { if (pinnedKeys.has(model.key)) return false; return !query || `${model.label} ${model.key}`.toLocaleLowerCase().includes(query); }); return [...pinned, ...matched].slice(0, 80); }, [modelOptions, modelQuery, selectedModel, settings?.modelThinkingLevels]); const selectedThinkingLevel = selectedModel ? settings?.modelThinkingLevels?.[selectedModel] ?? "" : ""; const updateModelThinking = (value: string) => { if (!selectedModel) return; const next = { ...(settings?.modelThinkingLevels ?? {}) }; if (!value) delete next[selectedModel]; else next[selectedModel] = value as PiThinkingLevel; void save("modelThinkingLevels", { modelThinkingLevels: next }); }; if (!settings) { return (
正在读取 Pi CLI 设置…
); } const isSaving = (key: string) => savingKey === key; return (

与 Pi CLI 的 /settings 共用配置

修改后立即写入 ~/.pi/agent/settings.json;主题和默认模型仍分别在“外观”和“模型”页设置。

{savingKey && <>保存中} {!savingKey && saveState === "saved" && <>已保存} {!savingKey && saveState === "error" && <>保存失败}
void save("compaction.enabled", { compaction: { enabled: value } })} /> void save("followUpMode", { followUpMode: value as PiSettings["followUpMode"] })} /> void save("hideThinkingBlock", { hideThinkingBlock: value })} /> ({ value, label: `${value} 格` }))} onChange={(value) => void save("terminal.imageWidthCells", { terminal: { imageWidthCells: Number(value) } })} /> void save("images.autoResize", { images: { autoResize: value } })} /> void save("images.blockImages", { images: { blockImages: value } })} /> void save("showHardwareCursor", { showHardwareCursor: value })} /> ({ value, label: String(value) }))} onChange={(value) => void save("outputPad", { outputPad: Number(value) as PiSettings["outputPad"] })} /> void save("transport", { transport: value as PiSettings["transport"] })} /> void save("defaultProjectTrust", { defaultProjectTrust: value as PiSettings["defaultProjectTrust"] })} /> void save("treeFilterMode", { treeFilterMode: value as PiSettings["treeFilterMode"] })} /> void save("warnings.anthropicExtraUsage", { warnings: { anthropicExtraUsage: value } })} />
void save("fullscreenExitOutput", { fullscreenExitOutput: value as PiSettings["fullscreenExitOutput"] })} /> setModelQuery(event.target.value)} placeholder="名称、提供商或模型 ID" className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 outline-none placeholder:text-gray-600 focus:border-blue-500" />
{Object.keys(settings.modelThinkingLevels ?? {}).length > 0 && (
当前覆盖 {Object.keys(settings.modelThinkingLevels ?? {}).length} 项
{Object.entries(settings.modelThinkingLevels ?? {}).map(([model, level]) => ( ))}
)}
本页按当前安装的 Pi 0.84.4 /settings 菜单映射。未在该菜单中出现的底层实验字段不会被改写。
); }