mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-08-08 14:02:08 +08:00
feat: add multi-model support
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
export function deepClone<T>(obj: T) {
|
||||
export function deepClone<T>(obj: T): T {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { createWebDavClient } from "./webdav";
|
||||
import { createUpstashClient } from "./upstash";
|
||||
import { SyncStore } from "@/app/store/sync";
|
||||
|
||||
export enum ProviderType {
|
||||
WebDAV = "webdav",
|
||||
@@ -27,7 +28,7 @@ export type SyncClient = {
|
||||
|
||||
export function createSyncClient<T extends ProviderType>(
|
||||
provider: T,
|
||||
config: SyncClientConfig[T],
|
||||
store: SyncStore,
|
||||
): SyncClient {
|
||||
return SyncClients[provider](config as any) as any;
|
||||
return SyncClients[provider](store);
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ export function createUpstashClient(store: SyncStore) {
|
||||
|
||||
async get() {
|
||||
const chunkCount = Number(await this.redisGet(chunkCountKey));
|
||||
if (!Number.isInteger(chunkCount)) return;
|
||||
if (!Number.isInteger(chunkCount)) return "";
|
||||
|
||||
const chunks = await Promise.all(
|
||||
new Array(chunkCount)
|
||||
|
@@ -1,19 +1,5 @@
|
||||
import { getClientConfig } from "../config/client";
|
||||
import { ApiPath, DEFAULT_CORS_HOST } from "../constant";
|
||||
|
||||
export function corsPath(path: string) {
|
||||
const baseUrl = getClientConfig()?.isApp ? `${DEFAULT_CORS_HOST}` : "";
|
||||
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
|
||||
if (!path.endsWith("/")) {
|
||||
path += "/";
|
||||
}
|
||||
|
||||
return `${baseUrl}${path}`;
|
||||
}
|
||||
import { ApiPath } from "../constant";
|
||||
import { getApiPath } from "./path";
|
||||
|
||||
export function corsFetch(
|
||||
url: string,
|
||||
@@ -25,7 +11,7 @@ export function corsFetch(
|
||||
throw Error("[CORS Fetch] url must starts with http/https");
|
||||
}
|
||||
|
||||
let proxyUrl = options.proxyUrl ?? corsPath(ApiPath.Cors);
|
||||
let proxyUrl = options.proxyUrl ?? getApiPath(ApiPath.Cors);
|
||||
if (!proxyUrl.endsWith("/")) {
|
||||
proxyUrl += "/";
|
||||
}
|
||||
|
13
app/utils/log.ts
Normal file
13
app/utils/log.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export function createLogger(prefix = "") {
|
||||
return {
|
||||
log(...args: any[]) {
|
||||
console.log(prefix, ...args);
|
||||
},
|
||||
error(...args: any[]) {
|
||||
console.error(prefix, ...args);
|
||||
},
|
||||
warn(...args: any[]) {
|
||||
console.warn(prefix, ...args);
|
||||
},
|
||||
};
|
||||
}
|
17
app/utils/object.ts
Normal file
17
app/utils/object.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export function pick<T extends object, U extends (keyof T)[]>(
|
||||
obj: T,
|
||||
...keys: U
|
||||
): Pick<T, U[number]> {
|
||||
const ret: any = {};
|
||||
keys.forEach((key) => (ret[key] = obj[key]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function omit<T extends object, U extends (keyof T)[]>(
|
||||
obj: T,
|
||||
...keys: U
|
||||
): Omit<T, U[number]> {
|
||||
const ret: any = { ...obj };
|
||||
keys.forEach((key) => delete ret[key]);
|
||||
return ret;
|
||||
}
|
16
app/utils/path.ts
Normal file
16
app/utils/path.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { getClientConfig } from "../config/client";
|
||||
import { ApiPath, REMOTE_API_HOST } from "../constant";
|
||||
|
||||
/**
|
||||
* Get api path according to desktop/web env
|
||||
*
|
||||
* 1. In desktop app, we always try to use a remote full path for better network experience
|
||||
* 2. In web app, we always try to use the original relative path
|
||||
*
|
||||
* @param path - /api/*
|
||||
* @returns
|
||||
*/
|
||||
export function getApiPath(path: ApiPath) {
|
||||
const baseUrl = getClientConfig()?.isApp ? `${REMOTE_API_HOST}` : "";
|
||||
return `${baseUrl}${path}`;
|
||||
}
|
19
app/utils/string.ts
Normal file
19
app/utils/string.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export function trimEnd(s: string, end = " ") {
|
||||
if (end.length === 0) return s;
|
||||
|
||||
while (s.endsWith(end)) {
|
||||
s = s.slice(0, -end.length);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
export function trimStart(s: string, start = " ") {
|
||||
if (start.length === 0) return s;
|
||||
|
||||
while (s.endsWith(start)) {
|
||||
s = s.slice(start.length);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
Reference in New Issue
Block a user