mirror of
				https://github.com/Yidadaa/ChatGPT-Next-Web.git
				synced 2025-11-04 16:57:27 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			268 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			268 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import {
 | 
						|
  GoogleSafetySettingsThreshold,
 | 
						|
  ServiceProvider,
 | 
						|
  StoreKey,
 | 
						|
  ApiPath,
 | 
						|
  OPENAI_BASE_URL,
 | 
						|
  ANTHROPIC_BASE_URL,
 | 
						|
  GEMINI_BASE_URL,
 | 
						|
  BAIDU_BASE_URL,
 | 
						|
  BYTEDANCE_BASE_URL,
 | 
						|
  ALIBABA_BASE_URL,
 | 
						|
  TENCENT_BASE_URL,
 | 
						|
  MOONSHOT_BASE_URL,
 | 
						|
  STABILITY_BASE_URL,
 | 
						|
  IFLYTEK_BASE_URL,
 | 
						|
  XAI_BASE_URL,
 | 
						|
  CHATGLM_BASE_URL,
 | 
						|
} from "../constant";
 | 
						|
import { getHeaders } from "../client/api";
 | 
						|
import { getClientConfig } from "../config/client";
 | 
						|
import { createPersistStore } from "../utils/store";
 | 
						|
import { ensure } from "../utils/clone";
 | 
						|
import { DEFAULT_CONFIG } from "./config";
 | 
						|
import { getModelProvider } from "../utils/model";
 | 
						|
 | 
						|
let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
 | 
						|
 | 
						|
const isApp = getClientConfig()?.buildMode === "export";
 | 
						|
 | 
						|
const DEFAULT_OPENAI_URL = isApp ? OPENAI_BASE_URL : ApiPath.OpenAI;
 | 
						|
 | 
						|
const DEFAULT_GOOGLE_URL = isApp ? GEMINI_BASE_URL : ApiPath.Google;
 | 
						|
 | 
						|
const DEFAULT_ANTHROPIC_URL = isApp ? ANTHROPIC_BASE_URL : ApiPath.Anthropic;
 | 
						|
 | 
						|
const DEFAULT_BAIDU_URL = isApp ? BAIDU_BASE_URL : ApiPath.Baidu;
 | 
						|
 | 
						|
const DEFAULT_BYTEDANCE_URL = isApp ? BYTEDANCE_BASE_URL : ApiPath.ByteDance;
 | 
						|
 | 
						|
const DEFAULT_ALIBABA_URL = isApp ? ALIBABA_BASE_URL : ApiPath.Alibaba;
 | 
						|
 | 
						|
const DEFAULT_TENCENT_URL = isApp ? TENCENT_BASE_URL : ApiPath.Tencent;
 | 
						|
 | 
						|
const DEFAULT_MOONSHOT_URL = isApp ? MOONSHOT_BASE_URL : ApiPath.Moonshot;
 | 
						|
 | 
						|
const DEFAULT_STABILITY_URL = isApp ? STABILITY_BASE_URL : ApiPath.Stability;
 | 
						|
 | 
						|
const DEFAULT_IFLYTEK_URL = isApp ? IFLYTEK_BASE_URL : ApiPath.Iflytek;
 | 
						|
 | 
						|
const DEFAULT_XAI_URL = isApp ? XAI_BASE_URL : ApiPath.XAI;
 | 
						|
 | 
						|
const DEFAULT_CHATGLM_URL = isApp ? CHATGLM_BASE_URL : ApiPath.ChatGLM;
 | 
						|
 | 
						|
