chatlab-cli 0.30.0 → 0.30.1-beta.2
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/dist/{chat-command-UZ23GKO7.mjs → chat-command-VBDMWOKL.mjs} +8 -8
- package/dist/{chunk-RDR6PS2R.mjs → chunk-326OCJOT.mjs} +2 -2
- package/dist/{chunk-A2SANKG4.mjs → chunk-36JGKW6K.mjs} +593 -254
- package/dist/chunk-36JGKW6K.mjs.map +1 -0
- package/dist/{chunk-ZFU2CHW3.mjs → chunk-5EE2EFPE.mjs} +4 -4
- package/dist/{chunk-4IZ3WKYU.mjs → chunk-D3DPCDII.mjs} +24 -11
- package/dist/chunk-D3DPCDII.mjs.map +1 -0
- package/dist/{chunk-FCCL5Z4W.mjs → chunk-KBSAVUFV.mjs} +7 -4
- package/dist/chunk-KBSAVUFV.mjs.map +1 -0
- package/dist/{chunk-7BZLS2KW.mjs → chunk-LVEJHB3X.mjs} +242 -236
- package/dist/chunk-LVEJHB3X.mjs.map +1 -0
- package/dist/{chunk-M55KW2HA.mjs → chunk-M2PXDX4G.mjs} +14 -12
- package/dist/chunk-M2PXDX4G.mjs.map +1 -0
- package/dist/{chunk-5UBHNQFZ.mjs → chunk-TCZHG3G7.mjs} +2 -2
- package/dist/{chunk-CNSYXRJP.mjs → chunk-TEX44HNL.mjs} +16 -12
- package/dist/chunk-TEX44HNL.mjs.map +1 -0
- package/dist/{chunk-P3ZOLTGS.mjs → chunk-ULNRUS55.mjs} +5 -3
- package/dist/chunk-ULNRUS55.mjs.map +1 -0
- package/dist/{chunk-MUPILWAZ.mjs → chunk-WV5GSRQM.mjs} +2 -2
- package/dist/cli.mjs +7 -7
- package/dist/contacts-worker.mjs +2 -2
- package/dist/{http-UWRA5FLB.mjs → http-L4AMELPZ.mjs} +11 -11
- package/dist/{import-745KQL7N.mjs → import-WWCSXGVS.mjs} +7 -7
- package/dist/index.mjs +11 -11
- package/dist/{mcp-UHN5JOHC.mjs → mcp-A4M3LT5O.mjs} +8 -8
- package/dist/people-relationships-worker.mjs +2 -2
- package/dist/semantic-index-worker.mjs +1 -1
- package/dist/{src-Y7MDRXLJ.mjs → src-MPNBTFOE.mjs} +8 -6
- package/dist/{stream-import-3JMXQD7P.mjs → stream-import-HIE7PNL4.mjs} +7 -7
- package/dist/{worker-runtime-63RYMGZI.mjs → worker-runtime-BJXO24XX.mjs} +5 -5
- package/dist-web/assets/{BufferResource-BVdJ_I5X.js → BufferResource-DPkMC1wo.js} +1 -1
- package/dist-web/assets/{CanvasRenderer-BaRuT54R.js → CanvasRenderer-DokMtSX9.js} +1 -1
- package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-N5CoiJzN.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-Ceg-0WOD.js} +4 -4
- package/dist-web/assets/{Filter-B7cNFtuE.js → Filter-Bo_p3BVX.js} +1 -1
- package/dist-web/assets/{MessageExportModal-B2Qm6VVj.js → MessageExportModal-Ch0tqQix.js} +1 -1
- package/dist-web/assets/{PageHeader-PjlWy9fC.js → PageHeader-CRlmZoKw.js} +1 -1
- package/dist-web/assets/{RelationshipGalaxyCanvas-11MafciW.js → RelationshipGalaxyCanvas-W_6XfPOG.js} +3 -3
- package/dist-web/assets/{RelationshipGalaxyThreeCanvas-C1I4B8NX.js → RelationshipGalaxyThreeCanvas-bB1nCwQ_.js} +1 -1
- package/dist-web/assets/{RenderTargetSystem-Chkz1WlI.js → RenderTargetSystem-obRi6fMT.js} +1 -1
- package/dist-web/assets/{WebGLRenderer-xK19ru58.js → WebGLRenderer-xcDlnrCZ.js} +1 -1
- package/dist-web/assets/{WebGPURenderer-CL5ZaKsn.js → WebGPURenderer-DbAOiiYr.js} +1 -1
- package/dist-web/assets/{browserAll-CyyNzRD_.js → browserAll-DVRJimO8.js} +1 -1
- package/dist-web/assets/{electron-MXaTKaMu.js → electron-BSGRuxX9.js} +1 -1
- package/dist-web/assets/{fetch-D1dDiFO4.js → fetch-7UN4YW3A.js} +1 -1
- package/dist-web/assets/{fetch-DaaJwT-5.js → fetch-B2alAySK.js} +1 -1
- package/dist-web/assets/{fetch-DpnIGZSN.js → fetch-B2rVTMYY.js} +1 -1
- package/dist-web/assets/{fetch-DTwdRTXM.js → fetch-BSShKcMt.js} +1 -1
- package/dist-web/assets/{fetch-DsTgYu_X.js → fetch-BmxMf3I6.js} +1 -1
- package/dist-web/assets/{fetch-u9GTMhMF.js → fetch-CR5UDFW7.js} +1 -1
- package/dist-web/assets/{fetch-DsE-xcP2.js → fetch-ChAsglT5.js} +1 -1
- package/dist-web/assets/{fetch-hKE53UO4.js → fetch-DWEjTdcP.js} +1 -1
- package/dist-web/assets/{fetch-DDnVXGte.js → fetch-DfoxedXR.js} +1 -1
- package/dist-web/assets/{fetch-DeA0ztwT.js → fetch-t0WsRKHW.js} +1 -1
- package/dist-web/assets/{index-BcXLcFnV.css → index-B4l3rHie.css} +1 -1
- package/dist-web/assets/{index-DqtXt3wl.js → index-BVUTV9_w.js} +1 -1
- package/dist-web/assets/{index-DFCYmzGE.js → index-BmXNdMV5.js} +2 -2
- package/dist-web/assets/index-BsXljrlg.js +22 -0
- package/dist-web/assets/index-CQ5lRCHt.js +173 -0
- package/dist-web/assets/{index-Btr5H7d-.js → index-CZv0ZOID.js} +2 -2
- package/dist-web/assets/{index-DqXHRIhI.js → index-CfgDqd_z.js} +1 -1
- package/dist-web/assets/{index-BnHKyESZ.js → index-CtVR_KuP.js} +1 -1
- package/dist-web/assets/{index-Dszv-QFp.js → index-DT0Bu8mH.js} +3 -3
- package/dist-web/assets/{index-DzLrWGXu.js → index-DjcWJv4b.js} +1 -1
- package/dist-web/assets/{web-DPVWfPS-.js → web-knHSvvNj.js} +1 -1
- package/dist-web/assets/{webworkerAll-DF5QV_vN.js → webworkerAll-CMKoykfD.js} +1 -1
- package/dist-web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-4IZ3WKYU.mjs.map +0 -1
- package/dist/chunk-7BZLS2KW.mjs.map +0 -1
- package/dist/chunk-A2SANKG4.mjs.map +0 -1
- package/dist/chunk-CNSYXRJP.mjs.map +0 -1
- package/dist/chunk-FCCL5Z4W.mjs.map +0 -1
- package/dist/chunk-M55KW2HA.mjs.map +0 -1
- package/dist/chunk-P3ZOLTGS.mjs.map +0 -1
- package/dist-web/assets/index-BVkE4qis.js +0 -22
- package/dist-web/assets/index-D04LWJop.js +0 -173
- /package/dist/{chat-command-UZ23GKO7.mjs.map → chat-command-VBDMWOKL.mjs.map} +0 -0
- /package/dist/{chunk-RDR6PS2R.mjs.map → chunk-326OCJOT.mjs.map} +0 -0
- /package/dist/{chunk-ZFU2CHW3.mjs.map → chunk-5EE2EFPE.mjs.map} +0 -0
- /package/dist/{chunk-5UBHNQFZ.mjs.map → chunk-TCZHG3G7.mjs.map} +0 -0
- /package/dist/{chunk-MUPILWAZ.mjs.map → chunk-WV5GSRQM.mjs.map} +0 -0
- /package/dist/{http-UWRA5FLB.mjs.map → http-L4AMELPZ.mjs.map} +0 -0
- /package/dist/{import-745KQL7N.mjs.map → import-WWCSXGVS.mjs.map} +0 -0
- /package/dist/{mcp-UHN5JOHC.mjs.map → mcp-A4M3LT5O.mjs.map} +0 -0
- /package/dist/{src-Y7MDRXLJ.mjs.map → src-MPNBTFOE.mjs.map} +0 -0
- /package/dist/{stream-import-3JMXQD7P.mjs.map → stream-import-HIE7PNL4.mjs.map} +0 -0
- /package/dist/{worker-runtime-63RYMGZI.mjs.map → worker-runtime-BJXO24XX.mjs.map} +0 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
createEmptyContactsDiagnostics,
|
|
10
10
|
normalizeContactsTimeRangePreset,
|
|
11
11
|
resolveContactsTimeRange
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-TEX44HNL.mjs";
|
|
13
13
|
import {
|
|
14
14
|
PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION,
|
|
15
15
|
buildPeopleRelationshipsNeighborhoodGraph,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
computePeopleRelationshipsSnapshot,
|
|
19
19
|
normalizePeopleRelationshipsTimeRangePreset,
|
|
20
20
|
resolvePeopleRelationshipsTimeRange
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-WV5GSRQM.mjs";
|
|
22
22
|
import {
|
|
23
23
|
BUILTIN_MODELS,
|
|
24
24
|
BUILTIN_PROVIDERS,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
updateMemberAliases,
|
|
81
81
|
updateSessionOwnerId,
|
|
82
82
|
writeAuthProfile
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-LVEJHB3X.mjs";
|
|
84
84
|
import {
|
|
85
85
|
__commonJS,
|
|
86
86
|
__export,
|
|
@@ -2837,128 +2837,29 @@ function writeParseResultToDb(db, meta, members, messages) {
|
|
|
2837
2837
|
return { messageCount, memberCount: members.length, skippedCount };
|
|
2838
2838
|
}
|
|
2839
2839
|
|
|
2840
|
-
// ../../packages/node-runtime/src/import/perf-logger.ts
|
|
2841
|
-
import * as fs from "fs";
|
|
2842
|
-
import * as path from "path";
|
|
2843
|
-
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
2844
|
-
LogLevel2["ERROR"] = "ERROR";
|
|
2845
|
-
LogLevel2["INFO"] = "INFO";
|
|
2846
|
-
return LogLevel2;
|
|
2847
|
-
})(LogLevel || {});
|
|
2848
|
-
var lastLogTime = Date.now();
|
|
2849
|
-
var lastMessageCount = 0;
|
|
2850
|
-
var currentLogFile = null;
|
|
2851
|
-
var errorCount = 0;
|
|
2852
|
-
function initPerfLog(sessionId, logDir) {
|
|
2853
|
-
try {
|
|
2854
|
-
if (!fs.existsSync(logDir)) {
|
|
2855
|
-
fs.mkdirSync(logDir, { recursive: true });
|
|
2856
|
-
}
|
|
2857
|
-
currentLogFile = path.join(logDir, `import_${sessionId}_${Date.now()}.log`);
|
|
2858
|
-
fs.writeFileSync(currentLogFile, `=== Import Log ===
|
|
2859
|
-
Start time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
2860
|
-
|
|
2861
|
-
`, "utf-8");
|
|
2862
|
-
} catch {
|
|
2863
|
-
}
|
|
2864
|
-
}
|
|
2865
|
-
function logPerf(event, messagesProcessed, batchSize) {
|
|
2866
|
-
const now = Date.now();
|
|
2867
|
-
const duration = now - lastLogTime;
|
|
2868
|
-
const messagesDelta = messagesProcessed - lastMessageCount;
|
|
2869
|
-
const speed = duration > 0 ? Math.round(messagesDelta / duration * 1e3) : 0;
|
|
2870
|
-
let memory = 0;
|
|
2871
|
-
try {
|
|
2872
|
-
const used = process.memoryUsage();
|
|
2873
|
-
memory = Math.round(used.heapUsed / 1024 / 1024);
|
|
2874
|
-
} catch {
|
|
2875
|
-
}
|
|
2876
|
-
const logLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${event} | messages: ${messagesProcessed.toLocaleString()} | elapsed: ${duration}ms | speed: ${speed.toLocaleString()}/s | memory: ${memory}MB` + (batchSize ? ` | batch: ${batchSize}` : "") + "\n";
|
|
2877
|
-
if (currentLogFile) {
|
|
2878
|
-
try {
|
|
2879
|
-
fs.appendFileSync(currentLogFile, logLine, "utf-8");
|
|
2880
|
-
} catch {
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
lastLogTime = now;
|
|
2884
|
-
lastMessageCount = messagesProcessed;
|
|
2885
|
-
}
|
|
2886
|
-
function logPerfDetail(detail) {
|
|
2887
|
-
if (currentLogFile) {
|
|
2888
|
-
try {
|
|
2889
|
-
fs.appendFileSync(currentLogFile, ` ${detail}
|
|
2890
|
-
`, "utf-8");
|
|
2891
|
-
} catch {
|
|
2892
|
-
}
|
|
2893
|
-
}
|
|
2894
|
-
}
|
|
2895
|
-
function resetPerfLog() {
|
|
2896
|
-
lastLogTime = Date.now();
|
|
2897
|
-
lastMessageCount = 0;
|
|
2898
|
-
currentLogFile = null;
|
|
2899
|
-
errorCount = 0;
|
|
2900
|
-
}
|
|
2901
|
-
function getCurrentLogFile() {
|
|
2902
|
-
return currentLogFile;
|
|
2903
|
-
}
|
|
2904
|
-
function writeLogLine(level, message) {
|
|
2905
|
-
if (!currentLogFile) return;
|
|
2906
|
-
const logLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] ${message}
|
|
2907
|
-
`;
|
|
2908
|
-
try {
|
|
2909
|
-
fs.appendFileSync(currentLogFile, logLine, "utf-8");
|
|
2910
|
-
} catch {
|
|
2911
|
-
}
|
|
2912
|
-
}
|
|
2913
|
-
function logError(message, error) {
|
|
2914
|
-
errorCount++;
|
|
2915
|
-
const errorDetail = error ? `: ${error.message}` : "";
|
|
2916
|
-
writeLogLine("ERROR" /* ERROR */, `${message}${errorDetail}`);
|
|
2917
|
-
}
|
|
2918
|
-
function logInfo(message) {
|
|
2919
|
-
writeLogLine("INFO" /* INFO */, message);
|
|
2920
|
-
}
|
|
2921
|
-
function getErrorCount() {
|
|
2922
|
-
return errorCount;
|
|
2923
|
-
}
|
|
2924
|
-
function logSummary(totalMessages, totalMembers) {
|
|
2925
|
-
if (!currentLogFile) return;
|
|
2926
|
-
const summary = `
|
|
2927
|
-
=== Import Summary ===
|
|
2928
|
-
End time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
2929
|
-
Total messages: ${totalMessages.toLocaleString()}
|
|
2930
|
-
Total members: ${totalMembers.toLocaleString()}
|
|
2931
|
-
Errors: ${errorCount}
|
|
2932
|
-
`;
|
|
2933
|
-
try {
|
|
2934
|
-
fs.appendFileSync(currentLogFile, summary, "utf-8");
|
|
2935
|
-
} catch {
|
|
2936
|
-
}
|
|
2937
|
-
}
|
|
2938
|
-
|
|
2939
2840
|
// ../../packages/parser/src/index.ts
|
|
2940
|
-
import * as
|
|
2941
|
-
import * as
|
|
2841
|
+
import * as fs17 from "fs";
|
|
2842
|
+
import * as path13 from "path";
|
|
2942
2843
|
|
|
2943
2844
|
// ../../packages/parser/src/sniffer.ts
|
|
2944
|
-
import * as
|
|
2945
|
-
import * as
|
|
2845
|
+
import * as fs from "fs";
|
|
2846
|
+
import * as path from "path";
|
|
2946
2847
|
var HEAD_SIZE = 64 * 1024;
|
|
2947
2848
|
function readFileHead(filePath, size = HEAD_SIZE) {
|
|
2948
|
-
const fd =
|
|
2849
|
+
const fd = fs.openSync(filePath, "r");
|
|
2949
2850
|
const buffer = Buffer.alloc(size);
|
|
2950
|
-
const bytesRead =
|
|
2951
|
-
|
|
2851
|
+
const bytesRead = fs.readSync(fd, buffer, 0, size, 0);
|
|
2852
|
+
fs.closeSync(fd);
|
|
2952
2853
|
return buffer.slice(0, bytesRead).toString("utf-8");
|
|
2953
2854
|
}
|
|
2954
2855
|
function getExtension(filePath) {
|
|
2955
|
-
return
|
|
2856
|
+
return path.extname(filePath).toLowerCase();
|
|
2956
2857
|
}
|
|
2957
2858
|
function matchHeadSignatures(headContent, patterns) {
|
|
2958
2859
|
return patterns.some((pattern) => pattern.test(headContent));
|
|
2959
2860
|
}
|
|
2960
2861
|
function matchFilenameSignatures(filePath, patterns) {
|
|
2961
|
-
const filename =
|
|
2862
|
+
const filename = path.basename(filePath);
|
|
2962
2863
|
return patterns.some((pattern) => pattern.test(filename));
|
|
2963
2864
|
}
|
|
2964
2865
|
function matchRequiredFields(headContent, fields) {
|
|
@@ -3106,18 +3007,18 @@ var import_stream_json = __toESM(require_stream_json(), 1);
|
|
|
3106
3007
|
var import_Pick = __toESM(require_Pick(), 1);
|
|
3107
3008
|
var import_StreamValues = __toESM(require_StreamValues(), 1);
|
|
3108
3009
|
var import_stream_chain = __toESM(require_stream_chain(), 1);
|
|
3109
|
-
import * as
|
|
3010
|
+
import * as fs3 from "fs";
|
|
3110
3011
|
|
|
3111
3012
|
// ../../packages/parser/src/utils.ts
|
|
3112
|
-
import * as
|
|
3013
|
+
import * as fs2 from "fs";
|
|
3113
3014
|
function getFileSize(filePath) {
|
|
3114
|
-
return
|
|
3015
|
+
return fs2.statSync(filePath).size;
|
|
3115
3016
|
}
|
|
3116
3017
|
function readFileHeadBytes(filePath, size) {
|
|
3117
|
-
const fd =
|
|
3018
|
+
const fd = fs2.openSync(filePath, "r");
|
|
3118
3019
|
const buffer = Buffer.alloc(size);
|
|
3119
|
-
const bytesRead =
|
|
3120
|
-
|
|
3020
|
+
const bytesRead = fs2.readSync(fd, buffer, 0, size, 0);
|
|
3021
|
+
fs2.closeSync(fd);
|
|
3121
3022
|
return buffer.slice(0, bytesRead).toString("utf-8");
|
|
3122
3023
|
}
|
|
3123
3024
|
var createProgress = (stage, bytesRead, totalBytes, messagesProcessed, message) => {
|
|
@@ -3147,13 +3048,185 @@ function isValidYear(timestampSeconds) {
|
|
|
3147
3048
|
}
|
|
3148
3049
|
|
|
3149
3050
|
// ../../packages/parser/src/formats/chatlab.ts
|
|
3150
|
-
import * as
|
|
3051
|
+
import * as path2 from "path";
|
|
3052
|
+
|
|
3053
|
+
// ../../packages/parser/src/native/loader.ts
|
|
3054
|
+
import { createRequire } from "module";
|
|
3055
|
+
var cachedModule;
|
|
3056
|
+
var cachedLoadError;
|
|
3057
|
+
function isNativeDisabled() {
|
|
3058
|
+
return process.env.CHATLAB_DISABLE_NATIVE_PERF === "1";
|
|
3059
|
+
}
|
|
3060
|
+
function isNativeParserModule(value) {
|
|
3061
|
+
return typeof value?.NativeParser === "function";
|
|
3062
|
+
}
|
|
3063
|
+
function requireNativeModule() {
|
|
3064
|
+
const requireFn = createRequire(import.meta.url);
|
|
3065
|
+
const module = requireFn("@openchatlab/parser-native");
|
|
3066
|
+
if (!isNativeParserModule(module)) {
|
|
3067
|
+
throw new Error("Native parser module missing NativeParser export");
|
|
3068
|
+
}
|
|
3069
|
+
return module;
|
|
3070
|
+
}
|
|
3071
|
+
function loadNativeParser() {
|
|
3072
|
+
if (isNativeDisabled()) return null;
|
|
3073
|
+
if (cachedModule !== void 0) return cachedModule;
|
|
3074
|
+
try {
|
|
3075
|
+
cachedModule = requireNativeModule();
|
|
3076
|
+
} catch (error) {
|
|
3077
|
+
cachedModule = null;
|
|
3078
|
+
cachedLoadError = error instanceof Error ? error.message : String(error);
|
|
3079
|
+
}
|
|
3080
|
+
return cachedModule;
|
|
3081
|
+
}
|
|
3082
|
+
function getNativeParserStatus() {
|
|
3083
|
+
if (isNativeDisabled()) return { available: false, disabled: true };
|
|
3084
|
+
const module = loadNativeParser();
|
|
3085
|
+
return { available: module !== null, disabled: false, error: module ? void 0 : cachedLoadError };
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
// ../../packages/parser/src/native/create-native-parser.ts
|
|
3089
|
+
var PROGRESS_POLL_INTERVAL_MS = 200;
|
|
3090
|
+
async function* pumpNativeParser(adapter, options2, parser11, fallback) {
|
|
3091
|
+
const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
|
|
3092
|
+
const totalBytes = getFileSize(filePath);
|
|
3093
|
+
const initialProgress = createProgress("parsing", 0, totalBytes, 0, "");
|
|
3094
|
+
yield { type: "progress", data: initialProgress };
|
|
3095
|
+
onProgress?.(initialProgress);
|
|
3096
|
+
onLog?.(
|
|
3097
|
+
"info",
|
|
3098
|
+
`[NativeParser] Parsing ${adapter.label} with Rust kernel, size: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`
|
|
3099
|
+
);
|
|
3100
|
+
const progressTimer = setInterval(() => {
|
|
3101
|
+
const progress = parser11.progress();
|
|
3102
|
+
onProgress?.(
|
|
3103
|
+
createProgress(
|
|
3104
|
+
"parsing",
|
|
3105
|
+
progress.bytesRead,
|
|
3106
|
+
totalBytes,
|
|
3107
|
+
progress.messagesProcessed,
|
|
3108
|
+
`\u5DF2\u5904\u7406 ${progress.messagesProcessed} \u6761\u6D88\u606F...`
|
|
3109
|
+
)
|
|
3110
|
+
);
|
|
3111
|
+
}, PROGRESS_POLL_INTERVAL_MS);
|
|
3112
|
+
try {
|
|
3113
|
+
await parser11.parse();
|
|
3114
|
+
} catch (error) {
|
|
3115
|
+
onLog?.(
|
|
3116
|
+
"warn",
|
|
3117
|
+
`[NativeParser] Rust parse failed, falling back to TS parser: ${error instanceof Error ? error.message : String(error)}`
|
|
3118
|
+
);
|
|
3119
|
+
yield* fallback(options2);
|
|
3120
|
+
return;
|
|
3121
|
+
} finally {
|
|
3122
|
+
clearInterval(progressTimer);
|
|
3123
|
+
}
|
|
3124
|
+
const metaJson = JSON.parse(parser11.metaJson());
|
|
3125
|
+
yield { type: "meta", data: adapter.mapMeta(metaJson) };
|
|
3126
|
+
const members = adapter.mapMembers(parser11.takeMembers(), metaJson);
|
|
3127
|
+
yield { type: "members", data: members };
|
|
3128
|
+
let messagesProcessed = 0;
|
|
3129
|
+
while (true) {
|
|
3130
|
+
const batch = parser11.takeBatch(batchSize);
|
|
3131
|
+
if (!batch) break;
|
|
3132
|
+
messagesProcessed += batch.length;
|
|
3133
|
+
yield { type: "messages", data: batch.map((message) => adapter.mapMessage(message, metaJson)) };
|
|
3134
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
3135
|
+
}
|
|
3136
|
+
const doneProgress = createProgress("done", totalBytes, totalBytes, messagesProcessed, "");
|
|
3137
|
+
yield { type: "progress", data: doneProgress };
|
|
3138
|
+
onProgress?.(doneProgress);
|
|
3139
|
+
onLog?.("info", `\u89E3\u6790\u5B8C\u6210: ${messagesProcessed} \u6761\u6D88\u606F, ${members.length} \u4E2A\u6210\u5458`);
|
|
3140
|
+
yield { type: "done", data: { messageCount: messagesProcessed, memberCount: members.length } };
|
|
3141
|
+
}
|
|
3142
|
+
function createNativeFirstParser(adapter, fallback) {
|
|
3143
|
+
return async function* (options2) {
|
|
3144
|
+
const native = loadNativeParser();
|
|
3145
|
+
if (!native) {
|
|
3146
|
+
yield* fallback(options2);
|
|
3147
|
+
return;
|
|
3148
|
+
}
|
|
3149
|
+
let parser11;
|
|
3150
|
+
try {
|
|
3151
|
+
parser11 = new native.NativeParser(
|
|
3152
|
+
adapter.formatId,
|
|
3153
|
+
options2.filePath,
|
|
3154
|
+
options2.formatOptions ? JSON.stringify(options2.formatOptions) : void 0
|
|
3155
|
+
);
|
|
3156
|
+
} catch (error) {
|
|
3157
|
+
options2.onLog?.(
|
|
3158
|
+
"warn",
|
|
3159
|
+
`[NativeParser] Failed to create Rust parser, falling back to TS parser: ${error instanceof Error ? error.message : String(error)}`
|
|
3160
|
+
);
|
|
3161
|
+
yield* fallback(options2);
|
|
3162
|
+
return;
|
|
3163
|
+
}
|
|
3164
|
+
yield* pumpNativeParser(adapter, options2, parser11, fallback);
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
// ../../packages/parser/src/native/chatlab-native.ts
|
|
3169
|
+
function toParsedMember(member, fromHead) {
|
|
3170
|
+
if (!fromHead) {
|
|
3171
|
+
return {
|
|
3172
|
+
platformId: member.platformId,
|
|
3173
|
+
accountName: member.accountName,
|
|
3174
|
+
groupNickname: member.groupNickname
|
|
3175
|
+
};
|
|
3176
|
+
}
|
|
3177
|
+
return {
|
|
3178
|
+
platformId: member.platformId,
|
|
3179
|
+
accountName: member.accountName,
|
|
3180
|
+
groupNickname: member.groupNickname,
|
|
3181
|
+
avatar: member.avatar,
|
|
3182
|
+
// Role objects pass through with their original key set ({id} or {id, name}).
|
|
3183
|
+
roles: member.roles?.map((role) => role.name !== void 0 ? { id: role.id, name: role.name } : { id: role.id })
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
var chatlabAdapter = {
|
|
3187
|
+
formatId: "chatlab",
|
|
3188
|
+
label: "ChatLab JSON",
|
|
3189
|
+
mapMeta(metaJson) {
|
|
3190
|
+
const meta = metaJson;
|
|
3191
|
+
return {
|
|
3192
|
+
name: meta.name,
|
|
3193
|
+
platform: meta.platform,
|
|
3194
|
+
type: meta.chatType,
|
|
3195
|
+
groupId: meta.groupId ?? void 0,
|
|
3196
|
+
groupAvatar: meta.groupAvatar ?? void 0
|
|
3197
|
+
};
|
|
3198
|
+
},
|
|
3199
|
+
mapMembers(members, metaJson) {
|
|
3200
|
+
const fromHead = metaJson.membersFromHead;
|
|
3201
|
+
return members.map((member) => toParsedMember(member, fromHead));
|
|
3202
|
+
},
|
|
3203
|
+
mapMessage(message) {
|
|
3204
|
+
return {
|
|
3205
|
+
senderPlatformId: message.senderPlatformId,
|
|
3206
|
+
senderAccountName: message.senderAccountName,
|
|
3207
|
+
senderGroupNickname: message.senderGroupNickname,
|
|
3208
|
+
// The kernel rejects non-number timestamps, so this is always set.
|
|
3209
|
+
timestamp: message.timestamp,
|
|
3210
|
+
type: message.messageType,
|
|
3211
|
+
// The kernel rejects a missing content key, so undefined here always
|
|
3212
|
+
// means the source value was JSON null.
|
|
3213
|
+
content: message.content ?? null,
|
|
3214
|
+
platformMessageId: message.platformMessageId,
|
|
3215
|
+
replyToMessageId: message.replyToMessageId
|
|
3216
|
+
};
|
|
3217
|
+
}
|
|
3218
|
+
};
|
|
3219
|
+
function withNativeChatlab(fallback) {
|
|
3220
|
+
return createNativeFirstParser(chatlabAdapter, fallback);
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
// ../../packages/parser/src/formats/chatlab.ts
|
|
3151
3224
|
var { parser } = import_stream_json.default;
|
|
3152
3225
|
var { pick } = import_Pick.default;
|
|
3153
3226
|
var { streamValues } = import_StreamValues.default;
|
|
3154
3227
|
var { chain } = import_stream_chain.default;
|
|
3155
3228
|
function extractNameFromFilePath(filePath) {
|
|
3156
|
-
const basename13 =
|
|
3229
|
+
const basename13 = path2.basename(filePath);
|
|
3157
3230
|
const name = basename13.replace(/\.json$/i, "");
|
|
3158
3231
|
return name || "\u672A\u77E5\u7FA4\u804A";
|
|
3159
3232
|
}
|
|
@@ -3242,7 +3315,7 @@ async function* parseChatLab(options2) {
|
|
|
3242
3315
|
const memberMapFromMessages = /* @__PURE__ */ new Map();
|
|
3243
3316
|
const messageBatch = [];
|
|
3244
3317
|
await new Promise((resolve2, reject) => {
|
|
3245
|
-
const readStream =
|
|
3318
|
+
const readStream = fs3.createReadStream(filePath, { encoding: "utf-8" });
|
|
3246
3319
|
readStream.on("data", (chunk) => {
|
|
3247
3320
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
3248
3321
|
});
|
|
@@ -3311,9 +3384,10 @@ async function* parseChatLab(options2) {
|
|
|
3311
3384
|
}
|
|
3312
3385
|
};
|
|
3313
3386
|
}
|
|
3387
|
+
var parseChatLabAccelerated = withNativeChatlab(parseChatLab);
|
|
3314
3388
|
var parser_ = {
|
|
3315
3389
|
feature,
|
|
3316
|
-
parse:
|
|
3390
|
+
parse: parseChatLabAccelerated
|
|
3317
3391
|
};
|
|
3318
3392
|
var module_ = {
|
|
3319
3393
|
feature,
|
|
@@ -3322,11 +3396,11 @@ var module_ = {
|
|
|
3322
3396
|
var chatlab_default = module_;
|
|
3323
3397
|
|
|
3324
3398
|
// ../../packages/parser/src/formats/chatlab-jsonl.ts
|
|
3325
|
-
import * as
|
|
3399
|
+
import * as fs4 from "fs";
|
|
3326
3400
|
import * as readline from "readline";
|
|
3327
|
-
import * as
|
|
3401
|
+
import * as path3 from "path";
|
|
3328
3402
|
function extractNameFromFilePath2(filePath) {
|
|
3329
|
-
const basename13 =
|
|
3403
|
+
const basename13 = path3.basename(filePath);
|
|
3330
3404
|
const name = basename13.replace(/\.jsonl$/i, "");
|
|
3331
3405
|
return name || "\u672A\u77E5\u7FA4\u804A";
|
|
3332
3406
|
}
|
|
@@ -3367,7 +3441,7 @@ async function* parseChatLabJsonl(options2) {
|
|
|
3367
3441
|
const messageBatch = [];
|
|
3368
3442
|
let meta = null;
|
|
3369
3443
|
let headerParsed = false;
|
|
3370
|
-
const fileStream =
|
|
3444
|
+
const fileStream = fs4.createReadStream(filePath, { encoding: "utf-8" });
|
|
3371
3445
|
const rl = readline.createInterface({
|
|
3372
3446
|
input: fileStream,
|
|
3373
3447
|
crlfDelay: Infinity
|
|
@@ -3490,16 +3564,16 @@ var import_stream_json3 = __toESM(require_stream_json(), 1);
|
|
|
3490
3564
|
var import_Pick3 = __toESM(require_Pick(), 1);
|
|
3491
3565
|
var import_StreamValues3 = __toESM(require_StreamValues(), 1);
|
|
3492
3566
|
var import_stream_chain3 = __toESM(require_stream_chain(), 1);
|
|
3493
|
-
import * as
|
|
3494
|
-
import * as
|
|
3567
|
+
import * as fs6 from "fs";
|
|
3568
|
+
import * as path5 from "path";
|
|
3495
3569
|
|
|
3496
3570
|
// ../../packages/parser/src/formats/shuakami-qq-preprocessor.ts
|
|
3497
3571
|
var import_stream_json2 = __toESM(require_stream_json(), 1);
|
|
3498
3572
|
var import_Pick2 = __toESM(require_Pick(), 1);
|
|
3499
3573
|
var import_StreamValues2 = __toESM(require_StreamValues(), 1);
|
|
3500
3574
|
var import_stream_chain2 = __toESM(require_stream_chain(), 1);
|
|
3501
|
-
import * as
|
|
3502
|
-
import * as
|
|
3575
|
+
import * as fs5 from "fs";
|
|
3576
|
+
import * as path4 from "path";
|
|
3503
3577
|
import * as os from "os";
|
|
3504
3578
|
var { parser: parser3 } = import_stream_json2.default;
|
|
3505
3579
|
var { pick: pick2 } = import_Pick2.default;
|
|
@@ -3507,11 +3581,11 @@ var { streamValues: streamValues2 } = import_StreamValues2.default;
|
|
|
3507
3581
|
var { chain: chain2 } = import_stream_chain2.default;
|
|
3508
3582
|
var PREPROCESS_THRESHOLD = 50 * 1024 * 1024;
|
|
3509
3583
|
function getTempDir() {
|
|
3510
|
-
return
|
|
3584
|
+
return path4.join(os.tmpdir(), "chatlab");
|
|
3511
3585
|
}
|
|
3512
3586
|
function ensureDir(dir) {
|
|
3513
|
-
if (!
|
|
3514
|
-
|
|
3587
|
+
if (!fs5.existsSync(dir)) {
|
|
3588
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
3515
3589
|
}
|
|
3516
3590
|
}
|
|
3517
3591
|
function extractJsonObject(content, key) {
|
|
@@ -3553,12 +3627,12 @@ function extractJsonObject(content, key) {
|
|
|
3553
3627
|
}
|
|
3554
3628
|
function readAvatarsFromFile(filePath) {
|
|
3555
3629
|
try {
|
|
3556
|
-
const stats =
|
|
3630
|
+
const stats = fs5.statSync(filePath);
|
|
3557
3631
|
const tailSize = Math.min(stats.size, 5e6);
|
|
3558
|
-
const fd =
|
|
3632
|
+
const fd = fs5.openSync(filePath, "r");
|
|
3559
3633
|
const buffer = Buffer.alloc(tailSize);
|
|
3560
|
-
|
|
3561
|
-
|
|
3634
|
+
fs5.readSync(fd, buffer, 0, tailSize, stats.size - tailSize);
|
|
3635
|
+
fs5.closeSync(fd);
|
|
3562
3636
|
const tailContent = buffer.toString("utf-8");
|
|
3563
3637
|
return extractJsonObject(tailContent, "avatars");
|
|
3564
3638
|
} catch {
|
|
@@ -3617,15 +3691,15 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3617
3691
|
let messagesProcessed = 0;
|
|
3618
3692
|
const tempDir = getTempDir();
|
|
3619
3693
|
ensureDir(tempDir);
|
|
3620
|
-
const outputFilename = `slim_${Date.now()}_${
|
|
3621
|
-
const outputPath =
|
|
3694
|
+
const outputFilename = `slim_${Date.now()}_${path4.basename(inputPath)}`;
|
|
3695
|
+
const outputPath = path4.join(tempDir, outputFilename);
|
|
3622
3696
|
onProgress?.(createProgress("parsing", 0, totalBytes, 0, ""));
|
|
3623
3697
|
const avatarsStr = readAvatarsFromFile(inputPath);
|
|
3624
3698
|
return new Promise((resolve2, reject) => {
|
|
3625
3699
|
const headChunks = [];
|
|
3626
3700
|
let headSize = 0;
|
|
3627
3701
|
const maxHeadSize = 1e5;
|
|
3628
|
-
const headStream =
|
|
3702
|
+
const headStream = fs5.createReadStream(inputPath, { encoding: "utf-8" });
|
|
3629
3703
|
let chatInfo = { name: "\u672A\u77E5\u7FA4\u804A", type: "group" };
|
|
3630
3704
|
let metadata;
|
|
3631
3705
|
let statistics;
|
|
@@ -3662,8 +3736,8 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3662
3736
|
} catch {
|
|
3663
3737
|
}
|
|
3664
3738
|
onProgress?.(createProgress("parsing", 0, totalBytes, 0, ""));
|
|
3665
|
-
const readStream =
|
|
3666
|
-
const writeStream =
|
|
3739
|
+
const readStream = fs5.createReadStream(inputPath, { encoding: "utf-8" });
|
|
3740
|
+
const writeStream = fs5.createWriteStream(outputPath, { encoding: "utf-8" });
|
|
3667
3741
|
readStream.on("data", (chunk) => {
|
|
3668
3742
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
3669
3743
|
});
|
|
@@ -3708,8 +3782,8 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3708
3782
|
});
|
|
3709
3783
|
pipeline2.on("error", (err) => {
|
|
3710
3784
|
writeStream.destroy();
|
|
3711
|
-
if (
|
|
3712
|
-
|
|
3785
|
+
if (fs5.existsSync(outputPath)) {
|
|
3786
|
+
fs5.unlinkSync(outputPath);
|
|
3713
3787
|
}
|
|
3714
3788
|
onProgress?.(createProgress("error", bytesRead, totalBytes, messagesProcessed, err.message));
|
|
3715
3789
|
reject(err);
|
|
@@ -3720,8 +3794,8 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3720
3794
|
}
|
|
3721
3795
|
function cleanupTempFile(filePath) {
|
|
3722
3796
|
try {
|
|
3723
|
-
if (
|
|
3724
|
-
|
|
3797
|
+
if (fs5.existsSync(filePath) && filePath.includes(getTempDir())) {
|
|
3798
|
+
fs5.unlinkSync(filePath);
|
|
3725
3799
|
}
|
|
3726
3800
|
} catch {
|
|
3727
3801
|
}
|
|
@@ -3788,7 +3862,7 @@ function extractJsonObject2(content, key) {
|
|
|
3788
3862
|
return null;
|
|
3789
3863
|
}
|
|
3790
3864
|
function extractNameFromFilePath3(filePath) {
|
|
3791
|
-
const basename13 =
|
|
3865
|
+
const basename13 = path5.basename(filePath);
|
|
3792
3866
|
return basename13.replace(/\.json$/i, "") || "\u672A\u77E5\u7FA4\u804A";
|
|
3793
3867
|
}
|
|
3794
3868
|
function countSenders(content) {
|
|
@@ -3873,7 +3947,7 @@ async function* parseV4(options2) {
|
|
|
3873
3947
|
const memberMap = /* @__PURE__ */ new Map();
|
|
3874
3948
|
const messageBatch = [];
|
|
3875
3949
|
await new Promise((resolve2, reject) => {
|
|
3876
|
-
const readStream =
|
|
3950
|
+
const readStream = fs6.createReadStream(filePath, { encoding: "utf-8" });
|
|
3877
3951
|
readStream.on("data", (chunk) => {
|
|
3878
3952
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
3879
3953
|
});
|
|
@@ -3931,12 +4005,12 @@ async function* parseV4(options2) {
|
|
|
3931
4005
|
});
|
|
3932
4006
|
const avatarsMap = /* @__PURE__ */ new Map();
|
|
3933
4007
|
try {
|
|
3934
|
-
const stats =
|
|
4008
|
+
const stats = fs6.statSync(filePath);
|
|
3935
4009
|
const tailSize = Math.min(stats.size, 5e6);
|
|
3936
|
-
const fd =
|
|
4010
|
+
const fd = fs6.openSync(filePath, "r");
|
|
3937
4011
|
const buffer = Buffer.alloc(tailSize);
|
|
3938
|
-
|
|
3939
|
-
|
|
4012
|
+
fs6.readSync(fd, buffer, 0, tailSize, stats.size - tailSize);
|
|
4013
|
+
fs6.closeSync(fd);
|
|
3940
4014
|
const tailContent = buffer.toString("utf-8");
|
|
3941
4015
|
const avatarsStr = extractJsonObject2(tailContent, "avatars");
|
|
3942
4016
|
if (avatarsStr) {
|
|
@@ -3988,8 +4062,8 @@ var module_3 = {
|
|
|
3988
4062
|
var shuakami_qq_exporter_default = module_3;
|
|
3989
4063
|
|
|
3990
4064
|
// ../../packages/parser/src/formats/shuakami-qq-exporter-chunked.ts
|
|
3991
|
-
import * as
|
|
3992
|
-
import * as
|
|
4065
|
+
import * as fs7 from "fs";
|
|
4066
|
+
import * as path6 from "path";
|
|
3993
4067
|
import * as readline2 from "readline";
|
|
3994
4068
|
var feature4 = {
|
|
3995
4069
|
id: "shuakami-qq-exporter-chunked",
|
|
@@ -4038,7 +4112,7 @@ function convertMessageType2(msgType, content, isRecalled) {
|
|
|
4038
4112
|
return 0 /* TEXT */;
|
|
4039
4113
|
}
|
|
4040
4114
|
function readManifest(manifestPath) {
|
|
4041
|
-
const content =
|
|
4115
|
+
const content = fs7.readFileSync(manifestPath, "utf-8");
|
|
4042
4116
|
return JSON.parse(content);
|
|
4043
4117
|
}
|
|
4044
4118
|
function getChunkRelativePath(chunk) {
|
|
@@ -4056,9 +4130,9 @@ function calculateTotalBytes(manifest, baseDir) {
|
|
|
4056
4130
|
let total = 0;
|
|
4057
4131
|
for (const chunk of manifest.chunked.chunks) {
|
|
4058
4132
|
const relativePath = getChunkRelativePath(chunk);
|
|
4059
|
-
const chunkPath =
|
|
4060
|
-
if (
|
|
4061
|
-
total +=
|
|
4133
|
+
const chunkPath = path6.join(baseDir, relativePath);
|
|
4134
|
+
if (fs7.existsSync(chunkPath)) {
|
|
4135
|
+
total += fs7.statSync(chunkPath).size;
|
|
4062
4136
|
}
|
|
4063
4137
|
}
|
|
4064
4138
|
return total;
|
|
@@ -4066,10 +4140,10 @@ function calculateTotalBytes(manifest, baseDir) {
|
|
|
4066
4140
|
function readAvatars(baseDir, avatarsInfo) {
|
|
4067
4141
|
const avatarsMap = /* @__PURE__ */ new Map();
|
|
4068
4142
|
if (!avatarsInfo?.file) return avatarsMap;
|
|
4069
|
-
const avatarsPath =
|
|
4070
|
-
if (!
|
|
4143
|
+
const avatarsPath = path6.join(baseDir, avatarsInfo.file);
|
|
4144
|
+
if (!fs7.existsSync(avatarsPath)) return avatarsMap;
|
|
4071
4145
|
try {
|
|
4072
|
-
const content =
|
|
4146
|
+
const content = fs7.readFileSync(avatarsPath, "utf-8");
|
|
4073
4147
|
const avatars = JSON.parse(content);
|
|
4074
4148
|
for (const [uin, avatar] of Object.entries(avatars)) {
|
|
4075
4149
|
if (avatar && typeof avatar === "string" && avatar.startsWith("data:image/")) {
|
|
@@ -4087,7 +4161,7 @@ async function* readJsonlFile(filePath, onParseError) {
|
|
|
4087
4161
|
let parseErrorCount = 0;
|
|
4088
4162
|
const MAX_PARSE_ERRORS_TO_LOG = 10;
|
|
4089
4163
|
try {
|
|
4090
|
-
fileStream =
|
|
4164
|
+
fileStream = fs7.createReadStream(filePath, { encoding: "utf-8" });
|
|
4091
4165
|
rl = readline2.createInterface({
|
|
4092
4166
|
input: fileStream,
|
|
4093
4167
|
crlfDelay: Infinity
|
|
@@ -4118,7 +4192,7 @@ async function* readJsonlFile(filePath, onParseError) {
|
|
|
4118
4192
|
async function* parseChunkedJsonl(options2) {
|
|
4119
4193
|
const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
|
|
4120
4194
|
const manifestPath = filePath;
|
|
4121
|
-
const baseDir =
|
|
4195
|
+
const baseDir = path6.dirname(manifestPath);
|
|
4122
4196
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 manifest: ${manifestPath}`);
|
|
4123
4197
|
onLog?.("info", `\u57FA\u7840\u76EE\u5F55: ${baseDir}`);
|
|
4124
4198
|
let manifest;
|
|
@@ -4172,13 +4246,13 @@ async function* parseChunkedJsonl(options2) {
|
|
|
4172
4246
|
for (let chunkIndex = 0; chunkIndex < manifest.chunked.chunks.length; chunkIndex++) {
|
|
4173
4247
|
const chunkInfo = manifest.chunked.chunks[chunkIndex];
|
|
4174
4248
|
const relativePath = getChunkRelativePath(chunkInfo);
|
|
4175
|
-
const chunkPath =
|
|
4249
|
+
const chunkPath = path6.join(baseDir, relativePath);
|
|
4176
4250
|
const chunkMessageCount = getChunkMessageCount(chunkInfo);
|
|
4177
|
-
if (!
|
|
4251
|
+
if (!fs7.existsSync(chunkPath)) {
|
|
4178
4252
|
onLog?.("error", `\u5206\u5757\u6587\u4EF6\u4E0D\u5B58\u5728: ${chunkPath}`);
|
|
4179
4253
|
continue;
|
|
4180
4254
|
}
|
|
4181
|
-
const chunkSize =
|
|
4255
|
+
const chunkSize = fs7.statSync(chunkPath).size;
|
|
4182
4256
|
let chunkMessagesRead = 0;
|
|
4183
4257
|
let chunkParseErrors = 0;
|
|
4184
4258
|
onLog?.(
|
|
@@ -4300,8 +4374,49 @@ var import_stream_json4 = __toESM(require_stream_json(), 1);
|
|
|
4300
4374
|
var import_Pick4 = __toESM(require_Pick(), 1);
|
|
4301
4375
|
var import_StreamValues4 = __toESM(require_StreamValues(), 1);
|
|
4302
4376
|
var import_stream_chain4 = __toESM(require_stream_chain(), 1);
|
|
4303
|
-
import * as
|
|
4304
|
-
import * as
|
|
4377
|
+
import * as fs8 from "fs";
|
|
4378
|
+
import * as path7 from "path";
|
|
4379
|
+
|
|
4380
|
+
// ../../packages/parser/src/native/weflow-native.ts
|
|
4381
|
+
var weflowAdapter = {
|
|
4382
|
+
formatId: "weflow",
|
|
4383
|
+
label: "WeFlow export",
|
|
4384
|
+
mapMeta(metaJson) {
|
|
4385
|
+
const meta = metaJson;
|
|
4386
|
+
return {
|
|
4387
|
+
name: meta.name,
|
|
4388
|
+
platform: KNOWN_PLATFORMS.WECHAT,
|
|
4389
|
+
type: meta.chatType === "private" ? "private" /* PRIVATE */ : "group" /* GROUP */,
|
|
4390
|
+
groupId: meta.groupId ?? void 0,
|
|
4391
|
+
groupAvatar: meta.groupAvatar ?? void 0,
|
|
4392
|
+
ownerId: meta.ownerId ?? void 0
|
|
4393
|
+
};
|
|
4394
|
+
},
|
|
4395
|
+
mapMembers(members) {
|
|
4396
|
+
return members.map((member) => ({
|
|
4397
|
+
platformId: member.platformId,
|
|
4398
|
+
accountName: member.accountName,
|
|
4399
|
+
avatar: member.avatar
|
|
4400
|
+
}));
|
|
4401
|
+
},
|
|
4402
|
+
mapMessage(message) {
|
|
4403
|
+
return {
|
|
4404
|
+
// The kernel always emits an id string (String(localId), JS semantics).
|
|
4405
|
+
platformMessageId: message.platformMessageId,
|
|
4406
|
+
senderPlatformId: message.senderPlatformId,
|
|
4407
|
+
senderAccountName: message.senderAccountName,
|
|
4408
|
+
// WeFlow has no separate group nickname field (same as the TS parser).
|
|
4409
|
+
senderGroupNickname: void 0,
|
|
4410
|
+
// The TS parser passes createTime through as-is, including null.
|
|
4411
|
+
timestamp: message.timestamp ?? null,
|
|
4412
|
+
type: message.messageType,
|
|
4413
|
+
content: message.content ?? null
|
|
4414
|
+
};
|
|
4415
|
+
}
|
|
4416
|
+
};
|
|
4417
|
+
function withNativeWeflow(fallback) {
|
|
4418
|
+
return createNativeFirstParser(weflowAdapter, fallback);
|
|
4419
|
+
}
|
|
4305
4420
|
|
|
4306
4421
|
// ../../packages/parser/src/formats/weflow-preprocessor.ts
|
|
4307
4422
|
var weflowPreprocessor = {
|
|
@@ -4333,7 +4448,7 @@ var { pick: pick4 } = import_Pick4.default;
|
|
|
4333
4448
|
var { streamValues: streamValues4 } = import_StreamValues4.default;
|
|
4334
4449
|
var { chain: chain4 } = import_stream_chain4.default;
|
|
4335
4450
|
function extractNameFromFilePath4(filePath) {
|
|
4336
|
-
const basename13 =
|
|
4451
|
+
const basename13 = path7.basename(filePath);
|
|
4337
4452
|
const name = basename13.replace(/\.json$/i, "");
|
|
4338
4453
|
return name || "\u672A\u77E5\u804A\u5929";
|
|
4339
4454
|
}
|
|
@@ -4402,7 +4517,7 @@ async function* parseWeFlow(options2) {
|
|
|
4402
4517
|
let session = null;
|
|
4403
4518
|
try {
|
|
4404
4519
|
await new Promise((resolve2) => {
|
|
4405
|
-
const sessionStream =
|
|
4520
|
+
const sessionStream = fs8.createReadStream(filePath, { encoding: "utf-8" });
|
|
4406
4521
|
let sessionContent = "";
|
|
4407
4522
|
let inSession = false;
|
|
4408
4523
|
let braceDepth = 0;
|
|
@@ -4525,7 +4640,7 @@ async function* parseWeFlow(options2) {
|
|
|
4525
4640
|
if (avatarsMap.size === 0) {
|
|
4526
4641
|
try {
|
|
4527
4642
|
await new Promise((resolve2) => {
|
|
4528
|
-
const avatarStream =
|
|
4643
|
+
const avatarStream = fs8.createReadStream(filePath, { encoding: "utf-8" });
|
|
4529
4644
|
let avatarsContent = "";
|
|
4530
4645
|
let inAvatars = false;
|
|
4531
4646
|
let braceDepth = 0;
|
|
@@ -4592,7 +4707,7 @@ async function* parseWeFlow(options2) {
|
|
|
4592
4707
|
let ownerId;
|
|
4593
4708
|
try {
|
|
4594
4709
|
await new Promise((resolve2) => {
|
|
4595
|
-
const scanStream =
|
|
4710
|
+
const scanStream = fs8.createReadStream(filePath, { encoding: "utf-8" });
|
|
4596
4711
|
const scanPipeline = chain4([scanStream, parser5(), pick4({ filter: /^messages\.\d+$/ }), streamValues4()]);
|
|
4597
4712
|
scanPipeline.on("data", ({ value }) => {
|
|
4598
4713
|
if (value.isSend === 1 && value.senderUsername && !value.senderUsername.endsWith("@chatroom")) {
|
|
@@ -4618,7 +4733,7 @@ async function* parseWeFlow(options2) {
|
|
|
4618
4733
|
const memberMap = /* @__PURE__ */ new Map();
|
|
4619
4734
|
const messageBatch = [];
|
|
4620
4735
|
await new Promise((resolve2, reject) => {
|
|
4621
|
-
const readStream =
|
|
4736
|
+
const readStream = fs8.createReadStream(filePath, { encoding: "utf-8" });
|
|
4622
4737
|
readStream.on("data", (chunk) => {
|
|
4623
4738
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
4624
4739
|
});
|
|
@@ -4713,9 +4828,10 @@ async function* parseWeFlow(options2) {
|
|
|
4713
4828
|
data: { messageCount: messagesProcessed, memberCount: memberMap.size }
|
|
4714
4829
|
};
|
|
4715
4830
|
}
|
|
4831
|
+
var parseWeFlowAccelerated = withNativeWeflow(parseWeFlow);
|
|
4716
4832
|
var parser_4 = {
|
|
4717
4833
|
feature: feature5,
|
|
4718
|
-
parse:
|
|
4834
|
+
parse: parseWeFlowAccelerated
|
|
4719
4835
|
};
|
|
4720
4836
|
var module_5 = {
|
|
4721
4837
|
feature: feature5,
|
|
@@ -4740,7 +4856,7 @@ var feature6 = {
|
|
|
4740
4856
|
};
|
|
4741
4857
|
var parser_5 = {
|
|
4742
4858
|
feature: feature6,
|
|
4743
|
-
parse:
|
|
4859
|
+
parse: parseWeFlowAccelerated
|
|
4744
4860
|
};
|
|
4745
4861
|
var module_6 = {
|
|
4746
4862
|
feature: feature6,
|
|
@@ -4754,7 +4870,7 @@ var import_stream_json5 = __toESM(require_stream_json(), 1);
|
|
|
4754
4870
|
var import_Pick5 = __toESM(require_Pick(), 1);
|
|
4755
4871
|
var import_StreamValues5 = __toESM(require_StreamValues(), 1);
|
|
4756
4872
|
var import_stream_chain5 = __toESM(require_stream_chain(), 1);
|
|
4757
|
-
import * as
|
|
4873
|
+
import * as fs9 from "fs";
|
|
4758
4874
|
var { parser: parser6 } = import_stream_json5.default;
|
|
4759
4875
|
var { pick: pick5 } = import_Pick5.default;
|
|
4760
4876
|
var { streamValues: streamValues5 } = import_StreamValues5.default;
|
|
@@ -4904,7 +5020,7 @@ async function* parseDiscordExporter(options2) {
|
|
|
4904
5020
|
const memberMap = /* @__PURE__ */ new Map();
|
|
4905
5021
|
const messageBatch = [];
|
|
4906
5022
|
await new Promise((resolve2, reject) => {
|
|
4907
|
-
const readStream =
|
|
5023
|
+
const readStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
4908
5024
|
readStream.on("data", (chunk) => {
|
|
4909
5025
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
4910
5026
|
});
|
|
@@ -5020,7 +5136,7 @@ var import_stream_chain6 = __toESM(require_stream_chain(), 1);
|
|
|
5020
5136
|
var import_stream_json6 = __toESM(require_stream_json(), 1);
|
|
5021
5137
|
var import_Pick6 = __toESM(require_Pick(), 1);
|
|
5022
5138
|
var import_StreamValues6 = __toESM(require_StreamValues(), 1);
|
|
5023
|
-
import * as
|
|
5139
|
+
import * as fs10 from "fs";
|
|
5024
5140
|
|
|
5025
5141
|
// ../../packages/parser/src/formats/utils/telegram-utils.ts
|
|
5026
5142
|
function mapChatType(telegramType) {
|
|
@@ -5106,7 +5222,7 @@ var feature8 = {
|
|
|
5106
5222
|
async function scanChats(filePath) {
|
|
5107
5223
|
const chats = [];
|
|
5108
5224
|
return new Promise((resolve2, reject) => {
|
|
5109
|
-
const readStream =
|
|
5225
|
+
const readStream = fs10.createReadStream(filePath, { encoding: "utf-8" });
|
|
5110
5226
|
const pipeline2 = chain6([readStream, parser7(), pick6({ filter: /^chats\.list\.\d+$/ }), streamValues6()]);
|
|
5111
5227
|
pipeline2.on("data", ({ value }) => {
|
|
5112
5228
|
const chat = value;
|
|
@@ -5139,7 +5255,7 @@ async function* parseTelegram(options2) {
|
|
|
5139
5255
|
onLog?.("info", `\u76EE\u6807\u804A\u5929\u7D22\u5F15: ${chatIndex}`);
|
|
5140
5256
|
const chatPathFilter = `chats.list.${chatIndex}`;
|
|
5141
5257
|
const chatData = await new Promise((resolve2, reject) => {
|
|
5142
|
-
const readStream =
|
|
5258
|
+
const readStream = fs10.createReadStream(filePath, { encoding: "utf-8" });
|
|
5143
5259
|
readStream.on("data", (chunk) => {
|
|
5144
5260
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
5145
5261
|
});
|
|
@@ -5247,7 +5363,7 @@ var telegram_native_default = module_8;
|
|
|
5247
5363
|
var import_stream_chain7 = __toESM(require_stream_chain(), 1);
|
|
5248
5364
|
var import_stream_json7 = __toESM(require_stream_json(), 1);
|
|
5249
5365
|
var import_StreamValues7 = __toESM(require_StreamValues(), 1);
|
|
5250
|
-
import * as
|
|
5366
|
+
import * as fs11 from "fs";
|
|
5251
5367
|
var { chain: chain7 } = import_stream_chain7.default;
|
|
5252
5368
|
var { parser: parser8 } = import_stream_json7.default;
|
|
5253
5369
|
var { streamValues: streamValues7 } = import_StreamValues7.default;
|
|
@@ -5277,7 +5393,7 @@ async function* parseTelegramSingle(options2) {
|
|
|
5277
5393
|
onProgress?.(initialProgress);
|
|
5278
5394
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Telegram \u5355\u804A\u5929 JSON \u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
5279
5395
|
const chatData = await new Promise((resolve2, reject) => {
|
|
5280
|
-
const readStream =
|
|
5396
|
+
const readStream = fs11.createReadStream(filePath, { encoding: "utf-8" });
|
|
5281
5397
|
const pipeline2 = chain7([readStream, parser8(), streamValues7()]);
|
|
5282
5398
|
let found = false;
|
|
5283
5399
|
pipeline2.on("data", ({ value }) => {
|
|
@@ -5375,11 +5491,11 @@ var module_9 = {
|
|
|
5375
5491
|
var telegram_native_single_default = module_9;
|
|
5376
5492
|
|
|
5377
5493
|
// ../../packages/parser/src/formats/whatsapp-native-txt.ts
|
|
5378
|
-
import * as
|
|
5379
|
-
import * as
|
|
5494
|
+
import * as fs12 from "fs";
|
|
5495
|
+
import * as path8 from "path";
|
|
5380
5496
|
import * as readline3 from "readline";
|
|
5381
5497
|
function extractNameFromFilePath5(filePath) {
|
|
5382
|
-
const basename13 =
|
|
5498
|
+
const basename13 = path8.basename(filePath);
|
|
5383
5499
|
const matchZhCn = basename13.match(/^与(.+?)的\s*WhatsApp\s*聊天\.txt$/i);
|
|
5384
5500
|
if (matchZhCn) return matchZhCn[1].trim();
|
|
5385
5501
|
const matchZhTw = basename13.match(/^與(.+?)的\s*WhatsApp\s*對話\.txt$/i);
|
|
@@ -5583,7 +5699,7 @@ async function* parseWhatsApp(options2) {
|
|
|
5583
5699
|
messagesProcessed++;
|
|
5584
5700
|
}
|
|
5585
5701
|
};
|
|
5586
|
-
const fileStream =
|
|
5702
|
+
const fileStream = fs12.createReadStream(filePath, { encoding: "utf-8" });
|
|
5587
5703
|
const rl = readline3.createInterface({
|
|
5588
5704
|
input: fileStream,
|
|
5589
5705
|
crlfDelay: Infinity
|
|
@@ -5703,11 +5819,11 @@ var module_10 = {
|
|
|
5703
5819
|
var whatsapp_native_txt_default = module_10;
|
|
5704
5820
|
|
|
5705
5821
|
// ../../packages/parser/src/formats/qq-native-txt.ts
|
|
5706
|
-
import * as
|
|
5707
|
-
import * as
|
|
5822
|
+
import * as fs13 from "fs";
|
|
5823
|
+
import * as path9 from "path";
|
|
5708
5824
|
import * as readline4 from "readline";
|
|
5709
5825
|
function extractNameFromFilePath6(filePath) {
|
|
5710
|
-
const basename13 =
|
|
5826
|
+
const basename13 = path9.basename(filePath);
|
|
5711
5827
|
const name = basename13.replace(/\.txt$/i, "");
|
|
5712
5828
|
return name || "\u672A\u77E5\u7FA4\u804A";
|
|
5713
5829
|
}
|
|
@@ -5789,7 +5905,7 @@ async function* parseTxt(options2) {
|
|
|
5789
5905
|
messagesProcessed++;
|
|
5790
5906
|
}
|
|
5791
5907
|
};
|
|
5792
|
-
const fileStream =
|
|
5908
|
+
const fileStream = fs13.createReadStream(filePath, { encoding: "utf-8" });
|
|
5793
5909
|
const rl = readline4.createInterface({
|
|
5794
5910
|
input: fileStream,
|
|
5795
5911
|
crlfDelay: Infinity
|
|
@@ -5889,8 +6005,8 @@ var module_11 = {
|
|
|
5889
6005
|
var qq_native_txt_default = module_11;
|
|
5890
6006
|
|
|
5891
6007
|
// ../../packages/parser/src/formats/instagram-native.ts
|
|
5892
|
-
import * as
|
|
5893
|
-
import * as
|
|
6008
|
+
import * as fs14 from "fs";
|
|
6009
|
+
import * as path10 from "path";
|
|
5894
6010
|
var feature12 = {
|
|
5895
6011
|
id: "instagram-native",
|
|
5896
6012
|
name: "Instagram \u5B98\u65B9\u5BFC\u51FA",
|
|
@@ -5916,7 +6032,7 @@ function decodeInstagramText(text) {
|
|
|
5916
6032
|
}
|
|
5917
6033
|
}
|
|
5918
6034
|
function extractNameFromFilePath7(filePath) {
|
|
5919
|
-
const basename13 =
|
|
6035
|
+
const basename13 = path10.basename(filePath);
|
|
5920
6036
|
return basename13.replace(/\.json$/i, "") || "\u672A\u77E5\u5BF9\u8BDD";
|
|
5921
6037
|
}
|
|
5922
6038
|
function isSystemMessage2(content) {
|
|
@@ -5985,7 +6101,7 @@ async function* parseInstagram(options2) {
|
|
|
5985
6101
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Instagram \u804A\u5929\u8BB0\u5F55\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
5986
6102
|
let data;
|
|
5987
6103
|
try {
|
|
5988
|
-
const content =
|
|
6104
|
+
const content = fs14.readFileSync(filePath, "utf-8");
|
|
5989
6105
|
data = JSON.parse(content);
|
|
5990
6106
|
} catch (error) {
|
|
5991
6107
|
const err = new Error(`\u65E0\u6CD5\u89E3\u6790 Instagram JSON \u6587\u4EF6: ${error}`);
|
|
@@ -6080,8 +6196,8 @@ var import_stream_chain8 = __toESM(require_stream_chain(), 1);
|
|
|
6080
6196
|
var import_stream_json8 = __toESM(require_stream_json(), 1);
|
|
6081
6197
|
var import_Pick7 = __toESM(require_Pick(), 1);
|
|
6082
6198
|
var import_StreamValues8 = __toESM(require_StreamValues(), 1);
|
|
6083
|
-
import * as
|
|
6084
|
-
import * as
|
|
6199
|
+
import * as fs15 from "fs";
|
|
6200
|
+
import * as path11 from "path";
|
|
6085
6201
|
var { chain: chain8 } = import_stream_chain8.default;
|
|
6086
6202
|
var { parser: parser9 } = import_stream_json8.default;
|
|
6087
6203
|
var { pick: pick7 } = import_Pick7.default;
|
|
@@ -6164,12 +6280,12 @@ function normalizeIdentity(user) {
|
|
|
6164
6280
|
};
|
|
6165
6281
|
}
|
|
6166
6282
|
function readJson(filePath) {
|
|
6167
|
-
return JSON.parse(
|
|
6283
|
+
return JSON.parse(fs15.readFileSync(filePath, "utf8"));
|
|
6168
6284
|
}
|
|
6169
6285
|
function resolveManifestFile(manifestDir, relativePath) {
|
|
6170
|
-
const resolved =
|
|
6171
|
-
const relative2 =
|
|
6172
|
-
if (relative2.startsWith("..") ||
|
|
6286
|
+
const resolved = path11.resolve(manifestDir, relativePath);
|
|
6287
|
+
const relative2 = path11.relative(manifestDir, resolved);
|
|
6288
|
+
if (relative2.startsWith("..") || path11.isAbsolute(relative2)) {
|
|
6173
6289
|
throw new Error(`Google Chat manifest path escapes its directory: ${relativePath}`);
|
|
6174
6290
|
}
|
|
6175
6291
|
return resolved;
|
|
@@ -6182,7 +6298,7 @@ function readManifest2(filePath) {
|
|
|
6182
6298
|
if (manifest.chatType !== "private" && manifest.chatType !== "group") {
|
|
6183
6299
|
throw new Error("Invalid Google Chat chat type");
|
|
6184
6300
|
}
|
|
6185
|
-
const manifestDir =
|
|
6301
|
+
const manifestDir = path11.dirname(filePath);
|
|
6186
6302
|
return {
|
|
6187
6303
|
manifest,
|
|
6188
6304
|
userInfoPath: resolveManifestFile(manifestDir, manifest.userInfoFile),
|
|
@@ -6260,7 +6376,7 @@ async function* parseGoogleChat(options2) {
|
|
|
6260
6376
|
});
|
|
6261
6377
|
}
|
|
6262
6378
|
yield { type: "members", data: Array.from(memberMap.values()) };
|
|
6263
|
-
const readStream =
|
|
6379
|
+
const readStream = fs15.createReadStream(messagesPath, { encoding: "utf8" });
|
|
6264
6380
|
let bytesRead = 0;
|
|
6265
6381
|
let messagesProcessed = 0;
|
|
6266
6382
|
readStream.on("data", (chunk) => {
|
|
@@ -6313,8 +6429,8 @@ var module_13 = {
|
|
|
6313
6429
|
var google_chat_takeout_default = module_13;
|
|
6314
6430
|
|
|
6315
6431
|
// ../../packages/parser/src/formats/line-native-txt.ts
|
|
6316
|
-
import * as
|
|
6317
|
-
import * as
|
|
6432
|
+
import * as fs16 from "fs";
|
|
6433
|
+
import * as path12 from "path";
|
|
6318
6434
|
var feature14 = {
|
|
6319
6435
|
id: "line-native-txt",
|
|
6320
6436
|
name: "LINE \u5B98\u65B9\u5BFC\u51FA TXT",
|
|
@@ -6342,7 +6458,7 @@ var feature14 = {
|
|
|
6342
6458
|
}
|
|
6343
6459
|
};
|
|
6344
6460
|
function extractNameFromFilePath8(filePath) {
|
|
6345
|
-
const basename13 =
|
|
6461
|
+
const basename13 = path12.basename(filePath, ".txt");
|
|
6346
6462
|
const name = basename13.replace(/^\[LINE\]\s*/i, "").trim();
|
|
6347
6463
|
return name || "\u672A\u77E5\u804A\u5929";
|
|
6348
6464
|
}
|
|
@@ -6522,7 +6638,7 @@ async function* parseLINE(options2) {
|
|
|
6522
6638
|
yield { type: "progress", data: initialProgress };
|
|
6523
6639
|
onProgress?.(initialProgress);
|
|
6524
6640
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 LINE \u5BFC\u51FA\u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
6525
|
-
const content =
|
|
6641
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
6526
6642
|
const lines = content.split("\n").map((line) => line.replace(/\r$/, ""));
|
|
6527
6643
|
let currentDate = null;
|
|
6528
6644
|
let chatName = extractNameFromFilePath8(filePath);
|
|
@@ -6830,12 +6946,12 @@ function findEntryFileInDirectory(dirPath, maxDepth = 1) {
|
|
|
6830
6946
|
if (depth > maxDepth) return null;
|
|
6831
6947
|
let entries;
|
|
6832
6948
|
try {
|
|
6833
|
-
entries =
|
|
6949
|
+
entries = fs17.readdirSync(current, { withFileTypes: true });
|
|
6834
6950
|
} catch {
|
|
6835
6951
|
return null;
|
|
6836
6952
|
}
|
|
6837
6953
|
for (const entry of entries) {
|
|
6838
|
-
const full =
|
|
6954
|
+
const full = path13.join(current, entry.name);
|
|
6839
6955
|
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
6840
6956
|
const format = detectFormat(full);
|
|
6841
6957
|
if (format) return full;
|
|
@@ -6843,7 +6959,7 @@ function findEntryFileInDirectory(dirPath, maxDepth = 1) {
|
|
|
6843
6959
|
}
|
|
6844
6960
|
for (const entry of entries) {
|
|
6845
6961
|
if (entry.isDirectory()) {
|
|
6846
|
-
const found = walk(
|
|
6962
|
+
const found = walk(path13.join(current, entry.name), depth + 1);
|
|
6847
6963
|
if (found) return found;
|
|
6848
6964
|
}
|
|
6849
6965
|
}
|
|
@@ -6874,6 +6990,122 @@ async function streamParseFile(filePath, callbacks, formatId) {
|
|
|
6874
6990
|
}
|
|
6875
6991
|
}
|
|
6876
6992
|
|
|
6993
|
+
// ../../packages/node-runtime/src/import/native-parser-status.ts
|
|
6994
|
+
var logged = false;
|
|
6995
|
+
function logNativeParserStatus() {
|
|
6996
|
+
if (logged) return;
|
|
6997
|
+
logged = true;
|
|
6998
|
+
const status = getNativeParserStatus();
|
|
6999
|
+
if (status.available) {
|
|
7000
|
+
appLogger.info("import", "Native parser kernels available (Rust module loaded)");
|
|
7001
|
+
} else if (status.disabled) {
|
|
7002
|
+
appLogger.info("import", "Native parser kernels disabled via CHATLAB_DISABLE_NATIVE_PERF=1; using TS parsers");
|
|
7003
|
+
} else {
|
|
7004
|
+
appLogger.warn("import", "Native parser kernels unavailable; imports fall back to TS parsers", {
|
|
7005
|
+
reason: status.error ?? "unknown"
|
|
7006
|
+
});
|
|
7007
|
+
}
|
|
7008
|
+
}
|
|
7009
|
+
|
|
7010
|
+
// ../../packages/node-runtime/src/import/perf-logger.ts
|
|
7011
|
+
import * as fs18 from "fs";
|
|
7012
|
+
import * as path14 from "path";
|
|
7013
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
7014
|
+
LogLevel2["ERROR"] = "ERROR";
|
|
7015
|
+
LogLevel2["INFO"] = "INFO";
|
|
7016
|
+
return LogLevel2;
|
|
7017
|
+
})(LogLevel || {});
|
|
7018
|
+
var lastLogTime = Date.now();
|
|
7019
|
+
var lastMessageCount = 0;
|
|
7020
|
+
var currentLogFile = null;
|
|
7021
|
+
var errorCount = 0;
|
|
7022
|
+
function initPerfLog(sessionId, logDir) {
|
|
7023
|
+
try {
|
|
7024
|
+
if (!fs18.existsSync(logDir)) {
|
|
7025
|
+
fs18.mkdirSync(logDir, { recursive: true });
|
|
7026
|
+
}
|
|
7027
|
+
currentLogFile = path14.join(logDir, `import_${sessionId}_${Date.now()}.log`);
|
|
7028
|
+
fs18.writeFileSync(currentLogFile, `=== Import Log ===
|
|
7029
|
+
Start time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
7030
|
+
|
|
7031
|
+
`, "utf-8");
|
|
7032
|
+
} catch {
|
|
7033
|
+
}
|
|
7034
|
+
}
|
|
7035
|
+
function logPerf(event, messagesProcessed, batchSize) {
|
|
7036
|
+
const now = Date.now();
|
|
7037
|
+
const duration = now - lastLogTime;
|
|
7038
|
+
const messagesDelta = messagesProcessed - lastMessageCount;
|
|
7039
|
+
const speed = duration > 0 ? Math.round(messagesDelta / duration * 1e3) : 0;
|
|
7040
|
+
let memory = 0;
|
|
7041
|
+
try {
|
|
7042
|
+
const used = process.memoryUsage();
|
|
7043
|
+
memory = Math.round(used.heapUsed / 1024 / 1024);
|
|
7044
|
+
} catch {
|
|
7045
|
+
}
|
|
7046
|
+
const logLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${event} | messages: ${messagesProcessed.toLocaleString()} | elapsed: ${duration}ms | speed: ${speed.toLocaleString()}/s | memory: ${memory}MB` + (batchSize ? ` | batch: ${batchSize}` : "") + "\n";
|
|
7047
|
+
if (currentLogFile) {
|
|
7048
|
+
try {
|
|
7049
|
+
fs18.appendFileSync(currentLogFile, logLine, "utf-8");
|
|
7050
|
+
} catch {
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
lastLogTime = now;
|
|
7054
|
+
lastMessageCount = messagesProcessed;
|
|
7055
|
+
}
|
|
7056
|
+
function logPerfDetail(detail) {
|
|
7057
|
+
if (currentLogFile) {
|
|
7058
|
+
try {
|
|
7059
|
+
fs18.appendFileSync(currentLogFile, ` ${detail}
|
|
7060
|
+
`, "utf-8");
|
|
7061
|
+
} catch {
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
}
|
|
7065
|
+
function resetPerfLog() {
|
|
7066
|
+
lastLogTime = Date.now();
|
|
7067
|
+
lastMessageCount = 0;
|
|
7068
|
+
currentLogFile = null;
|
|
7069
|
+
errorCount = 0;
|
|
7070
|
+
}
|
|
7071
|
+
function getCurrentLogFile() {
|
|
7072
|
+
return currentLogFile;
|
|
7073
|
+
}
|
|
7074
|
+
function writeLogLine(level, message) {
|
|
7075
|
+
if (!currentLogFile) return;
|
|
7076
|
+
const logLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] ${message}
|
|
7077
|
+
`;
|
|
7078
|
+
try {
|
|
7079
|
+
fs18.appendFileSync(currentLogFile, logLine, "utf-8");
|
|
7080
|
+
} catch {
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
function logError(message, error) {
|
|
7084
|
+
errorCount++;
|
|
7085
|
+
const errorDetail = error ? `: ${error.message}` : "";
|
|
7086
|
+
writeLogLine("ERROR" /* ERROR */, `${message}${errorDetail}`);
|
|
7087
|
+
}
|
|
7088
|
+
function logInfo(message) {
|
|
7089
|
+
writeLogLine("INFO" /* INFO */, message);
|
|
7090
|
+
}
|
|
7091
|
+
function getErrorCount() {
|
|
7092
|
+
return errorCount;
|
|
7093
|
+
}
|
|
7094
|
+
function logSummary(totalMessages, totalMembers) {
|
|
7095
|
+
if (!currentLogFile) return;
|
|
7096
|
+
const summary = `
|
|
7097
|
+
=== Import Summary ===
|
|
7098
|
+
End time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
7099
|
+
Total messages: ${totalMessages.toLocaleString()}
|
|
7100
|
+
Total members: ${totalMembers.toLocaleString()}
|
|
7101
|
+
Errors: ${errorCount}
|
|
7102
|
+
`;
|
|
7103
|
+
try {
|
|
7104
|
+
fs18.appendFileSync(currentLogFile, summary, "utf-8");
|
|
7105
|
+
} catch {
|
|
7106
|
+
}
|
|
7107
|
+
}
|
|
7108
|
+
|
|
6877
7109
|
// ../../packages/node-runtime/src/nlp/word-frequency.ts
|
|
6878
7110
|
function buildMessageQuery(timeFilter, memberId, excludeKeywords) {
|
|
6879
7111
|
const conditions = [];
|
|
@@ -7180,6 +7412,7 @@ function searchByFts(db, keywords, limit = 1e3, offset = 0) {
|
|
|
7180
7412
|
import * as fs20 from "fs";
|
|
7181
7413
|
var BATCH_COMMIT_SIZE = 5e4;
|
|
7182
7414
|
var CHECKPOINT_INTERVAL = 2e5;
|
|
7415
|
+
var yieldToEventLoop = () => new Promise((resolve2) => setImmediate(resolve2));
|
|
7183
7416
|
function defaultGenerateSessionId() {
|
|
7184
7417
|
const ts = Date.now();
|
|
7185
7418
|
const rand = Math.random().toString(36).substring(2, 8);
|
|
@@ -7310,7 +7543,7 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7310
7543
|
lastCheckpointCount = totalMessageCount;
|
|
7311
7544
|
}
|
|
7312
7545
|
onProgress({
|
|
7313
|
-
stage: "
|
|
7546
|
+
stage: "saving",
|
|
7314
7547
|
bytesRead: 0,
|
|
7315
7548
|
totalBytes: 0,
|
|
7316
7549
|
messagesProcessed: totalMessageCount,
|
|
@@ -7482,13 +7715,14 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7482
7715
|
inTransaction = false;
|
|
7483
7716
|
}
|
|
7484
7717
|
onProgress({
|
|
7485
|
-
stage: "
|
|
7718
|
+
stage: "saving",
|
|
7486
7719
|
bytesRead: 0,
|
|
7487
7720
|
totalBytes: 0,
|
|
7488
7721
|
messagesProcessed: totalMessageCount,
|
|
7489
7722
|
percentage: 100,
|
|
7490
7723
|
message: ""
|
|
7491
7724
|
});
|
|
7725
|
+
await yieldToEventLoop();
|
|
7492
7726
|
logger?.perf("Writing nickname history", totalMessageCount);
|
|
7493
7727
|
db.exec("BEGIN TRANSACTION");
|
|
7494
7728
|
let historyCount = 0;
|
|
@@ -7504,13 +7738,14 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7504
7738
|
db.exec("COMMIT");
|
|
7505
7739
|
logger?.perf(`Nickname history written (${historyCount} entries)`, totalMessageCount);
|
|
7506
7740
|
onProgress({
|
|
7507
|
-
stage: "
|
|
7741
|
+
stage: "indexing",
|
|
7508
7742
|
bytesRead: 0,
|
|
7509
7743
|
totalBytes: 0,
|
|
7510
7744
|
messagesProcessed: totalMessageCount,
|
|
7511
7745
|
percentage: 100,
|
|
7512
7746
|
message: ""
|
|
7513
7747
|
});
|
|
7748
|
+
await yieldToEventLoop();
|
|
7514
7749
|
logger?.perf("Creating indexes", totalMessageCount);
|
|
7515
7750
|
db.exec(CHAT_DB_INDEXES);
|
|
7516
7751
|
logger?.perf("Indexes created", totalMessageCount);
|
|
@@ -7521,13 +7756,14 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7521
7756
|
logger?.error("FTS index build failed (non-fatal)", ftsError instanceof Error ? ftsError : void 0);
|
|
7522
7757
|
}
|
|
7523
7758
|
onProgress({
|
|
7524
|
-
stage: "
|
|
7759
|
+
stage: "indexing",
|
|
7525
7760
|
bytesRead: 0,
|
|
7526
7761
|
totalBytes: 0,
|
|
7527
7762
|
messagesProcessed: totalMessageCount,
|
|
7528
7763
|
percentage: 100,
|
|
7529
7764
|
message: ""
|
|
7530
7765
|
});
|
|
7766
|
+
await yieldToEventLoop();
|
|
7531
7767
|
doCheckpoint();
|
|
7532
7768
|
logger?.perf("WAL checkpoint done", totalMessageCount);
|
|
7533
7769
|
try {
|
|
@@ -16817,6 +17053,7 @@ __export(relationships_exports, {
|
|
|
16817
17053
|
// ../../packages/node-runtime/src/semantic-index/config.ts
|
|
16818
17054
|
import fs30 from "fs";
|
|
16819
17055
|
import path27 from "path";
|
|
17056
|
+
var DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE = "huggingface";
|
|
16820
17057
|
var SEMANTIC_INDEX_CONFIG_VERSION = 1;
|
|
16821
17058
|
var SEARCH_MAX_RESULTS_DEFAULT = 10;
|
|
16822
17059
|
var SEARCH_MAX_RESULTS_MIN = 5;
|
|
@@ -16831,7 +17068,7 @@ function defaultSemanticIndexConfig() {
|
|
|
16831
17068
|
version: SEMANTIC_INDEX_CONFIG_VERSION,
|
|
16832
17069
|
enabled: true,
|
|
16833
17070
|
mode: "local",
|
|
16834
|
-
local: { modelId: "" },
|
|
17071
|
+
local: { modelId: "", downloadSource: DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE },
|
|
16835
17072
|
api: null,
|
|
16836
17073
|
searchMaxResults: SEARCH_MAX_RESULTS_DEFAULT
|
|
16837
17074
|
};
|
|
@@ -16876,7 +17113,10 @@ function normalizeConfig(raw) {
|
|
|
16876
17113
|
// 旧配置无 enabled 字段时默认开启,保证既有用户功能不被意外关闭
|
|
16877
17114
|
enabled: raw.enabled ?? true,
|
|
16878
17115
|
mode,
|
|
16879
|
-
local: {
|
|
17116
|
+
local: {
|
|
17117
|
+
modelId: raw.local?.modelId ?? base.local.modelId,
|
|
17118
|
+
downloadSource: raw.local?.downloadSource === "hf-mirror" ? "hf-mirror" : DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE
|
|
17119
|
+
},
|
|
16880
17120
|
api,
|
|
16881
17121
|
searchMaxResults: SEARCH_MAX_RESULTS_DEFAULT
|
|
16882
17122
|
};
|
|
@@ -16926,7 +17166,7 @@ import path28 from "path";
|
|
|
16926
17166
|
|
|
16927
17167
|
// ../../packages/node-runtime/src/semantic-index/chunker-config.ts
|
|
16928
17168
|
import { createHash as createHash2 } from "crypto";
|
|
16929
|
-
var CHUNKER_VERSION = "v1.
|
|
17169
|
+
var CHUNKER_VERSION = "v1.3";
|
|
16930
17170
|
var STRATEGY_ID = "balanced";
|
|
16931
17171
|
var DEFAULT_CHUNKER_CONFIG = {
|
|
16932
17172
|
parentGapSeconds: 1800,
|
|
@@ -16974,6 +17214,44 @@ function parseParentBounds(parentId) {
|
|
|
16974
17214
|
return { startMessageId, endMessageId };
|
|
16975
17215
|
}
|
|
16976
17216
|
|
|
17217
|
+
// ../../packages/node-runtime/src/semantic-index/tokens.ts
|
|
17218
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
17219
|
+
var UTF8_BYTES_PER_ESTIMATED_TOKEN = 4;
|
|
17220
|
+
function isCjkCharacter(char) {
|
|
17221
|
+
return /[\u3400-\u9fff\uf900-\ufaff]/u.test(char);
|
|
17222
|
+
}
|
|
17223
|
+
function estimateTokens2(text) {
|
|
17224
|
+
let cjk = 0;
|
|
17225
|
+
let other = 0;
|
|
17226
|
+
for (const ch of text) {
|
|
17227
|
+
if (isCjkCharacter(ch)) cjk++;
|
|
17228
|
+
else other++;
|
|
17229
|
+
}
|
|
17230
|
+
return cjk + Math.ceil(other / 4);
|
|
17231
|
+
}
|
|
17232
|
+
function clampEstimatedTokens(text, maxTokens) {
|
|
17233
|
+
const limit = Math.max(0, Math.floor(maxTokens));
|
|
17234
|
+
if (limit === 0) return "";
|
|
17235
|
+
const byteLimit = limit * UTF8_BYTES_PER_ESTIMATED_TOKEN;
|
|
17236
|
+
if (estimateTokens2(text) <= limit && Buffer2.byteLength(text, "utf8") <= byteLimit) return text;
|
|
17237
|
+
let cjk = 0;
|
|
17238
|
+
let other = 0;
|
|
17239
|
+
let bytes = 0;
|
|
17240
|
+
let end = 0;
|
|
17241
|
+
for (const char of text) {
|
|
17242
|
+
const isCjk = isCjkCharacter(char);
|
|
17243
|
+
const nextCjk = cjk + (isCjk ? 1 : 0);
|
|
17244
|
+
const nextOther = other + (isCjk ? 0 : 1);
|
|
17245
|
+
const nextBytes = bytes + Buffer2.byteLength(char, "utf8");
|
|
17246
|
+
if (nextCjk + Math.ceil(nextOther / 4) > limit || nextBytes > byteLimit) break;
|
|
17247
|
+
cjk = nextCjk;
|
|
17248
|
+
other = nextOther;
|
|
17249
|
+
bytes = nextBytes;
|
|
17250
|
+
end += char.length;
|
|
17251
|
+
}
|
|
17252
|
+
return text.slice(0, end);
|
|
17253
|
+
}
|
|
17254
|
+
|
|
16977
17255
|
// ../../packages/node-runtime/src/semantic-index/embedding/api.ts
|
|
16978
17256
|
var API_DOCUMENT_BATCH_SIZE = 8;
|
|
16979
17257
|
var defaultFetchFn = (url, init) => fetch(url, init);
|
|
@@ -17013,7 +17291,19 @@ var OpenAICompatibleEmbeddingProvider = class {
|
|
|
17013
17291
|
});
|
|
17014
17292
|
if (!response.ok) {
|
|
17015
17293
|
await response.text().catch(() => "");
|
|
17016
|
-
|
|
17294
|
+
const estimatedTokens = texts.map(estimateTokens2);
|
|
17295
|
+
const traceId = response.headers?.get("x-siliconcloud-trace-id")?.trim();
|
|
17296
|
+
const diagnostics = [
|
|
17297
|
+
`model=${this.config.model}`,
|
|
17298
|
+
`batchSize=${texts.length}`,
|
|
17299
|
+
`maxInputTokens=${Math.max(...estimatedTokens)}`,
|
|
17300
|
+
`totalInputTokens=${estimatedTokens.reduce((sum, count) => sum + count, 0)}`,
|
|
17301
|
+
`maxInputChars=${Math.max(...texts.map((text) => text.length))}`
|
|
17302
|
+
];
|
|
17303
|
+
if (traceId) diagnostics.push(`traceId=${traceId}`);
|
|
17304
|
+
const error = new Error(`Embedding API request failed: ${response.status} (${diagnostics.join(", ")})`);
|
|
17305
|
+
appLogger.error("semantic-index", "embedding API request failed", error);
|
|
17306
|
+
throw error;
|
|
17017
17307
|
}
|
|
17018
17308
|
const payload = await response.json();
|
|
17019
17309
|
const sorted = [...payload.data].sort((a, b) => a.index - b.index);
|
|
@@ -17045,6 +17335,11 @@ function clampTextChars(text, maxChars) {
|
|
|
17045
17335
|
// ../../packages/node-runtime/src/semantic-index/embedding/local.ts
|
|
17046
17336
|
var SOCKS_PROXY_PROTOCOLS = /* @__PURE__ */ new Set(["socks:", "socks4:", "socks5:"]);
|
|
17047
17337
|
var LOCAL_ONNX_SESSION_OPTIONS = { intraOpNumThreads: 1, interOpNumThreads: 1 };
|
|
17338
|
+
var HUGGING_FACE_MODEL_HOST = "https://huggingface.co/";
|
|
17339
|
+
var HF_MIRROR_MODEL_HOST = "https://hf-mirror.com/";
|
|
17340
|
+
function resolveModelDownloadRemoteHost(source) {
|
|
17341
|
+
return source === "hf-mirror" ? HF_MIRROR_MODEL_HOST : HUGGING_FACE_MODEL_HOST;
|
|
17342
|
+
}
|
|
17048
17343
|
async function createProxyFetch(proxyUrl) {
|
|
17049
17344
|
const parsed = new URL(proxyUrl);
|
|
17050
17345
|
if (SOCKS_PROXY_PROTOCOLS.has(parsed.protocol)) {
|
|
@@ -17059,8 +17354,15 @@ async function createProxyFetch(proxyUrl) {
|
|
|
17059
17354
|
return undiciFetch(input, nextInit);
|
|
17060
17355
|
});
|
|
17061
17356
|
}
|
|
17062
|
-
var defaultPipelineFactory = async ({
|
|
17357
|
+
var defaultPipelineFactory = async ({
|
|
17358
|
+
modelId,
|
|
17359
|
+
dtype,
|
|
17360
|
+
cacheDir,
|
|
17361
|
+
modelDownloadProxyUrl,
|
|
17362
|
+
modelDownloadSource
|
|
17363
|
+
}) => {
|
|
17063
17364
|
const transformers = await import("./transformers.node-PUMHAODN.mjs");
|
|
17365
|
+
transformers.env.remoteHost = resolveModelDownloadRemoteHost(modelDownloadSource);
|
|
17064
17366
|
if (cacheDir) {
|
|
17065
17367
|
transformers.env.cacheDir = cacheDir;
|
|
17066
17368
|
transformers.env.allowRemoteModels = true;
|
|
@@ -17101,6 +17403,7 @@ var LocalEmbeddingProvider = class {
|
|
|
17101
17403
|
dtype: this.profile.dtype,
|
|
17102
17404
|
cacheDir: this.options.cacheDir,
|
|
17103
17405
|
modelDownloadProxyUrl: this.options.modelDownloadProxyUrl,
|
|
17406
|
+
modelDownloadSource: this.options.modelDownloadSource,
|
|
17104
17407
|
sessionOptions: LOCAL_ONNX_SESSION_OPTIONS
|
|
17105
17408
|
}).catch((error) => {
|
|
17106
17409
|
this.extractorPromise = null;
|
|
@@ -17194,6 +17497,7 @@ function createEmbedder(config, deps = {}) {
|
|
|
17194
17497
|
return new LocalEmbeddingProvider(profile, {
|
|
17195
17498
|
cacheDir: deps.modelsCacheDir,
|
|
17196
17499
|
modelDownloadProxyUrl: deps.modelDownloadProxyUrl,
|
|
17500
|
+
modelDownloadSource: config.local.downloadSource,
|
|
17197
17501
|
pipelineFactory: deps.localPipelineFactory
|
|
17198
17502
|
});
|
|
17199
17503
|
}
|
|
@@ -17745,19 +18049,6 @@ var SemanticIndexJobQueue = class {
|
|
|
17745
18049
|
|
|
17746
18050
|
// ../../packages/node-runtime/src/semantic-index/chunker.ts
|
|
17747
18051
|
import { createHash as createHash3 } from "crypto";
|
|
17748
|
-
|
|
17749
|
-
// ../../packages/node-runtime/src/semantic-index/tokens.ts
|
|
17750
|
-
function estimateTokens2(text) {
|
|
17751
|
-
let cjk = 0;
|
|
17752
|
-
let other = 0;
|
|
17753
|
-
for (const ch of text) {
|
|
17754
|
-
if (/[\u3400-\u9fff\uf900-\ufaff]/u.test(ch)) cjk++;
|
|
17755
|
-
else other++;
|
|
17756
|
-
}
|
|
17757
|
-
return cjk + Math.ceil(other / 4);
|
|
17758
|
-
}
|
|
17759
|
-
|
|
17760
|
-
// ../../packages/node-runtime/src/semantic-index/chunker.ts
|
|
17761
18052
|
var VOID_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
17762
18053
|
1 /* IMAGE */,
|
|
17763
18054
|
2 /* VOICE */,
|
|
@@ -17842,6 +18133,9 @@ function sumEffectiveChars(messages) {
|
|
|
17842
18133
|
function sha256Hex2(input) {
|
|
17843
18134
|
return createHash3("sha256").update(input, "utf-8").digest("hex");
|
|
17844
18135
|
}
|
|
18136
|
+
var EMBEDDING_HEADER_BUDGET_RATIO = 0.25;
|
|
18137
|
+
var SOURCE_TITLE_HEADER_SHARE = 1 / 3;
|
|
18138
|
+
var SENDER_NAMES_BODY_BUDGET_RATIO = 0.1;
|
|
17845
18139
|
function pad2(n) {
|
|
17846
18140
|
return String(n).padStart(2, "0");
|
|
17847
18141
|
}
|
|
@@ -17859,23 +18153,51 @@ function formatTimeRange2(startTs, endTs) {
|
|
|
17859
18153
|
const sameDay = start.getFullYear() === end.getFullYear() && start.getMonth() === end.getMonth() && start.getDate() === end.getDate();
|
|
17860
18154
|
return `${formatDateTime(startTs)} - ${sameDay ? formatTime2(endTs) : formatDateTime(endTs)}`;
|
|
17861
18155
|
}
|
|
17862
|
-
function
|
|
18156
|
+
function resolveSenderNameTokenCap(nameTokenCounts, totalLimit) {
|
|
18157
|
+
const total = nameTokenCounts.reduce((sum, count) => sum + count, 0);
|
|
18158
|
+
if (total <= totalLimit) return null;
|
|
18159
|
+
const sorted = [...nameTokenCounts].sort((a, b) => a - b);
|
|
18160
|
+
let consumed = 0;
|
|
18161
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
18162
|
+
const cap = Math.floor((totalLimit - consumed) / (sorted.length - i));
|
|
18163
|
+
if (sorted[i] > cap) return cap;
|
|
18164
|
+
consumed += sorted[i];
|
|
18165
|
+
}
|
|
18166
|
+
return null;
|
|
18167
|
+
}
|
|
18168
|
+
function buildEmbeddingInput(source, messages, maxTokens) {
|
|
18169
|
+
const limit = Math.max(0, Math.floor(maxTokens));
|
|
18170
|
+
if (limit === 0) return "";
|
|
17863
18171
|
const effective = messages.filter((m) => !isSemanticVoid(m));
|
|
17864
18172
|
const startTs = messages[0].ts;
|
|
17865
18173
|
const endTs = messages[messages.length - 1].ts;
|
|
17866
|
-
const
|
|
18174
|
+
const headerLimit = Math.max(1, Math.floor(limit * EMBEDDING_HEADER_BUDGET_RATIO));
|
|
18175
|
+
const bodyFloor = Math.max(1, limit - headerLimit);
|
|
18176
|
+
const sourceTitleLimit = Math.max(1, Math.floor(headerLimit * SOURCE_TITLE_HEADER_SHARE));
|
|
18177
|
+
const senderNamesTotalLimit = Math.floor(bodyFloor * SENDER_NAMES_BODY_BUDGET_RATIO);
|
|
18178
|
+
const bodySenderNameCap = resolveSenderNameTokenCap(
|
|
18179
|
+
effective.map((m) => estimateTokens2(m.senderName)),
|
|
18180
|
+
senderNamesTotalLimit
|
|
18181
|
+
);
|
|
18182
|
+
const clampHeaderSenderName = (name) => clampEstimatedTokens(name, sourceTitleLimit);
|
|
18183
|
+
const clampBodySenderName = (name) => bodySenderNameCap === null ? name : clampEstimatedTokens(name, bodySenderNameCap);
|
|
18184
|
+
const headerLines = [];
|
|
17867
18185
|
const kindLabel = source.kind === "group" ? "\u7FA4\u804A" : "\u79C1\u804A";
|
|
17868
|
-
|
|
17869
|
-
|
|
18186
|
+
headerLines.push(`[\u6765\u6E90] ${clampEstimatedTokens(source.title, sourceTitleLimit)}\uFF08${kindLabel}\uFF09`);
|
|
18187
|
+
headerLines.push(`[\u65F6\u95F4\u8303\u56F4] ${formatTimeRange2(startTs, endTs)}`);
|
|
17870
18188
|
if (source.kind === "group") {
|
|
17871
|
-
const participants = [...new Set(effective.map((m) => m.senderName))];
|
|
17872
|
-
|
|
17873
|
-
}
|
|
17874
|
-
|
|
17875
|
-
|
|
17876
|
-
|
|
17877
|
-
|
|
17878
|
-
|
|
18189
|
+
const participants = [...new Set(effective.map((m) => clampHeaderSenderName(m.senderName)))];
|
|
18190
|
+
headerLines.push(`[\u53C2\u4E0E\u8005] ${participants.join("\u3001")}`);
|
|
18191
|
+
}
|
|
18192
|
+
const header = clampEstimatedTokens(headerLines.join("\n"), headerLimit);
|
|
18193
|
+
const separator = "\n\n";
|
|
18194
|
+
const remaining = Math.max(0, limit - estimateTokens2(header) - estimateTokens2(separator));
|
|
18195
|
+
const body = clampEstimatedTokens(
|
|
18196
|
+
effective.map((m) => `${clampBodySenderName(m.senderName)}: ${(m.content ?? "").trim()}`).join("\n"),
|
|
18197
|
+
remaining
|
|
18198
|
+
);
|
|
18199
|
+
const combined = body ? `${header}${separator}${body}` : header;
|
|
18200
|
+
return clampEstimatedTokens(combined, limit);
|
|
17879
18201
|
}
|
|
17880
18202
|
function rawContentHashOf(messages) {
|
|
17881
18203
|
return sha256Hex2(messages.map((m) => `${m.id}:${m.content ?? ""}`).join("\n"));
|
|
@@ -17950,7 +18272,7 @@ function chunkMessages(input) {
|
|
|
17950
18272
|
}
|
|
17951
18273
|
const startMessageId = draft[0].id;
|
|
17952
18274
|
const endMessageId = draft[draft.length - 1].id;
|
|
17953
|
-
const embeddingInput = buildEmbeddingInput(input.source, draft);
|
|
18275
|
+
const embeddingInput = buildEmbeddingInput(input.source, draft, config.childHardMaxTokens);
|
|
17954
18276
|
chunks.push({
|
|
17955
18277
|
localChunkId: `${parentId}#${startMessageId}-${endMessageId}`,
|
|
17956
18278
|
parentId,
|
|
@@ -18398,6 +18720,7 @@ var SemanticIndexService = class {
|
|
|
18398
18720
|
embedder = null;
|
|
18399
18721
|
embedderModelId = null;
|
|
18400
18722
|
modelPreloadStatus = "idle";
|
|
18723
|
+
modelPreloadGeneration = 0;
|
|
18401
18724
|
/** 当前激活的 chunker 身份(version + 参数 hash),随索引记录用于重建判定 */
|
|
18402
18725
|
chunkerVersion = CHUNKER_VERSION;
|
|
18403
18726
|
chunkerConfigHash = computeChunkerConfigHash(DEFAULT_CHUNKER_CONFIG);
|
|
@@ -18446,6 +18769,7 @@ var SemanticIndexService = class {
|
|
|
18446
18769
|
apiKey: options2?.apiKey,
|
|
18447
18770
|
writeAuthProfile: this.options.writeAuthProfile
|
|
18448
18771
|
});
|
|
18772
|
+
const preloadGeneration = ++this.modelPreloadGeneration;
|
|
18449
18773
|
this.embedder = null;
|
|
18450
18774
|
this.embedderModelId = null;
|
|
18451
18775
|
this.modelPreloadStatus = "idle";
|
|
@@ -18454,15 +18778,26 @@ var SemanticIndexService = class {
|
|
|
18454
18778
|
}
|
|
18455
18779
|
if (saved.enabled && isSemanticIndexConfigured(saved) && saved.mode === "local") {
|
|
18456
18780
|
const modelId = saved.local.modelId;
|
|
18781
|
+
const downloadSource = saved.local.downloadSource ?? DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE;
|
|
18457
18782
|
const cacheDir = this.options.modelsCacheDir;
|
|
18458
18783
|
this.modelPreloadStatus = "downloading";
|
|
18459
|
-
appLogger.info("semantic-index", "local embedding model preload started", { modelId, cacheDir });
|
|
18784
|
+
appLogger.info("semantic-index", "local embedding model preload started", { modelId, downloadSource, cacheDir });
|
|
18460
18785
|
void this.getEmbedder().preload?.().then(() => {
|
|
18786
|
+
if (preloadGeneration !== this.modelPreloadGeneration) return;
|
|
18461
18787
|
this.modelPreloadStatus = "ready";
|
|
18462
|
-
appLogger.info("semantic-index", "local embedding model preload completed", {
|
|
18788
|
+
appLogger.info("semantic-index", "local embedding model preload completed", {
|
|
18789
|
+
modelId,
|
|
18790
|
+
downloadSource,
|
|
18791
|
+
cacheDir
|
|
18792
|
+
});
|
|
18463
18793
|
}).catch((error) => {
|
|
18794
|
+
if (preloadGeneration !== this.modelPreloadGeneration) return;
|
|
18464
18795
|
this.modelPreloadStatus = "error";
|
|
18465
|
-
appLogger.error(
|
|
18796
|
+
appLogger.error(
|
|
18797
|
+
"semantic-index",
|
|
18798
|
+
`local embedding model preload failed: ${modelId} via ${downloadSource}`,
|
|
18799
|
+
error
|
|
18800
|
+
);
|
|
18466
18801
|
});
|
|
18467
18802
|
}
|
|
18468
18803
|
return saved;
|
|
@@ -18891,7 +19226,9 @@ ${text}`;
|
|
|
18891
19226
|
checkStop
|
|
18892
19227
|
});
|
|
18893
19228
|
const currentConfig = this.configStore.get();
|
|
18894
|
-
|
|
19229
|
+
const jobDownloadSource = jobConfig.mode === "local" ? jobConfig.local.downloadSource ?? DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE : null;
|
|
19230
|
+
const currentDownloadSource = currentConfig.mode === "local" ? currentConfig.local.downloadSource ?? DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE : null;
|
|
19231
|
+
if (result.status === "completed" && result.chunksWritten > 0 && jobConfig.mode === "local" && currentConfig.mode === "local" && currentConfig.local.modelId === jobConfig.local.modelId && currentDownloadSource === jobDownloadSource) {
|
|
18895
19232
|
this.modelPreloadStatus = "ready";
|
|
18896
19233
|
}
|
|
18897
19234
|
appLogger.info("semantic-index", "warmup job finished", {
|
|
@@ -19331,6 +19668,13 @@ async function pushImport(dbManager, sessionId, payload) {
|
|
|
19331
19668
|
|
|
19332
19669
|
export {
|
|
19333
19670
|
writeParseResultToDb,
|
|
19671
|
+
detectFormat,
|
|
19672
|
+
detectAllFormats,
|
|
19673
|
+
getSupportedFormats,
|
|
19674
|
+
getFormatFeatureById,
|
|
19675
|
+
scanMultiChatFile,
|
|
19676
|
+
findEntryFileInDirectory,
|
|
19677
|
+
logNativeParserStatus,
|
|
19334
19678
|
LogLevel,
|
|
19335
19679
|
initPerfLog,
|
|
19336
19680
|
logPerf,
|
|
@@ -19341,12 +19685,6 @@ export {
|
|
|
19341
19685
|
logInfo,
|
|
19342
19686
|
getErrorCount,
|
|
19343
19687
|
logSummary,
|
|
19344
|
-
detectFormat,
|
|
19345
|
-
detectAllFormats,
|
|
19346
|
-
getSupportedFormats,
|
|
19347
|
-
getFormatFeatureById,
|
|
19348
|
-
scanMultiChatFile,
|
|
19349
|
-
findEntryFileInDirectory,
|
|
19350
19688
|
computeWordFrequency,
|
|
19351
19689
|
segmentText,
|
|
19352
19690
|
isDictDownloaded,
|
|
@@ -19488,6 +19826,7 @@ export {
|
|
|
19488
19826
|
deriveParentId,
|
|
19489
19827
|
parseParentBounds,
|
|
19490
19828
|
estimateTokens2 as estimateTokens,
|
|
19829
|
+
DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE,
|
|
19491
19830
|
SEMANTIC_INDEX_CONFIG_VERSION,
|
|
19492
19831
|
SEARCH_MAX_RESULTS_DEFAULT,
|
|
19493
19832
|
SEARCH_MAX_RESULTS_MIN,
|
|
@@ -19529,4 +19868,4 @@ export {
|
|
|
19529
19868
|
MergeSessionCache,
|
|
19530
19869
|
pushImport
|
|
19531
19870
|
};
|
|
19532
|
-
//# sourceMappingURL=chunk-
|
|
19871
|
+
//# sourceMappingURL=chunk-36JGKW6K.mjs.map
|