mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-05-22 13:40:16 +09:00
fix: #314
This commit is contained in:
parent
0660a50dd4
commit
40b673054b
@ -97,7 +97,7 @@ ANTHROPIC_API_VERSION=
|
|||||||
ANTHROPIC_URL=
|
ANTHROPIC_URL=
|
||||||
|
|
||||||
### (optional)
|
### (optional)
|
||||||
WHITE_WEBDEV_ENDPOINTS=
|
WHITE_WEBDAV_ENDPOINTS=
|
||||||
|
|
||||||
# (optional)
|
# (optional)
|
||||||
# Default: zh-CN-YunxiNeural
|
# Default: zh-CN-YunxiNeural
|
||||||
|
@ -309,7 +309,7 @@ For ByteDance: use `modelName@bytedance=deploymentName` to customize model name
|
|||||||
|
|
||||||
Change default model
|
Change default model
|
||||||
|
|
||||||
### `WHITE_WEBDEV_ENDPOINTS` (optional)
|
### `WHITE_WEBDAV_ENDPOINTS` (optional)
|
||||||
|
|
||||||
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
||||||
- 每一个地址必须是一个完整的 endpoint
|
- 每一个地址必须是一个完整的 endpoint
|
||||||
|
@ -188,7 +188,7 @@ ByteDance Api Url.
|
|||||||
|
|
||||||
如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。
|
如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。
|
||||||
|
|
||||||
### `WHITE_WEBDEV_ENDPOINTS` (可选)
|
### `WHITE_WEBDAV_ENDPOINTS` (可选)
|
||||||
|
|
||||||
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
||||||
- 每一个地址必须是一个完整的 endpoint
|
- 每一个地址必须是一个完整的 endpoint
|
||||||
|
@ -193,7 +193,7 @@ ByteDance API の URL。
|
|||||||
|
|
||||||
リンクからのプリセット設定解析を無効にしたい場合は、この環境変数を 1 に設定します。
|
リンクからのプリセット設定解析を無効にしたい場合は、この環境変数を 1 に設定します。
|
||||||
|
|
||||||
### `WHITE_WEBDEV_ENDPOINTS` (オプション)
|
### `WHITE_WEBDAV_ENDPOINTS` (オプション)
|
||||||
|
|
||||||
アクセス許可を与える WebDAV サービスのアドレスを追加したい場合、このオプションを使用します。フォーマット要件:
|
アクセス許可を与える WebDAV サービスのアドレスを追加したい場合、このオプションを使用します。フォーマット要件:
|
||||||
- 各アドレスは完全なエンドポイントでなければなりません。
|
- 各アドレスは完全なエンドポイントでなければなりません。
|
||||||
|
73
app/api/artifacts/route.ts
Normal file
73
app/api/artifacts/route.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import md5 from "spark-md5";
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import { getServerSideConfig } from "@/app/config/server";
|
||||||
|
|
||||||
|
async function handle(req: NextRequest, res: NextResponse) {
|
||||||
|
const serverConfig = getServerSideConfig();
|
||||||
|
const storeUrl = () =>
|
||||||
|
`https://api.cloudflare.com/client/v4/accounts/${serverConfig.cloudflareAccountId}/storage/kv/namespaces/${serverConfig.cloudflareKVNamespaceId}`;
|
||||||
|
const storeHeaders = () => ({
|
||||||
|
Authorization: `Bearer ${serverConfig.cloudflareKVApiKey}`,
|
||||||
|
});
|
||||||
|
if (req.method === "POST") {
|
||||||
|
const clonedBody = await req.text();
|
||||||
|
const hashedCode = md5.hash(clonedBody).trim();
|
||||||
|
const body: {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
expiration_ttl?: number;
|
||||||
|
} = {
|
||||||
|
key: hashedCode,
|
||||||
|
value: clonedBody,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const ttl = parseInt(serverConfig.cloudflareKVTTL as string);
|
||||||
|
if (ttl > 60) {
|
||||||
|
body["expiration_ttl"] = ttl;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
const res = await fetch(`${storeUrl()}/bulk`, {
|
||||||
|
headers: {
|
||||||
|
...storeHeaders(),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify([body]),
|
||||||
|
});
|
||||||
|
const result = await res.json();
|
||||||
|
console.log("save data", result);
|
||||||
|
if (result?.success) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ code: 0, id: hashedCode, result },
|
||||||
|
{ status: res.status },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: true, msg: "Save data error" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (req.method === "GET") {
|
||||||
|
const id = req?.nextUrl?.searchParams?.get("id");
|
||||||
|
const res = await fetch(`${storeUrl()}/values/${id}`, {
|
||||||
|
headers: storeHeaders(),
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
return new Response(res.body, {
|
||||||
|
status: res.status,
|
||||||
|
statusText: res.statusText,
|
||||||
|
headers: res.headers,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: true, msg: "Invalid request" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const POST = handle;
|
||||||
|
export const GET = handle;
|
||||||
|
|
||||||
|
export const runtime = "edge";
|
@ -121,7 +121,25 @@ export function PreCode(props: { children: any }) {
|
|||||||
codeElement.style.whiteSpace = "pre-wrap";
|
codeElement.style.whiteSpace = "pre-wrap";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setTimeout(renderArtifacts, 1);
|
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
if (
|
||||||
|
mutation.type === "characterData" ||
|
||||||
|
mutation.type === "childList"
|
||||||
|
) {
|
||||||
|
renderArtifacts();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.observe(ref.current, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
characterData: true,
|
||||||
|
});
|
||||||
|
renderArtifacts();
|
||||||
|
return () => observer.disconnect();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import md5 from "spark-md5";
|
import md5 from "spark-md5";
|
||||||
import { DEFAULT_MODELS } from "../constant";
|
import { DEFAULT_MODELS, DEFAULT_GA_ID } from "../constant";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace NodeJS {
|
namespace NodeJS {
|
||||||
@ -101,19 +101,34 @@ export const getServerSideConfig = () => {
|
|||||||
|
|
||||||
if (disableGPT4) {
|
if (disableGPT4) {
|
||||||
if (customModels) customModels += ",";
|
if (customModels) customModels += ",";
|
||||||
customModels += DEFAULT_MODELS.filter((m) => m.name.startsWith("gpt-4"))
|
customModels += DEFAULT_MODELS.filter(
|
||||||
|
(m) =>
|
||||||
|
(m.name.startsWith("gpt-4") || m.name.startsWith("chatgpt-4o")) &&
|
||||||
|
!m.name.startsWith("gpt-4o-mini"),
|
||||||
|
)
|
||||||
.map((m) => "-" + m.name)
|
.map((m) => "-" + m.name)
|
||||||
.join(",");
|
.join(",");
|
||||||
if (defaultModel.startsWith("gpt-4")) defaultModel = "";
|
if (
|
||||||
|
(defaultModel.startsWith("gpt-4") ||
|
||||||
|
defaultModel.startsWith("chatgpt-4o")) &&
|
||||||
|
!defaultModel.startsWith("gpt-4o-mini")
|
||||||
|
)
|
||||||
|
defaultModel = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isStability = !!process.env.STABILITY_API_KEY;
|
||||||
|
|
||||||
const isAzure = !!process.env.AZURE_URL;
|
const isAzure = !!process.env.AZURE_URL;
|
||||||
const isGoogle = !!process.env.GOOGLE_API_KEY;
|
const isGoogle = !!process.env.GOOGLE_API_KEY;
|
||||||
const isAnthropic = !!process.env.ANTHROPIC_API_KEY;
|
const isAnthropic = !!process.env.ANTHROPIC_API_KEY;
|
||||||
|
const isTencent = !!process.env.TENCENT_API_KEY;
|
||||||
|
|
||||||
const isBaidu = !!process.env.BAIDU_API_KEY;
|
const isBaidu = !!process.env.BAIDU_API_KEY;
|
||||||
const isBytedance = !!process.env.BYTEDANCE_API_KEY;
|
const isBytedance = !!process.env.BYTEDANCE_API_KEY;
|
||||||
const isAlibaba = !!process.env.ALIBABA_API_KEY;
|
const isAlibaba = !!process.env.ALIBABA_API_KEY;
|
||||||
|
const isMoonshot = !!process.env.MOONSHOT_API_KEY;
|
||||||
|
const isIflytek = !!process.env.IFLYTEK_API_KEY;
|
||||||
|
const isXAI = !!process.env.XAI_API_KEY;
|
||||||
// const apiKeyEnvVar = process.env.OPENAI_API_KEY ?? "";
|
// const apiKeyEnvVar = process.env.OPENAI_API_KEY ?? "";
|
||||||
// const apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim());
|
// const apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim());
|
||||||
// const randomIndex = Math.floor(Math.random() * apiKeys.length);
|
// const randomIndex = Math.floor(Math.random() * apiKeys.length);
|
||||||
@ -122,8 +137,8 @@ export const getServerSideConfig = () => {
|
|||||||
// `[Server Config] using ${randomIndex + 1} of ${apiKeys.length} api key`,
|
// `[Server Config] using ${randomIndex + 1} of ${apiKeys.length} api key`,
|
||||||
// );
|
// );
|
||||||
|
|
||||||
const allowedWebDevEndpoints = (
|
const allowedWebDavEndpoints = (
|
||||||
process.env.WHITE_WEBDEV_ENDPOINTS ?? ""
|
process.env.WHITE_WEBDAV_ENDPOINTS ?? ""
|
||||||
).split(",");
|
).split(",");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -131,6 +146,10 @@ export const getServerSideConfig = () => {
|
|||||||
apiKey: getApiKey(process.env.OPENAI_API_KEY),
|
apiKey: getApiKey(process.env.OPENAI_API_KEY),
|
||||||
openaiOrgId: process.env.OPENAI_ORG_ID,
|
openaiOrgId: process.env.OPENAI_ORG_ID,
|
||||||
|
|
||||||
|
isStability,
|
||||||
|
stabilityUrl: process.env.STABILITY_URL,
|
||||||
|
stabilityApiKey: getApiKey(process.env.STABILITY_API_KEY),
|
||||||
|
|
||||||
isAzure,
|
isAzure,
|
||||||
azureUrl: process.env.AZURE_URL,
|
azureUrl: process.env.AZURE_URL,
|
||||||
azureApiKey: getApiKey(process.env.AZURE_API_KEY),
|
azureApiKey: getApiKey(process.env.AZURE_API_KEY),
|
||||||
@ -158,7 +177,31 @@ export const getServerSideConfig = () => {
|
|||||||
alibabaUrl: process.env.ALIBABA_URL,
|
alibabaUrl: process.env.ALIBABA_URL,
|
||||||
alibabaApiKey: getApiKey(process.env.ALIBABA_API_KEY),
|
alibabaApiKey: getApiKey(process.env.ALIBABA_API_KEY),
|
||||||
|
|
||||||
|
isTencent,
|
||||||
|
tencentUrl: process.env.TENCENT_URL,
|
||||||
|
tencentSecretKey: getApiKey(process.env.TENCENT_SECRET_KEY),
|
||||||
|
tencentSecretId: process.env.TENCENT_SECRET_ID,
|
||||||
|
|
||||||
|
isMoonshot,
|
||||||
|
moonshotUrl: process.env.MOONSHOT_URL,
|
||||||
|
moonshotApiKey: getApiKey(process.env.MOONSHOT_API_KEY),
|
||||||
|
|
||||||
|
isIflytek,
|
||||||
|
iflytekUrl: process.env.IFLYTEK_URL,
|
||||||
|
iflytekApiKey: process.env.IFLYTEK_API_KEY,
|
||||||
|
iflytekApiSecret: process.env.IFLYTEK_API_SECRET,
|
||||||
|
|
||||||
|
isXAI,
|
||||||
|
xaiUrl: process.env.XAI_URL,
|
||||||
|
xaiApiKey: getApiKey(process.env.XAI_API_KEY),
|
||||||
|
|
||||||
|
cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,
|
||||||
|
cloudflareKVNamespaceId: process.env.CLOUDFLARE_KV_NAMESPACE_ID,
|
||||||
|
cloudflareKVApiKey: getApiKey(process.env.CLOUDFLARE_KV_API_KEY),
|
||||||
|
cloudflareKVTTL: process.env.CLOUDFLARE_KV_TTL,
|
||||||
|
|
||||||
gtmId: process.env.GTM_ID,
|
gtmId: process.env.GTM_ID,
|
||||||
|
gaId: process.env.GA_ID || DEFAULT_GA_ID,
|
||||||
|
|
||||||
needCode: ACCESS_CODES.size > 0,
|
needCode: ACCESS_CODES.size > 0,
|
||||||
code: process.env.CODE,
|
code: process.env.CODE,
|
||||||
@ -173,19 +216,18 @@ export const getServerSideConfig = () => {
|
|||||||
disableFastLink: !!process.env.DISABLE_FAST_LINK,
|
disableFastLink: !!process.env.DISABLE_FAST_LINK,
|
||||||
customModels,
|
customModels,
|
||||||
defaultModel,
|
defaultModel,
|
||||||
|
allowedWebDavEndpoints,
|
||||||
|
|
||||||
isStoreFileToLocal:
|
isStoreFileToLocal:
|
||||||
!!process.env.NEXT_PUBLIC_ENABLE_NODEJS_PLUGIN &&
|
!!process.env.NEXT_PUBLIC_ENABLE_NODEJS_PLUGIN &&
|
||||||
!process.env.R2_ACCOUNT_ID &&
|
!process.env.R2_ACCOUNT_ID &&
|
||||||
!process.env.S3_ENDPOINT,
|
!process.env.S3_ENDPOINT,
|
||||||
|
|
||||||
isEnableRAG: !!process.env.ENABLE_RAG,
|
isEnableRAG: !!process.env.ENABLE_RAG,
|
||||||
ragEmbeddingModel:
|
ragEmbeddingModel:
|
||||||
process.env.RAG_EMBEDDING_MODEL ?? "text-embedding-3-large",
|
process.env.RAG_EMBEDDING_MODEL ?? "text-embedding-3-large",
|
||||||
ragChunkSize: process.env.RAG_CHUNK_SIZE ?? "2000",
|
ragChunkSize: process.env.RAG_CHUNK_SIZE ?? "2000",
|
||||||
ragChunkOverlap: process.env.RAG_CHUNK_OVERLAP ?? "200",
|
ragChunkOverlap: process.env.RAG_CHUNK_OVERLAP ?? "200",
|
||||||
ragReturnCount: process.env.RAG_RETURN_COUNT ?? "4",
|
ragReturnCount: process.env.RAG_RETURN_COUNT ?? "4",
|
||||||
allowedWebDevEndpoints,
|
|
||||||
|
|
||||||
edgeTTSVoiceName: process.env.EDGE_TTS_VOICE_NAME ?? "zh-CN-YunxiNeural",
|
edgeTTSVoiceName: process.env.EDGE_TTS_VOICE_NAME ?? "zh-CN-YunxiNeural",
|
||||||
isUseOpenAIEndpointForAllModels:
|
isUseOpenAIEndpointForAllModels:
|
||||||
!!process.env.USE_OPENAI_ENDPOINT_FOR_ALL_MODELS,
|
!!process.env.USE_OPENAI_ENDPOINT_FOR_ALL_MODELS,
|
||||||
|
@ -388,6 +388,8 @@ export const internalAllowedWebDavEndpoints = [
|
|||||||
"https://app.koofr.net/dav/Koofr",
|
"https://app.koofr.net/dav/Koofr",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const DEFAULT_GA_ID = "G-89WN60ZK2E";
|
||||||
|
|
||||||
export const MYFILES_BROWSER_TOOLS_SYSTEM_PROMPT = `
|
export const MYFILES_BROWSER_TOOLS_SYSTEM_PROMPT = `
|
||||||
# Tools
|
# Tools
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user