access.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import {
  2. GoogleSafetySettingsThreshold,
  3. ServiceProvider,
  4. StoreKey,
  5. OPENAI_BASE_URL,
  6. ANTHROPIC_BASE_URL,
  7. GEMINI_BASE_URL,
  8. BAIDU_BASE_URL,
  9. BYTEDANCE_BASE_URL,
  10. ALIBABA_BASE_URL,
  11. TENCENT_BASE_URL,
  12. MOONSHOT_BASE_URL,
  13. STABILITY_BASE_URL,
  14. IFLYTEK_BASE_URL,
  15. } from "../constant";
  16. import { getHeaders } from "../client/api";
  17. import { getClientConfig } from "../config/client";
  18. import { createPersistStore } from "../utils/store";
  19. import { ensure } from "../utils/clone";
  20. import { DEFAULT_CONFIG } from "./config";
  21. let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
  22. const isApp = getClientConfig()?.buildMode === "export";
  23. const DEFAULT_ACCESS_STATE = {
  24. accessCode: "",
  25. useCustomConfig: false,
  26. provider: ServiceProvider.OpenAI,
  27. // openai
  28. openaiUrl: OPENAI_BASE_URL,
  29. openaiApiKey: "",
  30. // azure
  31. azureUrl: "",
  32. azureApiKey: "",
  33. azureApiVersion: "2023-08-01-preview",
  34. // google ai studio
  35. googleUrl: GEMINI_BASE_URL,
  36. googleApiKey: "",
  37. googleApiVersion: "v1",
  38. googleSafetySettings: GoogleSafetySettingsThreshold.BLOCK_ONLY_HIGH,
  39. // anthropic
  40. anthropicUrl: ANTHROPIC_BASE_URL,
  41. anthropicApiKey: "",
  42. anthropicApiVersion: "2023-06-01",
  43. // baidu
  44. baiduUrl: BAIDU_BASE_URL,
  45. baiduApiKey: "",
  46. baiduSecretKey: "",
  47. // bytedance
  48. bytedanceUrl: BYTEDANCE_BASE_URL,
  49. bytedanceApiKey: "",
  50. // alibaba
  51. alibabaUrl: ALIBABA_BASE_URL,
  52. alibabaApiKey: "",
  53. // moonshot
  54. moonshotUrl: MOONSHOT_BASE_URL,
  55. moonshotApiKey: "",
  56. //stability
  57. stabilityUrl: STABILITY_BASE_URL,
  58. stabilityApiKey: "",
  59. // tencent
  60. tencentUrl: TENCENT_BASE_URL,
  61. tencentSecretKey: "",
  62. tencentSecretId: "",
  63. // iflytek
  64. iflytekUrl: IFLYTEK_BASE_URL,
  65. iflytekApiKey: "",
  66. iflytekApiSecret: "",
  67. // server config
  68. needCode: true,
  69. hideUserApiKey: false,
  70. hideBalanceQuery: false,
  71. disableGPT4: false,
  72. disableFastLink: false,
  73. customModels: "",
  74. defaultModel: "",
  75. // tts config
  76. edgeTTSVoiceName: "zh-CN-YunxiNeural",
  77. };
  78. export const useAccessStore = createPersistStore(
  79. { ...DEFAULT_ACCESS_STATE },
  80. (set, get) => ({
  81. enabledAccessControl() {
  82. this.fetch();
  83. return get().needCode;
  84. },
  85. edgeVoiceName() {
  86. this.fetch();
  87. return get().edgeTTSVoiceName;
  88. },
  89. isValidOpenAI() {
  90. return ensure(get(), ["openaiApiKey"]);
  91. },
  92. isValidAzure() {
  93. return ensure(get(), ["azureUrl", "azureApiKey", "azureApiVersion"]);
  94. },
  95. isValidGoogle() {
  96. return ensure(get(), ["googleApiKey"]);
  97. },
  98. isValidAnthropic() {
  99. return ensure(get(), ["anthropicApiKey"]);
  100. },
  101. isValidBaidu() {
  102. return ensure(get(), ["baiduApiKey", "baiduSecretKey"]);
  103. },
  104. isValidByteDance() {
  105. return ensure(get(), ["bytedanceApiKey"]);
  106. },
  107. isValidAlibaba() {
  108. return ensure(get(), ["alibabaApiKey"]);
  109. },
  110. isValidTencent() {
  111. return ensure(get(), ["tencentSecretKey", "tencentSecretId"]);
  112. },
  113. isValidMoonshot() {
  114. return ensure(get(), ["moonshotApiKey"]);
  115. },
  116. isValidIflytek() {
  117. return ensure(get(), ["iflytekApiKey"]);
  118. },
  119. isAuthorized() {
  120. this.fetch();
  121. // has token or has code or disabled access control
  122. return (
  123. this.isValidOpenAI() ||
  124. this.isValidAzure() ||
  125. this.isValidGoogle() ||
  126. this.isValidAnthropic() ||
  127. this.isValidBaidu() ||
  128. this.isValidByteDance() ||
  129. this.isValidAlibaba() ||
  130. this.isValidTencent() ||
  131. this.isValidMoonshot() ||
  132. this.isValidIflytek() ||
  133. !this.enabledAccessControl() ||
  134. (this.enabledAccessControl() && ensure(get(), ["accessCode"]))
  135. );
  136. },
  137. fetch() {
  138. if (fetchState > 0 || getClientConfig()?.buildMode === "export") return;
  139. fetchState = 1;
  140. fetch("/api/config", {
  141. method: "post",
  142. body: null,
  143. headers: {
  144. ...getHeaders(),
  145. },
  146. })
  147. .then((res) => res.json())
  148. .then((res) => {
  149. const defaultModel = res.defaultModel ?? "";
  150. if (defaultModel !== "") {
  151. const [model, providerName] = defaultModel.split("@");
  152. DEFAULT_CONFIG.modelConfig.model = model;
  153. DEFAULT_CONFIG.modelConfig.providerName = providerName;
  154. }
  155. return res;
  156. })
  157. .then((res: DangerConfig) => {
  158. console.log("[Config] got config from server", res);
  159. set(() => ({ ...res }));
  160. })
  161. .catch(() => {
  162. console.error("[Config] failed to fetch config");
  163. })
  164. .finally(() => {
  165. fetchState = 2;
  166. });
  167. },
  168. }),
  169. {
  170. name: StoreKey.Access,
  171. version: 2,
  172. migrate(persistedState, version) {
  173. if (version < 2) {
  174. const state = persistedState as {
  175. token: string;
  176. openaiApiKey: string;
  177. azureApiVersion: string;
  178. googleApiKey: string;
  179. };
  180. state.openaiApiKey = state.token;
  181. state.azureApiVersion = "2023-08-01-preview";
  182. }
  183. return persistedState as any;
  184. },
  185. },
  186. );