const DEFAULT_ACCESS_STATE = {
 | 
						|
  accessCode: "",
 | 
						|
  useCustomConfig: false,
 | 
						|
 | 
						|
  provider: ServiceProvider.OpenAI,
 | 
						|
 | 
						|
  // openai
 | 
						|
  openaiUrl: DEFAULT_OPENAI_URL,
 | 
						|
  openaiApiKey: "",
 | 
						|
 | 
						|
  // azure
 | 
						|
  azureUrl: "",
 | 
						|
  azureApiKey: "",
 | 
						|
  azureApiVersion: "2023-08-01-preview",
 | 
						|
 | 
						|
  // google ai studio
 | 
						|
  googleUrl: DEFAULT_GOOGLE_URL,
 | 
						|
  googleApiKey: "",
 | 
						|
  googleApiVersion: "v1",
 | 
						|
  googleSafetySettings: GoogleSafetySettingsThreshold.BLOCK_ONLY_HIGH,
 | 
						|
 | 
						|
  // anthropic
 | 
						|
  anthropicUrl: DEFAULT_ANTHROPIC_URL,
 | 
						|
  anthropicApiKey: "",
 | 
						|
  anthropicApiVersion: "2023-06-01",
 | 
						|
 | 
						|
  // baidu
 | 
						|
  baiduUrl: DEFAULT_BAIDU_URL,
 | 
						|
  baiduApiKey: "",
 | 
						|
  baiduSecretKey: "",
 | 
						|
 | 
						|
  // bytedance
 | 
						|
  bytedanceUrl: DEFAULT_BYTEDANCE_URL,
 | 
						|
  bytedanceApiKey: "",
 | 
						|
 | 
						|
  // alibaba
 | 
						|
  alibabaUrl: DEFAULT_ALIBABA_URL,
 | 
						|
  alibabaApiKey: "",
 | 
						|
 | 
						|
  // moonshot
 | 
						|
  moonshotUrl: DEFAULT_MOONSHOT_URL,
 | 
						|
  moonshotApiKey: "",
 | 
						|
 | 
						|
  //stability
 | 
						|
  stabilityUrl: DEFAULT_STABILITY_URL,
 | 
						|
  stabilityApiKey: "",
 | 
						|
 | 
						|
  // tencent
 | 
						|
  tencentUrl: DEFAULT_TENCENT_URL,
 | 
						|
  tencentSecretKey: "",
 | 
						|
  tencentSecretId: "",
 | 
						|
 | 
						|
  // iflytek
 | 
						|
  iflytekUrl: DEFAULT_IFLYTEK_URL,
 | 
						|
  iflytekApiKey: "",
 | 
						|
  iflytekApiSecret: "",
 | 
						|
 | 
						|
  // xai
 | 
						|
  xaiUrl: DEFAULT_XAI_URL,
 | 
						|
  xaiApiKey: "",
 | 
						|
 | 
						|
  // chatglm
 | 
						|
  chatglmUrl: DEFAULT_CHATGLM_URL,
 | 
						|
  chatglmApiKey: "",
 | 
						|
 | 
						|
  // server config
 | 
						|
  needCode: true,
 | 
						|
  hideUserApiKey: false,
 | 
						|
  hideBalanceQuery: false,
 | 
						|
  disableGPT4: false,
 | 
						|
  disableFastLink: false,
 | 
						|
  customModels: "",
 | 
						|
  defaultModel: "",
 | 
						|
 | 
						|
  // tts config
 | 
						|
  edgeTTSVoiceName: "zh-CN-YunxiNeural",
 | 
						|
};
 | 
						|
 | 
						|
