koishi-plugin-best-cave 2.7.9 → 2.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +48 -28
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -727,22 +727,33 @@ var HashManager = class {
|
|
|
727
727
|
const cavesToProcess = allCaves.filter((cave2) => !hashedCaveIds.has(cave2.id));
|
|
728
728
|
if (cavesToProcess.length === 0) return "无需补全回声洞哈希";
|
|
729
729
|
await session.send(`开始补全 ${cavesToProcess.length} 个回声洞的哈希...`);
|
|
730
|
-
|
|
730
|
+
let hashesToInsert = [];
|
|
731
731
|
let processedCaveCount = 0;
|
|
732
|
+
let totalHashesGenerated = 0;
|
|
732
733
|
let errorCount = 0;
|
|
734
|
+
const flushBatch = /* @__PURE__ */ __name(async () => {
|
|
735
|
+
if (hashesToInsert.length === 0) return;
|
|
736
|
+
await this.ctx.database.upsert("cave_hash", hashesToInsert);
|
|
737
|
+
totalHashesGenerated += hashesToInsert.length;
|
|
738
|
+
this.logger.info(`[${processedCaveCount}/${cavesToProcess.length}] 正在导入 ${hashesToInsert.length} 条回声洞哈希...`);
|
|
739
|
+
hashesToInsert = [];
|
|
740
|
+
}, "flushBatch");
|
|
733
741
|
for (const cave2 of cavesToProcess) {
|
|
734
742
|
processedCaveCount++;
|
|
735
743
|
try {
|
|
736
744
|
const newHashesForCave = await this.generateAllHashesForCave(cave2);
|
|
737
|
-
if (newHashesForCave.length > 0)
|
|
745
|
+
if (newHashesForCave.length > 0) {
|
|
746
|
+
hashesToInsert.push(...newHashesForCave);
|
|
747
|
+
}
|
|
748
|
+
if (hashesToInsert.length >= 100) await flushBatch();
|
|
738
749
|
} catch (error) {
|
|
739
750
|
errorCount++;
|
|
740
751
|
this.logger.warn(`补全回声洞(${cave2.id})哈希时出错: ${error.message}`);
|
|
741
752
|
}
|
|
742
753
|
}
|
|
743
|
-
|
|
754
|
+
await flushBatch();
|
|
744
755
|
const successCount = processedCaveCount - errorCount;
|
|
745
|
-
return `已补全 ${successCount} 个回声洞的 ${
|
|
756
|
+
return `已补全 ${successCount} 个回声洞的 ${totalHashesGenerated} 条哈希(失败 ${errorCount} 条)`;
|
|
746
757
|
} catch (error) {
|
|
747
758
|
this.logger.error("补全哈希失败:", error);
|
|
748
759
|
return `操作失败: ${error.message}`;
|
|
@@ -1088,10 +1099,13 @@ var AIManager = class {
|
|
|
1088
1099
|
const formatContent = /* @__PURE__ */ __name((elements) => elements.filter((el) => el.type === "text").map((el) => el.content).join(" "), "formatContent");
|
|
1089
1100
|
const userMessage = {
|
|
1090
1101
|
role: "user",
|
|
1091
|
-
content:
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1102
|
+
content: [{
|
|
1103
|
+
type: "input_text",
|
|
1104
|
+
text: JSON.stringify({
|
|
1105
|
+
new_content: { text: formatContent(newElements) },
|
|
1106
|
+
existing_contents: potentialDuplicates.map((cave) => ({ id: cave.id, text: formatContent(cave.elements) }))
|
|
1107
|
+
})
|
|
1108
|
+
}]
|
|
1095
1109
|
};
|
|
1096
1110
|
const response = await this.requestAI([userMessage], this.config.aiCheckPrompt, this.config.aiCheckSchema);
|
|
1097
1111
|
return {
|
|
@@ -1135,7 +1149,7 @@ var AIManager = class {
|
|
|
1135
1149
|
async getAnalysis(elements, mediaToSave, mediaBuffers) {
|
|
1136
1150
|
const userContent = [];
|
|
1137
1151
|
const combinedText = elements.filter((el) => el.type === "text" && el.content).map((el) => el.content).join("\n");
|
|
1138
|
-
if (combinedText.trim()) userContent.push({ type: "
|
|
1152
|
+
if (combinedText.trim()) userContent.push({ type: "input_text", text: combinedText });
|
|
1139
1153
|
const mediaMap = new Map(mediaBuffers?.map((m) => [m.fileName, m.buffer]));
|
|
1140
1154
|
const imageElements = elements.filter((el) => el.type === "image" && el.file);
|
|
1141
1155
|
for (const el of imageElements) {
|
|
@@ -1152,8 +1166,8 @@ var AIManager = class {
|
|
|
1152
1166
|
if (buffer) {
|
|
1153
1167
|
const mimeType = path3.extname(el.file).toLowerCase() === ".png" ? "image/png" : "image/jpeg";
|
|
1154
1168
|
userContent.push({
|
|
1155
|
-
type: "
|
|
1156
|
-
image_url:
|
|
1169
|
+
type: "input_image",
|
|
1170
|
+
image_url: `data:${mimeType};base64,${buffer.toString("base64")}`
|
|
1157
1171
|
});
|
|
1158
1172
|
}
|
|
1159
1173
|
} catch (error) {
|
|
@@ -1184,22 +1198,28 @@ var AIManager = class {
|
|
|
1184
1198
|
this.rateLimitResetTime = Date.now() + 6e4;
|
|
1185
1199
|
this.requestCount = 0;
|
|
1186
1200
|
}
|
|
1187
|
-
let schema
|
|
1188
|
-
|
|
1201
|
+
let schema;
|
|
1202
|
+
try {
|
|
1203
|
+
schema = JSON.parse(schemaString);
|
|
1204
|
+
} catch (error) {
|
|
1205
|
+
this.logger.error("解析 JSON Schema 失败:", error);
|
|
1206
|
+
throw new Error("无效的 JSON Schema 配置");
|
|
1207
|
+
}
|
|
1189
1208
|
const payload = {
|
|
1190
1209
|
model: this.config.aiModel,
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1210
|
+
input: [
|
|
1211
|
+
{ role: "system", content: systemPrompt },
|
|
1212
|
+
...messages
|
|
1213
|
+
],
|
|
1214
|
+
text: {
|
|
1215
|
+
format: {
|
|
1216
|
+
type: "json_schema",
|
|
1217
|
+
name: "extracted_data",
|
|
1218
|
+
schema
|
|
1198
1219
|
}
|
|
1199
|
-
}
|
|
1200
|
-
tool_choice: { type: "function", function: { name: toolName } }
|
|
1220
|
+
}
|
|
1201
1221
|
};
|
|
1202
|
-
const fullUrl = `${this.config.aiEndpoint.replace(/\/$/, "")}/
|
|
1222
|
+
const fullUrl = `${this.config.aiEndpoint.replace(/\/$/, "")}/responses`;
|
|
1203
1223
|
const headers = {
|
|
1204
1224
|
"Content-Type": "application/json",
|
|
1205
1225
|
"Authorization": `Bearer ${this.config.aiApiKey}`
|
|
@@ -1207,9 +1227,9 @@ var AIManager = class {
|
|
|
1207
1227
|
try {
|
|
1208
1228
|
this.requestCount++;
|
|
1209
1229
|
const response = await this.http.post(fullUrl, payload, { headers, timeout: 9e4 });
|
|
1210
|
-
const
|
|
1211
|
-
if (
|
|
1212
|
-
return JSON.parse(
|
|
1230
|
+
const responseText = response.output?.[0]?.content?.[0]?.text;
|
|
1231
|
+
if (responseText) {
|
|
1232
|
+
return JSON.parse(responseText);
|
|
1213
1233
|
} else {
|
|
1214
1234
|
this.logger.error("AI 响应格式不正确:", JSON.stringify(response));
|
|
1215
1235
|
throw new Error("AI 响应格式不正确");
|
|
@@ -1249,8 +1269,8 @@ var Config = import_koishi3.Schema.intersect([
|
|
|
1249
1269
|
import_koishi3.Schema.object({
|
|
1250
1270
|
enablePend: import_koishi3.Schema.boolean().default(false).description("启用审核"),
|
|
1251
1271
|
enableSimilarity: import_koishi3.Schema.boolean().default(false).description("启用查重"),
|
|
1252
|
-
textThreshold: import_koishi3.Schema.number().min(0).max(100).step(0.01).default(
|
|
1253
|
-
imageThreshold: import_koishi3.Schema.number().min(0).max(100).step(0.01).default(
|
|
1272
|
+
textThreshold: import_koishi3.Schema.number().min(0).max(100).step(0.01).default(95).description("文本相似度阈值 (%)"),
|
|
1273
|
+
imageThreshold: import_koishi3.Schema.number().min(0).max(100).step(0.01).default(95).description("图片相似度阈值 (%)")
|
|
1254
1274
|
}).description("复核配置"),
|
|
1255
1275
|
import_koishi3.Schema.object({
|
|
1256
1276
|
enableAI: import_koishi3.Schema.boolean().default(false).description("启用 AI"),
|