chatlab-cli 0.31.0 → 0.31.2-beta.1
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-CHV7RLBH.mjs → chat-command-V6NYTTPD.mjs} +8 -8
- package/dist/{chunk-DA5T64RY.mjs → chunk-54GVCXHZ.mjs} +2 -2
- package/dist/{chunk-T64GA5HP.mjs → chunk-5G2INROS.mjs} +867 -537
- package/dist/chunk-5G2INROS.mjs.map +1 -0
- package/dist/{chunk-JH5RAJT2.mjs → chunk-67HNEIKY.mjs} +2083 -1858
- package/dist/chunk-67HNEIKY.mjs.map +1 -0
- package/dist/{chunk-RD335EMA.mjs → chunk-7TDYBU5L.mjs} +29 -52
- package/dist/chunk-7TDYBU5L.mjs.map +1 -0
- package/dist/{chunk-RDCUGC24.mjs → chunk-HUKZ2PBC.mjs} +2 -2
- package/dist/{chunk-YPQ72HMX.mjs → chunk-LWC7JQ2W.mjs} +44 -5
- package/dist/chunk-LWC7JQ2W.mjs.map +1 -0
- package/dist/{chunk-EXD2SXWL.mjs → chunk-OIZ64ET3.mjs} +40 -7
- package/dist/chunk-OIZ64ET3.mjs.map +1 -0
- package/dist/{chunk-WQCY45U2.mjs → chunk-SJQVAKFA.mjs} +5 -4
- package/dist/chunk-SJQVAKFA.mjs.map +1 -0
- package/dist/{chunk-DBBL74RK.mjs → chunk-WL2ISRYH.mjs} +164 -82
- package/dist/chunk-WL2ISRYH.mjs.map +1 -0
- package/dist/{chunk-UWWFOEGF.mjs → chunk-XZ5FFDLX.mjs} +143 -137
- package/dist/chunk-XZ5FFDLX.mjs.map +1 -0
- package/dist/{chunk-SNCXU2QL.mjs → chunk-ZF67S6RY.mjs} +2 -2
- package/dist/cli.mjs +9 -7
- package/dist/contacts-worker.mjs +2 -2
- package/dist/global-insight-worker.mjs +1 -1
- package/dist/{http-3B5ARN7A.mjs → http-AMDWRKOH.mjs} +11 -11
- package/dist/{import-2DZGNSEX.mjs → import-WIJHB4LH.mjs} +9 -7
- package/dist/index.mjs +12 -12
- package/dist/{mcp-44I6FUUQ.mjs → mcp-NC5YNTM5.mjs} +8 -8
- package/dist/people-relationships-worker.mjs +2 -2
- package/dist/semantic-index-worker.mjs +1 -1
- package/dist/{src-R3QX6L3L.mjs → src-UY4GCVNF.mjs} +34 -6
- package/dist/{stream-import-VUEL2TTU.mjs → stream-import-JKQYRISL.mjs} +9 -7
- package/dist/{worker-runtime-GJAOIIZW.mjs → worker-runtime-KKUOJJTN.mjs} +5 -5
- package/dist-web/assets/{ActionToolsPanel-fAio70bI.css → ActionToolsPanel-BL0GQR6r.css} +1 -1
- package/dist-web/assets/ActionToolsPanel.vue_vue_type_script_setup_true_lang-DVdpZpfD.js +110 -0
- package/dist-web/assets/{BufferResource-BPGkshPa.js → BufferResource-i1amDJTV.js} +1 -1
- package/dist-web/assets/{CanvasRenderer-DTKkZhq4.js → CanvasRenderer-DGa7AjdC.js} +1 -1
- package/dist-web/assets/EChartWordcloud-BXC_4nUP.js +1 -0
- package/dist-web/assets/{Filter-CHXKzS2l.js → Filter-BTlq0yU-.js} +1 -1
- package/dist-web/assets/LoadingState.vue_vue_type_script_setup_true_lang-B2KAoiMG.js +1 -0
- package/dist-web/assets/MessageExportModal-D9C5t_zF.js +1 -0
- package/dist-web/assets/PageHeader-BEWr2vsg.js +1 -0
- package/dist-web/assets/{RelationshipGalaxyCanvas-Dwdy5flh.js → RelationshipGalaxyCanvas-CSgPNRif.js} +4 -4
- package/dist-web/assets/{RelationshipGalaxyThreeCanvas-CtY4TGen.js → RelationshipGalaxyThreeCanvas-CBAnU8vN.js} +1 -1
- package/dist-web/assets/{RenderTargetSystem-BE56mKRG.js → RenderTargetSystem-Ctlu222X.js} +1 -1
- package/dist-web/assets/ThemeCard.vue_vue_type_script_setup_true_lang-BWJ6kuSC.js +1 -0
- package/dist-web/assets/TimeSelect.vue_vue_type_script_setup_true_lang-D5vov0eO.js +1 -0
- package/dist-web/assets/{WebGLRenderer-Dm18dxOf.js → WebGLRenderer-D2Zvhmcw.js} +1 -1
- package/dist-web/assets/{WebGPURenderer-BF6TF-is.js → WebGPURenderer-BOtP6h9o.js} +1 -1
- package/dist-web/assets/annual-summary-time-range-CK0IIPsY.js +1 -0
- package/dist-web/assets/{base-CFPyD9Gy.js → base-BMjDSaj6.js} +1 -1
- package/dist-web/assets/{browserAll-Cn_CfkXl.js → browserAll-BhwLvWQY.js} +1 -1
- package/dist-web/assets/dateFormat-dteP1INW.js +1 -0
- package/dist-web/assets/{electron-B6xOabTq.js → electron-DCgfulPE.js} +1 -1
- package/dist-web/assets/{fetch-DMLq3xPG.js → fetch-6q7oz7ZO.js} +1 -1
- package/dist-web/assets/{fetch-C_EfVFJi.js → fetch-B_0HIxs5.js} +1 -1
- package/dist-web/assets/{fetch-DylpNKCR.js → fetch-BbU4MPPu.js} +1 -1
- package/dist-web/assets/fetch-BxHdB6X1.js +6 -0
- package/dist-web/assets/{fetch-CEhUu1Yu.js → fetch-CpvfCafG.js} +1 -1
- package/dist-web/assets/{fetch-etgwVKIw.js → fetch-CubnKpLG.js} +1 -1
- package/dist-web/assets/{fetch-BRXmDI_2.js → fetch-D5BrGna5.js} +1 -1
- package/dist-web/assets/fetch-DgXWr9nB.js +31 -0
- package/dist-web/assets/{fetch-BPkgnY0R.js → fetch-DvZuLuTE.js} +1 -1
- package/dist-web/assets/{fetch-DL_u25Ui.js → fetch-rJA9qLvd.js} +1 -1
- package/dist-web/assets/index-BfGKlkx3.js +2 -0
- package/dist-web/assets/index-BoalB6nB.js +1 -0
- package/dist-web/assets/index-Bp5VKUF9.js +1 -0
- package/dist-web/assets/index-Bs15Yc7I.js +1 -0
- package/dist-web/assets/index-CAjUCtGD.css +1 -0
- package/dist-web/assets/index-CLijvqy3.js +173 -0
- package/dist-web/assets/{index-0x1QPzKZ.js → index-CUzFFw5b.js} +1 -1
- package/dist-web/assets/index-Cj2GU1SR.js +1 -0
- package/dist-web/assets/{index-y7cxH1Et.css → index-CsqMIyA9.css} +1 -1
- package/dist-web/assets/index-CtmXho1w.css +1 -0
- package/dist-web/assets/index-D7aKwT6w.js +64 -0
- package/dist-web/assets/index-DXcFBsM1.js +24 -0
- package/dist-web/assets/index-DaZnh1zP.js +2 -0
- package/dist-web/assets/index-DeV8SAiM.js +25 -0
- package/dist-web/assets/index-WJCmqKnh.js +1 -0
- package/dist-web/assets/index-t6s0nOlb.js +1 -0
- package/dist-web/assets/people-page-header-D93GTPBO.js +1 -0
- package/dist-web/assets/vendor-nuxt-ui-DUpPmItD.js +15 -0
- package/dist-web/assets/vendor-reka-ui-BLnO2MqY.js +15 -0
- package/dist-web/assets/vendor-snapdom--nZvo8Sg.js +8 -0
- package/dist-web/assets/web-BoTDL3HM.js +1 -0
- package/dist-web/assets/{webworkerAll-BKGP--A4.js → webworkerAll-c0ZvpENM.js} +1 -1
- package/dist-web/index.html +5 -5
- package/package.json +1 -1
- package/dist/chunk-DBBL74RK.mjs.map +0 -1
- package/dist/chunk-EXD2SXWL.mjs.map +0 -1
- package/dist/chunk-JH5RAJT2.mjs.map +0 -1
- package/dist/chunk-RD335EMA.mjs.map +0 -1
- package/dist/chunk-T64GA5HP.mjs.map +0 -1
- package/dist/chunk-UWWFOEGF.mjs.map +0 -1
- package/dist/chunk-WQCY45U2.mjs.map +0 -1
- package/dist/chunk-YPQ72HMX.mjs.map +0 -1
- package/dist-web/assets/ActionToolsPanel.vue_vue_type_script_setup_true_lang-CdJT0t2f.js +0 -110
- package/dist-web/assets/EChartWordcloud-DU3ZYdgz.js +0 -1
- package/dist-web/assets/LoadingState.vue_vue_type_script_setup_true_lang-DACMroOe.js +0 -1
- package/dist-web/assets/MessageExportModal-h-zl0dx1.js +0 -1
- package/dist-web/assets/PageHeader-CK0hTsdx.js +0 -1
- package/dist-web/assets/ThemeCard.vue_vue_type_script_setup_true_lang-BoZyssJF.js +0 -1
- package/dist-web/assets/TimeSelect.vue_vue_type_script_setup_true_lang-27hMyAUE.js +0 -1
- package/dist-web/assets/annual-summary-time-range-DVLXK1r4.js +0 -1
- package/dist-web/assets/dateFormat-BcqNKTQ1.js +0 -1
- package/dist-web/assets/fetch-BUm1isWe.js +0 -5
- package/dist-web/assets/fetch-CBOJwwJp.js +0 -17
- package/dist-web/assets/index-B5S9FnfP.js +0 -1
- package/dist-web/assets/index-BS6loLHW.js +0 -1
- package/dist-web/assets/index-BrTlAl8b.js +0 -1
- package/dist-web/assets/index-C3TnydSt.js +0 -24
- package/dist-web/assets/index-CAWO10k1.js +0 -2
- package/dist-web/assets/index-C_0GHEcb.css +0 -1
- package/dist-web/assets/index-Chm17wNe.js +0 -2
- package/dist-web/assets/index-DAr_2DlV.js +0 -173
- package/dist-web/assets/index-Em6upenM.js +0 -64
- package/dist-web/assets/index-FoTy2Cce.js +0 -1
- package/dist-web/assets/index-YADL4XIp.js +0 -22
- package/dist-web/assets/index-_6lck7Bv.css +0 -1
- package/dist-web/assets/index-aMIgqj43.js +0 -1
- package/dist-web/assets/index-zZVsV5HB.js +0 -1
- package/dist-web/assets/people-page-header-BdKM1qhX.js +0 -1
- package/dist-web/assets/vendor-nuxt-ui-CS1uxE9C.js +0 -15
- package/dist-web/assets/vendor-reka-ui-Cta6JPvN.js +0 -11
- package/dist-web/assets/vendor-snapdom-XnBoh1gd.js +0 -8
- package/dist-web/assets/web-BUZ-dZy0.js +0 -1
- /package/dist/{chat-command-CHV7RLBH.mjs.map → chat-command-V6NYTTPD.mjs.map} +0 -0
- /package/dist/{chunk-DA5T64RY.mjs.map → chunk-54GVCXHZ.mjs.map} +0 -0
- /package/dist/{chunk-RDCUGC24.mjs.map → chunk-HUKZ2PBC.mjs.map} +0 -0
- /package/dist/{chunk-SNCXU2QL.mjs.map → chunk-ZF67S6RY.mjs.map} +0 -0
- /package/dist/{http-3B5ARN7A.mjs.map → http-AMDWRKOH.mjs.map} +0 -0
- /package/dist/{import-2DZGNSEX.mjs.map → import-WIJHB4LH.mjs.map} +0 -0
- /package/dist/{mcp-44I6FUUQ.mjs.map → mcp-NC5YNTM5.mjs.map} +0 -0
- /package/dist/{src-R3QX6L3L.mjs.map → src-UY4GCVNF.mjs.map} +0 -0
- /package/dist/{stream-import-VUEL2TTU.mjs.map → stream-import-JKQYRISL.mjs.map} +0 -0
- /package/dist/{worker-runtime-GJAOIIZW.mjs.map → worker-runtime-KKUOJJTN.mjs.map} +0 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
createEmptyContactsDiagnostics,
|
|
10
10
|
normalizeContactsTimeRangePreset,
|
|
11
11
|
resolveContactsTimeRange
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZF67S6RY.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-HUKZ2PBC.mjs";
|
|
22
22
|
import {
|
|
23
23
|
ANNUAL_SUMMARY_ALGORITHM_VERSION
|
|
24
24
|
} from "./chunk-YAQLYL52.mjs";
|
|
@@ -42,7 +42,9 @@ import {
|
|
|
42
42
|
clearSessionIndex,
|
|
43
43
|
collectPosTagStats,
|
|
44
44
|
deleteAnnualSummarySnapshots,
|
|
45
|
+
deleteAuthProfile,
|
|
45
46
|
deleteMember,
|
|
47
|
+
deleteMembers,
|
|
46
48
|
generateIncrementalSessionIndex,
|
|
47
49
|
generateMessageKey,
|
|
48
50
|
generateSessionIndex,
|
|
@@ -93,7 +95,7 @@ import {
|
|
|
93
95
|
updateSessionOwnerId,
|
|
94
96
|
writeAnnualSummarySnapshot,
|
|
95
97
|
writeAuthProfile
|
|
96
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-XZ5FFDLX.mjs";
|
|
97
99
|
import {
|
|
98
100
|
__commonJS,
|
|
99
101
|
__export,
|
|
@@ -709,8 +711,8 @@ var require_FilterBase = __commonJS({
|
|
|
709
711
|
var FilterBase = class _FilterBase extends Transform {
|
|
710
712
|
static stringFilter(string, separator) {
|
|
711
713
|
return (stack) => {
|
|
712
|
-
const
|
|
713
|
-
return
|
|
714
|
+
const path33 = stack.join(separator);
|
|
715
|
+
return path33.length === string.length && path33 === string || path33.length > string.length && path33.substr(0, string.length) === string && path33.substr(string.length, separator.length) === separator;
|
|
714
716
|
};
|
|
715
717
|
}
|
|
716
718
|
static regExpFilter(regExp, separator) {
|
|
@@ -1164,12 +1166,12 @@ var require_Assembler = __commonJS({
|
|
|
1164
1166
|
return (this.stack.length >> 1) + (this.done ? 0 : 1);
|
|
1165
1167
|
}
|
|
1166
1168
|
get path() {
|
|
1167
|
-
const
|
|
1169
|
+
const path33 = [];
|
|
1168
1170
|
for (let i = 0; i < this.stack.length; i += 2) {
|
|
1169
1171
|
const key = this.stack[i + 1];
|
|
1170
|
-
|
|
1172
|
+
path33.push(key === null ? this.stack[i].length : key);
|
|
1171
1173
|
}
|
|
1172
|
-
return
|
|
1174
|
+
return path33;
|
|
1173
1175
|
}
|
|
1174
1176
|
dropToLevel(level) {
|
|
1175
1177
|
if (level < this.depth) {
|
|
@@ -1451,7 +1453,7 @@ var require_pend = __commonJS({
|
|
|
1451
1453
|
var require_fd_slicer = __commonJS({
|
|
1452
1454
|
"../../packages/node-runtime/node_modules/yauzl/fd-slicer.js"(exports) {
|
|
1453
1455
|
"use strict";
|
|
1454
|
-
var
|
|
1456
|
+
var fs37 = __require("fs");
|
|
1455
1457
|
var util = __require("util");
|
|
1456
1458
|
var stream = __require("stream");
|
|
1457
1459
|
var Readable = stream.Readable;
|
|
@@ -1471,7 +1473,7 @@ var require_fd_slicer = __commonJS({
|
|
|
1471
1473
|
FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
|
|
1472
1474
|
var self = this;
|
|
1473
1475
|
self.pend.go(function(cb) {
|
|
1474
|
-
|
|
1476
|
+
fs37.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
|
|
1475
1477
|
cb();
|
|
1476
1478
|
callback(err, bytesRead, buffer2);
|
|
1477
1479
|
});
|
|
@@ -1488,7 +1490,7 @@ var require_fd_slicer = __commonJS({
|
|
|
1488
1490
|
self.refCount -= 1;
|
|
1489
1491
|
if (self.refCount < 0) throw new Error("invalid unref");
|
|
1490
1492
|
if (self.refCount > 0) return;
|
|
1491
|
-
|
|
1493
|
+
fs37.close(self.fd, onCloseDone);
|
|
1492
1494
|
function onCloseDone(err) {
|
|
1493
1495
|
if (err) {
|
|
1494
1496
|
self.emit("error", err);
|
|
@@ -1520,7 +1522,7 @@ var require_fd_slicer = __commonJS({
|
|
|
1520
1522
|
}
|
|
1521
1523
|
self.context.pend.go(function(cb) {
|
|
1522
1524
|
var buffer = Buffer.allocUnsafe(toRead);
|
|
1523
|
-
|
|
1525
|
+
fs37.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
|
|
1524
1526
|
if (err) {
|
|
1525
1527
|
self.destroy(err);
|
|
1526
1528
|
} else if (bytesRead === 0) {
|
|
@@ -1882,7 +1884,7 @@ var require_crc32 = __commonJS({
|
|
|
1882
1884
|
var require_yauzl = __commonJS({
|
|
1883
1885
|
"../../packages/node-runtime/node_modules/yauzl/index.js"(exports) {
|
|
1884
1886
|
"use strict";
|
|
1885
|
-
var
|
|
1887
|
+
var fs37 = __require("fs");
|
|
1886
1888
|
var zlib = __require("zlib");
|
|
1887
1889
|
var fd_slicer = require_fd_slicer();
|
|
1888
1890
|
var util = __require("util");
|
|
@@ -1907,39 +1909,39 @@ var require_yauzl = __commonJS({
|
|
|
1907
1909
|
exports.Entry = Entry;
|
|
1908
1910
|
exports.LocalFileHeader = LocalFileHeader;
|
|
1909
1911
|
exports.RandomAccessReader = RandomAccessReader;
|
|
1910
|
-
function openPromise2(
|
|
1911
|
-
return new Promise((
|
|
1912
|
-
open(
|
|
1912
|
+
function openPromise2(path33, options2) {
|
|
1913
|
+
return new Promise((resolve4, reject) => {
|
|
1914
|
+
open(path33, { ...options2, lazyEntries: true }, function(err, zipfile) {
|
|
1913
1915
|
if (err) return reject(err);
|
|
1914
|
-
|
|
1916
|
+
resolve4(zipfile);
|
|
1915
1917
|
});
|
|
1916
1918
|
});
|
|
1917
1919
|
}
|
|
1918
1920
|
function fromFdPromise(fd, options2) {
|
|
1919
|
-
return new Promise((
|
|
1921
|
+
return new Promise((resolve4, reject) => {
|
|
1920
1922
|
fromFd(fd, { ...options2, lazyEntries: true }, function(err, zipfile) {
|
|
1921
1923
|
if (err) return reject(err);
|
|
1922
|
-
|
|
1924
|
+
resolve4(zipfile);
|
|
1923
1925
|
});
|
|
1924
1926
|
});
|
|
1925
1927
|
}
|
|
1926
1928
|
function fromBufferPromise(buffer, options2) {
|
|
1927
|
-
return new Promise((
|
|
1929
|
+
return new Promise((resolve4, reject) => {
|
|
1928
1930
|
fromBuffer(buffer, { ...options2, lazyEntries: true }, function(err, zipfile) {
|
|
1929
1931
|
if (err) return reject(err);
|
|
1930
|
-
|
|
1932
|
+
resolve4(zipfile);
|
|
1931
1933
|
});
|
|
1932
1934
|
});
|
|
1933
1935
|
}
|
|
1934
1936
|
function fromRandomAccessReaderPromise(reader, totalSize, options2) {
|
|
1935
|
-
return new Promise((
|
|
1937
|
+
return new Promise((resolve4, reject) => {
|
|
1936
1938
|
fromRandomAccessReader(reader, totalSize, { ...options2, lazyEntries: true }, function(err, zipfile) {
|
|
1937
1939
|
if (err) return reject(err);
|
|
1938
|
-
|
|
1940
|
+
resolve4(zipfile);
|
|
1939
1941
|
});
|
|
1940
1942
|
});
|
|
1941
1943
|
}
|
|
1942
|
-
function open(
|
|
1944
|
+
function open(path33, options2, callback) {
|
|
1943
1945
|
if (typeof options2 === "function") {
|
|
1944
1946
|
callback = options2;
|
|
1945
1947
|
options2 = null;
|
|
@@ -1951,10 +1953,10 @@ var require_yauzl = __commonJS({
|
|
|
1951
1953
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
1952
1954
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
1953
1955
|
if (callback == null) callback = defaultCallback;
|
|
1954
|
-
|
|
1956
|
+
fs37.open(path33, "r", function(err, fd) {
|
|
1955
1957
|
if (err) return callback(err);
|
|
1956
1958
|
fromFd(fd, options2, function(err2, zipfile) {
|
|
1957
|
-
if (err2)
|
|
1959
|
+
if (err2) fs37.close(fd, defaultCallback);
|
|
1958
1960
|
callback(err2, zipfile);
|
|
1959
1961
|
});
|
|
1960
1962
|
});
|
|
@@ -1971,7 +1973,7 @@ var require_yauzl = __commonJS({
|
|
|
1971
1973
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
1972
1974
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
1973
1975
|
if (callback == null) callback = defaultCallback;
|
|
1974
|
-
|
|
1976
|
+
fs37.fstat(fd, function(err, stats) {
|
|
1975
1977
|
if (err) return callback(err);
|
|
1976
1978
|
var reader = new fd_slicer.FdSlicer(fd);
|
|
1977
1979
|
fromRandomAccessReader(reader, stats.size, options2, callback);
|
|
@@ -2219,15 +2221,15 @@ var require_yauzl = __commonJS({
|
|
|
2219
2221
|
if (self.autoClose) self.close();
|
|
2220
2222
|
}
|
|
2221
2223
|
function onEntry(entry) {
|
|
2222
|
-
let { resolve:
|
|
2224
|
+
let { resolve: resolve4 } = pendingResolveReject;
|
|
2223
2225
|
pendingResolveReject = null;
|
|
2224
|
-
|
|
2226
|
+
resolve4({ value: entry });
|
|
2225
2227
|
}
|
|
2226
2228
|
function onEnd() {
|
|
2227
|
-
let { resolve:
|
|
2229
|
+
let { resolve: resolve4 } = pendingResolveReject;
|
|
2228
2230
|
pendingResolveReject = null;
|
|
2229
2231
|
cleanup();
|
|
2230
|
-
|
|
2232
|
+
resolve4({ done: true });
|
|
2231
2233
|
}
|
|
2232
2234
|
function onError(err) {
|
|
2233
2235
|
let { reject } = pendingResolveReject;
|
|
@@ -2240,9 +2242,9 @@ var require_yauzl = __commonJS({
|
|
|
2240
2242
|
return this;
|
|
2241
2243
|
},
|
|
2242
2244
|
next() {
|
|
2243
|
-
const promise = new Promise((
|
|
2245
|
+
const promise = new Promise((resolve4, reject) => {
|
|
2244
2246
|
if (pendingResolveReject != null) throw new Error("next() called before previous Promise was resolved.");
|
|
2245
|
-
pendingResolveReject = { resolve:
|
|
2247
|
+
pendingResolveReject = { resolve: resolve4, reject };
|
|
2246
2248
|
});
|
|
2247
2249
|
self.readEntry();
|
|
2248
2250
|
return promise;
|
|
@@ -2431,26 +2433,26 @@ var require_yauzl = __commonJS({
|
|
|
2431
2433
|
});
|
|
2432
2434
|
};
|
|
2433
2435
|
ZipFile.prototype.openReadStreamPromise = function(entry, options2) {
|
|
2434
|
-
return new Promise((
|
|
2436
|
+
return new Promise((resolve4, reject) => {
|
|
2435
2437
|
this.openReadStream(entry, options2, function(err, readStream) {
|
|
2436
2438
|
if (err) return reject(err);
|
|
2437
|
-
|
|
2439
|
+
resolve4(readStream);
|
|
2438
2440
|
});
|
|
2439
2441
|
});
|
|
2440
2442
|
};
|
|
2441
2443
|
ZipFile.prototype.openReadStreamLowLevelPromise = function(fileDataStart, compressedSize, relativeStart, relativeEnd, decompress, uncompressedSize) {
|
|
2442
|
-
return new Promise((
|
|
2444
|
+
return new Promise((resolve4, reject) => {
|
|
2443
2445
|
this.openReadStream(fileDataStart, compressedSize, relativeStart, relativeEnd, decompress, uncompressedSize, function(err, readStream) {
|
|
2444
2446
|
if (err) return reject(err);
|
|
2445
|
-
|
|
2447
|
+
resolve4(readStream);
|
|
2446
2448
|
});
|
|
2447
2449
|
});
|
|
2448
2450
|
};
|
|
2449
2451
|
ZipFile.prototype.readLocalFileHeaderPromise = function(entry, options2) {
|
|
2450
|
-
return new Promise((
|
|
2452
|
+
return new Promise((resolve4, reject) => {
|
|
2451
2453
|
this.readLocalFileHeader(entry, options2, function(err, localFileHeader) {
|
|
2452
2454
|
if (err) return reject(err);
|
|
2453
|
-
|
|
2455
|
+
resolve4(localFileHeader);
|
|
2454
2456
|
});
|
|
2455
2457
|
});
|
|
2456
2458
|
};
|
|
@@ -2738,6 +2740,73 @@ var require_yauzl = __commonJS({
|
|
|
2738
2740
|
}
|
|
2739
2741
|
});
|
|
2740
2742
|
|
|
2743
|
+
// ../../packages/node-runtime/src/temp-workspace.ts
|
|
2744
|
+
import * as fs from "fs";
|
|
2745
|
+
import * as os from "os";
|
|
2746
|
+
import * as path from "path";
|
|
2747
|
+
var CHATLAB_TEMP_ROOT_ENV = "CHATLAB_TEMP_ROOT";
|
|
2748
|
+
var CHATLAB_TEMP_SCOPES = /* @__PURE__ */ new Set(["tests", "runtime", "imports", "merge", "sync", "parser", "build", "bench"]);
|
|
2749
|
+
function optionsEnv(options2) {
|
|
2750
|
+
return options2.env ?? process.env;
|
|
2751
|
+
}
|
|
2752
|
+
function resolveChatLabTempRoot(options2 = {}) {
|
|
2753
|
+
const envRoot = optionsEnv(options2)[CHATLAB_TEMP_ROOT_ENV]?.trim();
|
|
2754
|
+
if (envRoot) return path.resolve(envRoot);
|
|
2755
|
+
const platform2 = options2.platform ?? process.platform;
|
|
2756
|
+
const systemTempDir = options2.systemTempDir ?? os.tmpdir();
|
|
2757
|
+
return path.resolve(platform2 === "darwin" ? "/private/tmp/chatlab" : path.join(systemTempDir, "chatlab"));
|
|
2758
|
+
}
|
|
2759
|
+
function ensurePrivateOwnedDirectory(dirPath, label) {
|
|
2760
|
+
fs.mkdirSync(dirPath, { recursive: true, mode: 448 });
|
|
2761
|
+
const stats = fs.lstatSync(dirPath);
|
|
2762
|
+
if (stats.isSymbolicLink()) {
|
|
2763
|
+
throw new Error(`${label} must not be a symbolic link: ${dirPath}`);
|
|
2764
|
+
}
|
|
2765
|
+
if (!stats.isDirectory()) {
|
|
2766
|
+
throw new Error(`${label} must be a directory: ${dirPath}`);
|
|
2767
|
+
}
|
|
2768
|
+
if (typeof process.getuid === "function" && stats.uid !== process.getuid()) {
|
|
2769
|
+
throw new Error(`${label} is owned by another user: ${dirPath}`);
|
|
2770
|
+
}
|
|
2771
|
+
if (process.platform !== "win32") {
|
|
2772
|
+
fs.chmodSync(dirPath, 448);
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
function ensureChatLabTempRoot(options2 = {}) {
|
|
2776
|
+
const root = resolveChatLabTempRoot(options2);
|
|
2777
|
+
ensurePrivateOwnedDirectory(root, "ChatLab temp root");
|
|
2778
|
+
optionsEnv(options2)[CHATLAB_TEMP_ROOT_ENV] = root;
|
|
2779
|
+
return root;
|
|
2780
|
+
}
|
|
2781
|
+
function assertValidScope(scope) {
|
|
2782
|
+
if (!CHATLAB_TEMP_SCOPES.has(scope)) {
|
|
2783
|
+
throw new Error(`Invalid ChatLab temp scope: ${scope}`);
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
function assertValidPrefix(prefix) {
|
|
2787
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(prefix)) {
|
|
2788
|
+
throw new Error(`Invalid ChatLab temp prefix: ${prefix}`);
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
function getChatLabTempScopeDir(scope, options2 = {}) {
|
|
2792
|
+
assertValidScope(scope);
|
|
2793
|
+
const scopeDir = path.join(ensureChatLabTempRoot(options2), scope);
|
|
2794
|
+
ensurePrivateOwnedDirectory(scopeDir, "ChatLab temp scope");
|
|
2795
|
+
return scopeDir;
|
|
2796
|
+
}
|
|
2797
|
+
function createChatLabTempDir(scope, prefix, options2 = {}) {
|
|
2798
|
+
assertValidPrefix(prefix);
|
|
2799
|
+
return fs.mkdtempSync(path.join(getChatLabTempScopeDir(scope, options2), prefix));
|
|
2800
|
+
}
|
|
2801
|
+
function removeChatLabTempDir(dirPath, scope, options2 = {}) {
|
|
2802
|
+
const scopeDir = path.resolve(getChatLabTempScopeDir(scope, options2));
|
|
2803
|
+
const resolvedDir = path.resolve(dirPath);
|
|
2804
|
+
if (path.dirname(resolvedDir) !== scopeDir) {
|
|
2805
|
+
throw new Error(`Refusing to remove non-owned ChatLab temp directory: ${resolvedDir}`);
|
|
2806
|
+
}
|
|
2807
|
+
fs.rmSync(resolvedDir, { recursive: true, force: true });
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2741
2810
|
// ../../packages/node-runtime/src/import/write-parse-result.ts
|
|
2742
2811
|
function writeParseResultToDb(db, meta, members, messages) {
|
|
2743
2812
|
let messageCount = 0;
|
|
@@ -2852,28 +2921,28 @@ function writeParseResultToDb(db, meta, members, messages) {
|
|
|
2852
2921
|
}
|
|
2853
2922
|
|
|
2854
2923
|
// ../../packages/parser/src/index.ts
|
|
2855
|
-
import * as
|
|
2856
|
-
import * as
|
|
2924
|
+
import * as fs18 from "fs";
|
|
2925
|
+
import * as path14 from "path";
|
|
2857
2926
|
|
|
2858
2927
|
// ../../packages/parser/src/sniffer.ts
|
|
2859
|
-
import * as
|
|
2860
|
-
import * as
|
|
2928
|
+
import * as fs2 from "fs";
|
|
2929
|
+
import * as path2 from "path";
|
|
2861
2930
|
var HEAD_SIZE = 64 * 1024;
|
|
2862
2931
|
function readFileHead(filePath, size = HEAD_SIZE) {
|
|
2863
|
-
const fd =
|
|
2932
|
+
const fd = fs2.openSync(filePath, "r");
|
|
2864
2933
|
const buffer = Buffer.alloc(size);
|
|
2865
|
-
const bytesRead =
|
|
2866
|
-
|
|
2934
|
+
const bytesRead = fs2.readSync(fd, buffer, 0, size, 0);
|
|
2935
|
+
fs2.closeSync(fd);
|
|
2867
2936
|
return buffer.slice(0, bytesRead).toString("utf-8");
|
|
2868
2937
|
}
|
|
2869
2938
|
function getExtension(filePath) {
|
|
2870
|
-
return
|
|
2939
|
+
return path2.extname(filePath).toLowerCase();
|
|
2871
2940
|
}
|
|
2872
2941
|
function matchHeadSignatures(headContent, patterns) {
|
|
2873
2942
|
return patterns.some((pattern) => pattern.test(headContent));
|
|
2874
2943
|
}
|
|
2875
2944
|
function matchFilenameSignatures(filePath, patterns) {
|
|
2876
|
-
const filename =
|
|
2945
|
+
const filename = path2.basename(filePath);
|
|
2877
2946
|
return patterns.some((pattern) => pattern.test(filename));
|
|
2878
2947
|
}
|
|
2879
2948
|
function matchRequiredFields(headContent, fields) {
|
|
@@ -3021,18 +3090,18 @@ var import_stream_json = __toESM(require_stream_json(), 1);
|
|
|
3021
3090
|
var import_Pick = __toESM(require_Pick(), 1);
|
|
3022
3091
|
var import_StreamValues = __toESM(require_StreamValues(), 1);
|
|
3023
3092
|
var import_stream_chain = __toESM(require_stream_chain(), 1);
|
|
3024
|
-
import * as
|
|
3093
|
+
import * as fs4 from "fs";
|
|
3025
3094
|
|
|
3026
3095
|
// ../../packages/parser/src/utils.ts
|
|
3027
|
-
import * as
|
|
3096
|
+
import * as fs3 from "fs";
|
|
3028
3097
|
function getFileSize(filePath) {
|
|
3029
|
-
return
|
|
3098
|
+
return fs3.statSync(filePath).size;
|
|
3030
3099
|
}
|
|
3031
3100
|
function readFileHeadBytes(filePath, size) {
|
|
3032
|
-
const fd =
|
|
3101
|
+
const fd = fs3.openSync(filePath, "r");
|
|
3033
3102
|
const buffer = Buffer.alloc(size);
|
|
3034
|
-
const bytesRead =
|
|
3035
|
-
|
|
3103
|
+
const bytesRead = fs3.readSync(fd, buffer, 0, size, 0);
|
|
3104
|
+
fs3.closeSync(fd);
|
|
3036
3105
|
return buffer.slice(0, bytesRead).toString("utf-8");
|
|
3037
3106
|
}
|
|
3038
3107
|
var createProgress = (stage, bytesRead, totalBytes, messagesProcessed, message) => {
|
|
@@ -3062,7 +3131,7 @@ function isValidYear(timestampSeconds) {
|
|
|
3062
3131
|
}
|
|
3063
3132
|
|
|
3064
3133
|
// ../../packages/parser/src/formats/chatlab.ts
|
|
3065
|
-
import * as
|
|
3134
|
+
import * as path3 from "path";
|
|
3066
3135
|
|
|
3067
3136
|
// ../../packages/parser/src/native/loader.ts
|
|
3068
3137
|
import { createRequire } from "module";
|
|
@@ -3145,7 +3214,7 @@ async function* pumpNativeParser(adapter, options2, parser11, fallback) {
|
|
|
3145
3214
|
if (!batch) break;
|
|
3146
3215
|
messagesProcessed += batch.length;
|
|
3147
3216
|
yield { type: "messages", data: batch.map((message) => adapter.mapMessage(message, metaJson)) };
|
|
3148
|
-
await new Promise((
|
|
3217
|
+
await new Promise((resolve4) => setImmediate(resolve4));
|
|
3149
3218
|
}
|
|
3150
3219
|
const doneProgress = createProgress("done", totalBytes, totalBytes, messagesProcessed, "");
|
|
3151
3220
|
yield { type: "progress", data: doneProgress };
|
|
@@ -3243,7 +3312,7 @@ var { pick } = import_Pick.default;
|
|
|
3243
3312
|
var { streamValues } = import_StreamValues.default;
|
|
3244
3313
|
var { chain } = import_stream_chain.default;
|
|
3245
3314
|
function extractNameFromFilePath(filePath) {
|
|
3246
|
-
const basename13 =
|
|
3315
|
+
const basename13 = path3.basename(filePath);
|
|
3247
3316
|
const name = basename13.replace(/\.json$/i, "");
|
|
3248
3317
|
return name || "\u672A\u77E5\u7FA4\u804A";
|
|
3249
3318
|
}
|
|
@@ -3317,8 +3386,8 @@ async function* parseChatLab(options2) {
|
|
|
3317
3386
|
const members = [];
|
|
3318
3387
|
const memberMapFromMessages = /* @__PURE__ */ new Map();
|
|
3319
3388
|
const messageBatch = [];
|
|
3320
|
-
await new Promise((
|
|
3321
|
-
const readStream =
|
|
3389
|
+
await new Promise((resolve4, reject) => {
|
|
3390
|
+
const readStream = fs4.createReadStream(filePath, { encoding: "utf-8" });
|
|
3322
3391
|
readStream.on("data", (chunk) => {
|
|
3323
3392
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
3324
3393
|
});
|
|
@@ -3372,7 +3441,7 @@ async function* parseChatLab(options2) {
|
|
|
3372
3441
|
if (batchCollector.length > 0) {
|
|
3373
3442
|
messageBatch.push(...batchCollector);
|
|
3374
3443
|
}
|
|
3375
|
-
|
|
3444
|
+
resolve4();
|
|
3376
3445
|
});
|
|
3377
3446
|
pipeline2.on("error", reject);
|
|
3378
3447
|
});
|
|
@@ -3410,11 +3479,11 @@ var module_ = {
|
|
|
3410
3479
|
var chatlab_default = module_;
|
|
3411
3480
|
|
|
3412
3481
|
// ../../packages/parser/src/formats/chatlab-jsonl.ts
|
|
3413
|
-
import * as
|
|
3482
|
+
import * as fs5 from "fs";
|
|
3414
3483
|
import * as readline from "readline";
|
|
3415
|
-
import * as
|
|
3484
|
+
import * as path4 from "path";
|
|
3416
3485
|
function extractNameFromFilePath2(filePath) {
|
|
3417
|
-
const basename13 =
|
|
3486
|
+
const basename13 = path4.basename(filePath);
|
|
3418
3487
|
const name = basename13.replace(/\.jsonl$/i, "");
|
|
3419
3488
|
return name || "\u672A\u77E5\u7FA4\u804A";
|
|
3420
3489
|
}
|
|
@@ -3455,7 +3524,7 @@ async function* parseChatLabJsonl(options2) {
|
|
|
3455
3524
|
const messageBatch = [];
|
|
3456
3525
|
let meta = null;
|
|
3457
3526
|
let headerParsed = false;
|
|
3458
|
-
const fileStream =
|
|
3527
|
+
const fileStream = fs5.createReadStream(filePath, { encoding: "utf-8" });
|
|
3459
3528
|
const rl = readline.createInterface({
|
|
3460
3529
|
input: fileStream,
|
|
3461
3530
|
crlfDelay: Infinity
|
|
@@ -3580,28 +3649,30 @@ var import_stream_json3 = __toESM(require_stream_json(), 1);
|
|
|
3580
3649
|
var import_Pick3 = __toESM(require_Pick(), 1);
|
|
3581
3650
|
var import_StreamValues3 = __toESM(require_StreamValues(), 1);
|
|
3582
3651
|
var import_stream_chain3 = __toESM(require_stream_chain(), 1);
|
|
3583
|
-
import * as
|
|
3584
|
-
import * as
|
|
3652
|
+
import * as fs7 from "fs";
|
|
3653
|
+
import * as path6 from "path";
|
|
3585
3654
|
|
|
3586
3655
|
// ../../packages/parser/src/formats/shuakami-qq-preprocessor.ts
|
|
3587
3656
|
var import_stream_json2 = __toESM(require_stream_json(), 1);
|
|
3588
3657
|
var import_Pick2 = __toESM(require_Pick(), 1);
|
|
3589
3658
|
var import_StreamValues2 = __toESM(require_StreamValues(), 1);
|
|
3590
3659
|
var import_stream_chain2 = __toESM(require_stream_chain(), 1);
|
|
3591
|
-
import * as
|
|
3592
|
-
import * as
|
|
3593
|
-
import * as
|
|
3660
|
+
import * as fs6 from "fs";
|
|
3661
|
+
import * as path5 from "path";
|
|
3662
|
+
import * as os2 from "os";
|
|
3594
3663
|
var { parser: parser3 } = import_stream_json2.default;
|
|
3595
3664
|
var { pick: pick2 } = import_Pick2.default;
|
|
3596
3665
|
var { streamValues: streamValues2 } = import_StreamValues2.default;
|
|
3597
3666
|
var { chain: chain2 } = import_stream_chain2.default;
|
|
3598
3667
|
var PREPROCESS_THRESHOLD = 50 * 1024 * 1024;
|
|
3599
3668
|
function getTempDir() {
|
|
3600
|
-
|
|
3669
|
+
const configuredRoot = process.env.CHATLAB_TEMP_ROOT?.trim();
|
|
3670
|
+
const root = configuredRoot ? path5.resolve(configuredRoot) : path5.resolve(process.platform === "darwin" ? "/private/tmp/chatlab" : path5.join(os2.tmpdir(), "chatlab"));
|
|
3671
|
+
return path5.join(root, "parser");
|
|
3601
3672
|
}
|
|
3602
3673
|
function ensureDir(dir) {
|
|
3603
|
-
if (!
|
|
3604
|
-
|
|
3674
|
+
if (!fs6.existsSync(dir)) {
|
|
3675
|
+
fs6.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3605
3676
|
}
|
|
3606
3677
|
}
|
|
3607
3678
|
function extractJsonObject(content, key) {
|
|
@@ -3643,12 +3714,12 @@ function extractJsonObject(content, key) {
|
|
|
3643
3714
|
}
|
|
3644
3715
|
function readAvatarsFromFile(filePath) {
|
|
3645
3716
|
try {
|
|
3646
|
-
const stats =
|
|
3717
|
+
const stats = fs6.statSync(filePath);
|
|
3647
3718
|
const tailSize = Math.min(stats.size, 5e6);
|
|
3648
|
-
const fd =
|
|
3719
|
+
const fd = fs6.openSync(filePath, "r");
|
|
3649
3720
|
const buffer = Buffer.alloc(tailSize);
|
|
3650
|
-
|
|
3651
|
-
|
|
3721
|
+
fs6.readSync(fd, buffer, 0, tailSize, stats.size - tailSize);
|
|
3722
|
+
fs6.closeSync(fd);
|
|
3652
3723
|
const tailContent = buffer.toString("utf-8");
|
|
3653
3724
|
return extractJsonObject(tailContent, "avatars");
|
|
3654
3725
|
} catch {
|
|
@@ -3707,15 +3778,15 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3707
3778
|
let messagesProcessed = 0;
|
|
3708
3779
|
const tempDir = getTempDir();
|
|
3709
3780
|
ensureDir(tempDir);
|
|
3710
|
-
const outputFilename = `slim_${Date.now()}_${
|
|
3711
|
-
const outputPath =
|
|
3781
|
+
const outputFilename = `slim_${Date.now()}_${path5.basename(inputPath)}`;
|
|
3782
|
+
const outputPath = path5.join(tempDir, outputFilename);
|
|
3712
3783
|
onProgress?.(createProgress("parsing", 0, totalBytes, 0, ""));
|
|
3713
3784
|
const avatarsStr = readAvatarsFromFile(inputPath);
|
|
3714
|
-
return new Promise((
|
|
3785
|
+
return new Promise((resolve4, reject) => {
|
|
3715
3786
|
const headChunks = [];
|
|
3716
3787
|
let headSize = 0;
|
|
3717
3788
|
const maxHeadSize = 1e5;
|
|
3718
|
-
const headStream =
|
|
3789
|
+
const headStream = fs6.createReadStream(inputPath, { encoding: "utf-8" });
|
|
3719
3790
|
let chatInfo = { name: "\u672A\u77E5\u7FA4\u804A", type: "group" };
|
|
3720
3791
|
let metadata;
|
|
3721
3792
|
let statistics;
|
|
@@ -3752,8 +3823,8 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3752
3823
|
} catch {
|
|
3753
3824
|
}
|
|
3754
3825
|
onProgress?.(createProgress("parsing", 0, totalBytes, 0, ""));
|
|
3755
|
-
const readStream =
|
|
3756
|
-
const writeStream =
|
|
3826
|
+
const readStream = fs6.createReadStream(inputPath, { encoding: "utf-8" });
|
|
3827
|
+
const writeStream = fs6.createWriteStream(outputPath, { encoding: "utf-8" });
|
|
3757
3828
|
readStream.on("data", (chunk) => {
|
|
3758
3829
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
3759
3830
|
});
|
|
@@ -3793,13 +3864,13 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3793
3864
|
writeStream.end();
|
|
3794
3865
|
writeStream.on("finish", () => {
|
|
3795
3866
|
onProgress?.(createProgress("done", totalBytes, totalBytes, messagesProcessed, ""));
|
|
3796
|
-
|
|
3867
|
+
resolve4(outputPath);
|
|
3797
3868
|
});
|
|
3798
3869
|
});
|
|
3799
3870
|
pipeline2.on("error", (err) => {
|
|
3800
3871
|
writeStream.destroy();
|
|
3801
|
-
if (
|
|
3802
|
-
|
|
3872
|
+
if (fs6.existsSync(outputPath)) {
|
|
3873
|
+
fs6.unlinkSync(outputPath);
|
|
3803
3874
|
}
|
|
3804
3875
|
onProgress?.(createProgress("error", bytesRead, totalBytes, messagesProcessed, err.message));
|
|
3805
3876
|
reject(err);
|
|
@@ -3810,8 +3881,8 @@ async function preprocessQQJson(inputPath, onProgress) {
|
|
|
3810
3881
|
}
|
|
3811
3882
|
function cleanupTempFile(filePath) {
|
|
3812
3883
|
try {
|
|
3813
|
-
if (
|
|
3814
|
-
|
|
3884
|
+
if (fs6.existsSync(filePath) && path5.dirname(path5.resolve(filePath)) === path5.resolve(getTempDir())) {
|
|
3885
|
+
fs6.unlinkSync(filePath);
|
|
3815
3886
|
}
|
|
3816
3887
|
} catch {
|
|
3817
3888
|
}
|
|
@@ -3878,9 +3949,12 @@ function extractJsonObject2(content, key) {
|
|
|
3878
3949
|
return null;
|
|
3879
3950
|
}
|
|
3880
3951
|
function extractNameFromFilePath3(filePath) {
|
|
3881
|
-
const basename13 =
|
|
3952
|
+
const basename13 = path6.basename(filePath);
|
|
3882
3953
|
return basename13.replace(/\.json$/i, "") || "\u672A\u77E5\u7FA4\u804A";
|
|
3883
3954
|
}
|
|
3955
|
+
function isPlaceholderSenderId(id) {
|
|
3956
|
+
return id === "0" || id === "\u672A\u77E5";
|
|
3957
|
+
}
|
|
3884
3958
|
function countSenders(content) {
|
|
3885
3959
|
const sendersStart = content.indexOf('"senders"');
|
|
3886
3960
|
if (sendersStart === -1) return 0;
|
|
@@ -3895,8 +3969,19 @@ function countSenders(content) {
|
|
|
3895
3969
|
}
|
|
3896
3970
|
if (depth !== 0) return 0;
|
|
3897
3971
|
const sendersContent = content.slice(arrayStart + 1, i - 1);
|
|
3898
|
-
const uidMatches = sendersContent.
|
|
3899
|
-
|
|
3972
|
+
const uidMatches = sendersContent.matchAll(/"uid"\s*:\s*"([^"]*)"/g);
|
|
3973
|
+
let count = 0;
|
|
3974
|
+
for (const match of uidMatches) {
|
|
3975
|
+
const uid = match[1];
|
|
3976
|
+
if (uid && !isPlaceholderSenderId(uid)) count++;
|
|
3977
|
+
}
|
|
3978
|
+
return count;
|
|
3979
|
+
}
|
|
3980
|
+
function resolveChatType(chatInfoType, headContent) {
|
|
3981
|
+
if (chatInfoType === "group") return "group" /* GROUP */;
|
|
3982
|
+
const sendersCount = countSenders(headContent);
|
|
3983
|
+
if (chatInfoType === "private") return sendersCount > 2 ? "group" /* GROUP */ : "private" /* PRIVATE */;
|
|
3984
|
+
return sendersCount > 2 ? "group" /* GROUP */ : sendersCount > 0 ? "private" /* PRIVATE */ : "group" /* GROUP */;
|
|
3900
3985
|
}
|
|
3901
3986
|
function convertMessageType(messageType, content, isRecalled) {
|
|
3902
3987
|
if (isRecalled) return 81 /* RECALL */;
|
|
@@ -3950,8 +4035,7 @@ async function* parseV4(options2) {
|
|
|
3950
4035
|
}
|
|
3951
4036
|
} catch {
|
|
3952
4037
|
}
|
|
3953
|
-
const
|
|
3954
|
-
const chatType = sendersCount > 2 ? "group" /* GROUP */ : sendersCount > 0 ? "private" /* PRIVATE */ : "group" /* GROUP */;
|
|
4038
|
+
const chatType = resolveChatType(chatInfo.type, headContent);
|
|
3955
4039
|
const meta = {
|
|
3956
4040
|
name: chatInfo.name || extractNameFromFilePath3(filePath),
|
|
3957
4041
|
platform: KNOWN_PLATFORMS.QQ,
|
|
@@ -3962,15 +4046,15 @@ async function* parseV4(options2) {
|
|
|
3962
4046
|
yield { type: "meta", data: meta };
|
|
3963
4047
|
const memberMap = /* @__PURE__ */ new Map();
|
|
3964
4048
|
const messageBatch = [];
|
|
3965
|
-
await new Promise((
|
|
3966
|
-
const readStream =
|
|
4049
|
+
await new Promise((resolve4, reject) => {
|
|
4050
|
+
const readStream = fs7.createReadStream(filePath, { encoding: "utf-8" });
|
|
3967
4051
|
readStream.on("data", (chunk) => {
|
|
3968
4052
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
3969
4053
|
});
|
|
3970
4054
|
const pipeline2 = chain3([readStream, parser4(), pick3({ filter: /^messages\.\d+$/ }), streamValues3()]);
|
|
3971
4055
|
pipeline2.on("data", ({ value }) => {
|
|
3972
4056
|
const platformId = value.sender.uin || value.sender.uid || value.rawMessage?.senderUin || value.rawMessage?.senderUid;
|
|
3973
|
-
if (!platformId) {
|
|
4057
|
+
if (!platformId || isPlaceholderSenderId(platformId)) {
|
|
3974
4058
|
skippedMessages++;
|
|
3975
4059
|
return;
|
|
3976
4060
|
}
|
|
@@ -3989,9 +4073,11 @@ async function* parseV4(options2) {
|
|
|
3989
4073
|
skippedMessages++;
|
|
3990
4074
|
return;
|
|
3991
4075
|
}
|
|
3992
|
-
const
|
|
4076
|
+
const isSystem = value.system ?? value.isSystemMessage;
|
|
4077
|
+
const isRecalled = value.recalled ?? value.isRecalled;
|
|
4078
|
+
const type = isSystem ? 80 /* SYSTEM */ : convertMessageType(value.messageType, value.content, isRecalled);
|
|
3993
4079
|
let textContent = value.content?.text || "";
|
|
3994
|
-
if (
|
|
4080
|
+
if (isRecalled) textContent = "[\u5DF2\u64A4\u56DE] " + textContent;
|
|
3995
4081
|
messageBatch.push({
|
|
3996
4082
|
platformMessageId: value.messageId,
|
|
3997
4083
|
// 消息的平台原始 ID
|
|
@@ -4016,17 +4102,17 @@ async function* parseV4(options2) {
|
|
|
4016
4102
|
onProgress?.(progress);
|
|
4017
4103
|
}
|
|
4018
4104
|
});
|
|
4019
|
-
pipeline2.on("end",
|
|
4105
|
+
pipeline2.on("end", resolve4);
|
|
4020
4106
|
pipeline2.on("error", reject);
|
|
4021
4107
|
});
|
|
4022
4108
|
const avatarsMap = /* @__PURE__ */ new Map();
|
|
4023
4109
|
try {
|
|
4024
|
-
const stats =
|
|
4110
|
+
const stats = fs7.statSync(filePath);
|
|
4025
4111
|
const tailSize = Math.min(stats.size, 5e6);
|
|
4026
|
-
const fd =
|
|
4112
|
+
const fd = fs7.openSync(filePath, "r");
|
|
4027
4113
|
const buffer = Buffer.alloc(tailSize);
|
|
4028
|
-
|
|
4029
|
-
|
|
4114
|
+
fs7.readSync(fd, buffer, 0, tailSize, stats.size - tailSize);
|
|
4115
|
+
fs7.closeSync(fd);
|
|
4030
4116
|
const tailContent = buffer.toString("utf-8");
|
|
4031
4117
|
const avatarsStr = extractJsonObject2(tailContent, "avatars");
|
|
4032
4118
|
if (avatarsStr) {
|
|
@@ -4078,8 +4164,8 @@ var module_3 = {
|
|
|
4078
4164
|
var shuakami_qq_exporter_default = module_3;
|
|
4079
4165
|
|
|
4080
4166
|
// ../../packages/parser/src/formats/shuakami-qq-exporter-chunked.ts
|
|
4081
|
-
import * as
|
|
4082
|
-
import * as
|
|
4167
|
+
import * as fs8 from "fs";
|
|
4168
|
+
import * as path7 from "path";
|
|
4083
4169
|
import * as readline2 from "readline";
|
|
4084
4170
|
var feature4 = {
|
|
4085
4171
|
id: "shuakami-qq-exporter-chunked",
|
|
@@ -4128,7 +4214,7 @@ function convertMessageType2(msgType, content, isRecalled) {
|
|
|
4128
4214
|
return 0 /* TEXT */;
|
|
4129
4215
|
}
|
|
4130
4216
|
function readManifest(manifestPath) {
|
|
4131
|
-
const content =
|
|
4217
|
+
const content = fs8.readFileSync(manifestPath, "utf-8");
|
|
4132
4218
|
return JSON.parse(content);
|
|
4133
4219
|
}
|
|
4134
4220
|
function getChunkRelativePath(chunk) {
|
|
@@ -4146,9 +4232,9 @@ function calculateTotalBytes(manifest, baseDir) {
|
|
|
4146
4232
|
let total = 0;
|
|
4147
4233
|
for (const chunk of manifest.chunked.chunks) {
|
|
4148
4234
|
const relativePath = getChunkRelativePath(chunk);
|
|
4149
|
-
const chunkPath =
|
|
4150
|
-
if (
|
|
4151
|
-
total +=
|
|
4235
|
+
const chunkPath = path7.join(baseDir, relativePath);
|
|
4236
|
+
if (fs8.existsSync(chunkPath)) {
|
|
4237
|
+
total += fs8.statSync(chunkPath).size;
|
|
4152
4238
|
}
|
|
4153
4239
|
}
|
|
4154
4240
|
return total;
|
|
@@ -4156,10 +4242,10 @@ function calculateTotalBytes(manifest, baseDir) {
|
|
|
4156
4242
|
function readAvatars(baseDir, avatarsInfo) {
|
|
4157
4243
|
const avatarsMap = /* @__PURE__ */ new Map();
|
|
4158
4244
|
if (!avatarsInfo?.file) return avatarsMap;
|
|
4159
|
-
const avatarsPath =
|
|
4160
|
-
if (!
|
|
4245
|
+
const avatarsPath = path7.join(baseDir, avatarsInfo.file);
|
|
4246
|
+
if (!fs8.existsSync(avatarsPath)) return avatarsMap;
|
|
4161
4247
|
try {
|
|
4162
|
-
const content =
|
|
4248
|
+
const content = fs8.readFileSync(avatarsPath, "utf-8");
|
|
4163
4249
|
const avatars = JSON.parse(content);
|
|
4164
4250
|
for (const [uin, avatar] of Object.entries(avatars)) {
|
|
4165
4251
|
if (avatar && typeof avatar === "string" && avatar.startsWith("data:image/")) {
|
|
@@ -4177,7 +4263,7 @@ async function* readJsonlFile(filePath, onParseError) {
|
|
|
4177
4263
|
let parseErrorCount = 0;
|
|
4178
4264
|
const MAX_PARSE_ERRORS_TO_LOG = 10;
|
|
4179
4265
|
try {
|
|
4180
|
-
fileStream =
|
|
4266
|
+
fileStream = fs8.createReadStream(filePath, { encoding: "utf-8" });
|
|
4181
4267
|
rl = readline2.createInterface({
|
|
4182
4268
|
input: fileStream,
|
|
4183
4269
|
crlfDelay: Infinity
|
|
@@ -4208,7 +4294,7 @@ async function* readJsonlFile(filePath, onParseError) {
|
|
|
4208
4294
|
async function* parseChunkedJsonl(options2) {
|
|
4209
4295
|
const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
|
|
4210
4296
|
const manifestPath = filePath;
|
|
4211
|
-
const baseDir =
|
|
4297
|
+
const baseDir = path7.dirname(manifestPath);
|
|
4212
4298
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 manifest: ${manifestPath}`);
|
|
4213
4299
|
onLog?.("info", `\u57FA\u7840\u76EE\u5F55: ${baseDir}`);
|
|
4214
4300
|
let manifest;
|
|
@@ -4262,13 +4348,13 @@ async function* parseChunkedJsonl(options2) {
|
|
|
4262
4348
|
for (let chunkIndex = 0; chunkIndex < manifest.chunked.chunks.length; chunkIndex++) {
|
|
4263
4349
|
const chunkInfo = manifest.chunked.chunks[chunkIndex];
|
|
4264
4350
|
const relativePath = getChunkRelativePath(chunkInfo);
|
|
4265
|
-
const chunkPath =
|
|
4351
|
+
const chunkPath = path7.join(baseDir, relativePath);
|
|
4266
4352
|
const chunkMessageCount = getChunkMessageCount(chunkInfo);
|
|
4267
|
-
if (!
|
|
4353
|
+
if (!fs8.existsSync(chunkPath)) {
|
|
4268
4354
|
onLog?.("error", `\u5206\u5757\u6587\u4EF6\u4E0D\u5B58\u5728: ${chunkPath}`);
|
|
4269
4355
|
continue;
|
|
4270
4356
|
}
|
|
4271
|
-
const chunkSize =
|
|
4357
|
+
const chunkSize = fs8.statSync(chunkPath).size;
|
|
4272
4358
|
let chunkMessagesRead = 0;
|
|
4273
4359
|
let chunkParseErrors = 0;
|
|
4274
4360
|
onLog?.(
|
|
@@ -4390,8 +4476,8 @@ var import_stream_json4 = __toESM(require_stream_json(), 1);
|
|
|
4390
4476
|
var import_Pick4 = __toESM(require_Pick(), 1);
|
|
4391
4477
|
var import_StreamValues4 = __toESM(require_StreamValues(), 1);
|
|
4392
4478
|
var import_stream_chain4 = __toESM(require_stream_chain(), 1);
|
|
4393
|
-
import * as
|
|
4394
|
-
import * as
|
|
4479
|
+
import * as fs9 from "fs";
|
|
4480
|
+
import * as path8 from "path";
|
|
4395
4481
|
|
|
4396
4482
|
// ../../packages/parser/src/native/weflow-native.ts
|
|
4397
4483
|
var weflowAdapter = {
|
|
@@ -4464,7 +4550,7 @@ var { pick: pick4 } = import_Pick4.default;
|
|
|
4464
4550
|
var { streamValues: streamValues4 } = import_StreamValues4.default;
|
|
4465
4551
|
var { chain: chain4 } = import_stream_chain4.default;
|
|
4466
4552
|
function extractNameFromFilePath4(filePath) {
|
|
4467
|
-
const basename13 =
|
|
4553
|
+
const basename13 = path8.basename(filePath);
|
|
4468
4554
|
const name = basename13.replace(/\.json$/i, "");
|
|
4469
4555
|
return name || "\u672A\u77E5\u804A\u5929";
|
|
4470
4556
|
}
|
|
@@ -4532,8 +4618,8 @@ async function* parseWeFlow(options2) {
|
|
|
4532
4618
|
const headContent = readFileHeadBytes(filePath, 5e3);
|
|
4533
4619
|
let session = null;
|
|
4534
4620
|
try {
|
|
4535
|
-
await new Promise((
|
|
4536
|
-
const sessionStream =
|
|
4621
|
+
await new Promise((resolve4) => {
|
|
4622
|
+
const sessionStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
4537
4623
|
let sessionContent = "";
|
|
4538
4624
|
let inSession = false;
|
|
4539
4625
|
let braceDepth = 0;
|
|
@@ -4584,9 +4670,9 @@ async function* parseWeFlow(options2) {
|
|
|
4584
4670
|
} catch {
|
|
4585
4671
|
}
|
|
4586
4672
|
}
|
|
4587
|
-
|
|
4673
|
+
resolve4();
|
|
4588
4674
|
});
|
|
4589
|
-
sessionStream.on("error", () =>
|
|
4675
|
+
sessionStream.on("error", () => resolve4());
|
|
4590
4676
|
});
|
|
4591
4677
|
} catch {
|
|
4592
4678
|
}
|
|
@@ -4655,8 +4741,8 @@ async function* parseWeFlow(options2) {
|
|
|
4655
4741
|
}
|
|
4656
4742
|
if (avatarsMap.size === 0) {
|
|
4657
4743
|
try {
|
|
4658
|
-
await new Promise((
|
|
4659
|
-
const avatarStream =
|
|
4744
|
+
await new Promise((resolve4) => {
|
|
4745
|
+
const avatarStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
4660
4746
|
let avatarsContent = "";
|
|
4661
4747
|
let inAvatars = false;
|
|
4662
4748
|
let braceDepth = 0;
|
|
@@ -4712,9 +4798,9 @@ async function* parseWeFlow(options2) {
|
|
|
4712
4798
|
} catch {
|
|
4713
4799
|
}
|
|
4714
4800
|
}
|
|
4715
|
-
|
|
4801
|
+
resolve4();
|
|
4716
4802
|
});
|
|
4717
|
-
avatarStream.on("error", () =>
|
|
4803
|
+
avatarStream.on("error", () => resolve4());
|
|
4718
4804
|
});
|
|
4719
4805
|
} catch {
|
|
4720
4806
|
}
|
|
@@ -4722,8 +4808,8 @@ async function* parseWeFlow(options2) {
|
|
|
4722
4808
|
const groupAvatar = sessionData?.avatar || (groupId ? avatarsMap.get(groupId) : void 0);
|
|
4723
4809
|
let ownerId;
|
|
4724
4810
|
try {
|
|
4725
|
-
await new Promise((
|
|
4726
|
-
const scanStream =
|
|
4811
|
+
await new Promise((resolve4) => {
|
|
4812
|
+
const scanStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
4727
4813
|
const scanPipeline = chain4([scanStream, parser5(), pick4({ filter: /^messages\.\d+$/ }), streamValues4()]);
|
|
4728
4814
|
scanPipeline.on("data", ({ value }) => {
|
|
4729
4815
|
if (value.isSend === 1 && value.senderUsername && !value.senderUsername.endsWith("@chatroom")) {
|
|
@@ -4731,9 +4817,9 @@ async function* parseWeFlow(options2) {
|
|
|
4731
4817
|
scanStream.destroy();
|
|
4732
4818
|
}
|
|
4733
4819
|
});
|
|
4734
|
-
scanStream.on("close", () =>
|
|
4735
|
-
scanPipeline.on("end", () =>
|
|
4736
|
-
scanPipeline.on("error", () =>
|
|
4820
|
+
scanStream.on("close", () => resolve4());
|
|
4821
|
+
scanPipeline.on("end", () => resolve4());
|
|
4822
|
+
scanPipeline.on("error", () => resolve4());
|
|
4737
4823
|
});
|
|
4738
4824
|
} catch {
|
|
4739
4825
|
}
|
|
@@ -4748,8 +4834,8 @@ async function* parseWeFlow(options2) {
|
|
|
4748
4834
|
yield { type: "meta", data: meta };
|
|
4749
4835
|
const memberMap = /* @__PURE__ */ new Map();
|
|
4750
4836
|
const messageBatch = [];
|
|
4751
|
-
await new Promise((
|
|
4752
|
-
const readStream =
|
|
4837
|
+
await new Promise((resolve4, reject) => {
|
|
4838
|
+
const readStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
|
|
4753
4839
|
readStream.on("data", (chunk) => {
|
|
4754
4840
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
4755
4841
|
});
|
|
@@ -4821,7 +4907,7 @@ async function* parseWeFlow(options2) {
|
|
|
4821
4907
|
if (batchCollector.length > 0) {
|
|
4822
4908
|
messageBatch.push(...batchCollector);
|
|
4823
4909
|
}
|
|
4824
|
-
|
|
4910
|
+
resolve4();
|
|
4825
4911
|
});
|
|
4826
4912
|
pipeline2.on("error", reject);
|
|
4827
4913
|
});
|
|
@@ -4886,7 +4972,7 @@ var import_stream_json5 = __toESM(require_stream_json(), 1);
|
|
|
4886
4972
|
var import_Pick5 = __toESM(require_Pick(), 1);
|
|
4887
4973
|
var import_StreamValues5 = __toESM(require_StreamValues(), 1);
|
|
4888
4974
|
var import_stream_chain5 = __toESM(require_stream_chain(), 1);
|
|
4889
|
-
import * as
|
|
4975
|
+
import * as fs10 from "fs";
|
|
4890
4976
|
var { parser: parser6 } = import_stream_json5.default;
|
|
4891
4977
|
var { pick: pick5 } = import_Pick5.default;
|
|
4892
4978
|
var { streamValues: streamValues5 } = import_StreamValues5.default;
|
|
@@ -5035,8 +5121,8 @@ async function* parseDiscordExporter(options2) {
|
|
|
5035
5121
|
onLog?.("info", `\u7FA4\u804A\u540D\u79F0: ${chatName}`);
|
|
5036
5122
|
const memberMap = /* @__PURE__ */ new Map();
|
|
5037
5123
|
const messageBatch = [];
|
|
5038
|
-
await new Promise((
|
|
5039
|
-
const readStream =
|
|
5124
|
+
await new Promise((resolve4, reject) => {
|
|
5125
|
+
const readStream = fs10.createReadStream(filePath, { encoding: "utf-8" });
|
|
5040
5126
|
readStream.on("data", (chunk) => {
|
|
5041
5127
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
5042
5128
|
});
|
|
@@ -5114,7 +5200,7 @@ ${stickerTexts.join("\n")}` : stickerTexts.join("\n");
|
|
|
5114
5200
|
if (batchCollector.length > 0) {
|
|
5115
5201
|
messageBatch.push(...batchCollector);
|
|
5116
5202
|
}
|
|
5117
|
-
|
|
5203
|
+
resolve4();
|
|
5118
5204
|
});
|
|
5119
5205
|
pipeline2.on("error", reject);
|
|
5120
5206
|
});
|
|
@@ -5152,7 +5238,7 @@ var import_stream_chain6 = __toESM(require_stream_chain(), 1);
|
|
|
5152
5238
|
var import_stream_json6 = __toESM(require_stream_json(), 1);
|
|
5153
5239
|
var import_Pick6 = __toESM(require_Pick(), 1);
|
|
5154
5240
|
var import_StreamValues6 = __toESM(require_StreamValues(), 1);
|
|
5155
|
-
import * as
|
|
5241
|
+
import * as fs11 from "fs";
|
|
5156
5242
|
|
|
5157
5243
|
// ../../packages/parser/src/formats/utils/telegram-utils.ts
|
|
5158
5244
|
function mapChatType(telegramType) {
|
|
@@ -5237,8 +5323,8 @@ var feature8 = {
|
|
|
5237
5323
|
};
|
|
5238
5324
|
async function scanChats(filePath) {
|
|
5239
5325
|
const chats = [];
|
|
5240
|
-
return new Promise((
|
|
5241
|
-
const readStream =
|
|
5326
|
+
return new Promise((resolve4, reject) => {
|
|
5327
|
+
const readStream = fs11.createReadStream(filePath, { encoding: "utf-8" });
|
|
5242
5328
|
const pipeline2 = chain6([readStream, parser7(), pick6({ filter: /^chats\.list\.\d+$/ }), streamValues6()]);
|
|
5243
5329
|
pipeline2.on("data", ({ value }) => {
|
|
5244
5330
|
const chat = value;
|
|
@@ -5251,7 +5337,7 @@ async function scanChats(filePath) {
|
|
|
5251
5337
|
});
|
|
5252
5338
|
});
|
|
5253
5339
|
pipeline2.on("end", () => {
|
|
5254
|
-
|
|
5340
|
+
resolve4(chats);
|
|
5255
5341
|
});
|
|
5256
5342
|
pipeline2.on("error", (err) => {
|
|
5257
5343
|
reject(new Error(`\u626B\u63CF Telegram \u6587\u4EF6\u5931\u8D25: ${err.message}`));
|
|
@@ -5270,8 +5356,8 @@ async function* parseTelegram(options2) {
|
|
|
5270
5356
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Telegram JSON \u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
5271
5357
|
onLog?.("info", `\u76EE\u6807\u804A\u5929\u7D22\u5F15: ${chatIndex}`);
|
|
5272
5358
|
const chatPathFilter = `chats.list.${chatIndex}`;
|
|
5273
|
-
const chatData = await new Promise((
|
|
5274
|
-
const readStream =
|
|
5359
|
+
const chatData = await new Promise((resolve4, reject) => {
|
|
5360
|
+
const readStream = fs11.createReadStream(filePath, { encoding: "utf-8" });
|
|
5275
5361
|
readStream.on("data", (chunk) => {
|
|
5276
5362
|
bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
|
|
5277
5363
|
});
|
|
@@ -5284,10 +5370,10 @@ async function* parseTelegram(options2) {
|
|
|
5284
5370
|
let found = false;
|
|
5285
5371
|
pipeline2.on("data", ({ value }) => {
|
|
5286
5372
|
found = true;
|
|
5287
|
-
|
|
5373
|
+
resolve4(value);
|
|
5288
5374
|
});
|
|
5289
5375
|
pipeline2.on("end", () => {
|
|
5290
|
-
if (!found)
|
|
5376
|
+
if (!found) resolve4(null);
|
|
5291
5377
|
});
|
|
5292
5378
|
pipeline2.on("error", reject);
|
|
5293
5379
|
});
|
|
@@ -5379,7 +5465,7 @@ var telegram_native_default = module_8;
|
|
|
5379
5465
|
var import_stream_chain7 = __toESM(require_stream_chain(), 1);
|
|
5380
5466
|
var import_stream_json7 = __toESM(require_stream_json(), 1);
|
|
5381
5467
|
var import_StreamValues7 = __toESM(require_StreamValues(), 1);
|
|
5382
|
-
import * as
|
|
5468
|
+
import * as fs12 from "fs";
|
|
5383
5469
|
var { chain: chain7 } = import_stream_chain7.default;
|
|
5384
5470
|
var { parser: parser8 } = import_stream_json7.default;
|
|
5385
5471
|
var { streamValues: streamValues7 } = import_StreamValues7.default;
|
|
@@ -5408,18 +5494,18 @@ async function* parseTelegramSingle(options2) {
|
|
|
5408
5494
|
yield { type: "progress", data: initialProgress };
|
|
5409
5495
|
onProgress?.(initialProgress);
|
|
5410
5496
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Telegram \u5355\u804A\u5929 JSON \u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
5411
|
-
const chatData = await new Promise((
|
|
5412
|
-
const readStream =
|
|
5497
|
+
const chatData = await new Promise((resolve4, reject) => {
|
|
5498
|
+
const readStream = fs12.createReadStream(filePath, { encoding: "utf-8" });
|
|
5413
5499
|
const pipeline2 = chain7([readStream, parser8(), streamValues7()]);
|
|
5414
5500
|
let found = false;
|
|
5415
5501
|
pipeline2.on("data", ({ value }) => {
|
|
5416
5502
|
if (!found) {
|
|
5417
5503
|
found = true;
|
|
5418
|
-
|
|
5504
|
+
resolve4(value);
|
|
5419
5505
|
}
|
|
5420
5506
|
});
|
|
5421
5507
|
pipeline2.on("end", () => {
|
|
5422
|
-
if (!found)
|
|
5508
|
+
if (!found) resolve4(null);
|
|
5423
5509
|
});
|
|
5424
5510
|
pipeline2.on("error", reject);
|
|
5425
5511
|
});
|
|
@@ -5507,11 +5593,11 @@ var module_9 = {
|
|
|
5507
5593
|
var telegram_native_single_default = module_9;
|
|
5508
5594
|
|
|
5509
5595
|
// ../../packages/parser/src/formats/whatsapp-native-txt.ts
|
|
5510
|
-
import * as
|
|
5511
|
-
import * as
|
|
5596
|
+
import * as fs13 from "fs";
|
|
5597
|
+
import * as path9 from "path";
|
|
5512
5598
|
import * as readline3 from "readline";
|
|
5513
5599
|
function extractNameFromFilePath5(filePath) {
|
|
5514
|
-
const basename13 =
|
|
5600
|
+
const basename13 = path9.basename(filePath);
|
|
5515
5601
|
const matchZhCn = basename13.match(/^与(.+?)的\s*WhatsApp\s*聊天\.txt$/i);
|
|
5516
5602
|
if (matchZhCn) return matchZhCn[1].trim();
|
|
5517
5603
|
const matchZhTw = basename13.match(/^與(.+?)的\s*WhatsApp\s*對話\.txt$/i);
|
|
@@ -5519,7 +5605,7 @@ function extractNameFromFilePath5(filePath) {
|
|
|
5519
5605
|
return basename13.replace(/\.txt$/i, "") || "\u672A\u77E5\u804A\u5929";
|
|
5520
5606
|
}
|
|
5521
5607
|
function shouldInferPrivateChatName(filePath, fallbackName) {
|
|
5522
|
-
const basename13 =
|
|
5608
|
+
const basename13 = path9.basename(filePath);
|
|
5523
5609
|
return /^_chat\.txt$/i.test(basename13) || /^whatsapp(?:[-_\s].*)?$/i.test(fallbackName);
|
|
5524
5610
|
}
|
|
5525
5611
|
function inferPrivateChatName(memberMap, fallbackName) {
|
|
@@ -5698,7 +5784,7 @@ async function* parseWhatsApp(options2) {
|
|
|
5698
5784
|
messagesProcessed++;
|
|
5699
5785
|
}
|
|
5700
5786
|
};
|
|
5701
|
-
const fileStream =
|
|
5787
|
+
const fileStream = fs13.createReadStream(filePath, { encoding: "utf-8" });
|
|
5702
5788
|
const rl = readline3.createInterface({
|
|
5703
5789
|
input: fileStream,
|
|
5704
5790
|
crlfDelay: Infinity
|
|
@@ -5819,11 +5905,11 @@ var module_10 = {
|
|
|
5819
5905
|
var whatsapp_native_txt_default = module_10;
|
|
5820
5906
|
|
|
5821
5907
|
// ../../packages/parser/src/formats/qq-native-txt.ts
|
|
5822
|
-
import * as
|
|
5823
|
-
import * as
|
|
5908
|
+
import * as fs14 from "fs";
|
|
5909
|
+
import * as path10 from "path";
|
|
5824
5910
|
import * as readline4 from "readline";
|
|
5825
5911
|
function extractNameFromFilePath6(filePath) {
|
|
5826
|
-
const basename13 =
|
|
5912
|
+
const basename13 = path10.basename(filePath);
|
|
5827
5913
|
const name = basename13.replace(/\.txt$/i, "");
|
|
5828
5914
|
return name || "\u672A\u77E5\u7FA4\u804A";
|
|
5829
5915
|
}
|
|
@@ -5905,7 +5991,7 @@ async function* parseTxt(options2) {
|
|
|
5905
5991
|
messagesProcessed++;
|
|
5906
5992
|
}
|
|
5907
5993
|
};
|
|
5908
|
-
const fileStream =
|
|
5994
|
+
const fileStream = fs14.createReadStream(filePath, { encoding: "utf-8" });
|
|
5909
5995
|
const rl = readline4.createInterface({
|
|
5910
5996
|
input: fileStream,
|
|
5911
5997
|
crlfDelay: Infinity
|
|
@@ -6005,8 +6091,8 @@ var module_11 = {
|
|
|
6005
6091
|
var qq_native_txt_default = module_11;
|
|
6006
6092
|
|
|
6007
6093
|
// ../../packages/parser/src/formats/instagram-native.ts
|
|
6008
|
-
import * as
|
|
6009
|
-
import * as
|
|
6094
|
+
import * as fs15 from "fs";
|
|
6095
|
+
import * as path11 from "path";
|
|
6010
6096
|
var feature12 = {
|
|
6011
6097
|
id: "instagram-native",
|
|
6012
6098
|
name: "Instagram \u5B98\u65B9\u5BFC\u51FA",
|
|
@@ -6032,7 +6118,7 @@ function decodeInstagramText(text) {
|
|
|
6032
6118
|
}
|
|
6033
6119
|
}
|
|
6034
6120
|
function extractNameFromFilePath7(filePath) {
|
|
6035
|
-
const basename13 =
|
|
6121
|
+
const basename13 = path11.basename(filePath);
|
|
6036
6122
|
return basename13.replace(/\.json$/i, "") || "\u672A\u77E5\u5BF9\u8BDD";
|
|
6037
6123
|
}
|
|
6038
6124
|
function isSystemMessage2(content) {
|
|
@@ -6101,7 +6187,7 @@ async function* parseInstagram(options2) {
|
|
|
6101
6187
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Instagram \u804A\u5929\u8BB0\u5F55\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
6102
6188
|
let data;
|
|
6103
6189
|
try {
|
|
6104
|
-
const content =
|
|
6190
|
+
const content = fs15.readFileSync(filePath, "utf-8");
|
|
6105
6191
|
data = JSON.parse(content);
|
|
6106
6192
|
} catch (error) {
|
|
6107
6193
|
const err = new Error(`\u65E0\u6CD5\u89E3\u6790 Instagram JSON \u6587\u4EF6: ${error}`);
|
|
@@ -6196,8 +6282,8 @@ var import_stream_chain8 = __toESM(require_stream_chain(), 1);
|
|
|
6196
6282
|
var import_stream_json8 = __toESM(require_stream_json(), 1);
|
|
6197
6283
|
var import_Pick7 = __toESM(require_Pick(), 1);
|
|
6198
6284
|
var import_StreamValues8 = __toESM(require_StreamValues(), 1);
|
|
6199
|
-
import * as
|
|
6200
|
-
import * as
|
|
6285
|
+
import * as fs16 from "fs";
|
|
6286
|
+
import * as path12 from "path";
|
|
6201
6287
|
var { chain: chain8 } = import_stream_chain8.default;
|
|
6202
6288
|
var { parser: parser9 } = import_stream_json8.default;
|
|
6203
6289
|
var { pick: pick7 } = import_Pick7.default;
|
|
@@ -6280,12 +6366,12 @@ function normalizeIdentity(user) {
|
|
|
6280
6366
|
};
|
|
6281
6367
|
}
|
|
6282
6368
|
function readJson(filePath) {
|
|
6283
|
-
return JSON.parse(
|
|
6369
|
+
return JSON.parse(fs16.readFileSync(filePath, "utf8"));
|
|
6284
6370
|
}
|
|
6285
6371
|
function resolveManifestFile(manifestDir, relativePath) {
|
|
6286
|
-
const resolved =
|
|
6287
|
-
const relative2 =
|
|
6288
|
-
if (relative2.startsWith("..") ||
|
|
6372
|
+
const resolved = path12.resolve(manifestDir, relativePath);
|
|
6373
|
+
const relative2 = path12.relative(manifestDir, resolved);
|
|
6374
|
+
if (relative2.startsWith("..") || path12.isAbsolute(relative2)) {
|
|
6289
6375
|
throw new Error(`Google Chat manifest path escapes its directory: ${relativePath}`);
|
|
6290
6376
|
}
|
|
6291
6377
|
return resolved;
|
|
@@ -6298,7 +6384,7 @@ function readManifest2(filePath) {
|
|
|
6298
6384
|
if (manifest.chatType !== "private" && manifest.chatType !== "group") {
|
|
6299
6385
|
throw new Error("Invalid Google Chat chat type");
|
|
6300
6386
|
}
|
|
6301
|
-
const manifestDir =
|
|
6387
|
+
const manifestDir = path12.dirname(filePath);
|
|
6302
6388
|
return {
|
|
6303
6389
|
manifest,
|
|
6304
6390
|
userInfoPath: resolveManifestFile(manifestDir, manifest.userInfoFile),
|
|
@@ -6376,7 +6462,7 @@ async function* parseGoogleChat(options2) {
|
|
|
6376
6462
|
});
|
|
6377
6463
|
}
|
|
6378
6464
|
yield { type: "members", data: Array.from(memberMap.values()) };
|
|
6379
|
-
const readStream =
|
|
6465
|
+
const readStream = fs16.createReadStream(messagesPath, { encoding: "utf8" });
|
|
6380
6466
|
let bytesRead = 0;
|
|
6381
6467
|
let messagesProcessed = 0;
|
|
6382
6468
|
readStream.on("data", (chunk) => {
|
|
@@ -6429,8 +6515,8 @@ var module_13 = {
|
|
|
6429
6515
|
var google_chat_takeout_default = module_13;
|
|
6430
6516
|
|
|
6431
6517
|
// ../../packages/parser/src/formats/line-native-txt.ts
|
|
6432
|
-
import * as
|
|
6433
|
-
import * as
|
|
6518
|
+
import * as fs17 from "fs";
|
|
6519
|
+
import * as path13 from "path";
|
|
6434
6520
|
var feature14 = {
|
|
6435
6521
|
id: "line-native-txt",
|
|
6436
6522
|
name: "LINE \u5B98\u65B9\u5BFC\u51FA TXT",
|
|
@@ -6458,7 +6544,7 @@ var feature14 = {
|
|
|
6458
6544
|
}
|
|
6459
6545
|
};
|
|
6460
6546
|
function extractNameFromFilePath8(filePath) {
|
|
6461
|
-
const basename13 =
|
|
6547
|
+
const basename13 = path13.basename(filePath, ".txt");
|
|
6462
6548
|
const name = basename13.replace(/^\[LINE\]\s*/i, "").trim();
|
|
6463
6549
|
return name || "\u672A\u77E5\u804A\u5929";
|
|
6464
6550
|
}
|
|
@@ -6638,7 +6724,7 @@ async function* parseLINE(options2) {
|
|
|
6638
6724
|
yield { type: "progress", data: initialProgress };
|
|
6639
6725
|
onProgress?.(initialProgress);
|
|
6640
6726
|
onLog?.("info", `\u5F00\u59CB\u89E3\u6790 LINE \u5BFC\u51FA\u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
6641
|
-
const content =
|
|
6727
|
+
const content = fs17.readFileSync(filePath, "utf-8");
|
|
6642
6728
|
const lines = content.split("\n").map((line) => line.replace(/\r$/, ""));
|
|
6643
6729
|
let currentDate = null;
|
|
6644
6730
|
let chatName = extractNameFromFilePath8(filePath);
|
|
@@ -6946,12 +7032,12 @@ function findEntryFileInDirectory(dirPath, maxDepth = 1) {
|
|
|
6946
7032
|
if (depth > maxDepth) return null;
|
|
6947
7033
|
let entries;
|
|
6948
7034
|
try {
|
|
6949
|
-
entries =
|
|
7035
|
+
entries = fs18.readdirSync(current, { withFileTypes: true });
|
|
6950
7036
|
} catch {
|
|
6951
7037
|
return null;
|
|
6952
7038
|
}
|
|
6953
7039
|
for (const entry of entries) {
|
|
6954
|
-
const full =
|
|
7040
|
+
const full = path14.join(current, entry.name);
|
|
6955
7041
|
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
6956
7042
|
const format = detectFormat(full);
|
|
6957
7043
|
if (format) return full;
|
|
@@ -6959,7 +7045,7 @@ function findEntryFileInDirectory(dirPath, maxDepth = 1) {
|
|
|
6959
7045
|
}
|
|
6960
7046
|
for (const entry of entries) {
|
|
6961
7047
|
if (entry.isDirectory()) {
|
|
6962
|
-
const found = walk(
|
|
7048
|
+
const found = walk(path14.join(current, entry.name), depth + 1);
|
|
6963
7049
|
if (found) return found;
|
|
6964
7050
|
}
|
|
6965
7051
|
}
|
|
@@ -7008,8 +7094,8 @@ function logNativeParserStatus() {
|
|
|
7008
7094
|
}
|
|
7009
7095
|
|
|
7010
7096
|
// ../../packages/node-runtime/src/import/perf-logger.ts
|
|
7011
|
-
import * as
|
|
7012
|
-
import * as
|
|
7097
|
+
import * as fs19 from "fs";
|
|
7098
|
+
import * as path15 from "path";
|
|
7013
7099
|
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
7014
7100
|
LogLevel2["ERROR"] = "ERROR";
|
|
7015
7101
|
LogLevel2["INFO"] = "INFO";
|
|
@@ -7021,11 +7107,11 @@ var currentLogFile = null;
|
|
|
7021
7107
|
var errorCount = 0;
|
|
7022
7108
|
function initPerfLog(sessionId, logDir) {
|
|
7023
7109
|
try {
|
|
7024
|
-
if (!
|
|
7025
|
-
|
|
7110
|
+
if (!fs19.existsSync(logDir)) {
|
|
7111
|
+
fs19.mkdirSync(logDir, { recursive: true });
|
|
7026
7112
|
}
|
|
7027
|
-
currentLogFile =
|
|
7028
|
-
|
|
7113
|
+
currentLogFile = path15.join(logDir, `import_${sessionId}_${Date.now()}.log`);
|
|
7114
|
+
fs19.writeFileSync(currentLogFile, `=== Import Log ===
|
|
7029
7115
|
Start time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
7030
7116
|
|
|
7031
7117
|
`, "utf-8");
|
|
@@ -7046,7 +7132,7 @@ function logPerf(event, messagesProcessed, batchSize) {
|
|
|
7046
7132
|
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
7133
|
if (currentLogFile) {
|
|
7048
7134
|
try {
|
|
7049
|
-
|
|
7135
|
+
fs19.appendFileSync(currentLogFile, logLine, "utf-8");
|
|
7050
7136
|
} catch {
|
|
7051
7137
|
}
|
|
7052
7138
|
}
|
|
@@ -7056,7 +7142,7 @@ function logPerf(event, messagesProcessed, batchSize) {
|
|
|
7056
7142
|
function logPerfDetail(detail) {
|
|
7057
7143
|
if (currentLogFile) {
|
|
7058
7144
|
try {
|
|
7059
|
-
|
|
7145
|
+
fs19.appendFileSync(currentLogFile, ` ${detail}
|
|
7060
7146
|
`, "utf-8");
|
|
7061
7147
|
} catch {
|
|
7062
7148
|
}
|
|
@@ -7076,7 +7162,7 @@ function writeLogLine(level, message) {
|
|
|
7076
7162
|
const logLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] ${message}
|
|
7077
7163
|
`;
|
|
7078
7164
|
try {
|
|
7079
|
-
|
|
7165
|
+
fs19.appendFileSync(currentLogFile, logLine, "utf-8");
|
|
7080
7166
|
} catch {
|
|
7081
7167
|
}
|
|
7082
7168
|
}
|
|
@@ -7101,7 +7187,7 @@ Total members: ${totalMembers.toLocaleString()}
|
|
|
7101
7187
|
Errors: ${errorCount}
|
|
7102
7188
|
`;
|
|
7103
7189
|
try {
|
|
7104
|
-
|
|
7190
|
+
fs19.appendFileSync(currentLogFile, summary, "utf-8");
|
|
7105
7191
|
} catch {
|
|
7106
7192
|
}
|
|
7107
7193
|
}
|
|
@@ -7200,8 +7286,8 @@ function segmentText(text, locale, minLength) {
|
|
|
7200
7286
|
}
|
|
7201
7287
|
|
|
7202
7288
|
// ../../packages/node-runtime/src/nlp/dict-manager.ts
|
|
7203
|
-
import * as
|
|
7204
|
-
import * as
|
|
7289
|
+
import * as fs20 from "fs";
|
|
7290
|
+
import * as path16 from "path";
|
|
7205
7291
|
import { createHash } from "crypto";
|
|
7206
7292
|
var DICT_DOWNLOAD_URL_BASE = "https://chatlab.fun/assets/nlp";
|
|
7207
7293
|
var DICT_SHA256 = {
|
|
@@ -7213,19 +7299,19 @@ var AVAILABLE_DICTS = [
|
|
|
7213
7299
|
{ id: "zh-TW", label: "\u7E41\u9AD4\u4E2D\u6587", locale: "zh-TW" }
|
|
7214
7300
|
];
|
|
7215
7301
|
function getDictFilePath(nlpDir, dictId) {
|
|
7216
|
-
return
|
|
7302
|
+
return path16.join(nlpDir, `${dictId}.dict`);
|
|
7217
7303
|
}
|
|
7218
7304
|
function isDictDownloaded(nlpDir, dictId) {
|
|
7219
|
-
return
|
|
7305
|
+
return fs20.existsSync(getDictFilePath(nlpDir, dictId));
|
|
7220
7306
|
}
|
|
7221
7307
|
function getDictList(nlpDir) {
|
|
7222
7308
|
return AVAILABLE_DICTS.map((d) => {
|
|
7223
7309
|
const filePath = getDictFilePath(nlpDir, d.id);
|
|
7224
|
-
const downloaded =
|
|
7310
|
+
const downloaded = fs20.existsSync(filePath);
|
|
7225
7311
|
let fileSize;
|
|
7226
7312
|
if (downloaded) {
|
|
7227
7313
|
try {
|
|
7228
|
-
fileSize =
|
|
7314
|
+
fileSize = fs20.statSync(filePath).size;
|
|
7229
7315
|
} catch {
|
|
7230
7316
|
}
|
|
7231
7317
|
}
|
|
@@ -7234,9 +7320,9 @@ function getDictList(nlpDir) {
|
|
|
7234
7320
|
}
|
|
7235
7321
|
function loadDictBuffer(nlpDir, dictId) {
|
|
7236
7322
|
const filePath = getDictFilePath(nlpDir, dictId);
|
|
7237
|
-
if (!
|
|
7323
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
7238
7324
|
try {
|
|
7239
|
-
return
|
|
7325
|
+
return fs20.readFileSync(filePath);
|
|
7240
7326
|
} catch (error) {
|
|
7241
7327
|
console.error(`[NLP DictManager] Failed to read dict file: ${filePath}`, error);
|
|
7242
7328
|
return null;
|
|
@@ -7246,7 +7332,7 @@ async function downloadDict(nlpDir, dictId, onProgress) {
|
|
|
7246
7332
|
if (!AVAILABLE_DICTS.find((d) => d.id === dictId)) {
|
|
7247
7333
|
return { success: false, error: `Unknown dict: ${dictId}` };
|
|
7248
7334
|
}
|
|
7249
|
-
|
|
7335
|
+
fs20.mkdirSync(nlpDir, { recursive: true });
|
|
7250
7336
|
const url = `${DICT_DOWNLOAD_URL_BASE}/${dictId}.dict`;
|
|
7251
7337
|
const filePath = getDictFilePath(nlpDir, dictId);
|
|
7252
7338
|
const tmpPath = filePath + ".tmp";
|
|
@@ -7287,16 +7373,16 @@ async function downloadDict(nlpDir, dictId, onProgress) {
|
|
|
7287
7373
|
if (actualSha256 !== expectedSha256) {
|
|
7288
7374
|
return { success: false, error: "Dictionary integrity check failed (SHA256 mismatch)" };
|
|
7289
7375
|
}
|
|
7290
|
-
|
|
7291
|
-
if (
|
|
7292
|
-
|
|
7376
|
+
fs20.writeFileSync(tmpPath, buffer);
|
|
7377
|
+
if (fs20.existsSync(filePath)) fs20.unlinkSync(filePath);
|
|
7378
|
+
fs20.renameSync(tmpPath, filePath);
|
|
7293
7379
|
clearJiebaInstance(dictId);
|
|
7294
|
-
console.log(`[NLP DictManager] Dict downloaded: ${dictId} (${
|
|
7380
|
+
console.log(`[NLP DictManager] Dict downloaded: ${dictId} (${fs20.statSync(filePath).size} bytes)`);
|
|
7295
7381
|
return { success: true };
|
|
7296
7382
|
} catch (error) {
|
|
7297
|
-
if (
|
|
7383
|
+
if (fs20.existsSync(tmpPath)) {
|
|
7298
7384
|
try {
|
|
7299
|
-
|
|
7385
|
+
fs20.unlinkSync(tmpPath);
|
|
7300
7386
|
} catch {
|
|
7301
7387
|
}
|
|
7302
7388
|
}
|
|
@@ -7307,9 +7393,9 @@ async function downloadDict(nlpDir, dictId, onProgress) {
|
|
|
7307
7393
|
}
|
|
7308
7394
|
function deleteDict(nlpDir, dictId) {
|
|
7309
7395
|
const filePath = getDictFilePath(nlpDir, dictId);
|
|
7310
|
-
if (!
|
|
7396
|
+
if (!fs20.existsSync(filePath)) return { success: true };
|
|
7311
7397
|
try {
|
|
7312
|
-
|
|
7398
|
+
fs20.unlinkSync(filePath);
|
|
7313
7399
|
clearJiebaInstance(dictId);
|
|
7314
7400
|
console.log(`[NLP DictManager] Dict deleted: ${dictId}`);
|
|
7315
7401
|
return { success: true };
|
|
@@ -7409,7 +7495,7 @@ function searchByFts(db, keywords, limit = 1e3, offset = 0) {
|
|
|
7409
7495
|
}
|
|
7410
7496
|
|
|
7411
7497
|
// ../../packages/node-runtime/src/import/streaming-importer.ts
|
|
7412
|
-
import * as
|
|
7498
|
+
import * as fs21 from "fs";
|
|
7413
7499
|
|
|
7414
7500
|
// ../../packages/node-runtime/src/import/message-deduplicator.ts
|
|
7415
7501
|
function generateFallbackMessageKey(message) {
|
|
@@ -7441,7 +7527,7 @@ function registerMessageAndCheckDuplicate(message, state) {
|
|
|
7441
7527
|
// ../../packages/node-runtime/src/import/streaming-importer.ts
|
|
7442
7528
|
var BATCH_COMMIT_SIZE = 5e4;
|
|
7443
7529
|
var CHECKPOINT_INTERVAL = 2e5;
|
|
7444
|
-
var yieldToEventLoop = () => new Promise((
|
|
7530
|
+
var yieldToEventLoop = () => new Promise((resolve4) => setImmediate(resolve4));
|
|
7445
7531
|
function defaultGenerateSessionId() {
|
|
7446
7532
|
const ts = Date.now();
|
|
7447
7533
|
const rand = Math.random().toString(36).substring(2, 8);
|
|
@@ -7890,8 +7976,8 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7890
7976
|
}
|
|
7891
7977
|
return { success: true, sessionId, diagnostics };
|
|
7892
7978
|
}
|
|
7893
|
-
async function analyzeNewImport(filePath, onProgress) {
|
|
7894
|
-
const formatFeature = detectFormat(filePath);
|
|
7979
|
+
async function analyzeNewImport(filePath, onProgress, options2) {
|
|
7980
|
+
const formatFeature = options2?.formatId ? getFormatFeatureById(options2.formatId) : detectFormat(filePath);
|
|
7895
7981
|
if (!formatFeature) {
|
|
7896
7982
|
return {
|
|
7897
7983
|
totalMessages: 0,
|
|
@@ -7908,30 +7994,35 @@ async function analyzeNewImport(filePath, onProgress) {
|
|
|
7908
7994
|
let totalMessages = 0;
|
|
7909
7995
|
let newMessageCount = 0;
|
|
7910
7996
|
let duplicateCount = 0;
|
|
7911
|
-
await streamParseFile(
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
const
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7997
|
+
await streamParseFile(
|
|
7998
|
+
filePath,
|
|
7999
|
+
{
|
|
8000
|
+
formatOptions: options2?.chatIndex === void 0 ? void 0 : { chatIndex: options2.chatIndex },
|
|
8001
|
+
onMeta: (parsedMeta) => {
|
|
8002
|
+
meta = { name: parsedMeta.name, platform: parsedMeta.platform, type: parsedMeta.type };
|
|
8003
|
+
},
|
|
8004
|
+
onMembers: (members) => {
|
|
8005
|
+
for (const m of members) memberSet.add(m.platformId);
|
|
8006
|
+
},
|
|
8007
|
+
onProgress: (progress) => {
|
|
8008
|
+
onProgress(progress);
|
|
8009
|
+
},
|
|
8010
|
+
onMessageBatch: (batch) => {
|
|
8011
|
+
for (const msg of batch) {
|
|
8012
|
+
totalMessages++;
|
|
8013
|
+
if (!memberSet.has(msg.senderPlatformId)) memberSet.add(msg.senderPlatformId);
|
|
8014
|
+
const prepared = prepareMessageForCreate(msg);
|
|
8015
|
+
if ("skipCounter" in prepared) continue;
|
|
8016
|
+
if (registerMessageAndCheckDuplicate(prepared.message, dedupState)) {
|
|
8017
|
+
duplicateCount++;
|
|
8018
|
+
} else {
|
|
8019
|
+
newMessageCount++;
|
|
8020
|
+
}
|
|
7931
8021
|
}
|
|
7932
8022
|
}
|
|
7933
|
-
}
|
|
7934
|
-
|
|
8023
|
+
},
|
|
8024
|
+
options2?.formatId
|
|
8025
|
+
);
|
|
7935
8026
|
return { totalMessages, newMessageCount, duplicateCount, totalMembers: memberSet.size, meta };
|
|
7936
8027
|
}
|
|
7937
8028
|
async function streamParseFileInfo(filePath, deps) {
|
|
@@ -7939,7 +8030,7 @@ async function streamParseFileInfo(filePath, deps) {
|
|
|
7939
8030
|
if (!formatFeature) {
|
|
7940
8031
|
throw new Error("Unrecognized file format");
|
|
7941
8032
|
}
|
|
7942
|
-
const fileSize =
|
|
8033
|
+
const fileSize = fs21.statSync(filePath).size;
|
|
7943
8034
|
deps.onProgress({
|
|
7944
8035
|
stage: "parsing",
|
|
7945
8036
|
bytesRead: 0,
|
|
@@ -8028,7 +8119,7 @@ async function streamParseFileInfo(filePath, deps) {
|
|
|
8028
8119
|
}
|
|
8029
8120
|
db.close();
|
|
8030
8121
|
try {
|
|
8031
|
-
if (
|
|
8122
|
+
if (fs21.existsSync(tempDbPath)) fs21.unlinkSync(tempDbPath);
|
|
8032
8123
|
} catch {
|
|
8033
8124
|
}
|
|
8034
8125
|
throw error;
|
|
@@ -8128,8 +8219,8 @@ function normalizeImportTimestamp(timestamp) {
|
|
|
8128
8219
|
const value = typeof timestamp === "string" && timestamp.trim() !== "" ? Number(timestamp) : timestamp;
|
|
8129
8220
|
return typeof value === "number" && value > 0 && Number.isFinite(value) ? value : null;
|
|
8130
8221
|
}
|
|
8131
|
-
async function analyzeIncrementalImport(sessionId, filePath, deps) {
|
|
8132
|
-
const formatFeature = detectFormat(filePath);
|
|
8222
|
+
async function analyzeIncrementalImport(sessionId, filePath, deps, options2) {
|
|
8223
|
+
const formatFeature = options2?.formatId ? getFormatFeatureById(options2.formatId) : detectFormat(filePath);
|
|
8133
8224
|
if (!formatFeature) {
|
|
8134
8225
|
return { error: "error.unrecognized_format", newMessageCount: 0, duplicateCount: 0, totalInFile: 0 };
|
|
8135
8226
|
}
|
|
@@ -8144,27 +8235,32 @@ async function analyzeIncrementalImport(sessionId, filePath, deps) {
|
|
|
8144
8235
|
let totalInFile = 0;
|
|
8145
8236
|
let newMessageCount = 0;
|
|
8146
8237
|
let duplicateCount = 0;
|
|
8147
|
-
await streamParseFile(
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8238
|
+
await streamParseFile(
|
|
8239
|
+
filePath,
|
|
8240
|
+
{
|
|
8241
|
+
formatOptions: options2?.chatIndex === void 0 ? void 0 : { chatIndex: options2.chatIndex },
|
|
8242
|
+
onMeta: () => {
|
|
8243
|
+
},
|
|
8244
|
+
onMembers: () => {
|
|
8245
|
+
},
|
|
8246
|
+
onProgress: (progress) => {
|
|
8247
|
+
deps.onProgress(progress);
|
|
8248
|
+
},
|
|
8249
|
+
onMessageBatch: (batch) => {
|
|
8250
|
+
for (const msg of batch) {
|
|
8251
|
+
totalInFile++;
|
|
8252
|
+
const timestamp = normalizeImportTimestamp(msg.timestamp);
|
|
8253
|
+
if (timestamp === null) continue;
|
|
8254
|
+
if (isDuplicate({ ...msg, timestamp }, existingPlatformMsgIds, existingKeys, existingFallbackOnlyKeys)) {
|
|
8255
|
+
duplicateCount++;
|
|
8256
|
+
} else {
|
|
8257
|
+
newMessageCount++;
|
|
8258
|
+
}
|
|
8164
8259
|
}
|
|
8165
8260
|
}
|
|
8166
|
-
}
|
|
8167
|
-
|
|
8261
|
+
},
|
|
8262
|
+
options2?.formatId
|
|
8263
|
+
);
|
|
8168
8264
|
return { newMessageCount, duplicateCount, totalInFile };
|
|
8169
8265
|
}
|
|
8170
8266
|
async function incrementalImport(sessionId, filePath, deps, options2) {
|
|
@@ -8418,6 +8514,12 @@ async function incrementalImport(sessionId, filePath, deps, options2) {
|
|
|
8418
8514
|
}
|
|
8419
8515
|
}
|
|
8420
8516
|
|
|
8517
|
+
// ../../packages/node-runtime/src/import/session-id.ts
|
|
8518
|
+
var SAFE_IMPORT_SESSION_ID_RE = /^[A-Za-z0-9_@-][A-Za-z0-9._@-]{0,127}$/;
|
|
8519
|
+
function isValidImportSessionId(sessionId) {
|
|
8520
|
+
return SAFE_IMPORT_SESSION_ID_RE.test(sessionId) && !sessionId.includes("..");
|
|
8521
|
+
}
|
|
8522
|
+
|
|
8421
8523
|
// ../../packages/node-runtime/src/import/auto-import-matcher.ts
|
|
8422
8524
|
var MATCH_WINDOW_SIZE = 5;
|
|
8423
8525
|
function buildPrivateIdentity(ownerId, memberIds) {
|
|
@@ -8528,6 +8630,20 @@ async function resolveAutoImportTarget(filePath, deps, formatOptions) {
|
|
|
8528
8630
|
}
|
|
8529
8631
|
|
|
8530
8632
|
// ../../packages/node-runtime/src/import/auto-importer.ts
|
|
8633
|
+
async function planAutoImport(filePath, deps, options2) {
|
|
8634
|
+
if (options2.explicitSessionId) {
|
|
8635
|
+
if (!isValidImportSessionId(options2.explicitSessionId)) {
|
|
8636
|
+
throw new Error("sessionId contains invalid characters");
|
|
8637
|
+
}
|
|
8638
|
+
return deps.sessionExists(options2.explicitSessionId) ? { action: "incremental", sessionId: options2.explicitSessionId } : { action: "create", sessionId: options2.explicitSessionId };
|
|
8639
|
+
}
|
|
8640
|
+
const decision = await (deps.resolveTarget ?? resolveAutoImportTarget)(
|
|
8641
|
+
filePath,
|
|
8642
|
+
deps,
|
|
8643
|
+
options2.formatOptions
|
|
8644
|
+
);
|
|
8645
|
+
return decision.action === "incremental" ? { action: "incremental", sessionId: decision.sessionId, matchedBy: decision.matchedBy } : { action: "create", reason: decision.reason };
|
|
8646
|
+
}
|
|
8531
8647
|
function mapCreateResult(result, createReason) {
|
|
8532
8648
|
if (!result.success || !result.sessionId) {
|
|
8533
8649
|
return { success: false, error: result.error, diagnostics: result.diagnostics };
|
|
@@ -8539,6 +8655,11 @@ function mapCreateResult(result, createReason) {
|
|
|
8539
8655
|
...createReason ? { createReason } : {},
|
|
8540
8656
|
newMessageCount: result.diagnostics?.messagesWritten ?? 0,
|
|
8541
8657
|
duplicateCount: result.diagnostics?.duplicateCount ?? 0,
|
|
8658
|
+
batch: result.diagnostics ? {
|
|
8659
|
+
receivedCount: result.diagnostics.messagesReceived,
|
|
8660
|
+
writtenCount: result.diagnostics.messagesWritten,
|
|
8661
|
+
duplicateCount: result.diagnostics.duplicateCount
|
|
8662
|
+
} : void 0,
|
|
8542
8663
|
diagnostics: result.diagnostics
|
|
8543
8664
|
};
|
|
8544
8665
|
}
|
|
@@ -8550,61 +8671,41 @@ function mapIncrementalResult(sessionId, result, matchedBy) {
|
|
|
8550
8671
|
importMode: "incremental",
|
|
8551
8672
|
...matchedBy ? { matchedBy } : {},
|
|
8552
8673
|
newMessageCount: result.newMessageCount,
|
|
8553
|
-
duplicateCount: result.batch?.duplicateCount ?? 0
|
|
8674
|
+
duplicateCount: result.batch?.duplicateCount ?? 0,
|
|
8675
|
+
batch: result.batch,
|
|
8676
|
+
session: result.session,
|
|
8677
|
+
updates: result.updates
|
|
8554
8678
|
};
|
|
8555
8679
|
}
|
|
8556
8680
|
async function autoImportFile(filePath, deps, options2 = {}) {
|
|
8557
8681
|
try {
|
|
8558
|
-
if (options2.explicitSessionId) {
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
options2.explicitSessionId,
|
|
8562
|
-
await deps.appendSession(options2.explicitSessionId, filePath, options2.formatOptions)
|
|
8563
|
-
);
|
|
8564
|
-
appLogger.info("import", "Explicit incremental import completed", {
|
|
8565
|
-
sessionId: options2.explicitSessionId,
|
|
8566
|
-
success: result3.success,
|
|
8567
|
-
newMessageCount: result3.newMessageCount,
|
|
8568
|
-
duplicateCount: result3.duplicateCount
|
|
8569
|
-
});
|
|
8570
|
-
return result3;
|
|
8571
|
-
}
|
|
8572
|
-
const result2 = mapCreateResult(
|
|
8573
|
-
await deps.createSession(filePath, options2.formatOptions, options2.explicitSessionId)
|
|
8574
|
-
);
|
|
8575
|
-
appLogger.info("import", "Explicit session import completed", {
|
|
8576
|
-
sessionId: result2.sessionId,
|
|
8577
|
-
success: result2.success,
|
|
8578
|
-
importMode: result2.importMode
|
|
8682
|
+
if (!options2.explicitSessionId) {
|
|
8683
|
+
appLogger.info("import", "Automatic session matching started", {
|
|
8684
|
+
candidateCount: deps.listSessionIds().length
|
|
8579
8685
|
});
|
|
8580
|
-
return result2;
|
|
8581
8686
|
}
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
});
|
|
8585
|
-
const decision = await (deps.resolveTarget ?? resolveAutoImportTarget)(
|
|
8586
|
-
filePath,
|
|
8587
|
-
deps,
|
|
8588
|
-
options2.formatOptions
|
|
8589
|
-
);
|
|
8590
|
-
if (decision.action === "incremental") {
|
|
8687
|
+
const plan = await planAutoImport(filePath, deps, options2);
|
|
8688
|
+
if (plan.action === "incremental") {
|
|
8591
8689
|
const result2 = mapIncrementalResult(
|
|
8592
|
-
|
|
8593
|
-
await deps.appendSession(
|
|
8594
|
-
|
|
8690
|
+
plan.sessionId,
|
|
8691
|
+
await deps.appendSession(plan.sessionId, filePath, options2.formatOptions),
|
|
8692
|
+
plan.matchedBy
|
|
8595
8693
|
);
|
|
8596
|
-
appLogger.info("import", "
|
|
8597
|
-
sessionId:
|
|
8598
|
-
matchedBy:
|
|
8694
|
+
appLogger.info("import", "Incremental import completed", {
|
|
8695
|
+
sessionId: plan.sessionId,
|
|
8696
|
+
matchedBy: plan.matchedBy,
|
|
8599
8697
|
success: result2.success,
|
|
8600
8698
|
newMessageCount: result2.newMessageCount,
|
|
8601
8699
|
duplicateCount: result2.duplicateCount
|
|
8602
8700
|
});
|
|
8603
8701
|
return result2;
|
|
8604
8702
|
}
|
|
8605
|
-
const result = mapCreateResult(
|
|
8606
|
-
|
|
8607
|
-
|
|
8703
|
+
const result = mapCreateResult(
|
|
8704
|
+
await deps.createSession(filePath, options2.formatOptions, plan.sessionId),
|
|
8705
|
+
plan.reason
|
|
8706
|
+
);
|
|
8707
|
+
appLogger.info("import", "Import created a new session", {
|
|
8708
|
+
reason: plan.reason,
|
|
8608
8709
|
sessionId: result.sessionId,
|
|
8609
8710
|
success: result.success
|
|
8610
8711
|
});
|
|
@@ -8614,10 +8715,57 @@ async function autoImportFile(filePath, deps, options2 = {}) {
|
|
|
8614
8715
|
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
8615
8716
|
}
|
|
8616
8717
|
}
|
|
8718
|
+
async function analyzeAutoImportFile(filePath, deps, options2 = {}) {
|
|
8719
|
+
try {
|
|
8720
|
+
const plan = await planAutoImport(filePath, deps, options2);
|
|
8721
|
+
if (plan.action === "incremental") {
|
|
8722
|
+
const analysis2 = await deps.analyzeAppendSession(plan.sessionId, filePath, options2.formatOptions);
|
|
8723
|
+
if (analysis2.error) return { success: false, error: analysis2.error };
|
|
8724
|
+
const result2 = {
|
|
8725
|
+
success: true,
|
|
8726
|
+
importMode: "incremental",
|
|
8727
|
+
sessionId: plan.sessionId,
|
|
8728
|
+
...plan.matchedBy ? { matchedBy: plan.matchedBy } : {},
|
|
8729
|
+
totalMessageCount: analysis2.totalInFile,
|
|
8730
|
+
newMessageCount: analysis2.newMessageCount,
|
|
8731
|
+
duplicateCount: analysis2.duplicateCount
|
|
8732
|
+
};
|
|
8733
|
+
appLogger.info("import", "Incremental import analysis completed", {
|
|
8734
|
+
sessionId: plan.sessionId,
|
|
8735
|
+
matchedBy: plan.matchedBy,
|
|
8736
|
+
newMessageCount: analysis2.newMessageCount,
|
|
8737
|
+
duplicateCount: analysis2.duplicateCount
|
|
8738
|
+
});
|
|
8739
|
+
return result2;
|
|
8740
|
+
}
|
|
8741
|
+
const analysis = await deps.analyzeCreateSession(filePath, options2.formatOptions);
|
|
8742
|
+
if (analysis.error) return { success: false, error: analysis.error };
|
|
8743
|
+
const result = {
|
|
8744
|
+
success: true,
|
|
8745
|
+
importMode: "created",
|
|
8746
|
+
...plan.sessionId ? { sessionId: plan.sessionId } : {},
|
|
8747
|
+
...plan.reason ? { createReason: plan.reason } : {},
|
|
8748
|
+
totalMessageCount: analysis.totalMessages,
|
|
8749
|
+
newMessageCount: analysis.newMessageCount,
|
|
8750
|
+
duplicateCount: analysis.duplicateCount,
|
|
8751
|
+
totalMemberCount: analysis.totalMembers,
|
|
8752
|
+
meta: analysis.meta
|
|
8753
|
+
};
|
|
8754
|
+
appLogger.info("import", "New session import analysis completed", {
|
|
8755
|
+
reason: plan.reason,
|
|
8756
|
+
messageCount: analysis.totalMessages,
|
|
8757
|
+
memberCount: analysis.totalMembers
|
|
8758
|
+
});
|
|
8759
|
+
return result;
|
|
8760
|
+
} catch (error) {
|
|
8761
|
+
appLogger.error("import", "Automatic import analysis failed", error);
|
|
8762
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
8763
|
+
}
|
|
8764
|
+
}
|
|
8617
8765
|
|
|
8618
8766
|
// ../../packages/node-runtime/src/import/import-lock.ts
|
|
8619
|
-
import * as
|
|
8620
|
-
import * as
|
|
8767
|
+
import * as fs22 from "fs";
|
|
8768
|
+
import * as path17 from "path";
|
|
8621
8769
|
import { randomUUID } from "crypto";
|
|
8622
8770
|
var IMPORT_LOCK_FILENAME = ".chatlab-import.lock";
|
|
8623
8771
|
var IMPORT_IN_PROGRESS_ERROR_KEY = "error.import_in_progress";
|
|
@@ -8631,7 +8779,7 @@ var ImportInProgressError = class extends Error {
|
|
|
8631
8779
|
};
|
|
8632
8780
|
function parseOwner(lockPath) {
|
|
8633
8781
|
try {
|
|
8634
|
-
const parsed = JSON.parse(
|
|
8782
|
+
const parsed = JSON.parse(fs22.readFileSync(lockPath, "utf-8"));
|
|
8635
8783
|
if (typeof parsed.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0 || typeof parsed.token !== "string" || parsed.token.length === 0 || typeof parsed.startedAt !== "number") {
|
|
8636
8784
|
return null;
|
|
8637
8785
|
}
|
|
@@ -8654,13 +8802,13 @@ function removeStaleLock(lockPath) {
|
|
|
8654
8802
|
if (isProcessRunning(owner.pid)) return false;
|
|
8655
8803
|
} else {
|
|
8656
8804
|
try {
|
|
8657
|
-
if (Date.now() -
|
|
8805
|
+
if (Date.now() - fs22.statSync(lockPath).mtimeMs < 5e3) return false;
|
|
8658
8806
|
} catch {
|
|
8659
8807
|
return true;
|
|
8660
8808
|
}
|
|
8661
8809
|
}
|
|
8662
8810
|
try {
|
|
8663
|
-
|
|
8811
|
+
fs22.unlinkSync(lockPath);
|
|
8664
8812
|
appLogger.warn("import-lock", "Removed stale import lock", { ownerPid: owner?.pid });
|
|
8665
8813
|
return true;
|
|
8666
8814
|
} catch {
|
|
@@ -8669,7 +8817,7 @@ function removeStaleLock(lockPath) {
|
|
|
8669
8817
|
}
|
|
8670
8818
|
function releaseLock(lockPath, fd, owner) {
|
|
8671
8819
|
try {
|
|
8672
|
-
|
|
8820
|
+
fs22.closeSync(fd);
|
|
8673
8821
|
} catch (error) {
|
|
8674
8822
|
appLogger.error("import-lock", "Failed to close import lock", error);
|
|
8675
8823
|
}
|
|
@@ -8678,19 +8826,19 @@ function releaseLock(lockPath, fd, owner) {
|
|
|
8678
8826
|
appLogger.warn("import-lock", "Import lock ownership changed before release");
|
|
8679
8827
|
return;
|
|
8680
8828
|
}
|
|
8681
|
-
|
|
8829
|
+
fs22.unlinkSync(lockPath);
|
|
8682
8830
|
appLogger.info("import-lock", "Import lock released");
|
|
8683
8831
|
} catch (error) {
|
|
8684
8832
|
appLogger.error("import-lock", "Failed to release import lock", error);
|
|
8685
8833
|
}
|
|
8686
8834
|
}
|
|
8687
8835
|
async function withDataDirImportLock(userDataDir, task) {
|
|
8688
|
-
|
|
8689
|
-
const lockPath =
|
|
8836
|
+
fs22.mkdirSync(userDataDir, { recursive: true });
|
|
8837
|
+
const lockPath = path17.join(userDataDir, IMPORT_LOCK_FILENAME);
|
|
8690
8838
|
let fd = null;
|
|
8691
8839
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
8692
8840
|
try {
|
|
8693
|
-
fd =
|
|
8841
|
+
fd = fs22.openSync(lockPath, "wx");
|
|
8694
8842
|
break;
|
|
8695
8843
|
} catch (error) {
|
|
8696
8844
|
const code = error.code;
|
|
@@ -8709,8 +8857,8 @@ async function withDataDirImportLock(userDataDir, task) {
|
|
|
8709
8857
|
startedAt: Date.now()
|
|
8710
8858
|
};
|
|
8711
8859
|
try {
|
|
8712
|
-
|
|
8713
|
-
|
|
8860
|
+
fs22.writeFileSync(fd, JSON.stringify(owner), "utf-8");
|
|
8861
|
+
fs22.fsyncSync(fd);
|
|
8714
8862
|
appLogger.info("import-lock", "Import lock acquired");
|
|
8715
8863
|
return await task();
|
|
8716
8864
|
} finally {
|
|
@@ -8730,8 +8878,8 @@ var ArchiveImportError = class extends Error {
|
|
|
8730
8878
|
|
|
8731
8879
|
// ../../packages/node-runtime/src/import/archive/archive-reader.ts
|
|
8732
8880
|
var import_yauzl = __toESM(require_yauzl(), 1);
|
|
8733
|
-
import * as
|
|
8734
|
-
import * as
|
|
8881
|
+
import * as fs23 from "fs";
|
|
8882
|
+
import * as path18 from "path";
|
|
8735
8883
|
import { pipeline } from "stream/promises";
|
|
8736
8884
|
var DEFAULT_MAX_ENTRIES = 1e5;
|
|
8737
8885
|
var DEFAULT_MAX_ENTRY_BYTES = 20 * 1024 * 1024 * 1024;
|
|
@@ -8850,8 +8998,8 @@ var ZipArchiveReader = class {
|
|
|
8850
8998
|
await this.visitEntries(async (entry, openStream) => {
|
|
8851
8999
|
const destination = targets.get(entry.name);
|
|
8852
9000
|
if (!destination || entry.isDirectory) return;
|
|
8853
|
-
|
|
8854
|
-
await pipeline(await openStream(),
|
|
9001
|
+
fs23.mkdirSync(path18.dirname(destination), { recursive: true });
|
|
9002
|
+
await pipeline(await openStream(), fs23.createWriteStream(destination, { flags: "wx" }));
|
|
8855
9003
|
remaining.delete(entry.name);
|
|
8856
9004
|
});
|
|
8857
9005
|
if (remaining.size > 0) {
|
|
@@ -8868,8 +9016,8 @@ var import_stream_chain9 = __toESM(require_stream_chain(), 1);
|
|
|
8868
9016
|
var import_stream_json9 = __toESM(require_stream_json(), 1);
|
|
8869
9017
|
var import_Pick8 = __toESM(require_Pick(), 1);
|
|
8870
9018
|
var import_StreamValues9 = __toESM(require_StreamValues(), 1);
|
|
8871
|
-
import * as
|
|
8872
|
-
import * as
|
|
9019
|
+
import * as fs24 from "fs";
|
|
9020
|
+
import * as path19 from "path";
|
|
8873
9021
|
var { chain: chain9 } = import_stream_chain9.default;
|
|
8874
9022
|
var { parser: parser10 } = import_stream_json9.default;
|
|
8875
9023
|
var { pick: pick8 } = import_Pick8.default;
|
|
@@ -8998,16 +9146,16 @@ var GoogleChatTakeoutResolver = class {
|
|
|
8998
9146
|
`Google Chat conversation is missing required files: ${chat.chatId}`
|
|
8999
9147
|
);
|
|
9000
9148
|
}
|
|
9001
|
-
|
|
9149
|
+
fs24.mkdirSync(targetDir, { recursive: true });
|
|
9002
9150
|
await reader.pipeEntries(
|
|
9003
9151
|
/* @__PURE__ */ new Map([
|
|
9004
|
-
[userInfoEntry,
|
|
9005
|
-
[groupInfoEntry,
|
|
9006
|
-
[messagesEntry,
|
|
9152
|
+
[userInfoEntry, path19.join(targetDir, "user_info.json")],
|
|
9153
|
+
[groupInfoEntry, path19.join(targetDir, "group_info.json")],
|
|
9154
|
+
[messagesEntry, path19.join(targetDir, "messages.json")]
|
|
9007
9155
|
])
|
|
9008
9156
|
);
|
|
9009
|
-
const manifestPath =
|
|
9010
|
-
|
|
9157
|
+
const manifestPath = path19.join(targetDir, "google-chat-import.json");
|
|
9158
|
+
fs24.writeFileSync(
|
|
9011
9159
|
manifestPath,
|
|
9012
9160
|
JSON.stringify(
|
|
9013
9161
|
{
|
|
@@ -9030,8 +9178,8 @@ var GoogleChatTakeoutResolver = class {
|
|
|
9030
9178
|
};
|
|
9031
9179
|
|
|
9032
9180
|
// ../../packages/node-runtime/src/import/archive/source-manager.ts
|
|
9033
|
-
import * as
|
|
9034
|
-
import * as
|
|
9181
|
+
import * as fs25 from "fs";
|
|
9182
|
+
import * as path20 from "path";
|
|
9035
9183
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
9036
9184
|
var DEFAULT_TTL_MS = 30 * 60 * 1e3;
|
|
9037
9185
|
var ArchiveImportSourceManager = class {
|
|
@@ -9042,11 +9190,11 @@ var ArchiveImportSourceManager = class {
|
|
|
9042
9190
|
now;
|
|
9043
9191
|
resolvers;
|
|
9044
9192
|
constructor(options2 = {}) {
|
|
9045
|
-
this.tempRoot = options2.tempRoot ??
|
|
9193
|
+
this.tempRoot = options2.tempRoot ?? createChatLabTempDir("imports", "sources-");
|
|
9046
9194
|
this.ttlMs = options2.ttlMs ?? DEFAULT_TTL_MS;
|
|
9047
9195
|
this.now = options2.now ?? Date.now;
|
|
9048
9196
|
this.resolvers = options2.resolvers ?? [new GoogleChatTakeoutResolver()];
|
|
9049
|
-
|
|
9197
|
+
fs25.mkdirSync(this.tempRoot, { recursive: true });
|
|
9050
9198
|
}
|
|
9051
9199
|
prepareLocalArchive(archivePath) {
|
|
9052
9200
|
return this.prepareArchive(archivePath, false);
|
|
@@ -9103,7 +9251,7 @@ var ArchiveImportSourceManager = class {
|
|
|
9103
9251
|
`Archive conversation was not found: ${chatId}`
|
|
9104
9252
|
);
|
|
9105
9253
|
}
|
|
9106
|
-
const materializedDir =
|
|
9254
|
+
const materializedDir = fs25.mkdtempSync(path20.join(this.tempRoot, `materialized-${sourceId}-`));
|
|
9107
9255
|
try {
|
|
9108
9256
|
const reader = new ZipArchiveReader(record.archivePath);
|
|
9109
9257
|
const materialized = await record.resolver.materialize(reader, chat, materializedDir);
|
|
@@ -9154,7 +9302,7 @@ var ArchiveImportSourceManager = class {
|
|
|
9154
9302
|
}
|
|
9155
9303
|
removePath(targetPath) {
|
|
9156
9304
|
try {
|
|
9157
|
-
|
|
9305
|
+
fs25.rmSync(targetPath, { recursive: true, force: true });
|
|
9158
9306
|
} catch {
|
|
9159
9307
|
}
|
|
9160
9308
|
}
|
|
@@ -9224,12 +9372,12 @@ ${rawErrorLabel}: ${details}`;
|
|
|
9224
9372
|
}
|
|
9225
9373
|
|
|
9226
9374
|
// ../../packages/node-runtime/src/ai/assistant-parser.ts
|
|
9227
|
-
import * as
|
|
9375
|
+
import * as path21 from "path";
|
|
9228
9376
|
import matter from "gray-matter";
|
|
9229
9377
|
function parseAssistantFile(content, filePath) {
|
|
9230
9378
|
try {
|
|
9231
9379
|
const { data: fm, content: body } = matter(content);
|
|
9232
|
-
const id = fm.id ??
|
|
9380
|
+
const id = fm.id ?? path21.basename(filePath, ".md");
|
|
9233
9381
|
const name = fm.name;
|
|
9234
9382
|
if (!name) return null;
|
|
9235
9383
|
return {
|
|
@@ -9308,8 +9456,8 @@ var AssistantManager = class {
|
|
|
9308
9456
|
}
|
|
9309
9457
|
// ==================== Init ====================
|
|
9310
9458
|
init() {
|
|
9311
|
-
const { fs:
|
|
9312
|
-
|
|
9459
|
+
const { fs: fs37, assistantsDir } = this.deps;
|
|
9460
|
+
fs37.ensureDir(assistantsDir);
|
|
9313
9461
|
const generalCreated = this.ensureGeneralAssistants();
|
|
9314
9462
|
this.loadAll();
|
|
9315
9463
|
this.initialized = true;
|
|
@@ -9320,26 +9468,26 @@ var AssistantManager = class {
|
|
|
9320
9468
|
return { total: this.cache.size, generalCreated };
|
|
9321
9469
|
}
|
|
9322
9470
|
ensureGeneralAssistants() {
|
|
9323
|
-
const { fs:
|
|
9471
|
+
const { fs: fs37, assistantsDir } = this.deps;
|
|
9324
9472
|
let anyCreated = false;
|
|
9325
9473
|
for (const id of this.generalIds) {
|
|
9326
9474
|
const config = this.getBuiltinConfig(id);
|
|
9327
9475
|
if (!config) continue;
|
|
9328
|
-
const filePath =
|
|
9329
|
-
if (
|
|
9330
|
-
|
|
9476
|
+
const filePath = fs37.joinPath(assistantsDir, `${id}.md`);
|
|
9477
|
+
if (fs37.fileExists(filePath)) continue;
|
|
9478
|
+
fs37.writeFile(filePath, serializeAssistant({ ...config, builtinId: config.id }));
|
|
9331
9479
|
anyCreated = true;
|
|
9332
9480
|
}
|
|
9333
9481
|
return anyCreated;
|
|
9334
9482
|
}
|
|
9335
9483
|
loadAll() {
|
|
9336
|
-
const { fs:
|
|
9484
|
+
const { fs: fs37, assistantsDir } = this.deps;
|
|
9337
9485
|
this.cache.clear();
|
|
9338
|
-
const files =
|
|
9486
|
+
const files = fs37.listFiles(assistantsDir, ".md");
|
|
9339
9487
|
for (const file of files) {
|
|
9340
9488
|
try {
|
|
9341
|
-
const filePath =
|
|
9342
|
-
const content =
|
|
9489
|
+
const filePath = fs37.joinPath(assistantsDir, file);
|
|
9490
|
+
const content = fs37.readFile(filePath);
|
|
9343
9491
|
const config = parseAssistantFile(content, filePath);
|
|
9344
9492
|
if (config) {
|
|
9345
9493
|
this.cache.set(config.id, config);
|
|
@@ -9451,12 +9599,12 @@ var AssistantManager = class {
|
|
|
9451
9599
|
};
|
|
9452
9600
|
|
|
9453
9601
|
// ../../packages/node-runtime/src/ai/skill-parser.ts
|
|
9454
|
-
import * as
|
|
9602
|
+
import * as path22 from "path";
|
|
9455
9603
|
import matter2 from "gray-matter";
|
|
9456
9604
|
function parseSkillFile(content, filePath) {
|
|
9457
9605
|
try {
|
|
9458
9606
|
const { data: fm, content: prompt } = matter2(content);
|
|
9459
|
-
const id = fm.id ??
|
|
9607
|
+
const id = fm.id ?? path22.basename(filePath, ".md");
|
|
9460
9608
|
const name = fm.name;
|
|
9461
9609
|
if (!name) return null;
|
|
9462
9610
|
return {
|
|
@@ -9475,7 +9623,7 @@ function parseSkillFile(content, filePath) {
|
|
|
9475
9623
|
function extractSkillId(content, filePath) {
|
|
9476
9624
|
try {
|
|
9477
9625
|
const { data: fm } = matter2(content);
|
|
9478
|
-
return fm.id ??
|
|
9626
|
+
return fm.id ?? path22.basename(filePath, ".md");
|
|
9479
9627
|
} catch {
|
|
9480
9628
|
return null;
|
|
9481
9629
|
}
|
|
@@ -9494,8 +9642,8 @@ function validateChatScope(raw) {
|
|
|
9494
9642
|
|
|
9495
9643
|
// ../../packages/node-runtime/src/ai/chats.ts
|
|
9496
9644
|
import Database from "better-sqlite3";
|
|
9497
|
-
import * as
|
|
9498
|
-
import * as
|
|
9645
|
+
import * as fs26 from "fs";
|
|
9646
|
+
import * as path23 from "path";
|
|
9499
9647
|
var DEFAULT_GENERAL_ID = "general_cn";
|
|
9500
9648
|
var defaultLogger = {
|
|
9501
9649
|
warn(_category, message, extra) {
|
|
@@ -9514,14 +9662,14 @@ var AIChatManager = class {
|
|
|
9514
9662
|
this.nativeBinding = options2?.nativeBinding;
|
|
9515
9663
|
}
|
|
9516
9664
|
ensureDir(dir) {
|
|
9517
|
-
if (!
|
|
9518
|
-
|
|
9665
|
+
if (!fs26.existsSync(dir)) {
|
|
9666
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
9519
9667
|
}
|
|
9520
9668
|
}
|
|
9521
9669
|
getDb() {
|
|
9522
9670
|
if (this.db) return this.db;
|
|
9523
9671
|
this.ensureDir(this.aiDataDir);
|
|
9524
|
-
const dbPath =
|
|
9672
|
+
const dbPath = path23.join(this.aiDataDir, "conversations.db");
|
|
9525
9673
|
this.db = this.nativeBinding ? new Database(dbPath, { nativeBinding: this.nativeBinding }) : new Database(dbPath);
|
|
9526
9674
|
this.db.pragma("journal_mode = WAL");
|
|
9527
9675
|
this.db.exec(`
|
|
@@ -9764,16 +9912,16 @@ var AIChatManager = class {
|
|
|
9764
9912
|
if (allRows.length === 0) return [];
|
|
9765
9913
|
const rowMap = new Map(allRows.map((row) => [row.id, row]));
|
|
9766
9914
|
let currentId = leafMessageId ?? this.getActiveMessageId(aiChatId);
|
|
9767
|
-
const
|
|
9915
|
+
const path33 = [];
|
|
9768
9916
|
const seen = /* @__PURE__ */ new Set();
|
|
9769
9917
|
while (currentId && !seen.has(currentId)) {
|
|
9770
9918
|
seen.add(currentId);
|
|
9771
9919
|
const row = rowMap.get(currentId);
|
|
9772
9920
|
if (!row) break;
|
|
9773
|
-
|
|
9921
|
+
path33.push(row);
|
|
9774
9922
|
currentId = row.parentId;
|
|
9775
9923
|
}
|
|
9776
|
-
return
|
|
9924
|
+
return path33.length > 0 ? path33.reverse() : allRows;
|
|
9777
9925
|
}
|
|
9778
9926
|
// ==================== 生命周期 ====================
|
|
9779
9927
|
close() {
|
|
@@ -10343,21 +10491,21 @@ var SkillManagerCore = class {
|
|
|
10343
10491
|
}
|
|
10344
10492
|
// ==================== Init ====================
|
|
10345
10493
|
init() {
|
|
10346
|
-
const { fs:
|
|
10347
|
-
|
|
10494
|
+
const { fs: fs37, skillsDir } = this.deps;
|
|
10495
|
+
fs37.ensureDir(skillsDir);
|
|
10348
10496
|
this.loadAll();
|
|
10349
10497
|
this.initialized = true;
|
|
10350
10498
|
this.deps.logger?.info("SkillManager", "Initialized", { total: this.cache.size });
|
|
10351
10499
|
return { total: this.cache.size };
|
|
10352
10500
|
}
|
|
10353
10501
|
loadAll() {
|
|
10354
|
-
const { fs:
|
|
10502
|
+
const { fs: fs37, skillsDir } = this.deps;
|
|
10355
10503
|
this.cache.clear();
|
|
10356
|
-
const files =
|
|
10504
|
+
const files = fs37.listFiles(skillsDir, ".md");
|
|
10357
10505
|
for (const file of files) {
|
|
10358
10506
|
try {
|
|
10359
|
-
const filePath =
|
|
10360
|
-
const content =
|
|
10507
|
+
const filePath = fs37.joinPath(skillsDir, file);
|
|
10508
|
+
const content = fs37.readFile(filePath);
|
|
10361
10509
|
const def = parseSkillFile(content, filePath);
|
|
10362
10510
|
if (def) {
|
|
10363
10511
|
this.cache.set(def.id, def);
|
|
@@ -10509,8 +10657,8 @@ var SkillManagerCore = class {
|
|
|
10509
10657
|
};
|
|
10510
10658
|
|
|
10511
10659
|
// ../../packages/node-runtime/src/ai/skill-manager.ts
|
|
10512
|
-
import * as
|
|
10513
|
-
import * as
|
|
10660
|
+
import * as fs27 from "fs";
|
|
10661
|
+
import * as path24 from "path";
|
|
10514
10662
|
var SKILLS_DIR_NAME = "skills";
|
|
10515
10663
|
var defaultLogger2 = {
|
|
10516
10664
|
info: () => {
|
|
@@ -10520,26 +10668,26 @@ var defaultLogger2 = {
|
|
|
10520
10668
|
};
|
|
10521
10669
|
var nodeFs = {
|
|
10522
10670
|
ensureDir(dir) {
|
|
10523
|
-
|
|
10671
|
+
fs27.mkdirSync(dir, { recursive: true });
|
|
10524
10672
|
},
|
|
10525
10673
|
listFiles(dir, ext) {
|
|
10526
|
-
if (!
|
|
10527
|
-
return
|
|
10674
|
+
if (!fs27.existsSync(dir)) return [];
|
|
10675
|
+
return fs27.readdirSync(dir).filter((file) => file.endsWith(ext));
|
|
10528
10676
|
},
|
|
10529
10677
|
readFile(filePath) {
|
|
10530
|
-
return
|
|
10678
|
+
return fs27.readFileSync(filePath, "utf-8");
|
|
10531
10679
|
},
|
|
10532
10680
|
writeFile(filePath, content) {
|
|
10533
|
-
|
|
10681
|
+
fs27.writeFileSync(filePath, content, "utf-8");
|
|
10534
10682
|
},
|
|
10535
10683
|
deleteFile(filePath) {
|
|
10536
|
-
|
|
10684
|
+
fs27.unlinkSync(filePath);
|
|
10537
10685
|
},
|
|
10538
10686
|
fileExists(filePath) {
|
|
10539
|
-
return
|
|
10687
|
+
return fs27.existsSync(filePath);
|
|
10540
10688
|
},
|
|
10541
10689
|
joinPath(...parts) {
|
|
10542
|
-
return
|
|
10690
|
+
return path24.join(...parts);
|
|
10543
10691
|
}
|
|
10544
10692
|
};
|
|
10545
10693
|
var SkillManager = class {
|
|
@@ -10549,7 +10697,7 @@ var SkillManager = class {
|
|
|
10549
10697
|
this.logger = logger ?? defaultLogger2;
|
|
10550
10698
|
this.core = new SkillManagerCore({
|
|
10551
10699
|
fs: nodeFs,
|
|
10552
|
-
skillsDir:
|
|
10700
|
+
skillsDir: path24.join(aiDataDir, SKILLS_DIR_NAME),
|
|
10553
10701
|
builtinRawSkills: [],
|
|
10554
10702
|
logger: {
|
|
10555
10703
|
info: () => {
|
|
@@ -14379,9 +14527,9 @@ var localeMap = {
|
|
|
14379
14527
|
"ja-JP": ja_JP_default,
|
|
14380
14528
|
"zh-TW": zh_TW_default
|
|
14381
14529
|
};
|
|
14382
|
-
function getNestedValue(obj,
|
|
14530
|
+
function getNestedValue(obj, path33) {
|
|
14383
14531
|
let current = obj;
|
|
14384
|
-
for (const segment2 of
|
|
14532
|
+
for (const segment2 of path33.split(".")) {
|
|
14385
14533
|
if (current == null || typeof current !== "object") return void 0;
|
|
14386
14534
|
current = current[segment2];
|
|
14387
14535
|
}
|
|
@@ -14894,6 +15042,49 @@ var LLMConfigStore = class {
|
|
|
14894
15042
|
}
|
|
14895
15043
|
};
|
|
14896
15044
|
|
|
15045
|
+
// ../../packages/node-runtime/src/ai/file-config-storage.ts
|
|
15046
|
+
import * as fs28 from "fs";
|
|
15047
|
+
import * as path25 from "path";
|
|
15048
|
+
function createFileConfigStorage(baseDir) {
|
|
15049
|
+
return {
|
|
15050
|
+
readJson(key) {
|
|
15051
|
+
try {
|
|
15052
|
+
return JSON.parse(fs28.readFileSync(path25.join(baseDir, `${key}.json`), "utf-8"));
|
|
15053
|
+
} catch {
|
|
15054
|
+
return null;
|
|
15055
|
+
}
|
|
15056
|
+
},
|
|
15057
|
+
writeJson(key, data) {
|
|
15058
|
+
fs28.mkdirSync(baseDir, { recursive: true });
|
|
15059
|
+
fs28.writeFileSync(path25.join(baseDir, `${key}.json`), JSON.stringify(data, null, 2), "utf-8");
|
|
15060
|
+
}
|
|
15061
|
+
};
|
|
15062
|
+
}
|
|
15063
|
+
|
|
15064
|
+
// ../../packages/node-runtime/src/ai/auth-profile-llm-config-store.ts
|
|
15065
|
+
var defaultDeps = {
|
|
15066
|
+
resolveApiKey: (provider, authProfile) => resolveApiKey(provider, authProfile) || void 0,
|
|
15067
|
+
writeAuthProfile,
|
|
15068
|
+
deleteAuthProfile
|
|
15069
|
+
};
|
|
15070
|
+
function getAuthProfile2(config) {
|
|
15071
|
+
return config.authProfile;
|
|
15072
|
+
}
|
|
15073
|
+
function createAuthProfileLlmConfigStore(storage, deps = defaultDeps) {
|
|
15074
|
+
return new LLMConfigStore(storage, {
|
|
15075
|
+
resolveApiKey: deps.resolveApiKey,
|
|
15076
|
+
onApiKeyCreated: (config, apiKey) => {
|
|
15077
|
+
const profileName = config.name?.toLowerCase().replace(/\s+/g, "-") || config.provider;
|
|
15078
|
+
deps.writeAuthProfile(profileName, { type: "api_key", provider: config.provider, key: apiKey });
|
|
15079
|
+
return profileName;
|
|
15080
|
+
},
|
|
15081
|
+
onApiKeyDeleted: (config) => {
|
|
15082
|
+
const profileName = getAuthProfile2(config);
|
|
15083
|
+
if (profileName) deps.deleteAuthProfile(profileName);
|
|
15084
|
+
}
|
|
15085
|
+
});
|
|
15086
|
+
}
|
|
15087
|
+
|
|
14897
15088
|
// ../../packages/node-runtime/src/ai/custom-store.ts
|
|
14898
15089
|
function generateCustomId() {
|
|
14899
15090
|
return `custom:${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -15713,8 +15904,8 @@ function exportWithFormat(params, openDatabase) {
|
|
|
15713
15904
|
}
|
|
15714
15905
|
|
|
15715
15906
|
// ../../packages/node-runtime/src/merger/temp-db.ts
|
|
15716
|
-
import * as
|
|
15717
|
-
import * as
|
|
15907
|
+
import * as fs29 from "fs";
|
|
15908
|
+
import * as path26 from "path";
|
|
15718
15909
|
var TEMP_DB_SCHEMA = `
|
|
15719
15910
|
CREATE TABLE IF NOT EXISTS meta (
|
|
15720
15911
|
name TEXT NOT NULL,
|
|
@@ -15959,21 +16150,21 @@ function exportSessionToJson(db) {
|
|
|
15959
16150
|
}
|
|
15960
16151
|
function deleteTempDatabase(dbPath) {
|
|
15961
16152
|
try {
|
|
15962
|
-
if (
|
|
16153
|
+
if (fs29.existsSync(dbPath)) fs29.unlinkSync(dbPath);
|
|
15963
16154
|
const walPath = dbPath + "-wal";
|
|
15964
16155
|
const shmPath = dbPath + "-shm";
|
|
15965
|
-
if (
|
|
15966
|
-
if (
|
|
16156
|
+
if (fs29.existsSync(walPath)) fs29.unlinkSync(walPath);
|
|
16157
|
+
if (fs29.existsSync(shmPath)) fs29.unlinkSync(shmPath);
|
|
15967
16158
|
} catch {
|
|
15968
16159
|
}
|
|
15969
16160
|
}
|
|
15970
16161
|
function cleanupTempDatabases(tempDir) {
|
|
15971
16162
|
try {
|
|
15972
|
-
if (!
|
|
15973
|
-
const files =
|
|
16163
|
+
if (!fs29.existsSync(tempDir)) return;
|
|
16164
|
+
const files = fs29.readdirSync(tempDir);
|
|
15974
16165
|
for (const file of files) {
|
|
15975
16166
|
if (file.startsWith("merge_") && file.endsWith(".db")) {
|
|
15976
|
-
deleteTempDatabase(
|
|
16167
|
+
deleteTempDatabase(path26.join(tempDir, file));
|
|
15977
16168
|
}
|
|
15978
16169
|
}
|
|
15979
16170
|
} catch {
|
|
@@ -16052,6 +16243,7 @@ function deleteSession(adapter, sessionId) {
|
|
|
16052
16243
|
var member_service_exports = {};
|
|
16053
16244
|
__export(member_service_exports, {
|
|
16054
16245
|
deleteMember: () => deleteMember2,
|
|
16246
|
+
deleteMembers: () => deleteMembers2,
|
|
16055
16247
|
getMemberNameHistory: () => getMemberNameHistory2,
|
|
16056
16248
|
getMembers: () => getMembers,
|
|
16057
16249
|
getMembersPaginated: () => getMembersPaginated2,
|
|
@@ -16085,6 +16277,10 @@ function deleteMember2(adapter, sessionId, memberId) {
|
|
|
16085
16277
|
const db = adapter.ensureWritable(sessionId);
|
|
16086
16278
|
return deleteMember(db, memberId);
|
|
16087
16279
|
}
|
|
16280
|
+
function deleteMembers2(adapter, sessionId, memberIds) {
|
|
16281
|
+
const db = adapter.ensureWritable(sessionId);
|
|
16282
|
+
return deleteMembers(db, memberIds);
|
|
16283
|
+
}
|
|
16088
16284
|
function getMemberNameHistory2(adapter, sessionId, memberId) {
|
|
16089
16285
|
const db = adapter.ensureReadonly(sessionId);
|
|
16090
16286
|
return getMemberNameHistory(db, memberId);
|
|
@@ -16353,8 +16549,8 @@ function clearSessionOwner(adapter, sessionId) {
|
|
|
16353
16549
|
}
|
|
16354
16550
|
|
|
16355
16551
|
// ../../packages/node-runtime/src/services/contacts/overrides.ts
|
|
16356
|
-
import
|
|
16357
|
-
import
|
|
16552
|
+
import fs30 from "fs";
|
|
16553
|
+
import path27 from "path";
|
|
16358
16554
|
var CONTACT_OVERRIDES_FILE_NAME = "contact-overrides.json";
|
|
16359
16555
|
var CONTACT_OVERRIDES_TMP_PREFIX = "contact-overrides.tmp-";
|
|
16360
16556
|
var CONTACT_OVERRIDES_VERSION = 1;
|
|
@@ -16365,23 +16561,23 @@ function createEmptyContactOverridesFile() {
|
|
|
16365
16561
|
};
|
|
16366
16562
|
}
|
|
16367
16563
|
function getContactOverridesPath(snapshotDir) {
|
|
16368
|
-
return
|
|
16564
|
+
return path27.join(snapshotDir, CONTACT_OVERRIDES_FILE_NAME);
|
|
16369
16565
|
}
|
|
16370
16566
|
function readContactOverrides(snapshotDir) {
|
|
16371
16567
|
const filePath = getContactOverridesPath(snapshotDir);
|
|
16372
|
-
if (!
|
|
16568
|
+
if (!fs30.existsSync(filePath)) return createEmptyContactOverridesFile();
|
|
16373
16569
|
try {
|
|
16374
|
-
return normalizeContactOverrides(JSON.parse(
|
|
16570
|
+
return normalizeContactOverrides(JSON.parse(fs30.readFileSync(filePath, "utf-8")));
|
|
16375
16571
|
} catch (error) {
|
|
16376
16572
|
appLogger.warn("contacts", "contact overrides file is unreadable", error);
|
|
16377
16573
|
return createEmptyContactOverridesFile();
|
|
16378
16574
|
}
|
|
16379
16575
|
}
|
|
16380
16576
|
function writeContactOverrides(snapshotDir, overrides) {
|
|
16381
|
-
if (!
|
|
16382
|
-
const tmpPath =
|
|
16383
|
-
|
|
16384
|
-
|
|
16577
|
+
if (!fs30.existsSync(snapshotDir)) fs30.mkdirSync(snapshotDir, { recursive: true });
|
|
16578
|
+
const tmpPath = path27.join(snapshotDir, `${CONTACT_OVERRIDES_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
16579
|
+
fs30.writeFileSync(tmpPath, JSON.stringify(normalizeContactOverrides(overrides), null, 2), "utf-8");
|
|
16580
|
+
fs30.renameSync(tmpPath, getContactOverridesPath(snapshotDir));
|
|
16385
16581
|
}
|
|
16386
16582
|
function normalizeContactOverrides(value) {
|
|
16387
16583
|
const input = isRecord2(value) ? value : {};
|
|
@@ -16416,23 +16612,23 @@ function buildContactsSignature(adapter, timeRangePreset) {
|
|
|
16416
16612
|
}
|
|
16417
16613
|
|
|
16418
16614
|
// ../../packages/node-runtime/src/services/contacts/snapshot.ts
|
|
16419
|
-
import
|
|
16420
|
-
import
|
|
16615
|
+
import fs31 from "fs";
|
|
16616
|
+
import path28 from "path";
|
|
16421
16617
|
var CONTACTS_SNAPSHOT_TMP_PREFIX = "contacts-snapshot.tmp-";
|
|
16422
16618
|
function getContactsSnapshotPath(snapshotDir, timeRangePreset) {
|
|
16423
16619
|
const preset = normalizeContactsTimeRangePreset(timeRangePreset);
|
|
16424
|
-
return
|
|
16620
|
+
return path28.join(snapshotDir, `contacts-snapshot-${preset}.json`);
|
|
16425
16621
|
}
|
|
16426
16622
|
function readContactsSnapshot(snapshotDir, timeRangePreset, options2 = {}) {
|
|
16427
16623
|
const snapshotPath = getContactsSnapshotPath(snapshotDir, timeRangePreset);
|
|
16428
|
-
if (!
|
|
16624
|
+
if (!fs31.existsSync(snapshotPath)) return null;
|
|
16429
16625
|
try {
|
|
16430
|
-
return JSON.parse(
|
|
16626
|
+
return JSON.parse(fs31.readFileSync(snapshotPath, "utf-8"));
|
|
16431
16627
|
} catch (error) {
|
|
16432
16628
|
const ts = options2.now?.() ?? Date.now();
|
|
16433
|
-
const backupPath =
|
|
16629
|
+
const backupPath = path28.join(snapshotDir, `contacts-snapshot.corrupt-${ts}.json`);
|
|
16434
16630
|
try {
|
|
16435
|
-
|
|
16631
|
+
fs31.renameSync(snapshotPath, backupPath);
|
|
16436
16632
|
} catch (renameError) {
|
|
16437
16633
|
appLogger.warn("contacts", "failed to backup corrupt contacts snapshot", renameError);
|
|
16438
16634
|
}
|
|
@@ -16441,17 +16637,17 @@ function readContactsSnapshot(snapshotDir, timeRangePreset, options2 = {}) {
|
|
|
16441
16637
|
}
|
|
16442
16638
|
}
|
|
16443
16639
|
function writeContactsSnapshot(snapshotDir, snapshot) {
|
|
16444
|
-
if (!
|
|
16445
|
-
const tmpPath =
|
|
16446
|
-
|
|
16447
|
-
|
|
16640
|
+
if (!fs31.existsSync(snapshotDir)) fs31.mkdirSync(snapshotDir, { recursive: true });
|
|
16641
|
+
const tmpPath = path28.join(snapshotDir, `${CONTACTS_SNAPSHOT_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
16642
|
+
fs31.writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
16643
|
+
fs31.renameSync(tmpPath, getContactsSnapshotPath(snapshotDir, snapshot.timeRange.preset));
|
|
16448
16644
|
}
|
|
16449
16645
|
function cleanupContactsSnapshotTempFiles(snapshotDir) {
|
|
16450
|
-
if (!
|
|
16451
|
-
for (const name of
|
|
16646
|
+
if (!fs31.existsSync(snapshotDir)) return;
|
|
16647
|
+
for (const name of fs31.readdirSync(snapshotDir)) {
|
|
16452
16648
|
if (!name.startsWith(CONTACTS_SNAPSHOT_TMP_PREFIX)) continue;
|
|
16453
16649
|
try {
|
|
16454
|
-
|
|
16650
|
+
fs31.rmSync(path28.join(snapshotDir, name), { force: true });
|
|
16455
16651
|
} catch (error) {
|
|
16456
16652
|
appLogger.warn("contacts", "failed to remove contacts snapshot temp file", error);
|
|
16457
16653
|
}
|
|
@@ -16489,7 +16685,7 @@ function createWorker(workerData, entryUrlInput) {
|
|
|
16489
16685
|
return new Worker(bootstrap, options2);
|
|
16490
16686
|
}
|
|
16491
16687
|
function createContactsWorkerRunner(options2) {
|
|
16492
|
-
return ({ signature, timeRangePreset, signal, onProgress }) => new Promise((
|
|
16688
|
+
return ({ signature, timeRangePreset, signal, onProgress }) => new Promise((resolve4, reject) => {
|
|
16493
16689
|
if (signal.aborted) {
|
|
16494
16690
|
reject(createAbortError());
|
|
16495
16691
|
return;
|
|
@@ -16520,7 +16716,7 @@ function createContactsWorkerRunner(options2) {
|
|
|
16520
16716
|
if (message.type === "success" && message.snapshot) {
|
|
16521
16717
|
settled = true;
|
|
16522
16718
|
signal.removeEventListener("abort", abort);
|
|
16523
|
-
|
|
16719
|
+
resolve4(message.snapshot);
|
|
16524
16720
|
void worker.terminate();
|
|
16525
16721
|
return;
|
|
16526
16722
|
}
|
|
@@ -16949,23 +17145,23 @@ function buildPeopleRelationshipsSignature(adapter, timeRangePreset) {
|
|
|
16949
17145
|
}
|
|
16950
17146
|
|
|
16951
17147
|
// ../../packages/node-runtime/src/services/people/relationships/snapshot.ts
|
|
16952
|
-
import
|
|
16953
|
-
import
|
|
17148
|
+
import fs32 from "fs";
|
|
17149
|
+
import path29 from "path";
|
|
16954
17150
|
var PEOPLE_RELATIONSHIPS_SNAPSHOT_TMP_PREFIX = "people-relationships-snapshot.tmp-";
|
|
16955
17151
|
function getPeopleRelationshipsSnapshotPath(snapshotDir, timeRangePreset) {
|
|
16956
17152
|
const preset = normalizePeopleRelationshipsTimeRangePreset(timeRangePreset);
|
|
16957
|
-
return
|
|
17153
|
+
return path29.join(snapshotDir, `graph-snapshot-${preset}.json`);
|
|
16958
17154
|
}
|
|
16959
17155
|
function readPeopleRelationshipsSnapshot(snapshotDir, timeRangePreset, options2 = {}) {
|
|
16960
17156
|
const snapshotPath = getPeopleRelationshipsSnapshotPath(snapshotDir, timeRangePreset);
|
|
16961
|
-
if (!
|
|
17157
|
+
if (!fs32.existsSync(snapshotPath)) return null;
|
|
16962
17158
|
try {
|
|
16963
|
-
return JSON.parse(
|
|
17159
|
+
return JSON.parse(fs32.readFileSync(snapshotPath, "utf-8"));
|
|
16964
17160
|
} catch (error) {
|
|
16965
17161
|
const ts = options2.now?.() ?? Date.now();
|
|
16966
|
-
const backupPath =
|
|
17162
|
+
const backupPath = path29.join(snapshotDir, `graph-snapshot.corrupt-${ts}.json`);
|
|
16967
17163
|
try {
|
|
16968
|
-
|
|
17164
|
+
fs32.renameSync(snapshotPath, backupPath);
|
|
16969
17165
|
} catch (renameError) {
|
|
16970
17166
|
appLogger.warn("people-relationships", "failed to backup corrupt people relationships snapshot", renameError);
|
|
16971
17167
|
}
|
|
@@ -16974,17 +17170,17 @@ function readPeopleRelationshipsSnapshot(snapshotDir, timeRangePreset, options2
|
|
|
16974
17170
|
}
|
|
16975
17171
|
}
|
|
16976
17172
|
function writePeopleRelationshipsSnapshot(snapshotDir, snapshot) {
|
|
16977
|
-
if (!
|
|
16978
|
-
const tmpPath =
|
|
16979
|
-
|
|
16980
|
-
|
|
17173
|
+
if (!fs32.existsSync(snapshotDir)) fs32.mkdirSync(snapshotDir, { recursive: true });
|
|
17174
|
+
const tmpPath = path29.join(snapshotDir, `${PEOPLE_RELATIONSHIPS_SNAPSHOT_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
17175
|
+
fs32.writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
17176
|
+
fs32.renameSync(tmpPath, getPeopleRelationshipsSnapshotPath(snapshotDir, snapshot.timeRange.preset));
|
|
16981
17177
|
}
|
|
16982
17178
|
function cleanupPeopleRelationshipsSnapshotTempFiles(snapshotDir) {
|
|
16983
|
-
if (!
|
|
16984
|
-
for (const name of
|
|
17179
|
+
if (!fs32.existsSync(snapshotDir)) return;
|
|
17180
|
+
for (const name of fs32.readdirSync(snapshotDir)) {
|
|
16985
17181
|
if (!name.startsWith(PEOPLE_RELATIONSHIPS_SNAPSHOT_TMP_PREFIX)) continue;
|
|
16986
17182
|
try {
|
|
16987
|
-
|
|
17183
|
+
fs32.rmSync(path29.join(snapshotDir, name), { force: true });
|
|
16988
17184
|
} catch (error) {
|
|
16989
17185
|
appLogger.warn("people-relationships", "failed to remove people relationships snapshot temp file", error);
|
|
16990
17186
|
}
|
|
@@ -17022,7 +17218,7 @@ function createWorker2(workerData, entryUrlInput) {
|
|
|
17022
17218
|
return new Worker2(bootstrap, options2);
|
|
17023
17219
|
}
|
|
17024
17220
|
function createPeopleRelationshipsWorkerRunner(options2) {
|
|
17025
|
-
return ({ signature, timeRangePreset, signal, onProgress }) => new Promise((
|
|
17221
|
+
return ({ signature, timeRangePreset, signal, onProgress }) => new Promise((resolve4, reject) => {
|
|
17026
17222
|
if (signal.aborted) {
|
|
17027
17223
|
reject(createAbortError2());
|
|
17028
17224
|
return;
|
|
@@ -17053,7 +17249,7 @@ function createPeopleRelationshipsWorkerRunner(options2) {
|
|
|
17053
17249
|
if (message.type === "success" && message.snapshot) {
|
|
17054
17250
|
settled = true;
|
|
17055
17251
|
signal.removeEventListener("abort", abort);
|
|
17056
|
-
|
|
17252
|
+
resolve4(message.snapshot);
|
|
17057
17253
|
void worker.terminate();
|
|
17058
17254
|
return;
|
|
17059
17255
|
}
|
|
@@ -17506,7 +17702,7 @@ __export(relationships_exports, {
|
|
|
17506
17702
|
});
|
|
17507
17703
|
|
|
17508
17704
|
// ../../packages/node-runtime/src/services/global-insight/service.ts
|
|
17509
|
-
import
|
|
17705
|
+
import fs33 from "fs";
|
|
17510
17706
|
|
|
17511
17707
|
// ../../packages/node-runtime/src/services/global-insight/signature.ts
|
|
17512
17708
|
function buildAnnualSummarySignature(adapter, range) {
|
|
@@ -17533,7 +17729,7 @@ function resolveDefaultAnnualSummaryWorkerEntryUrl(currentModuleUrl = import.met
|
|
|
17533
17729
|
return entryExists(sibling) ? sibling : new URL("./global-insight-worker.js", moduleUrl);
|
|
17534
17730
|
}
|
|
17535
17731
|
function createAnnualSummaryWorkerRunner(options2) {
|
|
17536
|
-
return ({ signature, range, signal, onProgress }) => new Promise((
|
|
17732
|
+
return ({ signature, range, signal, onProgress }) => new Promise((resolve4, reject) => {
|
|
17537
17733
|
if (signal.aborted) {
|
|
17538
17734
|
reject(new Error("annual summary worker aborted"));
|
|
17539
17735
|
return;
|
|
@@ -17564,7 +17760,7 @@ function createAnnualSummaryWorkerRunner(options2) {
|
|
|
17564
17760
|
if (message.type === "success" && message.snapshot) {
|
|
17565
17761
|
settled = true;
|
|
17566
17762
|
signal.removeEventListener("abort", abort);
|
|
17567
|
-
|
|
17763
|
+
resolve4(message.snapshot);
|
|
17568
17764
|
void worker.terminate();
|
|
17569
17765
|
return;
|
|
17570
17766
|
}
|
|
@@ -17759,7 +17955,7 @@ var DefaultGlobalInsightService = class {
|
|
|
17759
17955
|
}
|
|
17760
17956
|
getSnapshot(range) {
|
|
17761
17957
|
const key = toAnnualSummaryRangeKey(range);
|
|
17762
|
-
if (this.snapshots.has(key) && !
|
|
17958
|
+
if (this.snapshots.has(key) && !fs33.existsSync(getAnnualSummarySnapshotPath(this.snapshotDir, range))) {
|
|
17763
17959
|
this.snapshots.delete(key);
|
|
17764
17960
|
}
|
|
17765
17961
|
if (!this.snapshots.has(key)) {
|
|
@@ -17807,8 +18003,8 @@ __export(global_insight_exports, {
|
|
|
17807
18003
|
});
|
|
17808
18004
|
|
|
17809
18005
|
// ../../packages/node-runtime/src/semantic-index/config.ts
|
|
17810
|
-
import
|
|
17811
|
-
import
|
|
18006
|
+
import fs34 from "fs";
|
|
18007
|
+
import path30 from "path";
|
|
17812
18008
|
var DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE = "huggingface";
|
|
17813
18009
|
var SEMANTIC_INDEX_CONFIG_VERSION = 1;
|
|
17814
18010
|
var SEARCH_MAX_RESULTS_DEFAULT = 10;
|
|
@@ -17897,9 +18093,9 @@ var SemanticIndexConfigStore = class {
|
|
|
17897
18093
|
return this.set({ ...this.get(), enabled });
|
|
17898
18094
|
}
|
|
17899
18095
|
get() {
|
|
17900
|
-
if (!
|
|
18096
|
+
if (!fs34.existsSync(this.filePath)) return defaultSemanticIndexConfig();
|
|
17901
18097
|
try {
|
|
17902
|
-
const raw = JSON.parse(
|
|
18098
|
+
const raw = JSON.parse(fs34.readFileSync(this.filePath, "utf-8"));
|
|
17903
18099
|
return normalizeConfig(raw);
|
|
17904
18100
|
} catch {
|
|
17905
18101
|
return defaultSemanticIndexConfig();
|
|
@@ -17907,9 +18103,9 @@ var SemanticIndexConfigStore = class {
|
|
|
17907
18103
|
}
|
|
17908
18104
|
set(config) {
|
|
17909
18105
|
const normalized = normalizeConfig(config);
|
|
17910
|
-
const dir =
|
|
17911
|
-
if (!
|
|
17912
|
-
|
|
18106
|
+
const dir = path30.dirname(this.filePath);
|
|
18107
|
+
if (!fs34.existsSync(dir)) fs34.mkdirSync(dir, { recursive: true });
|
|
18108
|
+
fs34.writeFileSync(this.filePath, JSON.stringify(normalized, null, 2), "utf-8");
|
|
17913
18109
|
return normalized;
|
|
17914
18110
|
}
|
|
17915
18111
|
resolveModelId() {
|
|
@@ -17918,7 +18114,7 @@ var SemanticIndexConfigStore = class {
|
|
|
17918
18114
|
};
|
|
17919
18115
|
|
|
17920
18116
|
// ../../packages/node-runtime/src/semantic-index/service.ts
|
|
17921
|
-
import
|
|
18117
|
+
import path31 from "path";
|
|
17922
18118
|
|
|
17923
18119
|
// ../../packages/node-runtime/src/semantic-index/chunker-config.ts
|
|
17924
18120
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -18239,8 +18435,8 @@ function createEmbedder(config, deps = {}) {
|
|
|
18239
18435
|
if (!config.api || !config.api.baseUrl || !config.api.model) {
|
|
18240
18436
|
throw new Error("semantic index API config incomplete: baseUrl and model are required");
|
|
18241
18437
|
}
|
|
18242
|
-
const
|
|
18243
|
-
const apiKey =
|
|
18438
|
+
const resolve4 = deps.resolveApiKey ?? resolveApiKey;
|
|
18439
|
+
const apiKey = resolve4("", config.api.authProfile);
|
|
18244
18440
|
return new OpenAICompatibleEmbeddingProvider(
|
|
18245
18441
|
{ baseUrl: config.api.baseUrl, apiKey, model: config.api.model },
|
|
18246
18442
|
{ fetchFn: deps.fetchFn }
|
|
@@ -18277,8 +18473,8 @@ function extensionSuffix(platform2) {
|
|
|
18277
18473
|
return "so";
|
|
18278
18474
|
}
|
|
18279
18475
|
function platformPackageName(platform2, arch2) {
|
|
18280
|
-
const
|
|
18281
|
-
return `${BASE_PACKAGE_NAME}-${
|
|
18476
|
+
const os3 = platform2 === "win32" ? "windows" : platform2;
|
|
18477
|
+
return `${BASE_PACKAGE_NAME}-${os3}-${arch2}`;
|
|
18282
18478
|
}
|
|
18283
18479
|
function getLoadablePath() {
|
|
18284
18480
|
if (!validPlatform(platform, arch)) {
|
|
@@ -18777,7 +18973,7 @@ var SemanticIndexJobQueue = class {
|
|
|
18777
18973
|
/** 等待队列清空(含当前任务) */
|
|
18778
18974
|
whenIdle() {
|
|
18779
18975
|
if (!this.processing && this.pending.length === 0) return Promise.resolve();
|
|
18780
|
-
return new Promise((
|
|
18976
|
+
return new Promise((resolve4) => this.idleResolvers.push(resolve4));
|
|
18781
18977
|
}
|
|
18782
18978
|
removePending(dbPathHash) {
|
|
18783
18979
|
this.pending = this.pending.filter((j) => j.dbPathHash !== dbPathHash);
|
|
@@ -18799,7 +18995,7 @@ var SemanticIndexJobQueue = class {
|
|
|
18799
18995
|
this.processing = false;
|
|
18800
18996
|
const resolvers = this.idleResolvers;
|
|
18801
18997
|
this.idleResolvers = [];
|
|
18802
|
-
for (const
|
|
18998
|
+
for (const resolve4 of resolvers) resolve4();
|
|
18803
18999
|
}
|
|
18804
19000
|
};
|
|
18805
19001
|
|
|
@@ -19449,16 +19645,16 @@ function resolveSearchToolEvidenceTokens(maxResultTokens) {
|
|
|
19449
19645
|
return maxResultTokens && maxResultTokens > 0 ? Math.min(SEARCH_TOOL_EVIDENCE_TOKENS, maxResultTokens) : SEARCH_TOOL_EVIDENCE_TOKENS;
|
|
19450
19646
|
}
|
|
19451
19647
|
function sessionIdFromDbPath(dbPath) {
|
|
19452
|
-
return
|
|
19648
|
+
return path31.basename(dbPath, ".db");
|
|
19453
19649
|
}
|
|
19454
19650
|
var SEMANTIC_INDEX_DB_FILE = "embedding_index.db";
|
|
19455
19651
|
var SEMANTIC_INDEX_CONFIG_FILE = "semantic-index-config.json";
|
|
19456
19652
|
function createSemanticIndexService(params) {
|
|
19457
19653
|
const { pathProvider } = params;
|
|
19458
19654
|
return new SemanticIndexService({
|
|
19459
|
-
vectorDbPath:
|
|
19460
|
-
configPath:
|
|
19461
|
-
modelsCacheDir:
|
|
19655
|
+
vectorDbPath: path31.join(pathProvider.getVectorDir(), SEMANTIC_INDEX_DB_FILE),
|
|
19656
|
+
configPath: path31.join(pathProvider.getAiDataDir(), SEMANTIC_INDEX_CONFIG_FILE),
|
|
19657
|
+
modelsCacheDir: path31.join(pathProvider.getAiDataDir(), "models", "semantic-index"),
|
|
19462
19658
|
modelDownloadProxyUrl: params.modelDownloadProxyUrl,
|
|
19463
19659
|
sessionAdapter: params.sessionAdapter,
|
|
19464
19660
|
nativeBinding: params.nativeBinding,
|
|
@@ -20008,8 +20204,8 @@ ${text}`;
|
|
|
20008
20204
|
};
|
|
20009
20205
|
|
|
20010
20206
|
// ../../packages/node-runtime/src/services/merge-cache.ts
|
|
20011
|
-
import * as
|
|
20012
|
-
import * as
|
|
20207
|
+
import * as fs35 from "fs";
|
|
20208
|
+
import * as path32 from "path";
|
|
20013
20209
|
import * as crypto from "crypto";
|
|
20014
20210
|
var MergeSessionCache = class {
|
|
20015
20211
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -20018,15 +20214,15 @@ var MergeSessionCache = class {
|
|
|
20018
20214
|
constructor(pathProvider, options2) {
|
|
20019
20215
|
this.tempDir = pathProvider.getTempDir();
|
|
20020
20216
|
this.nativeBinding = options2?.nativeBinding;
|
|
20021
|
-
if (!
|
|
20022
|
-
|
|
20217
|
+
if (!fs35.existsSync(this.tempDir)) {
|
|
20218
|
+
fs35.mkdirSync(this.tempDir, { recursive: true });
|
|
20023
20219
|
}
|
|
20024
20220
|
}
|
|
20025
20221
|
generateTempDbPath(filename) {
|
|
20026
20222
|
const ts = Date.now();
|
|
20027
20223
|
const rand = Math.random().toString(36).slice(2, 8);
|
|
20028
20224
|
const safeName = filename.replace(/[/\\?%*:|"<>]/g, "_").slice(0, 40);
|
|
20029
|
-
return
|
|
20225
|
+
return path32.join(this.tempDir, `merge_${safeName}_${ts}_${rand}.db`);
|
|
20030
20226
|
}
|
|
20031
20227
|
/** Store a parsed file's temp DB and return a handle for subsequent requests. */
|
|
20032
20228
|
store(filename, tempDbPath) {
|
|
@@ -20037,7 +20233,7 @@ var MergeSessionCache = class {
|
|
|
20037
20233
|
/** Open a TempDbReader for a given handle. Caller must close the reader. */
|
|
20038
20234
|
openReader(handle) {
|
|
20039
20235
|
const entry = this.cache.get(handle);
|
|
20040
|
-
if (!entry || !
|
|
20236
|
+
if (!entry || !fs35.existsSync(entry.tempDbPath)) return null;
|
|
20041
20237
|
const adapter = openBetterSqliteDatabase(entry.tempDbPath, {
|
|
20042
20238
|
readonly: true,
|
|
20043
20239
|
nativeBinding: this.nativeBinding
|
|
@@ -20082,20 +20278,44 @@ var MergeSessionCache = class {
|
|
|
20082
20278
|
};
|
|
20083
20279
|
|
|
20084
20280
|
// ../../packages/node-runtime/src/services/push-importer.ts
|
|
20085
|
-
import * as
|
|
20281
|
+
import * as fs36 from "fs";
|
|
20086
20282
|
var SYSTEM_SENDER_ID = "SYSTEM";
|
|
20087
20283
|
var SYSTEM_MEMBER_NAME = "\u7CFB\u7EDF\u6D88\u606F";
|
|
20284
|
+
function isRecord3(value) {
|
|
20285
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20286
|
+
}
|
|
20287
|
+
function validateOptionalString(value, field) {
|
|
20288
|
+
return value !== void 0 && typeof value !== "string" ? `${field} must be a string` : null;
|
|
20289
|
+
}
|
|
20088
20290
|
function validatePayload(payload, isNew) {
|
|
20291
|
+
if (!isRecord3(payload)) return "payload must be an object";
|
|
20089
20292
|
const messages = payload.messages;
|
|
20090
20293
|
if (!Array.isArray(messages) || messages.length === 0) return "messages is required and must be a non-empty array";
|
|
20294
|
+
if (payload.chatlab !== void 0) {
|
|
20295
|
+
if (!isRecord3(payload.chatlab)) return "chatlab must be an object";
|
|
20296
|
+
if (typeof payload.chatlab.version !== "string" || payload.chatlab.version.length === 0)
|
|
20297
|
+
return "chatlab.version must be a string";
|
|
20298
|
+
if (typeof payload.chatlab.exportedAt !== "number" || !Number.isFinite(payload.chatlab.exportedAt))
|
|
20299
|
+
return "chatlab.exportedAt must be a number";
|
|
20300
|
+
const generatorError = validateOptionalString(payload.chatlab.generator, "chatlab.generator");
|
|
20301
|
+
if (generatorError) return generatorError;
|
|
20302
|
+
}
|
|
20091
20303
|
if (isNew) {
|
|
20092
20304
|
if (!payload.chatlab) return "chatlab is required for new sessions";
|
|
20093
20305
|
if (!payload.meta) return "meta is required for new sessions";
|
|
20094
|
-
const m = payload.meta;
|
|
20095
|
-
if (!m.name) return "meta.name is required";
|
|
20096
|
-
if (!m.platform) return "meta.platform is required";
|
|
20097
|
-
if (!m.type) return "meta.type is required";
|
|
20098
20306
|
}
|
|
20307
|
+
if (payload.meta !== void 0) {
|
|
20308
|
+
if (!isRecord3(payload.meta)) return "meta must be an object";
|
|
20309
|
+
const metaFields = ["name", "platform", "type", "groupId", "groupAvatar", "ownerId"];
|
|
20310
|
+
for (const field of metaFields) {
|
|
20311
|
+
const error = validateOptionalString(payload.meta[field], `meta.${field}`);
|
|
20312
|
+
if (error) return error;
|
|
20313
|
+
}
|
|
20314
|
+
if (isNew && !payload.meta.name) return "meta.name is required";
|
|
20315
|
+
if (isNew && !payload.meta.platform) return "meta.platform is required";
|
|
20316
|
+
if (isNew && !payload.meta.type) return "meta.type is required";
|
|
20317
|
+
}
|
|
20318
|
+
if (payload.options !== void 0 && !isRecord3(payload.options)) return "options must be an object";
|
|
20099
20319
|
const { metaUpdateMode, memberUpdateMode } = payload.options ?? {};
|
|
20100
20320
|
if (metaUpdateMode !== void 0 && metaUpdateMode !== "patch" && metaUpdateMode !== "none") {
|
|
20101
20321
|
return `options.metaUpdateMode must be 'patch' or 'none'`;
|
|
@@ -20106,16 +20326,35 @@ function validatePayload(payload, isNew) {
|
|
|
20106
20326
|
if (payload.members !== void 0 && !Array.isArray(payload.members)) return "members must be an array";
|
|
20107
20327
|
if (payload.members) {
|
|
20108
20328
|
for (let i = 0; i < payload.members.length; i++) {
|
|
20109
|
-
|
|
20329
|
+
const member = payload.members[i];
|
|
20330
|
+
if (!isRecord3(member)) return `members[${i}] must be an object`;
|
|
20331
|
+
if (typeof member.platformId !== "string" || member.platformId.length === 0)
|
|
20110
20332
|
return `members[${i}].platformId must be a string`;
|
|
20333
|
+
for (const field of ["accountName", "groupNickname", "avatar"]) {
|
|
20334
|
+
const error = validateOptionalString(member[field], `members[${i}].${field}`);
|
|
20335
|
+
if (error) return error;
|
|
20336
|
+
}
|
|
20337
|
+
if (member.roles !== void 0) {
|
|
20338
|
+
if (!Array.isArray(member.roles)) return `members[${i}].roles must be an array`;
|
|
20339
|
+
for (let j = 0; j < member.roles.length; j++) {
|
|
20340
|
+
const role = member.roles[j];
|
|
20341
|
+
if (!isRecord3(role) || typeof role.id !== "string" || role.id.length === 0)
|
|
20342
|
+
return `members[${i}].roles[${j}].id must be a string`;
|
|
20343
|
+
}
|
|
20344
|
+
}
|
|
20111
20345
|
}
|
|
20112
20346
|
}
|
|
20113
20347
|
for (let i = 0; i < messages.length; i++) {
|
|
20114
20348
|
const msg = messages[i];
|
|
20349
|
+
if (!isRecord3(msg)) return `messages[${i}] must be an object`;
|
|
20115
20350
|
if (typeof msg.sender !== "string" || msg.sender.length === 0) return `messages[${i}].sender must be a string`;
|
|
20116
|
-
if (typeof msg.timestamp !== "number" || msg.timestamp <= 0)
|
|
20351
|
+
if (typeof msg.timestamp !== "number" || !Number.isFinite(msg.timestamp) || msg.timestamp <= 0)
|
|
20117
20352
|
return `messages[${i}].timestamp must be a positive number`;
|
|
20118
|
-
if (typeof msg.type !== "number") return `messages[${i}].type must be a number`;
|
|
20353
|
+
if (typeof msg.type !== "number" || !Number.isFinite(msg.type)) return `messages[${i}].type must be a number`;
|
|
20354
|
+
for (const field of ["accountName", "groupNickname"]) {
|
|
20355
|
+
const error = validateOptionalString(msg[field], `messages[${i}].${field}`);
|
|
20356
|
+
if (error) return error;
|
|
20357
|
+
}
|
|
20119
20358
|
if (msg.content !== void 0 && msg.content !== null && typeof msg.content !== "string")
|
|
20120
20359
|
return `messages[${i}].content must be a string or null`;
|
|
20121
20360
|
if (msg.platformMessageId !== void 0 && typeof msg.platformMessageId !== "string")
|
|
@@ -20136,47 +20375,79 @@ function normalizeSenderAccountName(sender, accountName) {
|
|
|
20136
20375
|
function normalizeSenderGroupNickname(sender, groupNickname) {
|
|
20137
20376
|
return sender === SYSTEM_SENDER_ID ? SYSTEM_MEMBER_NAME : groupNickname;
|
|
20138
20377
|
}
|
|
20139
|
-
function
|
|
20378
|
+
function isCountedMember(platformId) {
|
|
20379
|
+
return platformId !== SYSTEM_SENDER_ID;
|
|
20380
|
+
}
|
|
20381
|
+
function registerPushMessageAndCheckDuplicate(message, dedupState) {
|
|
20382
|
+
return registerMessageAndCheckDuplicate(
|
|
20383
|
+
{
|
|
20384
|
+
platformMessageId: message.platformMessageId,
|
|
20385
|
+
timestamp: message.timestamp,
|
|
20386
|
+
senderPlatformId: message.sender,
|
|
20387
|
+
type: message.type,
|
|
20388
|
+
content: message.content ?? null,
|
|
20389
|
+
replyToMessageId: message.replyToMessageId
|
|
20390
|
+
},
|
|
20391
|
+
dedupState
|
|
20392
|
+
);
|
|
20393
|
+
}
|
|
20394
|
+
function createExistingMessageDedupState(db) {
|
|
20395
|
+
const existingPmids = /* @__PURE__ */ new Set();
|
|
20396
|
+
const existingKeys = /* @__PURE__ */ new Set();
|
|
20397
|
+
const existingFallbackOnlyKeys = /* @__PURE__ */ new Set();
|
|
20398
|
+
const existingMessages = db.prepare(
|
|
20399
|
+
`SELECT msg.ts, m.platform_id, msg.type, msg.content, msg.reply_to_message_id, msg.platform_message_id
|
|
20400
|
+
FROM message msg
|
|
20401
|
+
JOIN member m ON msg.sender_id = m.id`
|
|
20402
|
+
).all();
|
|
20403
|
+
for (const message of existingMessages) {
|
|
20404
|
+
if (message.platform_message_id) existingPmids.add(message.platform_message_id);
|
|
20405
|
+
const key = generateFallbackMessageKey({
|
|
20406
|
+
timestamp: message.ts,
|
|
20407
|
+
senderPlatformId: message.platform_id,
|
|
20408
|
+
type: message.type,
|
|
20409
|
+
content: message.content,
|
|
20410
|
+
replyToMessageId: message.reply_to_message_id ?? void 0
|
|
20411
|
+
});
|
|
20412
|
+
existingKeys.add(key);
|
|
20413
|
+
if (!message.platform_message_id) existingFallbackOnlyKeys.add(key);
|
|
20414
|
+
}
|
|
20415
|
+
return createMessageDedupState(existingPmids, existingKeys, existingFallbackOnlyKeys);
|
|
20416
|
+
}
|
|
20417
|
+
function writeMessages(db, messages, dedupState) {
|
|
20140
20418
|
const insertMsg = db.prepare(
|
|
20141
20419
|
`INSERT INTO message (sender_id, sender_account_name, sender_group_nickname, ts, type, content, reply_to_message_id, platform_message_id)
|
|
20142
20420
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
20143
20421
|
);
|
|
20144
20422
|
const getMemberId = db.prepare("SELECT id FROM member WHERE platform_id = ?");
|
|
20145
|
-
const insertMinimalMember = db.prepare(
|
|
20423
|
+
const insertMinimalMember = db.prepare(
|
|
20424
|
+
"INSERT OR IGNORE INTO member (platform_id, account_name, group_nickname) VALUES (?, ?, ?)"
|
|
20425
|
+
);
|
|
20146
20426
|
const memberIdCache = /* @__PURE__ */ new Map();
|
|
20147
20427
|
let writtenCount = 0;
|
|
20148
20428
|
let duplicateCount = 0;
|
|
20429
|
+
let membersAdded = 0;
|
|
20149
20430
|
let minWrittenTs = Infinity;
|
|
20150
20431
|
const ftsEntries = [];
|
|
20151
20432
|
const sorted = [...messages].sort((a, b) => a.timestamp - b.timestamp);
|
|
20152
20433
|
db.transaction(() => {
|
|
20153
20434
|
for (const msg of sorted) {
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
duplicateCount++;
|
|
20158
|
-
continue;
|
|
20159
|
-
}
|
|
20160
|
-
if (existingKeys.has(key)) {
|
|
20161
|
-
duplicateCount++;
|
|
20162
|
-
continue;
|
|
20163
|
-
}
|
|
20164
|
-
existingPmids.add(msg.platformMessageId);
|
|
20165
|
-
existingKeys.add(key);
|
|
20166
|
-
} else {
|
|
20167
|
-
if (existingKeys.has(key)) {
|
|
20168
|
-
duplicateCount++;
|
|
20169
|
-
continue;
|
|
20170
|
-
}
|
|
20171
|
-
existingKeys.add(key);
|
|
20435
|
+
if (registerPushMessageAndCheckDuplicate(msg, dedupState)) {
|
|
20436
|
+
duplicateCount++;
|
|
20437
|
+
continue;
|
|
20172
20438
|
}
|
|
20173
20439
|
let memberId = memberIdCache.get(msg.sender);
|
|
20174
20440
|
if (!memberId) {
|
|
20175
|
-
insertMinimalMember.run(
|
|
20441
|
+
const insertResult = insertMinimalMember.run(
|
|
20442
|
+
msg.sender,
|
|
20443
|
+
normalizeSenderAccountName(msg.sender, msg.accountName) || null,
|
|
20444
|
+
normalizeSenderGroupNickname(msg.sender, msg.groupNickname) || null
|
|
20445
|
+
);
|
|
20176
20446
|
const row = getMemberId.get(msg.sender);
|
|
20177
20447
|
if (row) {
|
|
20178
20448
|
memberId = row.id;
|
|
20179
20449
|
memberIdCache.set(msg.sender, memberId);
|
|
20450
|
+
if (isCountedMember(msg.sender)) membersAdded += insertResult.changes;
|
|
20180
20451
|
}
|
|
20181
20452
|
}
|
|
20182
20453
|
if (!memberId) continue;
|
|
@@ -20195,7 +20466,7 @@ function writeMessages(db, messages, existingPmids, existingKeys) {
|
|
|
20195
20466
|
writtenCount++;
|
|
20196
20467
|
}
|
|
20197
20468
|
});
|
|
20198
|
-
return { writtenCount, duplicateCount, minWrittenTs, ftsEntries };
|
|
20469
|
+
return { writtenCount, duplicateCount, membersAdded, minWrittenTs, ftsEntries };
|
|
20199
20470
|
}
|
|
20200
20471
|
function fullImport(db, meta, members, messages) {
|
|
20201
20472
|
db.exec(CHAT_DB_SCHEMA);
|
|
@@ -20212,29 +20483,13 @@ function fullImport(db, meta, members, messages) {
|
|
|
20212
20483
|
}
|
|
20213
20484
|
}
|
|
20214
20485
|
const allMembers = extraMembers.length > 0 ? [...members, ...extraMembers] : members;
|
|
20215
|
-
const
|
|
20216
|
-
const hashKeys = /* @__PURE__ */ new Set();
|
|
20486
|
+
const dedupState = createMessageDedupState();
|
|
20217
20487
|
let duplicateCount = 0;
|
|
20218
20488
|
const dedupedMessages = [];
|
|
20219
20489
|
for (const msg of messages) {
|
|
20220
|
-
|
|
20221
|
-
|
|
20222
|
-
|
|
20223
|
-
duplicateCount++;
|
|
20224
|
-
continue;
|
|
20225
|
-
}
|
|
20226
|
-
if (hashKeys.has(key)) {
|
|
20227
|
-
duplicateCount++;
|
|
20228
|
-
continue;
|
|
20229
|
-
}
|
|
20230
|
-
pmids.add(msg.platformMessageId);
|
|
20231
|
-
hashKeys.add(key);
|
|
20232
|
-
} else {
|
|
20233
|
-
if (hashKeys.has(key)) {
|
|
20234
|
-
duplicateCount++;
|
|
20235
|
-
continue;
|
|
20236
|
-
}
|
|
20237
|
-
hashKeys.add(key);
|
|
20490
|
+
if (registerPushMessageAndCheckDuplicate(msg, dedupState)) {
|
|
20491
|
+
duplicateCount++;
|
|
20492
|
+
continue;
|
|
20238
20493
|
}
|
|
20239
20494
|
dedupedMessages.push(msg);
|
|
20240
20495
|
}
|
|
@@ -20262,15 +20517,12 @@ function fullImport(db, meta, members, messages) {
|
|
|
20262
20517
|
generateSessionIndex(db);
|
|
20263
20518
|
} catch {
|
|
20264
20519
|
}
|
|
20265
|
-
return { writtenCount: stats.messageCount, duplicateCount
|
|
20520
|
+
return { writtenCount: stats.messageCount, duplicateCount };
|
|
20266
20521
|
}
|
|
20267
|
-
function
|
|
20522
|
+
function writeIncrementalImport(db, payload) {
|
|
20268
20523
|
const metaUpdateMode = payload.options?.metaUpdateMode ?? "patch";
|
|
20269
20524
|
const memberUpdateMode = payload.options?.memberUpdateMode ?? "upsert";
|
|
20270
|
-
const
|
|
20271
|
-
const existingKeys = /* @__PURE__ */ new Set();
|
|
20272
|
-
db.prepare("SELECT platform_message_id FROM message WHERE platform_message_id IS NOT NULL").all().forEach((r) => existingPmids.add(r.platform_message_id));
|
|
20273
|
-
db.prepare(`SELECT msg.ts, m.platform_id, msg.content FROM message msg JOIN member m ON msg.sender_id = m.id`).all().forEach((r) => existingKeys.add(generateMessageKey(r.ts, r.platform_id, r.content)));
|
|
20525
|
+
const dedupState = createExistingMessageDedupState(db);
|
|
20274
20526
|
let metaUpdated = false;
|
|
20275
20527
|
let membersAdded = 0;
|
|
20276
20528
|
let membersUpdated = 0;
|
|
@@ -20307,22 +20559,23 @@ function incrementalImport2(db, payload) {
|
|
|
20307
20559
|
m.roles ? JSON.stringify(m.roles) : "[]"
|
|
20308
20560
|
);
|
|
20309
20561
|
if (!existed) {
|
|
20310
|
-
membersAdded++;
|
|
20562
|
+
if (isCountedMember(m.platformId)) membersAdded++;
|
|
20311
20563
|
const row = getMemberId.get(m.platformId);
|
|
20312
20564
|
if (row) existingMemberIds.add(m.platformId);
|
|
20313
|
-
} else {
|
|
20565
|
+
} else if (isCountedMember(m.platformId)) {
|
|
20314
20566
|
membersUpdated++;
|
|
20315
20567
|
}
|
|
20316
20568
|
}
|
|
20317
20569
|
});
|
|
20318
20570
|
}
|
|
20319
20571
|
const preWriteMaxTs = db.prepare("SELECT MAX(ts) as max_ts FROM message").get()?.max_ts ?? 0;
|
|
20320
|
-
const {
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
|
|
20324
|
-
|
|
20325
|
-
|
|
20572
|
+
const {
|
|
20573
|
+
writtenCount,
|
|
20574
|
+
duplicateCount,
|
|
20575
|
+
membersAdded: autoCreatedMembersAdded,
|
|
20576
|
+
minWrittenTs,
|
|
20577
|
+
ftsEntries
|
|
20578
|
+
} = writeMessages(db, payload.messages, dedupState);
|
|
20326
20579
|
if (ftsEntries.length > 0) {
|
|
20327
20580
|
try {
|
|
20328
20581
|
insertFtsEntries(db, ftsEntries);
|
|
@@ -20342,18 +20595,40 @@ function incrementalImport2(db, payload) {
|
|
|
20342
20595
|
if (!metaUpdated) {
|
|
20343
20596
|
db.prepare("UPDATE meta SET imported_at = ?").run(Math.floor(Date.now() / 1e3));
|
|
20344
20597
|
}
|
|
20345
|
-
return {
|
|
20598
|
+
return {
|
|
20599
|
+
writtenCount,
|
|
20600
|
+
duplicateCount,
|
|
20601
|
+
metaUpdated,
|
|
20602
|
+
membersAdded: membersAdded + autoCreatedMembersAdded,
|
|
20603
|
+
membersUpdated
|
|
20604
|
+
};
|
|
20605
|
+
}
|
|
20606
|
+
function incrementalImport2(db, payload) {
|
|
20607
|
+
return db.transaction(() => writeIncrementalImport(db, payload));
|
|
20346
20608
|
}
|
|
20347
|
-
var SAFE_SESSION_ID_RE = /^[a-zA-Z0-9_@-][a-zA-Z0-9_@.-]*$/;
|
|
20348
20609
|
async function pushImport(dbManager, sessionId, payload) {
|
|
20349
|
-
if (!SAFE_SESSION_ID_RE.test(sessionId) || sessionId.includes("..")) {
|
|
20350
|
-
return { ok: false, reason: "invalid_payload", message: "sessionId contains invalid characters" };
|
|
20351
|
-
}
|
|
20352
20610
|
try {
|
|
20353
|
-
return await withDataDirImportLock(
|
|
20354
|
-
|
|
20355
|
-
|
|
20356
|
-
|
|
20611
|
+
return await withDataDirImportLock(dbManager.getUserDataDir(), async () => {
|
|
20612
|
+
const outcome = await executePushImportUnlocked(
|
|
20613
|
+
{
|
|
20614
|
+
getDbPath: (id) => dbManager.getDbPath(id),
|
|
20615
|
+
openDatabase: (id, options2) => dbManager.openRawSessionDatabase(id, options2),
|
|
20616
|
+
deleteDatabase: (id) => {
|
|
20617
|
+
dbManager.deleteSessionDatabaseFiles(id);
|
|
20618
|
+
}
|
|
20619
|
+
},
|
|
20620
|
+
sessionId,
|
|
20621
|
+
payload
|
|
20622
|
+
);
|
|
20623
|
+
if (!outcome.ok) return outcome;
|
|
20624
|
+
try {
|
|
20625
|
+
dbManager.raiseCurrentChatDbCompatibilityGate();
|
|
20626
|
+
} catch (error) {
|
|
20627
|
+
if (outcome.result.created) dbManager.deleteSessionDatabaseFiles(sessionId);
|
|
20628
|
+
throw error;
|
|
20629
|
+
}
|
|
20630
|
+
return outcome;
|
|
20631
|
+
});
|
|
20357
20632
|
} catch (error) {
|
|
20358
20633
|
if (error instanceof ImportInProgressError) {
|
|
20359
20634
|
return {
|
|
@@ -20365,26 +20640,24 @@ async function pushImport(dbManager, sessionId, payload) {
|
|
|
20365
20640
|
throw error;
|
|
20366
20641
|
}
|
|
20367
20642
|
}
|
|
20368
|
-
async function
|
|
20369
|
-
|
|
20370
|
-
|
|
20643
|
+
async function executePushImportUnlocked(deps, sessionId, payload) {
|
|
20644
|
+
if (!isValidImportSessionId(sessionId)) {
|
|
20645
|
+
return { ok: false, reason: "invalid_payload", message: "sessionId contains invalid characters" };
|
|
20646
|
+
}
|
|
20647
|
+
const dbPath = deps.getDbPath(sessionId);
|
|
20648
|
+
const isNew = !fs36.existsSync(dbPath);
|
|
20371
20649
|
const validationError = validatePayload(payload, isNew);
|
|
20372
20650
|
if (validationError) {
|
|
20373
20651
|
return { ok: false, reason: "invalid_payload", message: validationError };
|
|
20374
20652
|
}
|
|
20375
20653
|
try {
|
|
20376
20654
|
if (isNew) {
|
|
20377
|
-
const db2 =
|
|
20655
|
+
const db2 = deps.openDatabase(sessionId, { create: true });
|
|
20378
20656
|
try {
|
|
20379
|
-
const { writtenCount, duplicateCount
|
|
20380
|
-
db2,
|
|
20381
|
-
payload.meta,
|
|
20382
|
-
payload.members ?? [],
|
|
20383
|
-
payload.messages
|
|
20384
|
-
);
|
|
20657
|
+
const { writtenCount, duplicateCount } = fullImport(db2, payload.meta, payload.members ?? [], payload.messages);
|
|
20385
20658
|
const session = queryStats(db2);
|
|
20386
|
-
|
|
20387
|
-
|
|
20659
|
+
const membersAdded = session.memberCount;
|
|
20660
|
+
const outcome = {
|
|
20388
20661
|
ok: true,
|
|
20389
20662
|
result: {
|
|
20390
20663
|
sessionId,
|
|
@@ -20394,16 +20667,17 @@ async function pushImportUnlocked(dbManager, sessionId, payload) {
|
|
|
20394
20667
|
updates: { metaUpdated: true, membersAdded, membersUpdated: 0 }
|
|
20395
20668
|
}
|
|
20396
20669
|
};
|
|
20670
|
+
appLogger.info("push-import", "Push import completed", outcome.result);
|
|
20671
|
+
return outcome;
|
|
20397
20672
|
} finally {
|
|
20398
20673
|
db2.close();
|
|
20399
20674
|
}
|
|
20400
20675
|
}
|
|
20401
|
-
const db =
|
|
20676
|
+
const db = deps.openDatabase(sessionId, { readonly: false });
|
|
20402
20677
|
try {
|
|
20403
20678
|
const { writtenCount, duplicateCount, metaUpdated, membersAdded, membersUpdated } = incrementalImport2(db, payload);
|
|
20404
20679
|
const session = queryStats(db);
|
|
20405
|
-
|
|
20406
|
-
return {
|
|
20680
|
+
const outcome = {
|
|
20407
20681
|
ok: true,
|
|
20408
20682
|
result: {
|
|
20409
20683
|
sessionId,
|
|
@@ -20413,6 +20687,8 @@ async function pushImportUnlocked(dbManager, sessionId, payload) {
|
|
|
20413
20687
|
updates: { metaUpdated, membersAdded, membersUpdated }
|
|
20414
20688
|
}
|
|
20415
20689
|
};
|
|
20690
|
+
appLogger.info("push-import", "Push import completed", outcome.result);
|
|
20691
|
+
return outcome;
|
|
20416
20692
|
} finally {
|
|
20417
20693
|
db.close();
|
|
20418
20694
|
}
|
|
@@ -20420,15 +20696,61 @@ async function pushImportUnlocked(dbManager, sessionId, payload) {
|
|
|
20420
20696
|
if (err instanceof DataDirCompatibilityError) throw err;
|
|
20421
20697
|
if (isNew) {
|
|
20422
20698
|
try {
|
|
20423
|
-
|
|
20699
|
+
deps.deleteDatabase(sessionId);
|
|
20424
20700
|
} catch {
|
|
20425
20701
|
}
|
|
20426
20702
|
}
|
|
20703
|
+
appLogger.error("push-import", "Push import failed", err);
|
|
20427
20704
|
return { ok: false, reason: "import_failed", message: err instanceof Error ? err.message : String(err) };
|
|
20428
20705
|
}
|
|
20429
20706
|
}
|
|
20430
20707
|
|
|
20708
|
+
// ../../packages/node-runtime/src/services/import-idempotency.ts
|
|
20709
|
+
import { createHash as createHash4 } from "crypto";
|
|
20710
|
+
var DEFAULT_IMPORT_IDEMPOTENCY_TTL_MS = 60 * 60 * 1e3;
|
|
20711
|
+
function hashImportBody(body) {
|
|
20712
|
+
return createHash4("sha256").update(JSON.stringify(body ?? "")).digest("hex");
|
|
20713
|
+
}
|
|
20714
|
+
var ImportIdempotencyCache = class {
|
|
20715
|
+
constructor(ttlMs = DEFAULT_IMPORT_IDEMPOTENCY_TTL_MS) {
|
|
20716
|
+
this.ttlMs = ttlMs;
|
|
20717
|
+
}
|
|
20718
|
+
ttlMs;
|
|
20719
|
+
entries = /* @__PURE__ */ new Map();
|
|
20720
|
+
start(key, bodyHash, now = Date.now()) {
|
|
20721
|
+
this.prune(now);
|
|
20722
|
+
const entry = this.entries.get(key);
|
|
20723
|
+
if (!entry) {
|
|
20724
|
+
this.entries.set(key, { bodyHash, status: "pending", timestamp: now });
|
|
20725
|
+
return { status: "started" };
|
|
20726
|
+
}
|
|
20727
|
+
if (entry.bodyHash !== bodyHash) return { status: "conflict" };
|
|
20728
|
+
if (entry.status === "pending") return { status: "pending" };
|
|
20729
|
+
return { status: "success", response: entry.response };
|
|
20730
|
+
}
|
|
20731
|
+
success(key, response) {
|
|
20732
|
+
const entry = this.entries.get(key);
|
|
20733
|
+
if (!entry) return;
|
|
20734
|
+
entry.status = "success";
|
|
20735
|
+
entry.response = response;
|
|
20736
|
+
}
|
|
20737
|
+
fail(key) {
|
|
20738
|
+
this.entries.delete(key);
|
|
20739
|
+
}
|
|
20740
|
+
prune(now) {
|
|
20741
|
+
for (const [key, entry] of this.entries) {
|
|
20742
|
+
if (now - entry.timestamp > this.ttlMs) this.entries.delete(key);
|
|
20743
|
+
}
|
|
20744
|
+
}
|
|
20745
|
+
};
|
|
20746
|
+
|
|
20431
20747
|
export {
|
|
20748
|
+
CHATLAB_TEMP_ROOT_ENV,
|
|
20749
|
+
resolveChatLabTempRoot,
|
|
20750
|
+
ensureChatLabTempRoot,
|
|
20751
|
+
getChatLabTempScopeDir,
|
|
20752
|
+
createChatLabTempDir,
|
|
20753
|
+
removeChatLabTempDir,
|
|
20432
20754
|
writeParseResultToDb,
|
|
20433
20755
|
detectFormat,
|
|
20434
20756
|
detectAllFormats,
|
|
@@ -20466,8 +20788,10 @@ export {
|
|
|
20466
20788
|
streamParseFileInfo,
|
|
20467
20789
|
analyzeIncrementalImport,
|
|
20468
20790
|
incrementalImport,
|
|
20791
|
+
isValidImportSessionId,
|
|
20469
20792
|
resolveAutoImportTarget,
|
|
20470
20793
|
autoImportFile,
|
|
20794
|
+
analyzeAutoImportFile,
|
|
20471
20795
|
IMPORT_LOCK_FILENAME,
|
|
20472
20796
|
IMPORT_IN_PROGRESS_ERROR_KEY,
|
|
20473
20797
|
ImportInProgressError,
|
|
@@ -20548,6 +20872,8 @@ export {
|
|
|
20548
20872
|
checkSessionsCanGenerateSummary,
|
|
20549
20873
|
MAX_CONFIG_COUNT,
|
|
20550
20874
|
LLMConfigStore,
|
|
20875
|
+
createFileConfigStorage,
|
|
20876
|
+
createAuthProfileLlmConfigStore,
|
|
20551
20877
|
CustomProviderStore,
|
|
20552
20878
|
CustomModelStore,
|
|
20553
20879
|
normalizeAnthropicBaseUrl,
|
|
@@ -20636,6 +20962,10 @@ export {
|
|
|
20636
20962
|
createSemanticIndexService,
|
|
20637
20963
|
SemanticIndexService,
|
|
20638
20964
|
MergeSessionCache,
|
|
20639
|
-
pushImport
|
|
20965
|
+
pushImport,
|
|
20966
|
+
executePushImportUnlocked,
|
|
20967
|
+
DEFAULT_IMPORT_IDEMPOTENCY_TTL_MS,
|
|
20968
|
+
hashImportBody,
|
|
20969
|
+
ImportIdempotencyCache
|
|
20640
20970
|
};
|
|
20641
|
-
//# sourceMappingURL=chunk-
|
|
20971
|
+
//# sourceMappingURL=chunk-5G2INROS.mjs.map
|