export const useAccessStore = createPersistStore(
 | 
						|
  { ...DEFAULT_ACCESS_STATE },
 | 
						|
 | 
						|
  (set, get) => ({
 | 
						|
    enabledAccessControl() {
 | 
						|
      this.fetch();
 | 
						|
 | 
						|
      return get().needCode;
 | 
						|
    },
 | 
						|
 | 
						|
    edgeVoiceName() {
 | 
						|
      this.fetch();
 | 
						|
 | 
						|
      return get().edgeTTSVoiceName;
 | 
						|
    },
 | 
						|
 | 
						|
    isValidOpenAI() {
 | 
						|
      return ensure(get(), ["openaiApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidAzure() {
 | 
						|
      return ensure(get(), ["azureUrl", "azureApiKey", "azureApiVersion"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidGoogle() {
 | 
						|
      return ensure(get(), ["googleApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidAnthropic() {
 | 
						|
      return ensure(get(), ["anthropicApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidBaidu() {
 | 
						|
      return ensure(get(), ["baiduApiKey", "baiduSecretKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidByteDance() {
 | 
						|
      return ensure(get(), ["bytedanceApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidAlibaba() {
 | 
						|
      return ensure(get(), ["alibabaApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidTencent() {
 | 
						|
      return ensure(get(), ["tencentSecretKey", "tencentSecretId"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidMoonshot() {
 | 
						|
      return ensure(get(), ["moonshotApiKey"]);
 | 
						|
    },
 | 
						|
    isValidIflytek() {
 | 
						|
      return ensure(get(), ["iflytekApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidXAI() {
 | 
						|
      return ensure(get(), ["xaiApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isValidChatGLM() {
 | 
						|
      return ensure(get(), ["chatglmApiKey"]);
 | 
						|
    },
 | 
						|
 | 
						|
    isAuthorized() {
 | 
						|
      this.fetch();
 | 
						|
 | 
						|
      // has token or has code or disabled access control
 | 
						|
      return (
 | 
						|
        this.isValidOpenAI() ||
 | 
						|
        this.isValidAzure() ||
 | 
						|
        this.isValidGoogle() ||
 | 
						|
        this.isValidAnthropic() ||
 | 
						|
        this.isValidBaidu() ||
 | 
						|
        this.isValidByteDance() ||
 | 
						|
        this.isValidAlibaba() ||
 | 
						|
        this.isValidTencent() ||
 | 
						|
        this.isValidMoonshot() ||
 | 
						|
        this.isValidIflytek() ||
 | 
						|
        this.isValidXAI() ||
 | 
						|
        this.isValidChatGLM() ||
 | 
						|
        !this.enabledAccessControl() ||
 | 
						|
        (this.enabledAccessControl() && ensure(get(), ["accessCode"]))
 | 
						|
      );
 | 
						|
    },
 | 
						|
    fetch() {
 | 
						|
      if (fetchState > 0 || getClientConfig()?.buildMode === "export") return;
 | 
						|
      fetchState = 1;
 | 
						|
      fetch("/api/config", {
 | 
						|
        method: "post",
 | 
						|
        body: null,
 | 
						|
        headers: {
 | 
						|
          ...getHeaders(),
 | 
						|
        },
 | 
						|
      })
 | 
						|
        .then((res) => res.json())
 | 
						|
        .then((res) => {
 | 
						|
          const defaultModel = res.defaultModel ?? "";
 | 
						|
          if (defaultModel !== "") {
 | 
						|
            const [model, providerName] = getModelProvider(defaultModel);
 | 
						|
            DEFAULT_CONFIG.modelConfig.model = model;
 | 
						|
            DEFAULT_CONFIG.modelConfig.providerName = providerName as any;
 | 
						|
          }
 | 
						|
 | 
						|
          return res;
 | 
						|
        })
 | 
						|
        .then((res: DangerConfig) => {
 | 
						|
          console.log("[Config] got config from server", res);
 | 
						|
          set(() => ({ ...res }));
 | 
						|
        })
 | 
						|
        .catch(() => {
 | 
						|
          console.error("[Config] failed to fetch config");
 | 
						|
        })
 | 
						|
        .finally(() => {
 | 
						|
          fetchState = 2;
 | 
						|
        });
 | 
						|
    },
 | 
						|
  }),
 | 
						|
  {
 | 
						|
    name: StoreKey.Access,
 | 
						|
    version: 2,
 | 
						|
    migrate(persistedState, version) {
 | 
						|
      if (version < 2) {
 | 
						|
        const state = persistedState as {
 | 
						|
          token: string;
 | 
						|
          openaiApiKey: string;
 | 
						|
          azureApiVersion: string;
 | 
						|
          googleApiKey: string;
 | 
						|
        };
 | 
						|
        state.openaiApiKey = state.token;
 | 
						|
        state.azureApiVersion = "2023-08-01-preview";
 | 
						|
      }
 | 
						|
 | 
						|
      return persistedState as any;
 | 
						|
    },
 | 
						|
  },
 | 
						|
);
 |