feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库

This commit is contained in:
ZhuiGuangAI Dev
2026-10-02 18:52:49 +08:00
parent b44601bb66
commit 8205ae709c
1185 changed files with 49841 additions and 12802 deletions
+27 -5
View File
@@ -15,7 +15,7 @@ const prisma = new PrismaClient({ adapter });
const openai = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/v1",
baseURL: "https://api.deepseek.com",
timeout: 120000,
maxRetries: 2,
});
@@ -290,7 +290,7 @@ async function generateDailyNews() {
}
const newsDataText = newsResults
.slice(0, 30)
.slice(0, 14)
.map((r, i) => `[${i + 1}] 标题: ${r.title}\n 内容: ${r.content || "(无摘要)"}\n 来源: ${r.url}\n 时间: ${r.pubDate || "未知"}`)
.join("\n\n");
@@ -304,12 +304,18 @@ async function generateDailyNews() {
model: process.env.DEEPSEEK_MODEL || "deepseek-v4-pro",
messages: [{ role: "user", content: prompt }],
temperature: 0.3,
}, { signal: AbortSignal.timeout(120000) });
// DeepSeek V4 reasoning token 计入 max_tokens 预算:预算不足会导致 content 为空(finish_reason=length)
max_tokens: 16384,
}, { signal: AbortSignal.timeout(180000) });
}, { maxRetries: 3, label: "DeepSeek News API" });
const u = completion.usage;
if (u) {
console.log(` ℹ️ tokens: prompt=${u.prompt_tokens} completion=${u.completion_tokens} reasoning=${u.completion_tokens_details?.reasoning_tokens ?? "n/a"} finish=${completion.choices[0]?.finish_reason}`);
}
const content = completion.choices[0]?.message?.content;
if (!content) {
throw new Error("DeepSeek 返回内容为空");
throw new Error(`DeepSeek 返回内容为空(finish_reason=${completion.choices[0]?.finish_reason},completion_tokens=${u?.completion_tokens},疑似 reasoning 占满 max_tokens)`);
}
let parsed;
@@ -367,13 +373,29 @@ async function generateDailyNews() {
return report;
}
async function generateWithRetry() {
for (let attempt = 0; attempt < 2; attempt++) {
try {
return await generateDailyNews();
} catch (e) {
const msg = String(e.message || e);
// 偶发中止/超时/上游 5xx 才重试;业务类错误直接抛出
const retryable = /abort|timeout|ETIMEDOUT|ECONNRESET|socket|fetch failed|502|503|429/i.test(msg);
if (!retryable || attempt === 1) throw e;
console.warn(`⚠️ 日报生成中止(${msg.slice(0, 80)}),30s 后重试 (${attempt + 1}/2)...`);
await new Promise((r) => setTimeout(r, 30000));
}
}
throw new Error("unreachable");
}
async function main() {
if (!process.env.DEEPSEEK_API_KEY) throw new Error("缺少环境变量: DEEPSEEK_API_KEY");
if (!process.env.DATABASE_URL) throw new Error("缺少环境变量: DATABASE_URL");
const startTime = new Date();
try {
const report = await generateDailyNews();
const report = await generateWithRetry();
const endTime = new Date();
const duration = endTime.getTime() - startTime.getTime();
await prisma.taskLog.create({