Z ZPI 文档 v0.3.8
介绍页

源码

packages/desktop/src/shared/config.ts

typescript118 行查看原文
import type { ThinkingLevel } from "@zpi-dev/agent";
import { anthropicMessagesCompatKeys, thinkingChoices } from "@zpi-dev/ai";
import { toThinking } from "@zpi-dev/builtin-plugins/models";
import { defaultCodePreview } from "@zpi-dev/ui/code-preview";
import type { InterfacePreferences, ModelSettings, ReasoningPreset } from "./bridge.ts";

export { toThinking } from "@zpi-dev/builtin-plugins/models";
export const modelDefaults = {
  contextWindow: 1000000,
  maxTokens: 128000,
  reasoning: true,
  compat: { supportsReasoningEffort: true },
} as const;
export const sidebarLimits = {
  default: 260,
  min: 200,
  max: 420,
  collapsed: 0,
  chatMin: 400,
  resizer: 4,
} as const;
export const uiFontSizeLimits = { min: 12, max: 20 } as const;
export const taskPinLimit = 5;
export function mergeDiscoveredModels<T extends ModelSettings>(
  current: readonly T[],
  discovered: readonly T[],
): T[] {
  const previous = new Map(current.map((model) => [model.id, model]));
  const discoveredIds = new Set(discovered.map((model) => model.id));
  return [
    ...discovered.map((model) => {
      const old = previous.get(model.id);
      return old?.useRecommendedConfig === false
        ? old
        : {
            ...model,
            useRecommendedConfig: true,
            ...(old?.enabled !== undefined ? { enabled: old.enabled } : {}),
          };
    }),
    ...current.filter(
      (model) => model.id && model.useRecommendedConfig === false && !discoveredIds.has(model.id),
    ),
  ];
}
export const reasoningPresets = ["none", "low", "medium", "high", "xhigh", "max"] as const;
export const reasoningLabels: Record<string, string> = {
  none: "关闭",
  off: "关闭",
  disabled: "关闭",
  minimal: "低",
  low: "低",
  medium: "中",
  high: "高",
  xhigh: "极高",
  max: "最高",
} as const;
export const defaultPreferences: InterfacePreferences = {
  codePreview: defaultCodePreview,
  theme: "system",
  fontSize: 14,
  showContextUsage: false,
  showModelPerformance: true,
  showSendButton: false,
  notificationEnabled: true,
  notificationSoundEnabled: true,
  sidebarCollapsed: false,
  sidebarWidth: sidebarLimits.default,
  collapsedProjectIds: [],
  projectsCollapsed: false,
  tasksCollapsed: false,
};
export function toPreset(level: ThinkingLevel, model?: ModelSettings): ReasoningPreset {
  if (model?.reasoningConfig && model.reasoning !== false && model.reasoningConfig.levels.includes(level))
    return level;
  if (level === "off") return "none";
  if (level === "minimal") return "low";
  return level;
}

export function availablePresets(model: ModelSettings): ReasoningPreset[] {
  const choices = thinkingChoices(reasoningModel(model));
  if (model.reasoningConfig) return choices.map((level) => toPreset(level, model));
  return reasoningPresets.filter((preset) => choices.includes(toThinking(preset)));
}
export function reasoningModel(model: ModelSettings, api?: import("@zpi-dev/ai").ProviderApi) {
  const protocol =
    api ??
    (model as Partial<import("@zpi-dev/ai").Model>).api ??
    (anthropicMessagesCompatKeys.some((key) => model.compat?.[key] !== undefined)
      ? "anthropic-messages"
      : "openai-completions");
  return {
    api: protocol,
    reasoning: model.reasoning ?? modelDefaults.reasoning,
    compat: { ...modelDefaults.compat, ...model.compat },
    thinkingLevelMap: model.thinkingLevelMap,
    defaultThinkingLevel: model.defaultThinkingLevel,
    reasoningConfig: model.reasoningConfig,
  };
}
export function defaultPreset(model: ModelSettings): ReasoningPreset {
  const choices = availablePresets(model);
  const medium = choices.find((level) => level === "medium" || level === "中");
  return medium ?? choices[Math.floor((choices.length - 1) / 2)] ?? "none";
}

export function modelReasoningLabel(model: ModelSettings | undefined, preset: ReasoningPreset): string {
  if (
    !model?.reasoningConfig &&
    model?.reasoning &&
    preset === "high" &&
    model.compat?.supportsReasoningEffort === false
  )
    return "默认";
  return reasoningLabels[preset] ?? preset;
}