mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-05-21 21:20:19 +09:00
fix: #314
This commit is contained in:
parent
0660a50dd4
commit
40b673054b
@ -97,7 +97,7 @@ ANTHROPIC_API_VERSION=
|
||||
ANTHROPIC_URL=
|
||||
|
||||
### (optional)
|
||||
WHITE_WEBDEV_ENDPOINTS=
|
||||
WHITE_WEBDAV_ENDPOINTS=
|
||||
|
||||
# (optional)
|
||||
# Default: zh-CN-YunxiNeural
|
||||
|
@ -309,7 +309,7 @@ For ByteDance: use `modelName@bytedance=deploymentName` to customize model name
|
||||
|
||||
Change default model
|
||||
|
||||
### `WHITE_WEBDEV_ENDPOINTS` (optional)
|
||||
### `WHITE_WEBDAV_ENDPOINTS` (optional)
|
||||
|
||||
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
||||
- 每一个地址必须是一个完整的 endpoint
|
||||
|
@ -188,7 +188,7 @@ ByteDance Api Url.
|
||||
|
||||
如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。
|
||||
|
||||
### `WHITE_WEBDEV_ENDPOINTS` (可选)
|
||||
### `WHITE_WEBDAV_ENDPOINTS` (可选)
|
||||
|
||||
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
||||
- 每一个地址必须是一个完整的 endpoint
|
||||
|
@ -193,7 +193,7 @@ ByteDance API の URL。
|
||||
|
||||
リンクからのプリセット設定解析を無効にしたい場合は、この環境変数を 1 に設定します。
|
||||
|
||||
### `WHITE_WEBDEV_ENDPOINTS` (オプション)
|
||||
### `WHITE_WEBDAV_ENDPOINTS` (オプション)
|
||||
|
||||
アクセス許可を与える 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";
|
||||
}
|
||||
});
|
||||
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 { DEFAULT_MODELS } from "../constant";
|
||||
import { DEFAULT_MODELS, DEFAULT_GA_ID } from "../constant";
|
||||
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
@ -101,19 +101,34 @@ export const getServerSideConfig = () => {
|
||||
|
||||
if (disableGPT4) {
|
||||
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)
|
||||
.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 isGoogle = !!process.env.GOOGLE_API_KEY;
|
||||
const isAnthropic = !!process.env.ANTHROPIC_API_KEY;
|
||||
const isTencent = !!process.env.TENCENT_API_KEY;
|
||||
|
||||
const isBaidu = !!process.env.BAIDU_API_KEY;
|
||||
const isBytedance = !!process.env.BYTEDANCE_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 apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim());
|
||||
// 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`,
|
||||
// );
|
||||
|
||||
const allowedWebDevEndpoints = (
|
||||
process.env.WHITE_WEBDEV_ENDPOINTS ?? ""
|
||||
const allowedWebDavEndpoints = (
|
||||
process.env.WHITE_WEBDAV_ENDPOINTS ?? ""
|
||||
).split(",");
|
||||
|
||||
return {
|
||||
@ -131,6 +146,10 @@ export const getServerSideConfig = () => {
|
||||
apiKey: getApiKey(process.env.OPENAI_API_KEY),
|
||||
openaiOrgId: process.env.OPENAI_ORG_ID,
|
||||
|
||||
isStability,
|
||||
stabilityUrl: process.env.STABILITY_URL,
|
||||
stabilityApiKey: getApiKey(process.env.STABILITY_API_KEY),
|
||||
|
||||
isAzure,
|
||||
azureUrl: process.env.AZURE_URL,
|
||||
azureApiKey: getApiKey(process.env.AZURE_API_KEY),
|
||||
@ -158,7 +177,31 @@ export const getServerSideConfig = () => {
|
||||
alibabaUrl: process.env.ALIBABA_URL,
|
||||
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,
|
||||
gaId: process.env.GA_ID || DEFAULT_GA_ID,
|
||||
|
||||
needCode: ACCESS_CODES.size > 0,
|
||||
code: process.env.CODE,
|
||||
@ -173,19 +216,18 @@ export const getServerSideConfig = () => {
|
||||
disableFastLink: !!process.env.DISABLE_FAST_LINK,
|
||||
customModels,
|
||||
defaultModel,
|
||||
allowedWebDavEndpoints,
|
||||
|
||||
isStoreFileToLocal:
|
||||
!!process.env.NEXT_PUBLIC_ENABLE_NODEJS_PLUGIN &&
|
||||
!process.env.R2_ACCOUNT_ID &&
|
||||
!process.env.S3_ENDPOINT,
|
||||
|
||||
isEnableRAG: !!process.env.ENABLE_RAG,
|
||||
ragEmbeddingModel:
|
||||
process.env.RAG_EMBEDDING_MODEL ?? "text-embedding-3-large",
|
||||
ragChunkSize: process.env.RAG_CHUNK_SIZE ?? "2000",
|
||||
ragChunkOverlap: process.env.RAG_CHUNK_OVERLAP ?? "200",
|
||||
ragReturnCount: process.env.RAG_RETURN_COUNT ?? "4",
|
||||
allowedWebDevEndpoints,
|
||||
|
||||
edgeTTSVoiceName: process.env.EDGE_TTS_VOICE_NAME ?? "zh-CN-YunxiNeural",
|
||||
isUseOpenAIEndpointForAllModels:
|
||||
!!process.env.USE_OPENAI_ENDPOINT_FOR_ALL_MODELS,
|
||||
|
@ -388,6 +388,8 @@ export const internalAllowedWebDavEndpoints = [
|
||||
"https://app.koofr.net/dav/Koofr",
|
||||
];
|
||||
|
||||
export const DEFAULT_GA_ID = "G-89WN60ZK2E";
|
||||
|
||||
export const MYFILES_BROWSER_TOOLS_SYSTEM_PROMPT = `
|
||||
# Tools
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user