chatlab-cli 0.27.1 → 0.28.0

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.
Files changed (71) hide show
  1. package/README.md +1 -1
  2. package/dist/{chat-command-B7POB3C3.mjs → chat-command-7WL5NMZ6.mjs} +5 -5
  3. package/dist/{chunk-I7BHOZPX.mjs → chunk-55WR6WKW.mjs} +84 -19
  4. package/dist/{chunk-I7BHOZPX.mjs.map → chunk-55WR6WKW.mjs.map} +1 -1
  5. package/dist/{chunk-3FUF3PEY.mjs → chunk-GFRG7TZQ.mjs} +27 -12
  6. package/dist/chunk-GFRG7TZQ.mjs.map +1 -0
  7. package/dist/{chunk-N3G43SCQ.mjs → chunk-GPF34WXV.mjs} +2560 -324
  8. package/dist/chunk-GPF34WXV.mjs.map +1 -0
  9. package/dist/{chunk-WQMKKUSD.mjs → chunk-VASK54KT.mjs} +2 -2
  10. package/dist/{chunk-3JNVGW62.mjs → chunk-WGS33EWH.mjs} +2 -2
  11. package/dist/{chunk-RJ4D4QWK.mjs → chunk-XNU5X7EV.mjs} +3 -3
  12. package/dist/{chunk-SIVERPF5.mjs → chunk-YQ2FJGBT.mjs} +172 -18
  13. package/dist/chunk-YQ2FJGBT.mjs.map +1 -0
  14. package/dist/{chunk-YUFYTDRH.mjs → chunk-YZDEZ6UI.mjs} +3 -3
  15. package/dist/{chunk-SAE2H2LN.mjs → chunk-ZSFVX6FM.mjs} +3 -3
  16. package/dist/cli.mjs +4 -4
  17. package/dist/{http-A54ZBBAY.mjs → http-C2FBHNZG.mjs} +9 -9
  18. package/dist/{import-EA3TB3S2.mjs → import-ED6JCPSJ.mjs} +5 -5
  19. package/dist/index.mjs +9 -9
  20. package/dist/{mcp-DJDOWHH3.mjs → mcp-5JIBER4M.mjs} +5 -5
  21. package/dist/semantic-index-worker.mjs +1 -1
  22. package/dist/{src-EKPMJRG6.mjs → src-WBNM42SL.mjs} +21 -3
  23. package/dist/{stream-import-FQFNRQ2B.mjs → stream-import-37U3SROO.mjs} +4 -4
  24. package/dist/{worker-runtime-UH2OBO3T.mjs → worker-runtime-6DGYL4TF.mjs} +2 -2
  25. package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-NL1sTF6i.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-CCz0Syxo.js} +5 -5
  26. package/dist-web/assets/{MessageExportModal-B60rvfCh.js → MessageExportModal-Dd6R-cX_.js} +1 -1
  27. package/dist-web/assets/electron-D9vE5t3H.js +1 -0
  28. package/dist-web/assets/electron-DGxVMsvC.js +1 -0
  29. package/dist-web/assets/{electron-BRUg9LnY.js → electron-DjminAKK.js} +1 -1
  30. package/dist-web/assets/{fetch-DSN-QYZE.js → fetch-B_kLRm6-.js} +1 -1
  31. package/dist-web/assets/{fetch-DLAp7h55.js → fetch-CURbMNJV.js} +1 -1
  32. package/dist-web/assets/fetch-Cle6QKmL.js +3 -0
  33. package/dist-web/assets/{fetch-BIpjJHxj.js → fetch-DFCYOQe5.js} +1 -1
  34. package/dist-web/assets/{fetch-DNSaxRnL.js → fetch-DOhCQ5J8.js} +1 -1
  35. package/dist-web/assets/{fetch-DE8gj5Ke.js → fetch-DV8A1dGB.js} +1 -1
  36. package/dist-web/assets/{fetch-C-m3IysH.js → fetch-Wad5mWVH.js} +1 -1
  37. package/dist-web/assets/{fetch-BRsMdFcn.js → fetch-r83wdzHy.js} +1 -1
  38. package/dist-web/assets/{fetch-Cma-mZjd.js → fetch-srCJzcWc.js} +1 -1
  39. package/dist-web/assets/{fetch-woAa3H2L.js → fetch-uM3erGZm.js} +1 -1
  40. package/dist-web/assets/index-7E5GSvR2.css +1 -0
  41. package/dist-web/assets/index-BCRHSc1k.js +173 -0
  42. package/dist-web/assets/{index-r_zHR2t9.js → index-BIvLzdwg.js} +1 -1
  43. package/dist-web/assets/{index-o6veAyTB.js → index-BpszRZ8V.js} +3 -3
  44. package/dist-web/assets/index-D5UgZUpS.js +12 -0
  45. package/dist-web/assets/{index-iwqJDVMJ.js → index-hOsKRsp6.js} +2 -2
  46. package/dist-web/assets/{index-B9I-Y3fR.js → index-tkbEq8av.js} +1 -1
  47. package/dist-web/assets/web-D27K6zSX.js +1 -0
  48. package/dist-web/index.html +2 -2
  49. package/package.json +1 -1
  50. package/dist/chunk-3FUF3PEY.mjs.map +0 -1
  51. package/dist/chunk-N3G43SCQ.mjs.map +0 -1
  52. package/dist/chunk-SIVERPF5.mjs.map +0 -1
  53. package/dist-web/assets/electron-2m4Vdk2z.js +0 -1
  54. package/dist-web/assets/electron-CRSL7qPM.js +0 -1
  55. package/dist-web/assets/fetch-DOEbyLSD.js +0 -3
  56. package/dist-web/assets/index-B3mDjury.js +0 -11
  57. package/dist-web/assets/index-GAU7LI1r.js +0 -173
  58. package/dist-web/assets/index-YmzTgkb2.css +0 -1
  59. package/dist-web/assets/web-C2UtGskd.js +0 -1
  60. /package/dist/{chat-command-B7POB3C3.mjs.map → chat-command-7WL5NMZ6.mjs.map} +0 -0
  61. /package/dist/{chunk-WQMKKUSD.mjs.map → chunk-VASK54KT.mjs.map} +0 -0
  62. /package/dist/{chunk-3JNVGW62.mjs.map → chunk-WGS33EWH.mjs.map} +0 -0
  63. /package/dist/{chunk-RJ4D4QWK.mjs.map → chunk-XNU5X7EV.mjs.map} +0 -0
  64. /package/dist/{chunk-YUFYTDRH.mjs.map → chunk-YZDEZ6UI.mjs.map} +0 -0
  65. /package/dist/{chunk-SAE2H2LN.mjs.map → chunk-ZSFVX6FM.mjs.map} +0 -0
  66. /package/dist/{http-A54ZBBAY.mjs.map → http-C2FBHNZG.mjs.map} +0 -0
  67. /package/dist/{import-EA3TB3S2.mjs.map → import-ED6JCPSJ.mjs.map} +0 -0
  68. /package/dist/{mcp-DJDOWHH3.mjs.map → mcp-5JIBER4M.mjs.map} +0 -0
  69. /package/dist/{src-EKPMJRG6.mjs.map → src-WBNM42SL.mjs.map} +0 -0
  70. /package/dist/{stream-import-FQFNRQ2B.mjs.map → stream-import-37U3SROO.mjs.map} +0 -0
  71. /package/dist/{worker-runtime-UH2OBO3T.mjs.map → worker-runtime-6DGYL4TF.mjs.map} +0 -0
@@ -51,6 +51,8 @@ import {
51
51
  deriveParentId,
52
52
  detectConflictsInMessages,
53
53
  estimateTokens,
54
+ extractErrorInfo,
55
+ extractErrorStack,
54
56
  extractFtsKeywords,
55
57
  formatEvidenceMessages,
56
58
  generateMessageKey,
@@ -82,7 +84,7 @@ import {
82
84
  vecTableName,
83
85
  vecTableSchema,
84
86
  writeConfigField
85
- } from "./chunk-I7BHOZPX.mjs";
87
+ } from "./chunk-55WR6WKW.mjs";
86
88
  import {
87
89
  __commonJS,
88
90
  __export,
@@ -97,8 +99,8 @@ var require_Utf8Stream = __commonJS({
97
99
  var { Transform } = __require("stream");
98
100
  var { StringDecoder } = __require("string_decoder");
99
101
  var Utf8Stream = class extends Transform {
100
- constructor(options) {
101
- super(Object.assign({}, options, { writableObjectMode: false }));
102
+ constructor(options2) {
103
+ super(Object.assign({}, options2, { writableObjectMode: false }));
102
104
  this._buffer = "";
103
105
  }
104
106
  _transform(chunk, encoding, callback) {
@@ -178,22 +180,22 @@ var require_Parser = __commonJS({
178
180
  var fromHex = (s) => String.fromCharCode(parseInt(s.slice(2), 16));
179
181
  var codes = { b: "\b", f: "\f", n: "\n", r: "\r", t: " ", '"': '"', "\\": "\\", "/": "/" };
180
182
  var Parser = class _Parser extends Utf8Stream {
181
- static make(options) {
182
- return new _Parser(options);
183
+ static make(options2) {
184
+ return new _Parser(options2);
183
185
  }
184
- constructor(options) {
185
- super(Object.assign({}, options, { readableObjectMode: true }));
186
+ constructor(options2) {
187
+ super(Object.assign({}, options2, { readableObjectMode: true }));
186
188
  this._packKeys = this._packStrings = this._packNumbers = this._streamKeys = this._streamStrings = this._streamNumbers = true;
187
- if (options) {
188
- "packValues" in options && (this._packKeys = this._packStrings = this._packNumbers = options.packValues);
189
- "packKeys" in options && (this._packKeys = options.packKeys);
190
- "packStrings" in options && (this._packStrings = options.packStrings);
191
- "packNumbers" in options && (this._packNumbers = options.packNumbers);
192
- "streamValues" in options && (this._streamKeys = this._streamStrings = this._streamNumbers = options.streamValues);
193
- "streamKeys" in options && (this._streamKeys = options.streamKeys);
194
- "streamStrings" in options && (this._streamStrings = options.streamStrings);
195
- "streamNumbers" in options && (this._streamNumbers = options.streamNumbers);
196
- this._jsonStreaming = options.jsonStreaming;
189
+ if (options2) {
190
+ "packValues" in options2 && (this._packKeys = this._packStrings = this._packNumbers = options2.packValues);
191
+ "packKeys" in options2 && (this._packKeys = options2.packKeys);
192
+ "packStrings" in options2 && (this._packStrings = options2.packStrings);
193
+ "packNumbers" in options2 && (this._packNumbers = options2.packNumbers);
194
+ "streamValues" in options2 && (this._streamKeys = this._streamStrings = this._streamNumbers = options2.streamValues);
195
+ "streamKeys" in options2 && (this._streamKeys = options2.streamKeys);
196
+ "streamStrings" in options2 && (this._streamStrings = options2.streamStrings);
197
+ "streamNumbers" in options2 && (this._streamNumbers = options2.streamNumbers);
198
+ this._jsonStreaming = options2.jsonStreaming;
197
199
  }
198
200
  !this._packKeys && (this._streamKeys = true);
199
201
  !this._packStrings && (this._streamStrings = true);
@@ -683,7 +685,7 @@ var require_stream_json = __commonJS({
683
685
  "use strict";
684
686
  var Parser = require_Parser();
685
687
  var emit = require_emit();
686
- var make = (options) => emit(new Parser(options));
688
+ var make = (options2) => emit(new Parser(options2));
687
689
  make.Parser = Parser;
688
690
  make.parser = Parser.parser;
689
691
  module.exports = make;
@@ -698,8 +700,8 @@ var require_FilterBase = __commonJS({
698
700
  var FilterBase = class _FilterBase extends Transform {
699
701
  static stringFilter(string, separator) {
700
702
  return (stack) => {
701
- const path18 = stack.join(separator);
702
- return path18.length === string.length && path18 === string || path18.length > string.length && path18.substr(0, string.length) === string && path18.substr(string.length, separator.length) === separator;
703
+ const path24 = stack.join(separator);
704
+ return path24.length === string.length && path24 === string || path24.length > string.length && path24.substr(0, string.length) === string && path24.substr(string.length, separator.length) === separator;
703
705
  };
704
706
  }
705
707
  static regExpFilter(regExp, separator) {
@@ -708,11 +710,11 @@ var require_FilterBase = __commonJS({
708
710
  static arrayReplacement(array) {
709
711
  return () => array;
710
712
  }
711
- constructor(options) {
712
- super(Object.assign({}, options, { writableObjectMode: true, readableObjectMode: true }));
713
+ constructor(options2) {
714
+ super(Object.assign({}, options2, { writableObjectMode: true, readableObjectMode: true }));
713
715
  this._transform = this._check;
714
716
  this._stack = [];
715
- const filter = options && options.filter, separator = options && options.pathSeparator || ".";
717
+ const filter = options2 && options2.filter, separator = options2 && options2.pathSeparator || ".";
716
718
  if (typeof filter == "string") {
717
719
  this._filter = _FilterBase.stringFilter(filter, separator);
718
720
  } else if (typeof filter == "function") {
@@ -720,19 +722,19 @@ var require_FilterBase = __commonJS({
720
722
  } else if (filter instanceof RegExp) {
721
723
  this._filter = _FilterBase.regExpFilter(filter, separator);
722
724
  }
723
- const replacement = options && options.replacement;
725
+ const replacement = options2 && options2.replacement;
724
726
  if (typeof replacement == "function") {
725
727
  this._replacement = replacement;
726
728
  } else {
727
729
  this._replacement = _FilterBase.arrayReplacement(replacement || _FilterBase.defaultReplacement);
728
730
  }
729
- this._allowEmptyReplacement = options && options.allowEmptyReplacement;
731
+ this._allowEmptyReplacement = options2 && options2.allowEmptyReplacement;
730
732
  this._streamKeys = true;
731
- if (options) {
732
- "streamValues" in options && (this._streamKeys = options.streamValues);
733
- "streamKeys" in options && (this._streamKeys = options.streamKeys);
733
+ if (options2) {
734
+ "streamValues" in options2 && (this._streamKeys = options2.streamValues);
735
+ "streamKeys" in options2 && (this._streamKeys = options2.streamKeys);
734
736
  }
735
- this._once = options && options.once;
737
+ this._once = options2 && options2.once;
736
738
  this._previousToken = "";
737
739
  }
738
740
  _check(chunk, _, callback) {
@@ -950,8 +952,8 @@ var require_stream_chain = __commonJS({
950
952
  var isWritableNodeStream = (obj) => obj && typeof obj.write === "function" && typeof obj.on === "function" && (!obj._readableState || (typeof obj._writableState === "object" ? obj._writableState.writable : null) !== false);
951
953
  var isDuplexNodeStream = (obj) => obj && typeof obj.pipe === "function" && obj._readableState && typeof obj.on === "function" && typeof obj.write === "function";
952
954
  var Chain = class _Chain extends Duplex {
953
- constructor(fns, options) {
954
- super(options || { writableObjectMode: true, readableObjectMode: true });
955
+ constructor(fns, options2) {
956
+ super(options2 || { writableObjectMode: true, readableObjectMode: true });
955
957
  if (!(fns instanceof Array) || !fns.length) {
956
958
  throw Error("Chain's argument should be a non-empty array.");
957
959
  }
@@ -978,7 +980,7 @@ var require_stream_chain = __commonJS({
978
980
  this.resume();
979
981
  this.output.on("finish", () => this.push(null));
980
982
  }
981
- if (!options || !options.skipEvents) {
983
+ if (!options2 || !options2.skipEvents) {
982
984
  this.streams.forEach((stream) => stream.on("error", (error) => this.emit("error", error)));
983
985
  }
984
986
  }
@@ -1001,8 +1003,8 @@ var require_stream_chain = __commonJS({
1001
1003
  _read() {
1002
1004
  this.output.resume();
1003
1005
  }
1004
- static make(fns, options) {
1005
- return new _Chain(fns, options);
1006
+ static make(fns, options2) {
1007
+ return new _Chain(fns, options2);
1006
1008
  }
1007
1009
  static sanitize(result, stream) {
1008
1010
  if (_Chain.isFinal(result)) {
@@ -1041,9 +1043,9 @@ var require_stream_chain = __commonJS({
1041
1043
  var require_withParser = __commonJS({
1042
1044
  "../../node_modules/stream-json/utils/withParser.js"(exports, module) {
1043
1045
  "use strict";
1044
- var { chain: chain8 } = require_stream_chain();
1046
+ var { chain: chain10 } = require_stream_chain();
1045
1047
  var Parser = require_Parser();
1046
- var withParser = (fn, options) => chain8([new Parser(options), fn(options)], Object.assign({}, options, { writableObjectMode: false, readableObjectMode: true }));
1048
+ var withParser = (fn, options2) => chain10([new Parser(options2), fn(options2)], Object.assign({}, options2, { writableObjectMode: false, readableObjectMode: true }));
1047
1049
  module.exports = withParser;
1048
1050
  }
1049
1051
  });
@@ -1055,11 +1057,11 @@ var require_Pick = __commonJS({
1055
1057
  var FilterBase = require_FilterBase();
1056
1058
  var withParser = require_withParser();
1057
1059
  var Pick = class _Pick extends FilterBase {
1058
- static make(options) {
1059
- return new _Pick(options);
1060
+ static make(options2) {
1061
+ return new _Pick(options2);
1060
1062
  }
1061
- static withParser(options) {
1062
- return withParser(_Pick.make, options);
1063
+ static withParser(options2) {
1064
+ return withParser(_Pick.make, options2);
1063
1065
  }
1064
1066
  _checkChunk(chunk) {
1065
1067
  switch (chunk.name) {
@@ -1122,20 +1124,20 @@ var require_Assembler = __commonJS({
1122
1124
  this.key = null;
1123
1125
  };
1124
1126
  var Assembler = class _Assembler extends EventEmitter {
1125
- static connectTo(stream, options) {
1126
- return new _Assembler(options).connectTo(stream);
1127
+ static connectTo(stream, options2) {
1128
+ return new _Assembler(options2).connectTo(stream);
1127
1129
  }
1128
- constructor(options) {
1130
+ constructor(options2) {
1129
1131
  super();
1130
1132
  this.stack = [];
1131
1133
  this.current = this.key = null;
1132
1134
  this.done = true;
1133
- if (options) {
1134
- this.reviver = typeof options.reviver == "function" && options.reviver;
1135
+ if (options2) {
1136
+ this.reviver = typeof options2.reviver == "function" && options2.reviver;
1135
1137
  if (this.reviver) {
1136
1138
  this.stringValue = this._saveValue = this._saveValueWithReviver;
1137
1139
  }
1138
- if (options.numberAsString) {
1140
+ if (options2.numberAsString) {
1139
1141
  this.numberValue = this.stringValue;
1140
1142
  }
1141
1143
  }
@@ -1153,12 +1155,12 @@ var require_Assembler = __commonJS({
1153
1155
  return (this.stack.length >> 1) + (this.done ? 0 : 1);
1154
1156
  }
1155
1157
  get path() {
1156
- const path18 = [];
1158
+ const path24 = [];
1157
1159
  for (let i = 0; i < this.stack.length; i += 2) {
1158
1160
  const key = this.stack[i + 1];
1159
- path18.push(key === null ? this.stack[i].length : key);
1161
+ path24.push(key === null ? this.stack[i].length : key);
1160
1162
  }
1161
- return path18;
1163
+ return path24;
1162
1164
  }
1163
1165
  dropToLevel(level) {
1164
1166
  if (level < this.depth) {
@@ -1272,17 +1274,17 @@ var require_StreamBase = __commonJS({
1272
1274
  }
1273
1275
  };
1274
1276
  var StreamBase = class extends Transform {
1275
- constructor(options) {
1276
- super(Object.assign({}, options, { writableObjectMode: true, readableObjectMode: true }));
1277
- if (options) {
1278
- this.objectFilter = options.objectFilter;
1279
- this.includeUndecided = options.includeUndecided;
1277
+ constructor(options2) {
1278
+ super(Object.assign({}, options2, { writableObjectMode: true, readableObjectMode: true }));
1279
+ if (options2) {
1280
+ this.objectFilter = options2.objectFilter;
1281
+ this.includeUndecided = options2.includeUndecided;
1280
1282
  }
1281
1283
  if (typeof this.objectFilter != "function") {
1282
1284
  this._filter = this._transform;
1283
1285
  }
1284
1286
  this._transform = this._wait || this._filter;
1285
- this._assembler = new Assembler(options);
1287
+ this._assembler = new Assembler(options2);
1286
1288
  }
1287
1289
  _transform(chunk, encoding, callback) {
1288
1290
  if (this._assembler[chunk.name]) {
@@ -1354,14 +1356,14 @@ var require_StreamValues = __commonJS({
1354
1356
  var StreamBase = require_StreamBase();
1355
1357
  var withParser = require_withParser();
1356
1358
  var StreamValues = class _StreamValues extends StreamBase {
1357
- static make(options) {
1358
- return new _StreamValues(options);
1359
+ static make(options2) {
1360
+ return new _StreamValues(options2);
1359
1361
  }
1360
- static withParser(options) {
1361
- return withParser(_StreamValues.make, Object.assign({}, options, { jsonStreaming: true }));
1362
+ static withParser(options2) {
1363
+ return withParser(_StreamValues.make, Object.assign({}, options2, { jsonStreaming: true }));
1362
1364
  }
1363
- constructor(options) {
1364
- super(options);
1365
+ constructor(options2) {
1366
+ super(options2);
1365
1367
  this._counter = 0;
1366
1368
  this._level = 0;
1367
1369
  }
@@ -1380,6 +1382,1353 @@ var require_StreamValues = __commonJS({
1380
1382
  }
1381
1383
  });
1382
1384
 
1385
+ // ../../node_modules/pend/index.js
1386
+ var require_pend = __commonJS({
1387
+ "../../node_modules/pend/index.js"(exports, module) {
1388
+ "use strict";
1389
+ module.exports = Pend;
1390
+ function Pend() {
1391
+ this.pending = 0;
1392
+ this.max = Infinity;
1393
+ this.listeners = [];
1394
+ this.waiting = [];
1395
+ this.error = null;
1396
+ }
1397
+ Pend.prototype.go = function(fn) {
1398
+ if (this.pending < this.max) {
1399
+ pendGo(this, fn);
1400
+ } else {
1401
+ this.waiting.push(fn);
1402
+ }
1403
+ };
1404
+ Pend.prototype.wait = function(cb) {
1405
+ if (this.pending === 0) {
1406
+ cb(this.error);
1407
+ } else {
1408
+ this.listeners.push(cb);
1409
+ }
1410
+ };
1411
+ Pend.prototype.hold = function() {
1412
+ return pendHold(this);
1413
+ };
1414
+ function pendHold(self) {
1415
+ self.pending += 1;
1416
+ var called = false;
1417
+ return onCb;
1418
+ function onCb(err) {
1419
+ if (called) throw new Error("callback called twice");
1420
+ called = true;
1421
+ self.error = self.error || err;
1422
+ self.pending -= 1;
1423
+ if (self.waiting.length > 0 && self.pending < self.max) {
1424
+ pendGo(self, self.waiting.shift());
1425
+ } else if (self.pending === 0) {
1426
+ var listeners = self.listeners;
1427
+ self.listeners = [];
1428
+ listeners.forEach(cbListener);
1429
+ }
1430
+ }
1431
+ function cbListener(listener) {
1432
+ listener(self.error);
1433
+ }
1434
+ }
1435
+ function pendGo(self, fn) {
1436
+ fn(pendHold(self));
1437
+ }
1438
+ }
1439
+ });
1440
+
1441
+ // ../../packages/node-runtime/node_modules/yauzl/fd-slicer.js
1442
+ var require_fd_slicer = __commonJS({
1443
+ "../../packages/node-runtime/node_modules/yauzl/fd-slicer.js"(exports) {
1444
+ "use strict";
1445
+ var fs29 = __require("fs");
1446
+ var util = __require("util");
1447
+ var stream = __require("stream");
1448
+ var Readable = stream.Readable;
1449
+ var PassThrough = stream.PassThrough;
1450
+ var Pend = require_pend();
1451
+ var EventEmitter = __require("events").EventEmitter;
1452
+ exports.BufferSlicer = BufferSlicer;
1453
+ exports.FdSlicer = FdSlicer;
1454
+ util.inherits(FdSlicer, EventEmitter);
1455
+ function FdSlicer(fd) {
1456
+ EventEmitter.call(this);
1457
+ this.fd = fd;
1458
+ this.pend = new Pend();
1459
+ this.pend.max = 1;
1460
+ this.refCount = 0;
1461
+ }
1462
+ FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
1463
+ var self = this;
1464
+ self.pend.go(function(cb) {
1465
+ fs29.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
1466
+ cb();
1467
+ callback(err, bytesRead, buffer2);
1468
+ });
1469
+ });
1470
+ };
1471
+ FdSlicer.prototype.createReadStream = function(options2) {
1472
+ return new ReadStream(this, options2);
1473
+ };
1474
+ FdSlicer.prototype.ref = function() {
1475
+ this.refCount += 1;
1476
+ };
1477
+ FdSlicer.prototype.unref = function() {
1478
+ var self = this;
1479
+ self.refCount -= 1;
1480
+ if (self.refCount < 0) throw new Error("invalid unref");
1481
+ if (self.refCount > 0) return;
1482
+ fs29.close(self.fd, onCloseDone);
1483
+ function onCloseDone(err) {
1484
+ if (err) {
1485
+ self.emit("error", err);
1486
+ } else {
1487
+ self.emit("close");
1488
+ }
1489
+ }
1490
+ };
1491
+ util.inherits(ReadStream, Readable);
1492
+ function ReadStream(context, options2) {
1493
+ options2 = options2 || {};
1494
+ Readable.call(this, options2);
1495
+ this.context = context;
1496
+ this.context.ref();
1497
+ this.start = options2.start || 0;
1498
+ this.endOffset = options2.end;
1499
+ this.pos = this.start;
1500
+ }
1501
+ ReadStream.prototype._read = function(n) {
1502
+ var self = this;
1503
+ var toRead = Math.min(self._readableState.highWaterMark, n);
1504
+ if (self.endOffset != null) {
1505
+ toRead = Math.min(toRead, self.endOffset - self.pos);
1506
+ }
1507
+ if (toRead <= 0) {
1508
+ self.push(null);
1509
+ this._cleanup();
1510
+ return;
1511
+ }
1512
+ self.context.pend.go(function(cb) {
1513
+ var buffer = Buffer.allocUnsafe(toRead);
1514
+ fs29.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
1515
+ if (err) {
1516
+ self.destroy(err);
1517
+ } else if (bytesRead === 0) {
1518
+ self.push(null);
1519
+ self._cleanup();
1520
+ } else {
1521
+ self.pos += bytesRead;
1522
+ self.push(buffer.slice(0, bytesRead));
1523
+ }
1524
+ cb();
1525
+ });
1526
+ });
1527
+ };
1528
+ ReadStream.prototype._destroy = function(err, cb) {
1529
+ this._cleanup();
1530
+ cb(err);
1531
+ };
1532
+ ReadStream.prototype._cleanup = function() {
1533
+ if (this.context != null) {
1534
+ this.context.unref();
1535
+ this.context = null;
1536
+ }
1537
+ };
1538
+ util.inherits(BufferSlicer, EventEmitter);
1539
+ function BufferSlicer(buffer) {
1540
+ EventEmitter.call(this);
1541
+ this.refCount = 0;
1542
+ this.buffer = buffer;
1543
+ }
1544
+ BufferSlicer.prototype.read = function(buffer, offset, length, position, callback) {
1545
+ if (!(0 <= offset && offset <= buffer.length)) throw new RangeError("offset outside buffer: 0 <= " + offset + " <= " + buffer.length);
1546
+ if (position < 0) throw new RangeError("position is negative: " + position);
1547
+ if (offset + length > buffer.length) {
1548
+ length = buffer.length - offset;
1549
+ }
1550
+ if (position + length > this.buffer.length) {
1551
+ length = this.buffer.length - position;
1552
+ }
1553
+ if (length <= 0) {
1554
+ setImmediate(function() {
1555
+ callback(null, 0);
1556
+ });
1557
+ return;
1558
+ }
1559
+ this.buffer.copy(buffer, offset, position, position + length);
1560
+ setImmediate(function() {
1561
+ callback(null, length);
1562
+ });
1563
+ };
1564
+ BufferSlicer.prototype.createReadStream = function(options2) {
1565
+ options2 = options2 || {};
1566
+ var readStream = new PassThrough(options2);
1567
+ readStream.start = options2.start || 0;
1568
+ readStream.endOffset = options2.end;
1569
+ readStream.pos = readStream.endOffset || this.buffer.length;
1570
+ var entireSlice = this.buffer.slice(readStream.start, readStream.pos);
1571
+ var maxChunkSize = 65536;
1572
+ var offset = 0;
1573
+ while (true) {
1574
+ var nextOffset = offset + maxChunkSize;
1575
+ if (nextOffset >= entireSlice.length) {
1576
+ if (offset < entireSlice.length) {
1577
+ readStream.write(entireSlice.slice(offset, entireSlice.length));
1578
+ }
1579
+ break;
1580
+ }
1581
+ readStream.write(entireSlice.slice(offset, nextOffset));
1582
+ offset = nextOffset;
1583
+ }
1584
+ readStream.end();
1585
+ return readStream;
1586
+ };
1587
+ BufferSlicer.prototype.ref = function() {
1588
+ this.refCount += 1;
1589
+ };
1590
+ BufferSlicer.prototype.unref = function() {
1591
+ this.refCount -= 1;
1592
+ if (this.refCount < 0) {
1593
+ throw new Error("invalid unref");
1594
+ }
1595
+ };
1596
+ }
1597
+ });
1598
+
1599
+ // ../../packages/node-runtime/node_modules/yauzl/crc32.js
1600
+ var require_crc32 = __commonJS({
1601
+ "../../packages/node-runtime/node_modules/yauzl/crc32.js"(exports, module) {
1602
+ "use strict";
1603
+ var CRC_TABLE = new Int32Array([
1604
+ 0,
1605
+ 1996959894,
1606
+ 3993919788,
1607
+ 2567524794,
1608
+ 124634137,
1609
+ 1886057615,
1610
+ 3915621685,
1611
+ 2657392035,
1612
+ 249268274,
1613
+ 2044508324,
1614
+ 3772115230,
1615
+ 2547177864,
1616
+ 162941995,
1617
+ 2125561021,
1618
+ 3887607047,
1619
+ 2428444049,
1620
+ 498536548,
1621
+ 1789927666,
1622
+ 4089016648,
1623
+ 2227061214,
1624
+ 450548861,
1625
+ 1843258603,
1626
+ 4107580753,
1627
+ 2211677639,
1628
+ 325883990,
1629
+ 1684777152,
1630
+ 4251122042,
1631
+ 2321926636,
1632
+ 335633487,
1633
+ 1661365465,
1634
+ 4195302755,
1635
+ 2366115317,
1636
+ 997073096,
1637
+ 1281953886,
1638
+ 3579855332,
1639
+ 2724688242,
1640
+ 1006888145,
1641
+ 1258607687,
1642
+ 3524101629,
1643
+ 2768942443,
1644
+ 901097722,
1645
+ 1119000684,
1646
+ 3686517206,
1647
+ 2898065728,
1648
+ 853044451,
1649
+ 1172266101,
1650
+ 3705015759,
1651
+ 2882616665,
1652
+ 651767980,
1653
+ 1373503546,
1654
+ 3369554304,
1655
+ 3218104598,
1656
+ 565507253,
1657
+ 1454621731,
1658
+ 3485111705,
1659
+ 3099436303,
1660
+ 671266974,
1661
+ 1594198024,
1662
+ 3322730930,
1663
+ 2970347812,
1664
+ 795835527,
1665
+ 1483230225,
1666
+ 3244367275,
1667
+ 3060149565,
1668
+ 1994146192,
1669
+ 31158534,
1670
+ 2563907772,
1671
+ 4023717930,
1672
+ 1907459465,
1673
+ 112637215,
1674
+ 2680153253,
1675
+ 3904427059,
1676
+ 2013776290,
1677
+ 251722036,
1678
+ 2517215374,
1679
+ 3775830040,
1680
+ 2137656763,
1681
+ 141376813,
1682
+ 2439277719,
1683
+ 3865271297,
1684
+ 1802195444,
1685
+ 476864866,
1686
+ 2238001368,
1687
+ 4066508878,
1688
+ 1812370925,
1689
+ 453092731,
1690
+ 2181625025,
1691
+ 4111451223,
1692
+ 1706088902,
1693
+ 314042704,
1694
+ 2344532202,
1695
+ 4240017532,
1696
+ 1658658271,
1697
+ 366619977,
1698
+ 2362670323,
1699
+ 4224994405,
1700
+ 1303535960,
1701
+ 984961486,
1702
+ 2747007092,
1703
+ 3569037538,
1704
+ 1256170817,
1705
+ 1037604311,
1706
+ 2765210733,
1707
+ 3554079995,
1708
+ 1131014506,
1709
+ 879679996,
1710
+ 2909243462,
1711
+ 3663771856,
1712
+ 1141124467,
1713
+ 855842277,
1714
+ 2852801631,
1715
+ 3708648649,
1716
+ 1342533948,
1717
+ 654459306,
1718
+ 3188396048,
1719
+ 3373015174,
1720
+ 1466479909,
1721
+ 544179635,
1722
+ 3110523913,
1723
+ 3462522015,
1724
+ 1591671054,
1725
+ 702138776,
1726
+ 2966460450,
1727
+ 3352799412,
1728
+ 1504918807,
1729
+ 783551873,
1730
+ 3082640443,
1731
+ 3233442989,
1732
+ 3988292384,
1733
+ 2596254646,
1734
+ 62317068,
1735
+ 1957810842,
1736
+ 3939845945,
1737
+ 2647816111,
1738
+ 81470997,
1739
+ 1943803523,
1740
+ 3814918930,
1741
+ 2489596804,
1742
+ 225274430,
1743
+ 2053790376,
1744
+ 3826175755,
1745
+ 2466906013,
1746
+ 167816743,
1747
+ 2097651377,
1748
+ 4027552580,
1749
+ 2265490386,
1750
+ 503444072,
1751
+ 1762050814,
1752
+ 4150417245,
1753
+ 2154129355,
1754
+ 426522225,
1755
+ 1852507879,
1756
+ 4275313526,
1757
+ 2312317920,
1758
+ 282753626,
1759
+ 1742555852,
1760
+ 4189708143,
1761
+ 2394877945,
1762
+ 397917763,
1763
+ 1622183637,
1764
+ 3604390888,
1765
+ 2714866558,
1766
+ 953729732,
1767
+ 1340076626,
1768
+ 3518719985,
1769
+ 2797360999,
1770
+ 1068828381,
1771
+ 1219638859,
1772
+ 3624741850,
1773
+ 2936675148,
1774
+ 906185462,
1775
+ 1090812512,
1776
+ 3747672003,
1777
+ 2825379669,
1778
+ 829329135,
1779
+ 1181335161,
1780
+ 3412177804,
1781
+ 3160834842,
1782
+ 628085408,
1783
+ 1382605366,
1784
+ 3423369109,
1785
+ 3138078467,
1786
+ 570562233,
1787
+ 1426400815,
1788
+ 3317316542,
1789
+ 2998733608,
1790
+ 733239954,
1791
+ 1555261956,
1792
+ 3268935591,
1793
+ 3050360625,
1794
+ 752459403,
1795
+ 1541320221,
1796
+ 2607071920,
1797
+ 3965973030,
1798
+ 1969922972,
1799
+ 40735498,
1800
+ 2617837225,
1801
+ 3943577151,
1802
+ 1913087877,
1803
+ 83908371,
1804
+ 2512341634,
1805
+ 3803740692,
1806
+ 2075208622,
1807
+ 213261112,
1808
+ 2463272603,
1809
+ 3855990285,
1810
+ 2094854071,
1811
+ 198958881,
1812
+ 2262029012,
1813
+ 4057260610,
1814
+ 1759359992,
1815
+ 534414190,
1816
+ 2176718541,
1817
+ 4139329115,
1818
+ 1873836001,
1819
+ 414664567,
1820
+ 2282248934,
1821
+ 4279200368,
1822
+ 1711684554,
1823
+ 285281116,
1824
+ 2405801727,
1825
+ 4167216745,
1826
+ 1634467795,
1827
+ 376229701,
1828
+ 2685067896,
1829
+ 3608007406,
1830
+ 1308918612,
1831
+ 956543938,
1832
+ 2808555105,
1833
+ 3495958263,
1834
+ 1231636301,
1835
+ 1047427035,
1836
+ 2932959818,
1837
+ 3654703836,
1838
+ 1088359270,
1839
+ 936918e3,
1840
+ 2847714899,
1841
+ 3736837829,
1842
+ 1202900863,
1843
+ 817233897,
1844
+ 3183342108,
1845
+ 3401237130,
1846
+ 1404277552,
1847
+ 615818150,
1848
+ 3134207493,
1849
+ 3453421203,
1850
+ 1423857449,
1851
+ 601450431,
1852
+ 3009837614,
1853
+ 3294710456,
1854
+ 1567103746,
1855
+ 711928724,
1856
+ 3020668471,
1857
+ 3272380065,
1858
+ 1510334235,
1859
+ 755167117
1860
+ ]);
1861
+ function crc32(buf) {
1862
+ let crc = -1;
1863
+ for (let x of buf) {
1864
+ crc = CRC_TABLE[(crc ^ x) & 255] ^ crc >>> 8;
1865
+ }
1866
+ return (crc ^ -1) >>> 0;
1867
+ }
1868
+ module.exports = crc32;
1869
+ }
1870
+ });
1871
+
1872
+ // ../../packages/node-runtime/node_modules/yauzl/index.js
1873
+ var require_yauzl = __commonJS({
1874
+ "../../packages/node-runtime/node_modules/yauzl/index.js"(exports) {
1875
+ "use strict";
1876
+ var fs29 = __require("fs");
1877
+ var zlib = __require("zlib");
1878
+ var fd_slicer = require_fd_slicer();
1879
+ var util = __require("util");
1880
+ var EventEmitter = __require("events").EventEmitter;
1881
+ var Transform = __require("stream").Transform;
1882
+ var PassThrough = __require("stream").PassThrough;
1883
+ var Writable = __require("stream").Writable;
1884
+ var crc32 = typeof zlib.crc32 === "function" ? zlib.crc32 : require_crc32();
1885
+ exports.open = open;
1886
+ exports.fromFd = fromFd;
1887
+ exports.fromBuffer = fromBuffer;
1888
+ exports.fromRandomAccessReader = fromRandomAccessReader;
1889
+ exports.openPromise = openPromise2;
1890
+ exports.fromFdPromise = fromFdPromise;
1891
+ exports.fromBufferPromise = fromBufferPromise;
1892
+ exports.fromRandomAccessReaderPromise = fromRandomAccessReaderPromise;
1893
+ exports.dosDateTimeToDate = dosDateTimeToDate;
1894
+ exports.getFileNameLowLevel = getFileNameLowLevel;
1895
+ exports.validateFileName = validateFileName;
1896
+ exports.parseExtraFields = parseExtraFields;
1897
+ exports.ZipFile = ZipFile;
1898
+ exports.Entry = Entry;
1899
+ exports.LocalFileHeader = LocalFileHeader;
1900
+ exports.RandomAccessReader = RandomAccessReader;
1901
+ function openPromise2(path24, options2) {
1902
+ return new Promise((resolve3, reject) => {
1903
+ open(path24, { ...options2, lazyEntries: true }, function(err, zipfile) {
1904
+ if (err) return reject(err);
1905
+ resolve3(zipfile);
1906
+ });
1907
+ });
1908
+ }
1909
+ function fromFdPromise(fd, options2) {
1910
+ return new Promise((resolve3, reject) => {
1911
+ fromFd(fd, { ...options2, lazyEntries: true }, function(err, zipfile) {
1912
+ if (err) return reject(err);
1913
+ resolve3(zipfile);
1914
+ });
1915
+ });
1916
+ }
1917
+ function fromBufferPromise(buffer, options2) {
1918
+ return new Promise((resolve3, reject) => {
1919
+ fromBuffer(buffer, { ...options2, lazyEntries: true }, function(err, zipfile) {
1920
+ if (err) return reject(err);
1921
+ resolve3(zipfile);
1922
+ });
1923
+ });
1924
+ }
1925
+ function fromRandomAccessReaderPromise(reader, totalSize, options2) {
1926
+ return new Promise((resolve3, reject) => {
1927
+ fromRandomAccessReader(reader, totalSize, { ...options2, lazyEntries: true }, function(err, zipfile) {
1928
+ if (err) return reject(err);
1929
+ resolve3(zipfile);
1930
+ });
1931
+ });
1932
+ }
1933
+ function open(path24, options2, callback) {
1934
+ if (typeof options2 === "function") {
1935
+ callback = options2;
1936
+ options2 = null;
1937
+ }
1938
+ if (options2 == null) options2 = {};
1939
+ if (options2.autoClose == null) options2.autoClose = true;
1940
+ if (options2.lazyEntries == null) options2.lazyEntries = false;
1941
+ if (options2.decodeStrings == null) options2.decodeStrings = true;
1942
+ if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
1943
+ if (options2.strictFileNames == null) options2.strictFileNames = false;
1944
+ if (callback == null) callback = defaultCallback;
1945
+ fs29.open(path24, "r", function(err, fd) {
1946
+ if (err) return callback(err);
1947
+ fromFd(fd, options2, function(err2, zipfile) {
1948
+ if (err2) fs29.close(fd, defaultCallback);
1949
+ callback(err2, zipfile);
1950
+ });
1951
+ });
1952
+ }
1953
+ function fromFd(fd, options2, callback) {
1954
+ if (typeof options2 === "function") {
1955
+ callback = options2;
1956
+ options2 = null;
1957
+ }
1958
+ if (options2 == null) options2 = {};
1959
+ if (options2.autoClose == null) options2.autoClose = false;
1960
+ if (options2.lazyEntries == null) options2.lazyEntries = false;
1961
+ if (options2.decodeStrings == null) options2.decodeStrings = true;
1962
+ if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
1963
+ if (options2.strictFileNames == null) options2.strictFileNames = false;
1964
+ if (callback == null) callback = defaultCallback;
1965
+ fs29.fstat(fd, function(err, stats) {
1966
+ if (err) return callback(err);
1967
+ var reader = new fd_slicer.FdSlicer(fd);
1968
+ fromRandomAccessReader(reader, stats.size, options2, callback);
1969
+ });
1970
+ }
1971
+ function fromBuffer(buffer, options2, callback) {
1972
+ if (typeof options2 === "function") {
1973
+ callback = options2;
1974
+ options2 = null;
1975
+ }
1976
+ if (options2 == null) options2 = {};
1977
+ options2.autoClose = false;
1978
+ if (options2.lazyEntries == null) options2.lazyEntries = false;
1979
+ if (options2.decodeStrings == null) options2.decodeStrings = true;
1980
+ if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
1981
+ if (options2.strictFileNames == null) options2.strictFileNames = false;
1982
+ var reader = new fd_slicer.BufferSlicer(buffer);
1983
+ fromRandomAccessReader(reader, buffer.length, options2, callback);
1984
+ }
1985
+ function fromRandomAccessReader(reader, totalSize, options2, callback) {
1986
+ if (typeof options2 === "function") {
1987
+ callback = options2;
1988
+ options2 = null;
1989
+ }
1990
+ if (options2 == null) options2 = {};
1991
+ if (options2.autoClose == null) options2.autoClose = true;
1992
+ if (options2.lazyEntries == null) options2.lazyEntries = false;
1993
+ if (options2.decodeStrings == null) options2.decodeStrings = true;
1994
+ var decodeStrings = !!options2.decodeStrings;
1995
+ if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
1996
+ if (options2.strictFileNames == null) options2.strictFileNames = false;
1997
+ if (callback == null) callback = defaultCallback;
1998
+ if (typeof totalSize !== "number") throw new Error("expected totalSize parameter to be a number");
1999
+ if (totalSize > Number.MAX_SAFE_INTEGER) {
2000
+ throw new Error("zip file too large. only file sizes up to 2^52 are supported due to JavaScript's Number type being an IEEE 754 double.");
2001
+ }
2002
+ reader.ref();
2003
+ var eocdrWithoutCommentSize = 22;
2004
+ var zip64EocdlSize = 20;
2005
+ var maxCommentSize = 65535;
2006
+ var bufferSize = Math.min(zip64EocdlSize + eocdrWithoutCommentSize + maxCommentSize, totalSize);
2007
+ var buffer = newBuffer(bufferSize);
2008
+ var bufferReadStart = totalSize - buffer.length;
2009
+ readAndAssertNoEof(reader, buffer, 0, bufferSize, bufferReadStart, function(err) {
2010
+ if (err) return callback(err);
2011
+ for (var i = bufferSize - eocdrWithoutCommentSize; i >= 0; i -= 1) {
2012
+ if (buffer.readUInt32LE(i) !== 101010256) continue;
2013
+ var eocdrBuffer = buffer.subarray(i);
2014
+ var diskNumber = eocdrBuffer.readUInt16LE(4);
2015
+ var entryCount = eocdrBuffer.readUInt16LE(10);
2016
+ var centralDirectoryOffset = eocdrBuffer.readUInt32LE(16);
2017
+ var commentLength = eocdrBuffer.readUInt16LE(20);
2018
+ var expectedCommentLength = eocdrBuffer.length - eocdrWithoutCommentSize;
2019
+ if (commentLength !== expectedCommentLength) {
2020
+ return callback(new Error("Invalid comment length. Expected: " + expectedCommentLength + ". Found: " + commentLength + ". Are there extra bytes at the end of the file? Or is the end of central dir signature `PK\u263A\u263B` in the comment?"));
2021
+ }
2022
+ var comment = decodeStrings ? decodeBuffer(eocdrBuffer.subarray(22), false) : eocdrBuffer.subarray(22);
2023
+ if (i - zip64EocdlSize >= 0 && buffer.readUInt32LE(i - zip64EocdlSize) === 117853008) {
2024
+ var zip64EocdlBuffer = buffer.subarray(i - zip64EocdlSize, i - zip64EocdlSize + zip64EocdlSize);
2025
+ var zip64EocdrOffset = readUInt64LE(zip64EocdlBuffer, 8);
2026
+ var zip64EocdrBuffer = newBuffer(56);
2027
+ return readAndAssertNoEof(reader, zip64EocdrBuffer, 0, zip64EocdrBuffer.length, zip64EocdrOffset, function(err2) {
2028
+ if (err2) return callback(err2);
2029
+ if (zip64EocdrBuffer.readUInt32LE(0) !== 101075792) {
2030
+ return callback(new Error("invalid zip64 end of central directory record signature"));
2031
+ }
2032
+ diskNumber = zip64EocdrBuffer.readUInt32LE(16);
2033
+ if (diskNumber !== 0) {
2034
+ return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber));
2035
+ }
2036
+ entryCount = readUInt64LE(zip64EocdrBuffer, 32);
2037
+ centralDirectoryOffset = readUInt64LE(zip64EocdrBuffer, 48);
2038
+ return callback(null, new ZipFile(reader, centralDirectoryOffset, totalSize, entryCount, comment, options2.autoClose, options2.lazyEntries, decodeStrings, options2.validateEntrySizes, options2.strictFileNames));
2039
+ });
2040
+ }
2041
+ if (diskNumber !== 0) {
2042
+ return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber));
2043
+ }
2044
+ return callback(null, new ZipFile(reader, centralDirectoryOffset, totalSize, entryCount, comment, options2.autoClose, options2.lazyEntries, decodeStrings, options2.validateEntrySizes, options2.strictFileNames));
2045
+ }
2046
+ callback(new Error("End of central directory record signature not found. Either not a zip file, or file is truncated."));
2047
+ });
2048
+ }
2049
+ util.inherits(ZipFile, EventEmitter);
2050
+ function ZipFile(reader, centralDirectoryOffset, fileSize, entryCount, comment, autoClose, lazyEntries, decodeStrings, validateEntrySizes, strictFileNames) {
2051
+ var self = this;
2052
+ EventEmitter.call(self);
2053
+ self.reader = reader;
2054
+ self.reader.on("error", function(err) {
2055
+ emitError(self, err);
2056
+ });
2057
+ self.reader.once("close", function() {
2058
+ self.emit("close");
2059
+ });
2060
+ self.readEntryCursor = centralDirectoryOffset;
2061
+ self.fileSize = fileSize;
2062
+ self.entryCount = entryCount;
2063
+ self.comment = comment;
2064
+ self.entriesRead = 0;
2065
+ self.autoClose = !!autoClose;
2066
+ self.lazyEntries = !!lazyEntries;
2067
+ self.decodeStrings = !!decodeStrings;
2068
+ self.validateEntrySizes = !!validateEntrySizes;
2069
+ self.strictFileNames = !!strictFileNames;
2070
+ self.isOpen = true;
2071
+ self.emittedError = false;
2072
+ self.hasEachEntryBeenCalled = false;
2073
+ if (!self.lazyEntries) self._readEntry();
2074
+ }
2075
+ ZipFile.prototype.close = function() {
2076
+ if (!this.isOpen) return;
2077
+ this.isOpen = false;
2078
+ this.reader.unref();
2079
+ };
2080
+ function emitErrorAndAutoClose(self, err) {
2081
+ if (self.autoClose) self.close();
2082
+ emitError(self, err);
2083
+ }
2084
+ function emitError(self, err) {
2085
+ if (self.emittedError) return;
2086
+ self.emittedError = true;
2087
+ self.emit("error", err);
2088
+ }
2089
+ ZipFile.prototype.readEntry = function() {
2090
+ if (!this.lazyEntries) throw new Error("readEntry() called without lazyEntries:true");
2091
+ this._readEntry();
2092
+ };
2093
+ ZipFile.prototype._readEntry = function() {
2094
+ var self = this;
2095
+ if (self.entryCount === self.entriesRead) {
2096
+ setImmediate(function() {
2097
+ if (self.autoClose) self.close();
2098
+ if (self.emittedError) return;
2099
+ self.emit("end");
2100
+ });
2101
+ return;
2102
+ }
2103
+ if (self.emittedError) return;
2104
+ var buffer = newBuffer(46);
2105
+ readAndAssertNoEof(self.reader, buffer, 0, buffer.length, self.readEntryCursor, function(err) {
2106
+ if (err) return emitErrorAndAutoClose(self, err);
2107
+ if (self.emittedError) return;
2108
+ var entry = new Entry();
2109
+ var signature = buffer.readUInt32LE(0);
2110
+ if (signature !== 33639248) return emitErrorAndAutoClose(self, new Error("invalid central directory file header signature: 0x" + signature.toString(16)));
2111
+ entry.versionMadeBy = buffer.readUInt16LE(4);
2112
+ entry.versionNeededToExtract = buffer.readUInt16LE(6);
2113
+ entry.generalPurposeBitFlag = buffer.readUInt16LE(8);
2114
+ entry.compressionMethod = buffer.readUInt16LE(10);
2115
+ entry.lastModFileTime = buffer.readUInt16LE(12);
2116
+ entry.lastModFileDate = buffer.readUInt16LE(14);
2117
+ entry.crc32 = buffer.readUInt32LE(16);
2118
+ entry.compressedSize = buffer.readUInt32LE(20);
2119
+ entry.uncompressedSize = buffer.readUInt32LE(24);
2120
+ entry.fileNameLength = buffer.readUInt16LE(28);
2121
+ entry.extraFieldLength = buffer.readUInt16LE(30);
2122
+ entry.fileCommentLength = buffer.readUInt16LE(32);
2123
+ entry.internalFileAttributes = buffer.readUInt16LE(36);
2124
+ entry.externalFileAttributes = buffer.readUInt32LE(38);
2125
+ entry.relativeOffsetOfLocalHeader = buffer.readUInt32LE(42);
2126
+ if (entry.generalPurposeBitFlag & 64) return emitErrorAndAutoClose(self, new Error("strong encryption is not supported"));
2127
+ self.readEntryCursor += 46;
2128
+ buffer = newBuffer(entry.fileNameLength + entry.extraFieldLength + entry.fileCommentLength);
2129
+ readAndAssertNoEof(self.reader, buffer, 0, buffer.length, self.readEntryCursor, function(err2) {
2130
+ if (err2) return emitErrorAndAutoClose(self, err2);
2131
+ if (self.emittedError) return;
2132
+ entry.fileNameRaw = buffer.subarray(0, entry.fileNameLength);
2133
+ var fileCommentStart = entry.fileNameLength + entry.extraFieldLength;
2134
+ entry.extraFieldRaw = buffer.subarray(entry.fileNameLength, fileCommentStart);
2135
+ entry.fileCommentRaw = buffer.subarray(fileCommentStart, fileCommentStart + entry.fileCommentLength);
2136
+ try {
2137
+ entry.extraFields = parseExtraFields(entry.extraFieldRaw);
2138
+ } catch (err3) {
2139
+ return emitErrorAndAutoClose(self, err3);
2140
+ }
2141
+ if (self.decodeStrings) {
2142
+ var isUtf8 = (entry.generalPurposeBitFlag & 2048) !== 0;
2143
+ entry.fileComment = decodeBuffer(entry.fileCommentRaw, isUtf8);
2144
+ entry.fileName = getFileNameLowLevel(entry.generalPurposeBitFlag, entry.fileNameRaw, entry.extraFields, self.strictFileNames);
2145
+ var errorMessage = validateFileName(entry.fileName);
2146
+ if (errorMessage != null) return emitErrorAndAutoClose(self, new Error(errorMessage));
2147
+ } else {
2148
+ entry.fileComment = entry.fileCommentRaw;
2149
+ entry.fileName = entry.fileNameRaw;
2150
+ }
2151
+ entry.comment = entry.fileComment;
2152
+ self.readEntryCursor += buffer.length;
2153
+ self.entriesRead += 1;
2154
+ for (var i = 0; i < entry.extraFields.length; i++) {
2155
+ var extraField = entry.extraFields[i];
2156
+ if (extraField.id !== 1) continue;
2157
+ var zip64EiefBuffer = extraField.data;
2158
+ var index = 0;
2159
+ if (entry.uncompressedSize === 4294967295) {
2160
+ if (index + 8 > zip64EiefBuffer.length) {
2161
+ return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include uncompressed size"));
2162
+ }
2163
+ entry.uncompressedSize = readUInt64LE(zip64EiefBuffer, index);
2164
+ index += 8;
2165
+ }
2166
+ if (entry.compressedSize === 4294967295) {
2167
+ if (index + 8 > zip64EiefBuffer.length) {
2168
+ return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include compressed size"));
2169
+ }
2170
+ entry.compressedSize = readUInt64LE(zip64EiefBuffer, index);
2171
+ index += 8;
2172
+ }
2173
+ if (entry.relativeOffsetOfLocalHeader === 4294967295) {
2174
+ if (index + 8 > zip64EiefBuffer.length) {
2175
+ return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include relative header offset"));
2176
+ }
2177
+ entry.relativeOffsetOfLocalHeader = readUInt64LE(zip64EiefBuffer, index);
2178
+ index += 8;
2179
+ }
2180
+ break;
2181
+ }
2182
+ if (self.validateEntrySizes && entry.compressionMethod === 0) {
2183
+ var expectedCompressedSize = entry.uncompressedSize;
2184
+ if (entry.isEncrypted()) {
2185
+ expectedCompressedSize += 12;
2186
+ }
2187
+ if (entry.compressedSize !== expectedCompressedSize) {
2188
+ var msg = "compressed/uncompressed size mismatch for stored file: " + entry.compressedSize + " != " + entry.uncompressedSize;
2189
+ return emitErrorAndAutoClose(self, new Error(msg));
2190
+ }
2191
+ }
2192
+ self.emit("entry", entry);
2193
+ if (!self.lazyEntries) self._readEntry();
2194
+ });
2195
+ });
2196
+ };
2197
+ ZipFile.prototype.eachEntry = function() {
2198
+ const self = this;
2199
+ if (!self.lazyEntries) throw new Error("eachEntry() requires lazyEntries: true");
2200
+ if (self.hasEachEntryBeenCalled) throw new Error("eachEntry() must only be called once per ZipFile");
2201
+ self.hasEachEntryBeenCalled = true;
2202
+ let pendingResolveReject = null;
2203
+ self.on("entry", onEntry);
2204
+ self.on("end", onEnd);
2205
+ self.on("error", onError);
2206
+ function cleanup() {
2207
+ self.removeListener("entry", onEntry);
2208
+ self.removeListener("end", onEnd);
2209
+ self.removeListener("error", onError);
2210
+ if (self.autoClose) self.close();
2211
+ }
2212
+ function onEntry(entry) {
2213
+ let { resolve: resolve3 } = pendingResolveReject;
2214
+ pendingResolveReject = null;
2215
+ resolve3({ value: entry });
2216
+ }
2217
+ function onEnd() {
2218
+ let { resolve: resolve3 } = pendingResolveReject;
2219
+ pendingResolveReject = null;
2220
+ cleanup();
2221
+ resolve3({ done: true });
2222
+ }
2223
+ function onError(err) {
2224
+ let { reject } = pendingResolveReject;
2225
+ pendingResolveReject = null;
2226
+ cleanup();
2227
+ reject(err);
2228
+ }
2229
+ return {
2230
+ [Symbol.asyncIterator]() {
2231
+ return this;
2232
+ },
2233
+ next() {
2234
+ const promise = new Promise((resolve3, reject) => {
2235
+ if (pendingResolveReject != null) throw new Error("next() called before previous Promise was resolved.");
2236
+ pendingResolveReject = { resolve: resolve3, reject };
2237
+ });
2238
+ self.readEntry();
2239
+ return promise;
2240
+ },
2241
+ return(value) {
2242
+ cleanup();
2243
+ return Promise.resolve({ done: true, value });
2244
+ },
2245
+ throw(value) {
2246
+ cleanup();
2247
+ return Promise.reject(value);
2248
+ }
2249
+ };
2250
+ };
2251
+ ZipFile.prototype.openReadStream = function(entry, options2, callback) {
2252
+ var self = this;
2253
+ var relativeStart = 0;
2254
+ var relativeEnd = entry.compressedSize;
2255
+ if (callback == null) {
2256
+ callback = options2;
2257
+ options2 = null;
2258
+ }
2259
+ if (options2 == null) {
2260
+ options2 = {};
2261
+ } else {
2262
+ if (options2.decodeFileData === false) {
2263
+ if (options2.decrypt != null) {
2264
+ throw new Error("cannot use options.decrypt when options.decodeFileData === false");
2265
+ }
2266
+ if (options2.decompress != null) {
2267
+ throw new Error("cannot use options.decompress when options.decodeFileData === false");
2268
+ }
2269
+ } else {
2270
+ if (options2.decrypt != null) {
2271
+ if (!entry.isEncrypted()) {
2272
+ throw new Error("options.decrypt can only be specified for encrypted entries. See also option decodeFileData.");
2273
+ }
2274
+ if (options2.decrypt !== false) throw new Error("invalid options.decrypt value: " + options2.decrypt);
2275
+ if (entry.isCompressed()) {
2276
+ if (options2.decompress !== false) throw new Error("entry is encrypted and compressed, and options.decompress !== false. See also option decodeFileData.");
2277
+ }
2278
+ }
2279
+ if (options2.decompress != null) {
2280
+ if (!entry.isCompressed()) {
2281
+ throw new Error("options.decompress can only be specified for compressed entries. See also option decodeFileData.");
2282
+ }
2283
+ if (!(options2.decompress === false || options2.decompress === true)) {
2284
+ throw new Error("invalid options.decompress value: " + options2.decompress);
2285
+ }
2286
+ decompress = options2.decompress;
2287
+ }
2288
+ }
2289
+ if (options2.start != null) {
2290
+ relativeStart = options2.start;
2291
+ if (relativeStart < 0) throw new Error("options.start < 0");
2292
+ if (relativeStart > entry.compressedSize) throw new Error("options.start > entry.compressedSize");
2293
+ }
2294
+ if (options2.end != null) {
2295
+ relativeEnd = options2.end;
2296
+ if (relativeEnd < 0) throw new Error("options.end < 0");
2297
+ if (relativeEnd > entry.compressedSize) throw new Error("options.end > entry.compressedSize");
2298
+ if (relativeEnd < relativeStart) throw new Error("options.end < options.start");
2299
+ }
2300
+ }
2301
+ var rawMode = options2.decodeFileData === false || // Explicitly requested raw.
2302
+ (entry.compressionMethod === 0 || // Naturally without compression.
2303
+ entry.compressionMethod === 8 && options2.decompress === false) && (!entry.isEncrypted() || // Naturally without encryption.
2304
+ options2.decrypt === false);
2305
+ if (options2.start != null || options2.end != null) {
2306
+ if (!rawMode) throw new Error("start/end range require options.decodeFileData === false for non-trivial encoded entries.");
2307
+ }
2308
+ if (!self.isOpen) return callback(new Error("closed"));
2309
+ if (entry.isEncrypted() && !rawMode) {
2310
+ if (options2.decrypt !== false) return callback(new Error("entry is encrypted, and options.decodeFileData !== false"));
2311
+ }
2312
+ var decompress;
2313
+ if (rawMode) {
2314
+ decompress = false;
2315
+ } else if (entry.compressionMethod === 8) {
2316
+ decompress = options2.decodeFileData !== true;
2317
+ } else {
2318
+ return callback(new Error("unsupported compression method: " + entry.compressionMethod));
2319
+ }
2320
+ self.readLocalFileHeader(entry, { minimal: true }, function(err, localFileHeader) {
2321
+ if (err) return callback(err);
2322
+ self.openReadStreamLowLevel(
2323
+ localFileHeader.fileDataStart,
2324
+ entry.compressedSize,
2325
+ relativeStart,
2326
+ relativeEnd,
2327
+ decompress,
2328
+ entry.uncompressedSize,
2329
+ callback
2330
+ );
2331
+ });
2332
+ };
2333
+ ZipFile.prototype.openReadStreamLowLevel = function(fileDataStart, compressedSize, relativeStart, relativeEnd, decompress, uncompressedSize, callback) {
2334
+ var self = this;
2335
+ var fileDataEnd = fileDataStart + compressedSize;
2336
+ var readStream = self.reader.createReadStream({
2337
+ start: fileDataStart + relativeStart,
2338
+ end: fileDataStart + relativeEnd
2339
+ });
2340
+ var endpointStream = readStream;
2341
+ if (decompress) {
2342
+ var destroyed = false;
2343
+ var inflateFilter = zlib.createInflateRaw();
2344
+ readStream.on("error", function(err) {
2345
+ setImmediate(function() {
2346
+ if (!destroyed) inflateFilter.emit("error", err);
2347
+ });
2348
+ });
2349
+ readStream.pipe(inflateFilter);
2350
+ if (self.validateEntrySizes) {
2351
+ endpointStream = new AssertByteCountStream(uncompressedSize);
2352
+ inflateFilter.on("error", function(err) {
2353
+ setImmediate(function() {
2354
+ if (!destroyed) endpointStream.emit("error", err);
2355
+ });
2356
+ });
2357
+ inflateFilter.pipe(endpointStream);
2358
+ } else {
2359
+ endpointStream = inflateFilter;
2360
+ }
2361
+ installDestroyFn(endpointStream, function() {
2362
+ destroyed = true;
2363
+ if (inflateFilter !== endpointStream) inflateFilter.unpipe(endpointStream);
2364
+ readStream.unpipe(inflateFilter);
2365
+ readStream.destroy();
2366
+ });
2367
+ }
2368
+ callback(null, endpointStream);
2369
+ };
2370
+ ZipFile.prototype.readLocalFileHeader = function(entry, options2, callback) {
2371
+ var self = this;
2372
+ if (callback == null) {
2373
+ callback = options2;
2374
+ options2 = null;
2375
+ }
2376
+ if (options2 == null) options2 = {};
2377
+ self.reader.ref();
2378
+ var buffer = newBuffer(30);
2379
+ readAndAssertNoEof(self.reader, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader, function(err) {
2380
+ try {
2381
+ if (err) return callback(err);
2382
+ var signature = buffer.readUInt32LE(0);
2383
+ if (signature !== 67324752) {
2384
+ return callback(new Error("invalid local file header signature: 0x" + signature.toString(16)));
2385
+ }
2386
+ var fileNameLength = buffer.readUInt16LE(26);
2387
+ var extraFieldLength = buffer.readUInt16LE(28);
2388
+ var fileDataStart = entry.relativeOffsetOfLocalHeader + 30 + fileNameLength + extraFieldLength;
2389
+ if (fileDataStart + entry.compressedSize > self.fileSize) {
2390
+ return callback(new Error("file data overflows file bounds: " + fileDataStart + " + " + entry.compressedSize + " > " + self.fileSize));
2391
+ }
2392
+ if (options2.minimal) {
2393
+ return callback(null, { fileDataStart });
2394
+ }
2395
+ var localFileHeader = new LocalFileHeader();
2396
+ localFileHeader.fileDataStart = fileDataStart;
2397
+ localFileHeader.versionNeededToExtract = buffer.readUInt16LE(4);
2398
+ localFileHeader.generalPurposeBitFlag = buffer.readUInt16LE(6);
2399
+ localFileHeader.compressionMethod = buffer.readUInt16LE(8);
2400
+ localFileHeader.lastModFileTime = buffer.readUInt16LE(10);
2401
+ localFileHeader.lastModFileDate = buffer.readUInt16LE(12);
2402
+ localFileHeader.crc32 = buffer.readUInt32LE(14);
2403
+ localFileHeader.compressedSize = buffer.readUInt32LE(18);
2404
+ localFileHeader.uncompressedSize = buffer.readUInt32LE(22);
2405
+ localFileHeader.fileNameLength = fileNameLength;
2406
+ localFileHeader.extraFieldLength = extraFieldLength;
2407
+ buffer = newBuffer(fileNameLength + extraFieldLength);
2408
+ self.reader.ref();
2409
+ readAndAssertNoEof(self.reader, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader + 30, function(err2) {
2410
+ try {
2411
+ if (err2) return callback(err2);
2412
+ localFileHeader.fileName = buffer.subarray(0, fileNameLength);
2413
+ localFileHeader.extraField = buffer.subarray(fileNameLength);
2414
+ return callback(null, localFileHeader);
2415
+ } finally {
2416
+ self.reader.unref();
2417
+ }
2418
+ });
2419
+ } finally {
2420
+ self.reader.unref();
2421
+ }
2422
+ });
2423
+ };
2424
+ ZipFile.prototype.openReadStreamPromise = function(entry, options2) {
2425
+ return new Promise((resolve3, reject) => {
2426
+ this.openReadStream(entry, options2, function(err, readStream) {
2427
+ if (err) return reject(err);
2428
+ resolve3(readStream);
2429
+ });
2430
+ });
2431
+ };
2432
+ ZipFile.prototype.openReadStreamLowLevelPromise = function(fileDataStart, compressedSize, relativeStart, relativeEnd, decompress, uncompressedSize) {
2433
+ return new Promise((resolve3, reject) => {
2434
+ this.openReadStream(fileDataStart, compressedSize, relativeStart, relativeEnd, decompress, uncompressedSize, function(err, readStream) {
2435
+ if (err) return reject(err);
2436
+ resolve3(readStream);
2437
+ });
2438
+ });
2439
+ };
2440
+ ZipFile.prototype.readLocalFileHeaderPromise = function(entry, options2) {
2441
+ return new Promise((resolve3, reject) => {
2442
+ this.readLocalFileHeader(entry, options2, function(err, localFileHeader) {
2443
+ if (err) return reject(err);
2444
+ resolve3(localFileHeader);
2445
+ });
2446
+ });
2447
+ };
2448
+ function Entry() {
2449
+ }
2450
+ Entry.prototype.getLastModDate = function(options2) {
2451
+ if (options2 == null) options2 = {};
2452
+ if (!options2.forceDosFormat) {
2453
+ for (var i = 0; i < this.extraFields.length; i++) {
2454
+ var extraField = this.extraFields[i];
2455
+ if (extraField.id === 21589) {
2456
+ var data = extraField.data;
2457
+ if (data.length < 5) continue;
2458
+ var flags = data[0];
2459
+ var HAS_MTIME = 1;
2460
+ if (!(flags & HAS_MTIME)) continue;
2461
+ var posixTimestamp = data.readInt32LE(1);
2462
+ return new Date(posixTimestamp * 1e3);
2463
+ } else if (extraField.id === 10) {
2464
+ var data = extraField.data;
2465
+ if (data.length !== 32) continue;
2466
+ if (data.readUInt16LE(4) !== 1) continue;
2467
+ if (data.readUInt16LE(6) !== 24) continue;
2468
+ var hundredNanoSecondsSince1601 = data.readUInt32LE(8) + 4294967296 * data.readInt32LE(12);
2469
+ var millisecondsSince1970 = hundredNanoSecondsSince1601 / 1e4 - 116444736e5;
2470
+ return new Date(millisecondsSince1970);
2471
+ }
2472
+ }
2473
+ }
2474
+ return dosDateTimeToDate(this.lastModFileDate, this.lastModFileTime, options2.timezone);
2475
+ };
2476
+ Entry.prototype.canDecodeFileData = function() {
2477
+ return !this.isEncrypted() && (this.compressionMethod === 0 || this.compressionMethod === 8);
2478
+ };
2479
+ Entry.prototype.isEncrypted = function() {
2480
+ return (this.generalPurposeBitFlag & 1) !== 0;
2481
+ };
2482
+ Entry.prototype.isCompressed = function() {
2483
+ return this.compressionMethod === 8;
2484
+ };
2485
+ function LocalFileHeader() {
2486
+ }
2487
+ function dosDateTimeToDate(date, time, timezone) {
2488
+ var day = date & 31;
2489
+ var month = (date >> 5 & 15) - 1;
2490
+ var year = (date >> 9 & 127) + 1980;
2491
+ var millisecond = 0;
2492
+ var second = (time & 31) * 2;
2493
+ var minute = time >> 5 & 63;
2494
+ var hour = time >> 11 & 31;
2495
+ if (timezone == null || timezone === "local") {
2496
+ return new Date(year, month, day, hour, minute, second, millisecond);
2497
+ } else if (timezone === "UTC") {
2498
+ return new Date(Date.UTC(year, month, day, hour, minute, second, millisecond));
2499
+ } else {
2500
+ throw new Error("unrecognized options.timezone: " + options.timezone);
2501
+ }
2502
+ }
2503
+ function getFileNameLowLevel(generalPurposeBitFlag, fileNameBuffer, extraFields, strictFileNames) {
2504
+ var fileName = null;
2505
+ for (var i = 0; i < extraFields.length; i++) {
2506
+ var extraField = extraFields[i];
2507
+ if (extraField.id === 28789) {
2508
+ if (extraField.data.length < 6) {
2509
+ continue;
2510
+ }
2511
+ if (extraField.data.readUInt8(0) !== 1) {
2512
+ continue;
2513
+ }
2514
+ var oldNameCrc32 = extraField.data.readUInt32LE(1);
2515
+ if (crc32(fileNameBuffer) !== oldNameCrc32) {
2516
+ continue;
2517
+ }
2518
+ fileName = decodeBuffer(extraField.data.subarray(5), true);
2519
+ break;
2520
+ }
2521
+ }
2522
+ if (fileName == null) {
2523
+ var isUtf8 = (generalPurposeBitFlag & 2048) !== 0;
2524
+ fileName = decodeBuffer(fileNameBuffer, isUtf8);
2525
+ }
2526
+ if (!strictFileNames) {
2527
+ fileName = fileName.replace(/\\/g, "/");
2528
+ }
2529
+ return fileName;
2530
+ }
2531
+ function validateFileName(fileName) {
2532
+ if (fileName.indexOf("\\") !== -1) {
2533
+ return "invalid characters in fileName: " + fileName;
2534
+ }
2535
+ if (/^[a-zA-Z]:/.test(fileName) || /^\//.test(fileName)) {
2536
+ return "absolute path: " + fileName;
2537
+ }
2538
+ if (fileName.split("/").indexOf("..") !== -1) {
2539
+ return "invalid relative path: " + fileName;
2540
+ }
2541
+ return null;
2542
+ }
2543
+ function parseExtraFields(extraFieldBuffer) {
2544
+ var extraFields = [];
2545
+ var i = 0;
2546
+ while (i < extraFieldBuffer.length - 3) {
2547
+ var headerId = extraFieldBuffer.readUInt16LE(i + 0);
2548
+ var dataSize = extraFieldBuffer.readUInt16LE(i + 2);
2549
+ var dataStart = i + 4;
2550
+ var dataEnd = dataStart + dataSize;
2551
+ if (dataEnd > extraFieldBuffer.length) throw new Error("extra field length exceeds extra field buffer size");
2552
+ var dataBuffer = extraFieldBuffer.subarray(dataStart, dataEnd);
2553
+ extraFields.push({
2554
+ id: headerId,
2555
+ data: dataBuffer
2556
+ });
2557
+ i = dataEnd;
2558
+ }
2559
+ return extraFields;
2560
+ }
2561
+ function readAndAssertNoEof(reader, buffer, offset, length, position, callback) {
2562
+ if (length === 0) {
2563
+ return setImmediate(function() {
2564
+ callback(null, newBuffer(0));
2565
+ });
2566
+ }
2567
+ reader.read(buffer, offset, length, position, function(err, bytesRead) {
2568
+ if (err) return callback(err);
2569
+ if (bytesRead < length) {
2570
+ return callback(new Error("unexpected EOF"));
2571
+ }
2572
+ callback();
2573
+ });
2574
+ }
2575
+ util.inherits(AssertByteCountStream, Transform);
2576
+ function AssertByteCountStream(byteCount) {
2577
+ Transform.call(this);
2578
+ this.actualByteCount = 0;
2579
+ this.expectedByteCount = byteCount;
2580
+ }
2581
+ AssertByteCountStream.prototype._transform = function(chunk, encoding, cb) {
2582
+ this.actualByteCount += chunk.length;
2583
+ if (this.actualByteCount > this.expectedByteCount) {
2584
+ var msg = "too many bytes in the stream. expected " + this.expectedByteCount + ". got at least " + this.actualByteCount;
2585
+ return cb(new Error(msg));
2586
+ }
2587
+ cb(null, chunk);
2588
+ };
2589
+ AssertByteCountStream.prototype._flush = function(cb) {
2590
+ if (this.actualByteCount < this.expectedByteCount) {
2591
+ var msg = "not enough bytes in the stream. expected " + this.expectedByteCount + ". got only " + this.actualByteCount;
2592
+ return cb(new Error(msg));
2593
+ }
2594
+ cb();
2595
+ };
2596
+ util.inherits(RandomAccessReader, EventEmitter);
2597
+ function RandomAccessReader() {
2598
+ EventEmitter.call(this);
2599
+ this.refCount = 0;
2600
+ }
2601
+ RandomAccessReader.prototype.ref = function() {
2602
+ this.refCount += 1;
2603
+ };
2604
+ RandomAccessReader.prototype.unref = function() {
2605
+ var self = this;
2606
+ self.refCount -= 1;
2607
+ if (self.refCount > 0) return;
2608
+ if (self.refCount < 0) throw new Error("invalid unref");
2609
+ self.close(onCloseDone);
2610
+ function onCloseDone(err) {
2611
+ if (err) return self.emit("error", err);
2612
+ self.emit("close");
2613
+ }
2614
+ };
2615
+ RandomAccessReader.prototype.createReadStream = function(options2) {
2616
+ if (options2 == null) options2 = {};
2617
+ var start = options2.start;
2618
+ var end = options2.end;
2619
+ if (start === end) {
2620
+ var emptyStream = new PassThrough();
2621
+ setImmediate(function() {
2622
+ emptyStream.end();
2623
+ });
2624
+ return emptyStream;
2625
+ }
2626
+ var stream = this._readStreamForRange(start, end);
2627
+ var destroyed = false;
2628
+ var refUnrefFilter = new RefUnrefFilter(this);
2629
+ stream.on("error", function(err) {
2630
+ setImmediate(function() {
2631
+ if (!destroyed) refUnrefFilter.emit("error", err);
2632
+ });
2633
+ });
2634
+ installDestroyFn(refUnrefFilter, function() {
2635
+ stream.unpipe(refUnrefFilter);
2636
+ refUnrefFilter.unref();
2637
+ stream.destroy();
2638
+ });
2639
+ var byteCounter = new AssertByteCountStream(end - start);
2640
+ refUnrefFilter.on("error", function(err) {
2641
+ setImmediate(function() {
2642
+ if (!destroyed) byteCounter.emit("error", err);
2643
+ });
2644
+ });
2645
+ installDestroyFn(byteCounter, function() {
2646
+ destroyed = true;
2647
+ refUnrefFilter.unpipe(byteCounter);
2648
+ refUnrefFilter.destroy();
2649
+ });
2650
+ return stream.pipe(refUnrefFilter).pipe(byteCounter);
2651
+ };
2652
+ RandomAccessReader.prototype._readStreamForRange = function(start, end) {
2653
+ throw new Error("not implemented");
2654
+ };
2655
+ RandomAccessReader.prototype.read = function(buffer, offset, length, position, callback) {
2656
+ var readStream = this.createReadStream({ start: position, end: position + length });
2657
+ var writeStream = new Writable();
2658
+ var written = 0;
2659
+ writeStream._write = function(chunk, encoding, cb) {
2660
+ chunk.copy(buffer, offset + written, 0, chunk.length);
2661
+ written += chunk.length;
2662
+ cb();
2663
+ };
2664
+ writeStream.on("finish", callback);
2665
+ readStream.on("error", function(error) {
2666
+ callback(error);
2667
+ });
2668
+ readStream.pipe(writeStream);
2669
+ };
2670
+ RandomAccessReader.prototype.close = function(callback) {
2671
+ setImmediate(callback);
2672
+ };
2673
+ util.inherits(RefUnrefFilter, PassThrough);
2674
+ function RefUnrefFilter(context) {
2675
+ PassThrough.call(this);
2676
+ this.context = context;
2677
+ this.context.ref();
2678
+ this.unreffedYet = false;
2679
+ }
2680
+ RefUnrefFilter.prototype._flush = function(cb) {
2681
+ this.unref();
2682
+ cb();
2683
+ };
2684
+ RefUnrefFilter.prototype.unref = function(cb) {
2685
+ if (this.unreffedYet) return;
2686
+ this.unreffedYet = true;
2687
+ this.context.unref();
2688
+ };
2689
+ var cp437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
2690
+ function decodeBuffer(buffer, isUtf8) {
2691
+ if (isUtf8) {
2692
+ return buffer.toString("utf8");
2693
+ } else {
2694
+ var result = "";
2695
+ for (var i = 0; i < buffer.length; i++) {
2696
+ result += cp437[buffer[i]];
2697
+ }
2698
+ return result;
2699
+ }
2700
+ }
2701
+ function readUInt64LE(buffer, offset) {
2702
+ var lower32 = buffer.readUInt32LE(offset);
2703
+ var upper32 = buffer.readUInt32LE(offset + 4);
2704
+ return upper32 * 4294967296 + lower32;
2705
+ }
2706
+ var newBuffer;
2707
+ if (typeof Buffer.allocUnsafe === "function") {
2708
+ newBuffer = function(len) {
2709
+ return Buffer.allocUnsafe(len);
2710
+ };
2711
+ } else {
2712
+ newBuffer = function(len) {
2713
+ return new Buffer(len);
2714
+ };
2715
+ }
2716
+ function installDestroyFn(stream, fn) {
2717
+ if (typeof stream.destroy === "function") {
2718
+ stream._destroy = function(err, cb) {
2719
+ fn();
2720
+ if (cb != null) cb(err);
2721
+ };
2722
+ } else {
2723
+ stream.destroy = fn;
2724
+ }
2725
+ }
2726
+ function defaultCallback(err) {
2727
+ if (err) throw err;
2728
+ }
2729
+ }
2730
+ });
2731
+
1383
2732
  // ../../packages/node-runtime/src/import/write-parse-result.ts
1384
2733
  function writeParseResultToDb(db, meta, members, messages) {
1385
2734
  let messageCount = 0;
@@ -1592,8 +2941,8 @@ Errors: ${errorCount}
1592
2941
  }
1593
2942
 
1594
2943
  // ../../packages/parser/src/index.ts
1595
- import * as fs17 from "fs";
1596
- import * as path13 from "path";
2944
+ import * as fs18 from "fs";
2945
+ import * as path14 from "path";
1597
2946
 
1598
2947
  // ../../packages/parser/src/sniffer.ts
1599
2948
  import * as fs2 from "fs";
@@ -1647,9 +2996,9 @@ var FormatSniffer = class {
1647
2996
  sniff(filePath) {
1648
2997
  const ext = getExtension(filePath);
1649
2998
  const headContent = readFileHead(filePath);
1650
- for (const { feature: feature14 } of this.formats) {
1651
- if (this.matchFeature(feature14, ext, headContent, filePath)) {
1652
- return feature14;
2999
+ for (const { feature: feature15 } of this.formats) {
3000
+ if (this.matchFeature(feature15, ext, headContent, filePath)) {
3001
+ return feature15;
1653
3002
  }
1654
3003
  }
1655
3004
  return null;
@@ -1662,9 +3011,9 @@ var FormatSniffer = class {
1662
3011
  getParser(filePath) {
1663
3012
  const ext = getExtension(filePath);
1664
3013
  const headContent = readFileHead(filePath);
1665
- for (const { feature: feature14, parser: parser9 } of this.formats) {
1666
- if (this.matchFeature(feature14, ext, headContent, filePath)) {
1667
- return parser9;
3014
+ for (const { feature: feature15, parser: parser11 } of this.formats) {
3015
+ if (this.matchFeature(feature15, ext, headContent, filePath)) {
3016
+ return parser11;
1668
3017
  }
1669
3018
  }
1670
3019
  return null;
@@ -1679,9 +3028,9 @@ var FormatSniffer = class {
1679
3028
  const ext = getExtension(filePath);
1680
3029
  const headContent = readFileHead(filePath);
1681
3030
  const results = [];
1682
- for (const { feature: feature14 } of this.formats) {
1683
- if (this.matchFeature(feature14, ext, headContent, filePath)) {
1684
- results.push(feature14);
3031
+ for (const { feature: feature15 } of this.formats) {
3032
+ if (this.matchFeature(feature15, ext, headContent, filePath)) {
3033
+ results.push(feature15);
1685
3034
  }
1686
3035
  }
1687
3036
  return results;
@@ -1696,9 +3045,9 @@ var FormatSniffer = class {
1696
3045
  const ext = getExtension(filePath);
1697
3046
  const headContent = readFileHead(filePath);
1698
3047
  const results = [];
1699
- for (const { feature: feature14, parser: parser9 } of this.formats) {
1700
- if (this.matchFeature(feature14, ext, headContent, filePath)) {
1701
- results.push(parser9);
3048
+ for (const { feature: feature15, parser: parser11 } of this.formats) {
3049
+ if (this.matchFeature(feature15, ext, headContent, filePath)) {
3050
+ results.push(parser11);
1702
3051
  }
1703
3052
  }
1704
3053
  return results;
@@ -1719,11 +3068,11 @@ var FormatSniffer = class {
1719
3068
  /**
1720
3069
  * 检查特征是否匹配
1721
3070
  */
1722
- matchFeature(feature14, ext, headContent, filePath) {
1723
- if (!feature14.extensions.includes(ext)) {
3071
+ matchFeature(feature15, ext, headContent, filePath) {
3072
+ if (!feature15.extensions.includes(ext)) {
1724
3073
  return false;
1725
3074
  }
1726
- const { signatures } = feature14;
3075
+ const { signatures } = feature15;
1727
3076
  let headMatch = true;
1728
3077
  if (signatures.head && signatures.head.length > 0) {
1729
3078
  headMatch = matchHeadSignatures(headContent, signatures.head);
@@ -1826,8 +3175,8 @@ var feature = {
1826
3175
  requiredFields: ["chatlab"]
1827
3176
  }
1828
3177
  };
1829
- async function* parseChatLab(options) {
1830
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
3178
+ async function* parseChatLab(options2) {
3179
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
1831
3180
  const totalBytes = getFileSize(filePath);
1832
3181
  let bytesRead = 0;
1833
3182
  let messagesProcessed = 0;
@@ -1896,14 +3245,14 @@ async function* parseChatLab(options) {
1896
3245
  }
1897
3246
  const memberMapFromMessages = /* @__PURE__ */ new Map();
1898
3247
  const messageBatch = [];
1899
- await new Promise((resolve2, reject) => {
3248
+ await new Promise((resolve3, reject) => {
1900
3249
  const readStream = fs4.createReadStream(filePath, { encoding: "utf-8" });
1901
3250
  readStream.on("data", (chunk) => {
1902
3251
  bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
1903
3252
  });
1904
- const pipeline = chain([readStream, parser(), pick({ filter: /^messages\.\d+$/ }), streamValues()]);
3253
+ const pipeline2 = chain([readStream, parser(), pick({ filter: /^messages\.\d+$/ }), streamValues()]);
1905
3254
  const batchCollector = [];
1906
- pipeline.on("data", ({ value }) => {
3255
+ pipeline2.on("data", ({ value }) => {
1907
3256
  const msg = value;
1908
3257
  if (members.length === 0) {
1909
3258
  memberMapFromMessages.set(msg.sender, {
@@ -1936,13 +3285,13 @@ async function* parseChatLab(options) {
1936
3285
  onProgress?.(progress);
1937
3286
  }
1938
3287
  });
1939
- pipeline.on("end", () => {
3288
+ pipeline2.on("end", () => {
1940
3289
  if (batchCollector.length > 0) {
1941
3290
  messageBatch.push(...batchCollector);
1942
3291
  }
1943
- resolve2();
3292
+ resolve3();
1944
3293
  });
1945
- pipeline.on("error", reject);
3294
+ pipeline2.on("error", reject);
1946
3295
  });
1947
3296
  if (members.length > 0) {
1948
3297
  yield { type: "members", data: members };
@@ -2008,8 +3357,8 @@ var feature2 = {
2008
3357
  head: [/^\s*\{.*"_type"\s*:\s*"header".*"chatlab"/]
2009
3358
  }
2010
3359
  };
2011
- async function* parseChatLabJsonl(options) {
2012
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
3360
+ async function* parseChatLabJsonl(options2) {
3361
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
2013
3362
  const totalBytes = getFileSize(filePath);
2014
3363
  let bytesRead = 0;
2015
3364
  let messagesProcessed = 0;
@@ -2276,7 +3625,7 @@ async function preprocessQQJson(inputPath, onProgress) {
2276
3625
  const outputPath = path5.join(tempDir, outputFilename);
2277
3626
  onProgress?.(createProgress("parsing", 0, totalBytes, 0, ""));
2278
3627
  const avatarsStr = readAvatarsFromFile(inputPath);
2279
- return new Promise((resolve2, reject) => {
3628
+ return new Promise((resolve3, reject) => {
2280
3629
  const headChunks = [];
2281
3630
  let headSize = 0;
2282
3631
  const maxHeadSize = 1e5;
@@ -2326,8 +3675,8 @@ async function preprocessQQJson(inputPath, onProgress) {
2326
3675
  const headerJson = JSON.stringify(header);
2327
3676
  writeStream.write(headerJson.slice(0, -2) + "\n");
2328
3677
  let isFirstMessage = true;
2329
- const pipeline = chain2([readStream, parser3(), pick2({ filter: /^messages\.\d+$/ }), streamValues2()]);
2330
- pipeline.on("data", ({ value }) => {
3678
+ const pipeline2 = chain2([readStream, parser3(), pick2({ filter: /^messages\.\d+$/ }), streamValues2()]);
3679
+ pipeline2.on("data", ({ value }) => {
2331
3680
  const slimMsg = slimMessage(value);
2332
3681
  const msgJson = JSON.stringify(slimMsg);
2333
3682
  if (isFirstMessage) {
@@ -2349,7 +3698,7 @@ async function preprocessQQJson(inputPath, onProgress) {
2349
3698
  );
2350
3699
  }
2351
3700
  });
2352
- pipeline.on("end", () => {
3701
+ pipeline2.on("end", () => {
2353
3702
  writeStream.write("\n]");
2354
3703
  if (avatarsStr) {
2355
3704
  writeStream.write(',"avatars":' + avatarsStr);
@@ -2358,10 +3707,10 @@ async function preprocessQQJson(inputPath, onProgress) {
2358
3707
  writeStream.end();
2359
3708
  writeStream.on("finish", () => {
2360
3709
  onProgress?.(createProgress("done", totalBytes, totalBytes, messagesProcessed, ""));
2361
- resolve2(outputPath);
3710
+ resolve3(outputPath);
2362
3711
  });
2363
3712
  });
2364
- pipeline.on("error", (err) => {
3713
+ pipeline2.on("error", (err) => {
2365
3714
  writeStream.destroy();
2366
3715
  if (fs6.existsSync(outputPath)) {
2367
3716
  fs6.unlinkSync(outputPath);
@@ -2496,8 +3845,8 @@ function convertMessageType(messageType, content, isRecalled) {
2496
3845
  if (messageType === 9) return 25 /* REPLY */;
2497
3846
  return 0 /* TEXT */;
2498
3847
  }
2499
- async function* parseV4(options) {
2500
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
3848
+ async function* parseV4(options2) {
3849
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
2501
3850
  const totalBytes = getFileSize(filePath);
2502
3851
  let bytesRead = 0;
2503
3852
  let messagesProcessed = 0;
@@ -2527,13 +3876,13 @@ async function* parseV4(options) {
2527
3876
  yield { type: "meta", data: meta };
2528
3877
  const memberMap = /* @__PURE__ */ new Map();
2529
3878
  const messageBatch = [];
2530
- await new Promise((resolve2, reject) => {
3879
+ await new Promise((resolve3, reject) => {
2531
3880
  const readStream = fs7.createReadStream(filePath, { encoding: "utf-8" });
2532
3881
  readStream.on("data", (chunk) => {
2533
3882
  bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
2534
3883
  });
2535
- const pipeline = chain3([readStream, parser4(), pick3({ filter: /^messages\.\d+$/ }), streamValues3()]);
2536
- pipeline.on("data", ({ value }) => {
3884
+ const pipeline2 = chain3([readStream, parser4(), pick3({ filter: /^messages\.\d+$/ }), streamValues3()]);
3885
+ pipeline2.on("data", ({ value }) => {
2537
3886
  const platformId = value.sender.uin || value.sender.uid || value.rawMessage?.senderUin || value.rawMessage?.senderUid;
2538
3887
  if (!platformId) {
2539
3888
  skippedMessages++;
@@ -2581,8 +3930,8 @@ async function* parseV4(options) {
2581
3930
  onProgress?.(progress);
2582
3931
  }
2583
3932
  });
2584
- pipeline.on("end", resolve2);
2585
- pipeline.on("error", reject);
3933
+ pipeline2.on("end", resolve3);
3934
+ pipeline2.on("error", reject);
2586
3935
  });
2587
3936
  const avatarsMap = /* @__PURE__ */ new Map();
2588
3937
  try {
@@ -2770,8 +4119,8 @@ async function* readJsonlFile(filePath, onParseError) {
2770
4119
  }
2771
4120
  }
2772
4121
  }
2773
- async function* parseChunkedJsonl(options) {
2774
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
4122
+ async function* parseChunkedJsonl(options2) {
4123
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
2775
4124
  const manifestPath = filePath;
2776
4125
  const baseDir = path7.dirname(manifestPath);
2777
4126
  onLog?.("info", `\u5F00\u59CB\u89E3\u6790 manifest: ${manifestPath}`);
@@ -3044,8 +4393,8 @@ function convertMessageType3(typeStr) {
3044
4393
  return 99 /* OTHER */;
3045
4394
  }
3046
4395
  }
3047
- async function* parseWeFlow(options) {
3048
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
4396
+ async function* parseWeFlow(options2) {
4397
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
3049
4398
  const totalBytes = getFileSize(filePath);
3050
4399
  let bytesRead = 0;
3051
4400
  let messagesProcessed = 0;
@@ -3056,7 +4405,7 @@ async function* parseWeFlow(options) {
3056
4405
  const headContent = readFileHeadBytes(filePath, 5e3);
3057
4406
  let session = null;
3058
4407
  try {
3059
- await new Promise((resolve2) => {
4408
+ await new Promise((resolve3) => {
3060
4409
  const sessionStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
3061
4410
  let sessionContent = "";
3062
4411
  let inSession = false;
@@ -3108,9 +4457,9 @@ async function* parseWeFlow(options) {
3108
4457
  } catch {
3109
4458
  }
3110
4459
  }
3111
- resolve2();
4460
+ resolve3();
3112
4461
  });
3113
- sessionStream.on("error", () => resolve2());
4462
+ sessionStream.on("error", () => resolve3());
3114
4463
  });
3115
4464
  } catch {
3116
4465
  }
@@ -3179,7 +4528,7 @@ async function* parseWeFlow(options) {
3179
4528
  }
3180
4529
  if (avatarsMap.size === 0) {
3181
4530
  try {
3182
- await new Promise((resolve2) => {
4531
+ await new Promise((resolve3) => {
3183
4532
  const avatarStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
3184
4533
  let avatarsContent = "";
3185
4534
  let inAvatars = false;
@@ -3236,9 +4585,9 @@ async function* parseWeFlow(options) {
3236
4585
  } catch {
3237
4586
  }
3238
4587
  }
3239
- resolve2();
4588
+ resolve3();
3240
4589
  });
3241
- avatarStream.on("error", () => resolve2());
4590
+ avatarStream.on("error", () => resolve3());
3242
4591
  });
3243
4592
  } catch {
3244
4593
  }
@@ -3246,7 +4595,7 @@ async function* parseWeFlow(options) {
3246
4595
  const groupAvatar = sessionData?.avatar || (groupId ? avatarsMap.get(groupId) : void 0);
3247
4596
  let ownerId;
3248
4597
  try {
3249
- await new Promise((resolve2) => {
4598
+ await new Promise((resolve3) => {
3250
4599
  const scanStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
3251
4600
  const scanPipeline = chain4([scanStream, parser5(), pick4({ filter: /^messages\.\d+$/ }), streamValues4()]);
3252
4601
  scanPipeline.on("data", ({ value }) => {
@@ -3255,9 +4604,9 @@ async function* parseWeFlow(options) {
3255
4604
  scanStream.destroy();
3256
4605
  }
3257
4606
  });
3258
- scanStream.on("close", () => resolve2());
3259
- scanPipeline.on("end", () => resolve2());
3260
- scanPipeline.on("error", () => resolve2());
4607
+ scanStream.on("close", () => resolve3());
4608
+ scanPipeline.on("end", () => resolve3());
4609
+ scanPipeline.on("error", () => resolve3());
3261
4610
  });
3262
4611
  } catch {
3263
4612
  }
@@ -3272,12 +4621,12 @@ async function* parseWeFlow(options) {
3272
4621
  yield { type: "meta", data: meta };
3273
4622
  const memberMap = /* @__PURE__ */ new Map();
3274
4623
  const messageBatch = [];
3275
- await new Promise((resolve2, reject) => {
4624
+ await new Promise((resolve3, reject) => {
3276
4625
  const readStream = fs9.createReadStream(filePath, { encoding: "utf-8" });
3277
4626
  readStream.on("data", (chunk) => {
3278
4627
  bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
3279
4628
  });
3280
- const pipeline = chain4([readStream, parser5(), pick4({ filter: /^messages\.\d+$/ }), streamValues4()]);
4629
+ const pipeline2 = chain4([readStream, parser5(), pick4({ filter: /^messages\.\d+$/ }), streamValues4()]);
3281
4630
  const processMessage = (msg) => {
3282
4631
  if (!msg.senderUsername || msg.createTime === void 0) {
3283
4632
  return null;
@@ -3322,7 +4671,7 @@ async function* parseWeFlow(options) {
3322
4671
  };
3323
4672
  };
3324
4673
  const batchCollector = [];
3325
- pipeline.on("data", ({ value }) => {
4674
+ pipeline2.on("data", ({ value }) => {
3326
4675
  const parsed = processMessage(value);
3327
4676
  if (parsed) {
3328
4677
  batchCollector.push(parsed);
@@ -3341,13 +4690,13 @@ async function* parseWeFlow(options) {
3341
4690
  }
3342
4691
  }
3343
4692
  });
3344
- pipeline.on("end", () => {
4693
+ pipeline2.on("end", () => {
3345
4694
  if (batchCollector.length > 0) {
3346
4695
  messageBatch.push(...batchCollector);
3347
4696
  }
3348
- resolve2();
4697
+ resolve3();
3349
4698
  });
3350
- pipeline.on("error", reject);
4699
+ pipeline2.on("error", reject);
3351
4700
  });
3352
4701
  const members = Array.from(memberMap.values()).map((m) => ({
3353
4702
  platformId: m.platformId,
@@ -3521,8 +4870,8 @@ function convertRoles(discordRoles) {
3521
4870
  name: role.name
3522
4871
  }));
3523
4872
  }
3524
- async function* parseDiscordExporter(options) {
3525
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
4873
+ async function* parseDiscordExporter(options2) {
4874
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
3526
4875
  const totalBytes = getFileSize(filePath);
3527
4876
  let bytesRead = 0;
3528
4877
  let messagesProcessed = 0;
@@ -3558,14 +4907,14 @@ async function* parseDiscordExporter(options) {
3558
4907
  onLog?.("info", `\u7FA4\u804A\u540D\u79F0: ${chatName}`);
3559
4908
  const memberMap = /* @__PURE__ */ new Map();
3560
4909
  const messageBatch = [];
3561
- await new Promise((resolve2, reject) => {
4910
+ await new Promise((resolve3, reject) => {
3562
4911
  const readStream = fs10.createReadStream(filePath, { encoding: "utf-8" });
3563
4912
  readStream.on("data", (chunk) => {
3564
4913
  bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
3565
4914
  });
3566
- const pipeline = chain5([readStream, parser6(), pick5({ filter: /^messages\.\d+$/ }), streamValues5()]);
4915
+ const pipeline2 = chain5([readStream, parser6(), pick5({ filter: /^messages\.\d+$/ }), streamValues5()]);
3567
4916
  const batchCollector = [];
3568
- pipeline.on("data", ({ value }) => {
4917
+ pipeline2.on("data", ({ value }) => {
3569
4918
  const msg = value;
3570
4919
  const author = msg.author;
3571
4920
  if (!memberMap.has(author.id)) {
@@ -3633,13 +4982,13 @@ ${stickerTexts.join("\n")}` : stickerTexts.join("\n");
3633
4982
  onProgress?.(progress);
3634
4983
  }
3635
4984
  });
3636
- pipeline.on("end", () => {
4985
+ pipeline2.on("end", () => {
3637
4986
  if (batchCollector.length > 0) {
3638
4987
  messageBatch.push(...batchCollector);
3639
4988
  }
3640
- resolve2();
4989
+ resolve3();
3641
4990
  });
3642
- pipeline.on("error", reject);
4991
+ pipeline2.on("error", reject);
3643
4992
  });
3644
4993
  const members = Array.from(memberMap.values());
3645
4994
  yield { type: "members", data: members };
@@ -3760,10 +5109,10 @@ var feature8 = {
3760
5109
  };
3761
5110
  async function scanChats(filePath) {
3762
5111
  const chats = [];
3763
- return new Promise((resolve2, reject) => {
5112
+ return new Promise((resolve3, reject) => {
3764
5113
  const readStream = fs11.createReadStream(filePath, { encoding: "utf-8" });
3765
- const pipeline = chain6([readStream, parser7(), pick6({ filter: /^chats\.list\.\d+$/ }), streamValues6()]);
3766
- pipeline.on("data", ({ value }) => {
5114
+ const pipeline2 = chain6([readStream, parser7(), pick6({ filter: /^chats\.list\.\d+$/ }), streamValues6()]);
5115
+ pipeline2.on("data", ({ value }) => {
3767
5116
  const chat = value;
3768
5117
  chats.push({
3769
5118
  index: chats.length,
@@ -3773,16 +5122,16 @@ async function scanChats(filePath) {
3773
5122
  messageCount: Array.isArray(chat.messages) ? chat.messages.length : 0
3774
5123
  });
3775
5124
  });
3776
- pipeline.on("end", () => {
3777
- resolve2(chats);
5125
+ pipeline2.on("end", () => {
5126
+ resolve3(chats);
3778
5127
  });
3779
- pipeline.on("error", (err) => {
5128
+ pipeline2.on("error", (err) => {
3780
5129
  reject(new Error(`\u626B\u63CF Telegram \u6587\u4EF6\u5931\u8D25: ${err.message}`));
3781
5130
  });
3782
5131
  });
3783
5132
  }
3784
- async function* parseTelegram(options) {
3785
- const { filePath, batchSize = 5e3, formatOptions, onProgress, onLog } = options;
5133
+ async function* parseTelegram(options2) {
5134
+ const { filePath, batchSize = 5e3, formatOptions, onProgress, onLog } = options2;
3786
5135
  const chatIndex = formatOptions?.chatIndex ?? 0;
3787
5136
  const totalBytes = getFileSize(filePath);
3788
5137
  let bytesRead = 0;
@@ -3793,26 +5142,26 @@ async function* parseTelegram(options) {
3793
5142
  onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Telegram JSON \u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
3794
5143
  onLog?.("info", `\u76EE\u6807\u804A\u5929\u7D22\u5F15: ${chatIndex}`);
3795
5144
  const chatPathFilter = `chats.list.${chatIndex}`;
3796
- const chatData = await new Promise((resolve2, reject) => {
5145
+ const chatData = await new Promise((resolve3, reject) => {
3797
5146
  const readStream = fs11.createReadStream(filePath, { encoding: "utf-8" });
3798
5147
  readStream.on("data", (chunk) => {
3799
5148
  bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
3800
5149
  });
3801
- const pipeline = chain6([
5150
+ const pipeline2 = chain6([
3802
5151
  readStream,
3803
5152
  parser7(),
3804
5153
  pick6({ filter: new RegExp(`^${chatPathFilter.replace(".", "\\.")}$`) }),
3805
5154
  streamValues6()
3806
5155
  ]);
3807
5156
  let found = false;
3808
- pipeline.on("data", ({ value }) => {
5157
+ pipeline2.on("data", ({ value }) => {
3809
5158
  found = true;
3810
- resolve2(value);
5159
+ resolve3(value);
3811
5160
  });
3812
- pipeline.on("end", () => {
3813
- if (!found) resolve2(null);
5161
+ pipeline2.on("end", () => {
5162
+ if (!found) resolve3(null);
3814
5163
  });
3815
- pipeline.on("error", reject);
5164
+ pipeline2.on("error", reject);
3816
5165
  });
3817
5166
  if (!chatData) {
3818
5167
  onLog?.("error", `\u672A\u627E\u5230\u7D22\u5F15 ${chatIndex} \u5BF9\u5E94\u7684\u804A\u5929`);
@@ -3923,28 +5272,28 @@ var feature9 = {
3923
5272
  }
3924
5273
  }
3925
5274
  };
3926
- async function* parseTelegramSingle(options) {
3927
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
5275
+ async function* parseTelegramSingle(options2) {
5276
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
3928
5277
  const totalBytes = getFileSize(filePath);
3929
5278
  let messagesProcessed = 0;
3930
5279
  const initialProgress = createProgress("parsing", 0, totalBytes, 0, "");
3931
5280
  yield { type: "progress", data: initialProgress };
3932
5281
  onProgress?.(initialProgress);
3933
5282
  onLog?.("info", `\u5F00\u59CB\u89E3\u6790 Telegram \u5355\u804A\u5929 JSON \u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
3934
- const chatData = await new Promise((resolve2, reject) => {
5283
+ const chatData = await new Promise((resolve3, reject) => {
3935
5284
  const readStream = fs12.createReadStream(filePath, { encoding: "utf-8" });
3936
- const pipeline = chain7([readStream, parser8(), streamValues7()]);
5285
+ const pipeline2 = chain7([readStream, parser8(), streamValues7()]);
3937
5286
  let found = false;
3938
- pipeline.on("data", ({ value }) => {
5287
+ pipeline2.on("data", ({ value }) => {
3939
5288
  if (!found) {
3940
5289
  found = true;
3941
- resolve2(value);
5290
+ resolve3(value);
3942
5291
  }
3943
5292
  });
3944
- pipeline.on("end", () => {
3945
- if (!found) resolve2(null);
5293
+ pipeline2.on("end", () => {
5294
+ if (!found) resolve3(null);
3946
5295
  });
3947
- pipeline.on("error", reject);
5296
+ pipeline2.on("error", reject);
3948
5297
  });
3949
5298
  if (!chatData) {
3950
5299
  onLog?.("error", "\u65E0\u6CD5\u89E3\u6790 Telegram \u5355\u804A\u5929\u6587\u4EF6");
@@ -4202,8 +5551,8 @@ function parseV1Timestamp(timeStr) {
4202
5551
  const ts = Math.floor(date.getTime() / 1e3);
4203
5552
  return isNaN(ts) ? 0 : ts;
4204
5553
  }
4205
- async function* parseWhatsApp(options) {
4206
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
5554
+ async function* parseWhatsApp(options2) {
5555
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
4207
5556
  const totalBytes = getFileSize(filePath);
4208
5557
  let bytesRead = 0;
4209
5558
  let messagesProcessed = 0;
@@ -4410,8 +5759,8 @@ function cleanNickname(nickname) {
4410
5759
  return nickname.replace(/^(【[^】]*】\s*)+/, "").trim();
4411
5760
  }
4412
5761
  var lastValidNickname = /* @__PURE__ */ new Map();
4413
- async function* parseTxt(options) {
4414
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
5762
+ async function* parseTxt(options2) {
5763
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
4415
5764
  const totalBytes = getFileSize(filePath);
4416
5765
  let bytesRead = 0;
4417
5766
  let messagesProcessed = 0;
@@ -4630,8 +5979,8 @@ function getMessageContent(msg) {
4630
5979
  }
4631
5980
  return "[\u672A\u77E5\u6D88\u606F]";
4632
5981
  }
4633
- async function* parseInstagram(options) {
4634
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
5982
+ async function* parseInstagram(options2) {
5983
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
4635
5984
  const totalBytes = getFileSize(filePath);
4636
5985
  let messagesProcessed = 0;
4637
5986
  const initialProgress = createProgress("parsing", 0, totalBytes, 0, "\u6B63\u5728\u89E3\u6790 Instagram \u804A\u5929\u8BB0\u5F55...");
@@ -4730,10 +6079,247 @@ var module_12 = {
4730
6079
  };
4731
6080
  var instagram_native_default = module_12;
4732
6081
 
4733
- // ../../packages/parser/src/formats/line-native-txt.ts
6082
+ // ../../packages/parser/src/formats/google-chat-takeout.ts
6083
+ var import_stream_chain8 = __toESM(require_stream_chain(), 1);
6084
+ var import_stream_json8 = __toESM(require_stream_json(), 1);
6085
+ var import_Pick7 = __toESM(require_Pick(), 1);
6086
+ var import_StreamValues8 = __toESM(require_StreamValues(), 1);
4734
6087
  import * as fs16 from "fs";
4735
6088
  import * as path12 from "path";
6089
+ var { chain: chain8 } = import_stream_chain8.default;
6090
+ var { parser: parser9 } = import_stream_json8.default;
6091
+ var { pick: pick7 } = import_Pick7.default;
6092
+ var { streamValues: streamValues8 } = import_StreamValues8.default;
6093
+ var ENGLISH_MONTHS = /* @__PURE__ */ new Map([
6094
+ ["january", 0],
6095
+ ["february", 1],
6096
+ ["march", 2],
6097
+ ["april", 3],
6098
+ ["may", 4],
6099
+ ["june", 5],
6100
+ ["july", 6],
6101
+ ["august", 7],
6102
+ ["september", 8],
6103
+ ["october", 9],
6104
+ ["november", 10],
6105
+ ["december", 11]
6106
+ ]);
4736
6107
  var feature13 = {
6108
+ id: "google-chat-takeout",
6109
+ name: "Google Chat Takeout",
6110
+ platform: KNOWN_PLATFORMS.GOOGLE_CHAT,
6111
+ priority: 24,
6112
+ extensions: [".json"],
6113
+ signatures: {
6114
+ head: [/"format"\s*:\s*"chatlab-google-chat-takeout"/],
6115
+ requiredFields: ["format", "version", "messagesFile"]
6116
+ }
6117
+ };
6118
+ function normalizeSpaces(value) {
6119
+ return value.replace(/[\u00a0\u202f]/g, " ").replace(/\s+/g, " ").trim();
6120
+ }
6121
+ function createUtcTimestamp(year, monthIndex, day, hour, minute, second) {
6122
+ const timestampMs = Date.UTC(year, monthIndex, day, hour, minute, second);
6123
+ const date = new Date(timestampMs);
6124
+ if (date.getUTCFullYear() !== year || date.getUTCMonth() !== monthIndex || date.getUTCDate() !== day || date.getUTCHours() !== hour || date.getUTCMinutes() !== minute || date.getUTCSeconds() !== second) {
6125
+ return null;
6126
+ }
6127
+ return Math.floor(timestampMs / 1e3);
6128
+ }
6129
+ function parseChineseUtcDate(value) {
6130
+ const match = normalizeSpaces(value).match(
6131
+ /^(\d{4})年(\d{1,2})月(\d{1,2})日(?:星期[一二三四五六日天])?\s+UTC\s+(\d{1,2}):(\d{2}):(\d{2})$/
6132
+ );
6133
+ if (!match) return null;
6134
+ return createUtcTimestamp(
6135
+ Number(match[1]),
6136
+ Number(match[2]) - 1,
6137
+ Number(match[3]),
6138
+ Number(match[4]),
6139
+ Number(match[5]),
6140
+ Number(match[6])
6141
+ );
6142
+ }
6143
+ function parseEnglishUtcDate(value) {
6144
+ const match = normalizeSpaces(value).match(
6145
+ /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\s+([A-Za-z]+)\s+(\d{1,2}),\s+(\d{4})\s+at\s+(\d{1,2}):(\d{2}):(\d{2})\s+(AM|PM)\s+UTC$/i
6146
+ );
6147
+ if (!match) return null;
6148
+ const monthIndex = ENGLISH_MONTHS.get(match[1].toLowerCase());
6149
+ if (monthIndex === void 0) return null;
6150
+ let hour = Number(match[4]);
6151
+ if (hour < 1 || hour > 12) return null;
6152
+ if (match[7].toUpperCase() === "AM") {
6153
+ if (hour === 12) hour = 0;
6154
+ } else if (hour !== 12) {
6155
+ hour += 12;
6156
+ }
6157
+ return createUtcTimestamp(Number(match[3]), monthIndex, Number(match[2]), hour, Number(match[5]), Number(match[6]));
6158
+ }
6159
+ function parseGoogleChatDate(value) {
6160
+ return parseChineseUtcDate(value) ?? parseEnglishUtcDate(value);
6161
+ }
6162
+ function normalizeIdentity(user) {
6163
+ const email = user?.email?.trim().toLowerCase();
6164
+ const name = user?.name?.trim() || email || "Unknown";
6165
+ return {
6166
+ platformId: email || name.toLowerCase(),
6167
+ name
6168
+ };
6169
+ }
6170
+ function readJson(filePath) {
6171
+ return JSON.parse(fs16.readFileSync(filePath, "utf8"));
6172
+ }
6173
+ function resolveManifestFile(manifestDir, relativePath) {
6174
+ const resolved = path12.resolve(manifestDir, relativePath);
6175
+ const relative2 = path12.relative(manifestDir, resolved);
6176
+ if (relative2.startsWith("..") || path12.isAbsolute(relative2)) {
6177
+ throw new Error(`Google Chat manifest path escapes its directory: ${relativePath}`);
6178
+ }
6179
+ return resolved;
6180
+ }
6181
+ function readManifest2(filePath) {
6182
+ const manifest = readJson(filePath);
6183
+ if (manifest.format !== "chatlab-google-chat-takeout" || manifest.version !== 1) {
6184
+ throw new Error("Invalid Google Chat import manifest");
6185
+ }
6186
+ if (manifest.chatType !== "private" && manifest.chatType !== "group") {
6187
+ throw new Error("Invalid Google Chat chat type");
6188
+ }
6189
+ const manifestDir = path12.dirname(filePath);
6190
+ return {
6191
+ manifest,
6192
+ userInfoPath: resolveManifestFile(manifestDir, manifest.userInfoFile),
6193
+ groupInfoPath: resolveManifestFile(manifestDir, manifest.groupInfoFile),
6194
+ messagesPath: resolveManifestFile(manifestDir, manifest.messagesFile)
6195
+ };
6196
+ }
6197
+ function getAttachmentName(attachment) {
6198
+ return attachment.original_name?.trim() || attachment.export_name?.trim() || null;
6199
+ }
6200
+ function buildQuotePrefix(message) {
6201
+ const quote = message.quoted_message_metadata;
6202
+ const quoteText = quote?.text?.trim();
6203
+ if (!quoteText) return null;
6204
+ const creator = quote?.creator?.name?.trim() || quote?.creator?.email?.trim();
6205
+ return creator ? `> ${creator}: ${quoteText}` : `> ${quoteText}`;
6206
+ }
6207
+ function buildMessageContent(message) {
6208
+ const parts = [];
6209
+ const quote = buildQuotePrefix(message);
6210
+ if (quote) parts.push(quote);
6211
+ const text = message.text?.trim();
6212
+ if (text) parts.push(text);
6213
+ for (const attachment of message.attached_files ?? []) {
6214
+ const name = getAttachmentName(attachment);
6215
+ if (name) parts.push(`[\u9644\u4EF6] ${name}`);
6216
+ }
6217
+ return parts.length > 0 ? parts.join("\n") : "[\u4E0D\u652F\u6301\u7684 Google Chat \u6D88\u606F]";
6218
+ }
6219
+ function detectMessageType5(message) {
6220
+ if (message.text?.trim()) return 0 /* TEXT */;
6221
+ if ((message.attached_files ?? []).some((attachment) => getAttachmentName(attachment))) {
6222
+ return 4 /* FILE */;
6223
+ }
6224
+ return 99 /* OTHER */;
6225
+ }
6226
+ function deriveChatName(manifest, groupInfo, ownerId) {
6227
+ if (manifest.chatName?.trim()) return manifest.chatName.trim();
6228
+ if (manifest.chatType === "group" && groupInfo.name?.trim()) return groupInfo.name.trim();
6229
+ const otherMember = (groupInfo.members ?? []).map(normalizeIdentity).find((member) => !ownerId || member.platformId !== ownerId);
6230
+ return otherMember?.name || groupInfo.members?.map((member) => normalizeIdentity(member).name).join(", ") || manifest.chatId;
6231
+ }
6232
+ async function* parseGoogleChat(options2) {
6233
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
6234
+ const { manifest, userInfoPath, groupInfoPath, messagesPath } = readManifest2(filePath);
6235
+ const userInfo = readJson(userInfoPath);
6236
+ const groupInfo = readJson(groupInfoPath);
6237
+ const owner = userInfo.user ? normalizeIdentity(userInfo.user) : null;
6238
+ const totalBytes = getFileSize(messagesPath);
6239
+ const initialProgress = createProgress("parsing", 0, totalBytes, 0, "");
6240
+ yield { type: "progress", data: initialProgress };
6241
+ onProgress?.(initialProgress);
6242
+ yield {
6243
+ type: "meta",
6244
+ data: {
6245
+ name: deriveChatName(manifest, groupInfo, owner?.platformId),
6246
+ platform: KNOWN_PLATFORMS.GOOGLE_CHAT,
6247
+ type: manifest.chatType === "group" ? "group" /* GROUP */ : "private" /* PRIVATE */,
6248
+ ...manifest.chatType === "group" ? { groupId: manifest.chatId } : {},
6249
+ ownerId: owner?.platformId
6250
+ }
6251
+ };
6252
+ const memberMap = /* @__PURE__ */ new Map();
6253
+ for (const member of groupInfo.members ?? []) {
6254
+ const identity = normalizeIdentity(member);
6255
+ memberMap.set(identity.platformId, {
6256
+ platformId: identity.platformId,
6257
+ accountName: identity.name
6258
+ });
6259
+ }
6260
+ if (owner && !memberMap.has(owner.platformId)) {
6261
+ memberMap.set(owner.platformId, {
6262
+ platformId: owner.platformId,
6263
+ accountName: owner.name
6264
+ });
6265
+ }
6266
+ yield { type: "members", data: Array.from(memberMap.values()) };
6267
+ const readStream = fs16.createReadStream(messagesPath, { encoding: "utf8" });
6268
+ let bytesRead = 0;
6269
+ let messagesProcessed = 0;
6270
+ readStream.on("data", (chunk) => {
6271
+ bytesRead += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
6272
+ });
6273
+ const pipeline2 = chain8([readStream, parser9(), pick7({ filter: /^messages\.\d+$/ }), streamValues8()]);
6274
+ const messageBatch = [];
6275
+ try {
6276
+ for await (const item of pipeline2) {
6277
+ const message = item.value;
6278
+ const sender = normalizeIdentity(message.creator);
6279
+ messageBatch.push({
6280
+ platformMessageId: message.message_id ? String(message.message_id) : void 0,
6281
+ senderPlatformId: sender.platformId,
6282
+ senderAccountName: sender.name,
6283
+ timestamp: parseGoogleChatDate(message.created_date ?? message.updated_date ?? "") ?? Number.NaN,
6284
+ type: detectMessageType5(message),
6285
+ content: buildMessageContent(message)
6286
+ });
6287
+ messagesProcessed++;
6288
+ if (messageBatch.length >= batchSize) {
6289
+ yield { type: "messages", data: messageBatch.splice(0) };
6290
+ const progress = createProgress("parsing", bytesRead, totalBytes, messagesProcessed, "");
6291
+ yield { type: "progress", data: progress };
6292
+ onProgress?.(progress);
6293
+ }
6294
+ }
6295
+ } catch (error) {
6296
+ const message = error instanceof Error ? error.message : String(error);
6297
+ onLog?.("error", `Failed to parse Google Chat messages: ${message}`);
6298
+ yield { type: "error", data: new Error(`Failed to parse Google Chat messages: ${message}`) };
6299
+ return;
6300
+ }
6301
+ if (messageBatch.length > 0) {
6302
+ yield { type: "messages", data: messageBatch };
6303
+ }
6304
+ const doneProgress = createProgress("done", totalBytes, totalBytes, messagesProcessed, "");
6305
+ yield { type: "progress", data: doneProgress };
6306
+ onProgress?.(doneProgress);
6307
+ yield { type: "done", data: { messageCount: messagesProcessed, memberCount: memberMap.size } };
6308
+ }
6309
+ var parser_12 = {
6310
+ feature: feature13,
6311
+ parse: parseGoogleChat
6312
+ };
6313
+ var module_13 = {
6314
+ feature: feature13,
6315
+ parser: parser_12
6316
+ };
6317
+ var google_chat_takeout_default = module_13;
6318
+
6319
+ // ../../packages/parser/src/formats/line-native-txt.ts
6320
+ import * as fs17 from "fs";
6321
+ import * as path13 from "path";
6322
+ var feature14 = {
4737
6323
  id: "line-native-txt",
4738
6324
  name: "LINE \u5B98\u65B9\u5BFC\u51FA TXT",
4739
6325
  platform: KNOWN_PLATFORMS.LINE,
@@ -4760,7 +6346,7 @@ var feature13 = {
4760
6346
  }
4761
6347
  };
4762
6348
  function extractNameFromFilePath8(filePath) {
4763
- const basename11 = path12.basename(filePath, ".txt");
6349
+ const basename11 = path13.basename(filePath, ".txt");
4764
6350
  const name = basename11.replace(/^\[LINE\]\s*/i, "").trim();
4765
6351
  return name || "\u672A\u77E5\u804A\u5929";
4766
6352
  }
@@ -4882,7 +6468,7 @@ var SPECIAL_MESSAGE_TYPES = {
4882
6468
  "[\u30CE\u30FC\u30C8]": 0 /* TEXT */
4883
6469
  // JA
4884
6470
  };
4885
- function detectMessageType5(content) {
6471
+ function detectMessageType6(content) {
4886
6472
  for (const [pattern, type] of Object.entries(SPECIAL_MESSAGE_TYPES)) {
4887
6473
  if (content === pattern || content.startsWith(pattern)) {
4888
6474
  return type;
@@ -4932,15 +6518,15 @@ function detectMessageType5(content) {
4932
6518
  }
4933
6519
  return 0 /* TEXT */;
4934
6520
  }
4935
- async function* parseLINE(options) {
4936
- const { filePath, batchSize = 5e3, onProgress, onLog } = options;
6521
+ async function* parseLINE(options2) {
6522
+ const { filePath, batchSize = 5e3, onProgress, onLog } = options2;
4937
6523
  const totalBytes = getFileSize(filePath);
4938
6524
  let messagesProcessed = 0;
4939
6525
  const initialProgress = createProgress("parsing", 0, totalBytes, 0, "");
4940
6526
  yield { type: "progress", data: initialProgress };
4941
6527
  onProgress?.(initialProgress);
4942
6528
  onLog?.("info", `\u5F00\u59CB\u89E3\u6790 LINE \u5BFC\u51FA\u6587\u4EF6\uFF0C\u5927\u5C0F: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`);
4943
- const content = fs16.readFileSync(filePath, "utf-8");
6529
+ const content = fs17.readFileSync(filePath, "utf-8");
4944
6530
  const lines = content.split("\n").map((line) => line.replace(/\r$/, ""));
4945
6531
  let currentDate = null;
4946
6532
  let chatName = extractNameFromFilePath8(filePath);
@@ -5033,7 +6619,7 @@ async function* parseLINE(options) {
5033
6619
  now.setHours(hours, minutes, 0, 0);
5034
6620
  timestamp = Math.floor(now.getTime() / 1e3);
5035
6621
  }
5036
- const msgType = detectMessageType5(content2);
6622
+ const msgType = detectMessageType6(content2);
5037
6623
  if (!memberMap.has(sender)) {
5038
6624
  memberMap.set(sender, {
5039
6625
  platformId: sender,
@@ -5141,15 +6727,15 @@ async function* parseLINE(options) {
5141
6727
  data: { messageCount: messagesProcessed, memberCount }
5142
6728
  };
5143
6729
  }
5144
- var parser_12 = {
5145
- feature: feature13,
6730
+ var parser_13 = {
6731
+ feature: feature14,
5146
6732
  parse: parseLINE
5147
6733
  };
5148
- var module_13 = {
5149
- feature: feature13,
5150
- parser: parser_12
6734
+ var module_14 = {
6735
+ feature: feature14,
6736
+ parser: parser_13
5151
6737
  };
5152
- var line_native_txt_default = module_13;
6738
+ var line_native_txt_default = module_14;
5153
6739
 
5154
6740
  // ../../packages/parser/src/formats/index.ts
5155
6741
  var formats = [
@@ -5167,6 +6753,8 @@ var formats = [
5167
6753
  // 优先级 22 - Telegram 官方全量导出 JSON
5168
6754
  telegram_native_single_default,
5169
6755
  // 优先级 23 - Telegram 单聊天导出 JSON
6756
+ google_chat_takeout_default,
6757
+ // 优先级 24 - Google Chat Takeout 内部 manifest
5170
6758
  instagram_native_default,
5171
6759
  // 优先级 25 - Instagram 官方导出
5172
6760
  whatsapp_native_txt_default,
@@ -5198,22 +6786,22 @@ function getFormatFeatureById(formatId) {
5198
6786
  return all.find((f) => f.id === formatId) ?? null;
5199
6787
  }
5200
6788
  function getPreprocessor(filePath) {
5201
- const feature14 = sniffer.sniff(filePath);
5202
- if (!feature14) return null;
5203
- const module = formats.find((m) => m.feature.id === feature14.id);
6789
+ const feature15 = sniffer.sniff(filePath);
6790
+ if (!feature15) return null;
6791
+ const module = formats.find((m) => m.feature.id === feature15.id);
5204
6792
  return module?.preprocessor || null;
5205
6793
  }
5206
6794
  async function scanMultiChatFile(filePath) {
5207
- const feature14 = sniffer.sniff(filePath);
5208
- if (!feature14) {
6795
+ const feature15 = sniffer.sniff(filePath);
6796
+ if (!feature15) {
5209
6797
  throw new Error(`\u65E0\u6CD5\u8BC6\u522B\u6587\u4EF6\u683C\u5F0F: ${filePath}`);
5210
6798
  }
5211
- if (!feature14.multiChat) {
5212
- throw new Error(`\u683C\u5F0F "${feature14.name}" \u4E0D\u662F\u591A\u804A\u5929\u683C\u5F0F`);
6799
+ if (!feature15.multiChat) {
6800
+ throw new Error(`\u683C\u5F0F "${feature15.name}" \u4E0D\u662F\u591A\u804A\u5929\u683C\u5F0F`);
5213
6801
  }
5214
- const module = formats.find((m) => m.feature.id === feature14.id);
6802
+ const module = formats.find((m) => m.feature.id === feature15.id);
5215
6803
  if (!module?.scanChats) {
5216
- throw new Error(`\u683C\u5F0F "${feature14.name}" \u58F0\u660E\u4E86 multiChat \u4F46\u672A\u5B9E\u73B0 scanChats`);
6804
+ throw new Error(`\u683C\u5F0F "${feature15.name}" \u58F0\u660E\u4E86 multiChat \u4F46\u672A\u5B9E\u73B0 scanChats`);
5217
6805
  }
5218
6806
  return module.scanChats(filePath);
5219
6807
  }
@@ -5223,35 +6811,35 @@ function needsPreprocess(filePath) {
5223
6811
  const fileSize = getFileSize(filePath);
5224
6812
  return preprocessor.needsPreprocess(filePath, fileSize);
5225
6813
  }
5226
- async function* parseFile(options) {
5227
- const parser9 = sniffer.getParser(options.filePath);
5228
- if (!parser9) {
5229
- yield { type: "error", data: new Error(`\u65E0\u6CD5\u8BC6\u522B\u6587\u4EF6\u683C\u5F0F: ${options.filePath}`) };
6814
+ async function* parseFile(options2) {
6815
+ const parser11 = sniffer.getParser(options2.filePath);
6816
+ if (!parser11) {
6817
+ yield { type: "error", data: new Error(`\u65E0\u6CD5\u8BC6\u522B\u6587\u4EF6\u683C\u5F0F: ${options2.filePath}`) };
5230
6818
  return;
5231
6819
  }
5232
- console.log(`[Parser V2] Using parser: ${parser9.feature.name}`);
5233
- yield* parser9.parse(options);
6820
+ console.log(`[Parser V2] Using parser: ${parser11.feature.name}`);
6821
+ yield* parser11.parse(options2);
5234
6822
  }
5235
- async function* parseFileWithFormat(formatId, options) {
5236
- const parser9 = sniffer.getParserById(formatId);
5237
- if (!parser9) {
6823
+ async function* parseFileWithFormat(formatId, options2) {
6824
+ const parser11 = sniffer.getParserById(formatId);
6825
+ if (!parser11) {
5238
6826
  yield { type: "error", data: new Error(`\u672A\u77E5\u7684\u683C\u5F0F ID: ${formatId}`) };
5239
6827
  return;
5240
6828
  }
5241
- console.log(`[Parser V2] Using parser (explicit): ${parser9.feature.name}`);
5242
- yield* parser9.parse(options);
6829
+ console.log(`[Parser V2] Using parser (explicit): ${parser11.feature.name}`);
6830
+ yield* parser11.parse(options2);
5243
6831
  }
5244
6832
  function findEntryFileInDirectory(dirPath, maxDepth = 1) {
5245
6833
  function walk(current, depth) {
5246
6834
  if (depth > maxDepth) return null;
5247
6835
  let entries;
5248
6836
  try {
5249
- entries = fs17.readdirSync(current, { withFileTypes: true });
6837
+ entries = fs18.readdirSync(current, { withFileTypes: true });
5250
6838
  } catch {
5251
6839
  return null;
5252
6840
  }
5253
6841
  for (const entry of entries) {
5254
- const full = path13.join(current, entry.name);
6842
+ const full = path14.join(current, entry.name);
5255
6843
  if (entry.isFile() && entry.name.endsWith(".json")) {
5256
6844
  const format = detectFormat(full);
5257
6845
  if (format) return full;
@@ -5259,7 +6847,7 @@ function findEntryFileInDirectory(dirPath, maxDepth = 1) {
5259
6847
  }
5260
6848
  for (const entry of entries) {
5261
6849
  if (entry.isDirectory()) {
5262
- const found = walk(path13.join(current, entry.name), depth + 1);
6850
+ const found = walk(path14.join(current, entry.name), depth + 1);
5263
6851
  if (found) return found;
5264
6852
  }
5265
6853
  }
@@ -5291,7 +6879,7 @@ async function streamParseFile(filePath, callbacks, formatId) {
5291
6879
  }
5292
6880
 
5293
6881
  // ../../packages/node-runtime/src/import/streaming-importer.ts
5294
- import * as fs18 from "fs";
6882
+ import * as fs19 from "fs";
5295
6883
  var BATCH_COMMIT_SIZE = 5e4;
5296
6884
  var CHECKPOINT_INTERVAL = 2e5;
5297
6885
  function defaultGenerateSessionId() {
@@ -5302,11 +6890,11 @@ function defaultGenerateSessionId() {
5302
6890
  async function streamingImport(filePath, deps, formatOptions, externalSessionId) {
5303
6891
  if (formatOptions?.formatId) {
5304
6892
  const formatId = formatOptions.formatId;
5305
- const feature14 = getFormatFeatureById(formatId);
5306
- if (!feature14) {
6893
+ const feature15 = getFormatFeatureById(formatId);
6894
+ if (!feature15) {
5307
6895
  return { success: false, error: "error.unknown_format_id" };
5308
6896
  }
5309
- return streamImportSingle(filePath, deps, feature14, formatOptions, externalSessionId);
6897
+ return streamImportSingle(filePath, deps, feature15, formatOptions, externalSessionId);
5310
6898
  }
5311
6899
  const candidates = detectAllFormats(filePath);
5312
6900
  if (candidates.length === 0) {
@@ -5741,7 +7329,7 @@ async function streamParseFileInfo(filePath, deps) {
5741
7329
  if (!formatFeature) {
5742
7330
  throw new Error("Unrecognized file format");
5743
7331
  }
5744
- const fileSize = fs18.statSync(filePath).size;
7332
+ const fileSize = fs19.statSync(filePath).size;
5745
7333
  deps.onProgress({
5746
7334
  stage: "parsing",
5747
7335
  bytesRead: 0,
@@ -5830,7 +7418,7 @@ async function streamParseFileInfo(filePath, deps) {
5830
7418
  }
5831
7419
  db.close();
5832
7420
  try {
5833
- if (fs18.existsSync(tempDbPath)) fs18.unlinkSync(tempDbPath);
7421
+ if (fs19.existsSync(tempDbPath)) fs19.unlinkSync(tempDbPath);
5834
7422
  } catch {
5835
7423
  }
5836
7424
  throw error;
@@ -5963,7 +7551,7 @@ async function analyzeIncrementalImport(sessionId, filePath, deps) {
5963
7551
  });
5964
7552
  return { newMessageCount, duplicateCount, totalInFile };
5965
7553
  }
5966
- async function incrementalImport(sessionId, filePath, deps, options) {
7554
+ async function incrementalImport(sessionId, filePath, deps, options2) {
5967
7555
  const formatFeature = detectFormat(filePath);
5968
7556
  if (!formatFeature) {
5969
7557
  return { success: false, newMessageCount: 0, error: "error.unrecognized_format" };
@@ -5974,8 +7562,8 @@ async function incrementalImport(sessionId, filePath, deps, options) {
5974
7562
  } catch {
5975
7563
  return { success: false, newMessageCount: 0, error: "error.session_not_found" };
5976
7564
  }
5977
- const metaUpdateMode = options?.metaUpdateMode ?? "patch";
5978
- const memberUpdateMode = options?.memberUpdateMode ?? "upsert";
7565
+ const metaUpdateMode = options2?.metaUpdateMode ?? "patch";
7566
+ const memberUpdateMode = options2?.memberUpdateMode ?? "upsert";
5979
7567
  try {
5980
7568
  let trackError2 = function(index, reason, detail) {
5981
7569
  errorCount2++;
@@ -6194,14 +7782,550 @@ async function incrementalImport(sessionId, filePath, deps, options) {
6194
7782
  }
6195
7783
  }
6196
7784
 
6197
- // ../../packages/node-runtime/src/node-path-provider.ts
7785
+ // ../../packages/node-runtime/src/import/archive/archive-reader.ts
7786
+ var import_yauzl = __toESM(require_yauzl(), 1);
6198
7787
  import * as fs20 from "fs";
6199
- import * as os2 from "os";
6200
7788
  import * as path15 from "path";
7789
+ import { pipeline } from "stream/promises";
7790
+
7791
+ // ../../packages/node-runtime/src/import/archive/errors.ts
7792
+ var ArchiveImportError = class extends Error {
7793
+ constructor(code, message, options2) {
7794
+ super(message, options2);
7795
+ this.code = code;
7796
+ this.name = "ArchiveImportError";
7797
+ }
7798
+ code;
7799
+ };
7800
+
7801
+ // ../../packages/node-runtime/src/import/archive/archive-reader.ts
7802
+ var DEFAULT_MAX_ENTRIES = 1e5;
7803
+ var DEFAULT_MAX_ENTRY_BYTES = 20 * 1024 * 1024 * 1024;
7804
+ var DEFAULT_MAX_COMPRESSION_RATIO = 1e4;
7805
+ function validateArchiveEntryName(fileName) {
7806
+ if (fileName.startsWith("/") || /^[A-Za-z]:\//.test(fileName) || fileName.includes("\\") || fileName.split("/").includes("..")) {
7807
+ throw new ArchiveImportError("error.archive_unsafe_path", `Unsafe archive entry path: ${fileName}`);
7808
+ }
7809
+ }
7810
+ function mapArchiveError(error) {
7811
+ if (error instanceof ArchiveImportError) return error;
7812
+ const message = error instanceof Error ? error.message : String(error);
7813
+ return new ArchiveImportError("error.archive_corrupt", `Invalid ZIP archive: ${message}`, {
7814
+ cause: error
7815
+ });
7816
+ }
7817
+ function toSummary(entry) {
7818
+ return {
7819
+ name: entry.fileName,
7820
+ compressedSize: entry.compressedSize,
7821
+ uncompressedSize: entry.uncompressedSize,
7822
+ compressionMethod: entry.compressionMethod,
7823
+ isDirectory: entry.fileName.endsWith("/")
7824
+ };
7825
+ }
7826
+ function validateEntry(entry, options2) {
7827
+ validateArchiveEntryName(entry.fileName);
7828
+ if (entry.isEncrypted()) {
7829
+ throw new ArchiveImportError("error.archive_encrypted", `Encrypted ZIP entry is not supported: ${entry.fileName}`);
7830
+ }
7831
+ if (!entry.canDecodeFileData() || entry.compressionMethod !== 0 && entry.compressionMethod !== 8) {
7832
+ throw new ArchiveImportError(
7833
+ "error.archive_unsupported",
7834
+ `Unsupported ZIP compression method for entry: ${entry.fileName}`
7835
+ );
7836
+ }
7837
+ if (entry.uncompressedSize > options2.maxEntryBytes) {
7838
+ throw new ArchiveImportError("error.archive_limit_exceeded", `ZIP entry exceeds the size limit: ${entry.fileName}`);
7839
+ }
7840
+ if (entry.uncompressedSize > 0) {
7841
+ const ratio = entry.compressedSize === 0 ? Number.POSITIVE_INFINITY : entry.uncompressedSize / entry.compressedSize;
7842
+ if (ratio > options2.maxCompressionRatio) {
7843
+ throw new ArchiveImportError(
7844
+ "error.archive_limit_exceeded",
7845
+ `ZIP entry exceeds the compression ratio limit: ${entry.fileName}`
7846
+ );
7847
+ }
7848
+ }
7849
+ }
7850
+ var ZipArchiveReader = class {
7851
+ constructor(archivePath, options2 = {}) {
7852
+ this.archivePath = archivePath;
7853
+ this.options = {
7854
+ maxEntries: options2.maxEntries ?? DEFAULT_MAX_ENTRIES,
7855
+ maxEntryBytes: options2.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES,
7856
+ maxCompressionRatio: options2.maxCompressionRatio ?? DEFAULT_MAX_COMPRESSION_RATIO
7857
+ };
7858
+ }
7859
+ archivePath;
7860
+ options;
7861
+ async open() {
7862
+ try {
7863
+ return await (0, import_yauzl.openPromise)(this.archivePath, {
7864
+ autoClose: true,
7865
+ decodeStrings: true,
7866
+ validateEntrySizes: true,
7867
+ strictFileNames: true
7868
+ });
7869
+ } catch (error) {
7870
+ throw mapArchiveError(error);
7871
+ }
7872
+ }
7873
+ async listEntries() {
7874
+ const entries = [];
7875
+ await this.visitEntries((entry) => {
7876
+ entries.push(entry);
7877
+ });
7878
+ return entries;
7879
+ }
7880
+ /**
7881
+ * 每次只推进一个 ZIP 条目;visitor 若打开流,必须等待流消费结束后返回。
7882
+ * 这样大 ZIP 不会同时创建大量 inflate stream。
7883
+ */
7884
+ async visitEntries(visitor) {
7885
+ const zipFile = await this.open();
7886
+ let count = 0;
7887
+ try {
7888
+ for await (const entry of zipFile.eachEntry()) {
7889
+ count++;
7890
+ if (count > this.options.maxEntries) {
7891
+ throw new ArchiveImportError("error.archive_limit_exceeded", "ZIP archive contains too many entries");
7892
+ }
7893
+ validateEntry(entry, this.options);
7894
+ let opened = false;
7895
+ const openStream = async () => {
7896
+ if (opened) {
7897
+ throw new ArchiveImportError("error.archive_corrupt", `ZIP entry stream opened twice: ${entry.fileName}`);
7898
+ }
7899
+ opened = true;
7900
+ try {
7901
+ return await zipFile.openReadStreamPromise(entry);
7902
+ } catch (error) {
7903
+ throw mapArchiveError(error);
7904
+ }
7905
+ };
7906
+ await visitor(toSummary(entry), openStream);
7907
+ }
7908
+ } catch (error) {
7909
+ throw mapArchiveError(error);
7910
+ } finally {
7911
+ if (zipFile.isOpen) zipFile.close();
7912
+ }
7913
+ }
7914
+ async pipeEntries(targets) {
7915
+ const remaining = new Set(targets.keys());
7916
+ await this.visitEntries(async (entry, openStream) => {
7917
+ const destination = targets.get(entry.name);
7918
+ if (!destination || entry.isDirectory) return;
7919
+ fs20.mkdirSync(path15.dirname(destination), { recursive: true });
7920
+ await pipeline(await openStream(), fs20.createWriteStream(destination, { flags: "wx" }));
7921
+ remaining.delete(entry.name);
7922
+ });
7923
+ if (remaining.size > 0) {
7924
+ throw new ArchiveImportError(
7925
+ "error.archive_corrupt",
7926
+ `ZIP archive is missing expected entries: ${Array.from(remaining).join(", ")}`
7927
+ );
7928
+ }
7929
+ }
7930
+ };
7931
+
7932
+ // ../../packages/node-runtime/src/import/archive/google-chat-resolver.ts
7933
+ var import_stream_chain9 = __toESM(require_stream_chain(), 1);
7934
+ var import_stream_json9 = __toESM(require_stream_json(), 1);
7935
+ var import_Pick8 = __toESM(require_Pick(), 1);
7936
+ var import_StreamValues9 = __toESM(require_StreamValues(), 1);
7937
+ import * as fs21 from "fs";
7938
+ import * as path16 from "path";
7939
+ var { chain: chain9 } = import_stream_chain9.default;
7940
+ var { parser: parser10 } = import_stream_json9.default;
7941
+ var { pick: pick8 } = import_Pick8.default;
7942
+ var { streamValues: streamValues9 } = import_StreamValues9.default;
7943
+ var GROUP_FILE = /^Takeout\/Google Chat\/Groups\/((DM|Space) [^/]+)\/(group_info|messages)\.json$/;
7944
+ var USER_INFO_FILE = /^Takeout\/Google Chat\/Users\/[^/]+\/user_info\.json$/;
7945
+ var TAKEOUT_ROOT = /^Takeout\/([^/]+)\//;
7946
+ var MAX_METADATA_BYTES = 5 * 1024 * 1024;
7947
+ async function readSmallJson(stream, maxBytes = MAX_METADATA_BYTES) {
7948
+ const chunks = [];
7949
+ let total = 0;
7950
+ for await (const chunk of stream) {
7951
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
7952
+ total += buffer.length;
7953
+ if (total > maxBytes) {
7954
+ throw new ArchiveImportError("error.archive_limit_exceeded", "Google Chat metadata exceeds the size limit");
7955
+ }
7956
+ chunks.push(buffer);
7957
+ }
7958
+ try {
7959
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
7960
+ } catch (error) {
7961
+ throw new ArchiveImportError("error.archive_corrupt", "Invalid Google Chat metadata JSON", { cause: error });
7962
+ }
7963
+ }
7964
+ async function countMessages(stream) {
7965
+ const pipeline2 = chain9([stream, parser10(), pick8({ filter: /^messages\.\d+$/ }), streamValues9()]);
7966
+ let count = 0;
7967
+ try {
7968
+ for await (const _item of pipeline2) count++;
7969
+ return count;
7970
+ } catch (error) {
7971
+ throw new ArchiveImportError("error.archive_corrupt", "Invalid Google Chat messages JSON", { cause: error });
7972
+ }
7973
+ }
7974
+ function normalizeEmail(user) {
7975
+ return user?.email?.trim().toLowerCase() || null;
7976
+ }
7977
+ function deriveConversationName(draft, ownerEmail) {
7978
+ const groupInfo = draft.groupInfo;
7979
+ if (draft.kind === "Space" && groupInfo?.name?.trim()) return groupInfo.name.trim();
7980
+ const members = groupInfo?.members ?? [];
7981
+ const other = members.find((member) => {
7982
+ const email = normalizeEmail(member);
7983
+ return !ownerEmail || email !== ownerEmail;
7984
+ });
7985
+ return other?.name?.trim() || other?.email?.trim() || members[0]?.name?.trim() || draft.chatId;
7986
+ }
7987
+ var GoogleChatTakeoutResolver = class {
7988
+ id = "google-chat-takeout";
7989
+ platform = "google-chat";
7990
+ detect(entries) {
7991
+ const products = /* @__PURE__ */ new Set();
7992
+ const groupFiles = /* @__PURE__ */ new Map();
7993
+ for (const entry of entries) {
7994
+ const product = entry.name.match(TAKEOUT_ROOT)?.[1];
7995
+ if (product) products.add(product);
7996
+ const match = entry.name.match(GROUP_FILE);
7997
+ if (!match) continue;
7998
+ const files = groupFiles.get(match[1]) ?? /* @__PURE__ */ new Set();
7999
+ files.add(match[3]);
8000
+ groupFiles.set(match[1], files);
8001
+ }
8002
+ return products.size === 1 && products.has("Google Chat") && Array.from(groupFiles.values()).some((files) => files.has("group_info") && files.has("messages"));
8003
+ }
8004
+ /**
8005
+ * 扫描时按 ZIP 顺序消费必要 JSON。会话元数据和消息计数先暂存,
8006
+ * 等 owner 信息齐备后统一生成名称,避免依赖归档内部文件顺序。
8007
+ */
8008
+ async scan(reader) {
8009
+ let ownerEmail = null;
8010
+ const drafts = /* @__PURE__ */ new Map();
8011
+ await reader.visitEntries(async (entry, openStream) => {
8012
+ if (USER_INFO_FILE.test(entry.name)) {
8013
+ const ownerInfo = await readSmallJson(await openStream());
8014
+ ownerEmail = normalizeEmail(ownerInfo.user);
8015
+ return;
8016
+ }
8017
+ const match = entry.name.match(GROUP_FILE);
8018
+ if (!match) return;
8019
+ const chatId = `Groups/${match[1]}`;
8020
+ const draft = drafts.get(chatId) ?? {
8021
+ chatId,
8022
+ kind: match[2]
8023
+ };
8024
+ if (match[3] === "group_info") {
8025
+ draft.groupInfoEntry = entry.name;
8026
+ draft.groupInfo = await readSmallJson(await openStream());
8027
+ } else {
8028
+ draft.messagesEntry = entry.name;
8029
+ draft.messageCount = await countMessages(await openStream());
8030
+ }
8031
+ drafts.set(chatId, draft);
8032
+ });
8033
+ if (drafts.size === 0) {
8034
+ throw new ArchiveImportError(
8035
+ "error.google_chat_structure_not_found",
8036
+ "Google Chat conversation structure was not found"
8037
+ );
8038
+ }
8039
+ return Array.from(drafts.values()).map((draft) => {
8040
+ if (!draft.groupInfoEntry || !draft.messagesEntry || !draft.groupInfo || draft.messageCount === void 0) {
8041
+ throw new ArchiveImportError(
8042
+ "error.google_chat_conversation_incomplete",
8043
+ `Google Chat conversation is missing required files: ${draft.chatId}`
8044
+ );
8045
+ }
8046
+ return {
8047
+ chatId: draft.chatId,
8048
+ name: deriveConversationName(draft, ownerEmail),
8049
+ type: draft.kind === "Space" ? "group" : "private",
8050
+ messageCount: draft.messageCount,
8051
+ memberCount: draft.groupInfo.members?.length ?? 0
8052
+ };
8053
+ }).sort((a, b) => a.chatId.localeCompare(b.chatId));
8054
+ }
8055
+ async materialize(reader, chat, targetDir) {
8056
+ const entries = await reader.listEntries();
8057
+ const groupPrefix = `Takeout/Google Chat/${chat.chatId}/`;
8058
+ const userInfoEntry = entries.find((entry) => USER_INFO_FILE.test(entry.name))?.name;
8059
+ const groupInfoEntry = `${groupPrefix}group_info.json`;
8060
+ const messagesEntry = `${groupPrefix}messages.json`;
8061
+ if (!userInfoEntry || !entries.some((entry) => entry.name === groupInfoEntry) || !entries.some((entry) => entry.name === messagesEntry)) {
8062
+ throw new ArchiveImportError(
8063
+ "error.google_chat_conversation_incomplete",
8064
+ `Google Chat conversation is missing required files: ${chat.chatId}`
8065
+ );
8066
+ }
8067
+ fs21.mkdirSync(targetDir, { recursive: true });
8068
+ await reader.pipeEntries(
8069
+ /* @__PURE__ */ new Map([
8070
+ [userInfoEntry, path16.join(targetDir, "user_info.json")],
8071
+ [groupInfoEntry, path16.join(targetDir, "group_info.json")],
8072
+ [messagesEntry, path16.join(targetDir, "messages.json")]
8073
+ ])
8074
+ );
8075
+ const manifestPath = path16.join(targetDir, "google-chat-import.json");
8076
+ fs21.writeFileSync(
8077
+ manifestPath,
8078
+ JSON.stringify(
8079
+ {
8080
+ format: "chatlab-google-chat-takeout",
8081
+ version: 1,
8082
+ chatId: chat.chatId,
8083
+ chatType: chat.type,
8084
+ chatName: chat.name,
8085
+ userInfoFile: "user_info.json",
8086
+ groupInfoFile: "group_info.json",
8087
+ messagesFile: "messages.json"
8088
+ },
8089
+ null,
8090
+ 2
8091
+ ),
8092
+ { encoding: "utf8", flag: "wx" }
8093
+ );
8094
+ return { manifestPath };
8095
+ }
8096
+ };
8097
+
8098
+ // ../../packages/node-runtime/src/import/archive/source-manager.ts
8099
+ import * as fs22 from "fs";
8100
+ import * as path17 from "path";
8101
+ import { randomUUID } from "crypto";
8102
+ var DEFAULT_TTL_MS = 30 * 60 * 1e3;
8103
+ var ArchiveImportSourceManager = class {
8104
+ records = /* @__PURE__ */ new Map();
8105
+ expiredSourceIds = /* @__PURE__ */ new Set();
8106
+ tempRoot;
8107
+ ttlMs;
8108
+ now;
8109
+ resolvers;
8110
+ constructor(options2 = {}) {
8111
+ this.tempRoot = options2.tempRoot ?? path17.join(process.cwd(), ".chatlab-import-sources");
8112
+ this.ttlMs = options2.ttlMs ?? DEFAULT_TTL_MS;
8113
+ this.now = options2.now ?? Date.now;
8114
+ this.resolvers = options2.resolvers ?? [new GoogleChatTakeoutResolver()];
8115
+ fs22.mkdirSync(this.tempRoot, { recursive: true });
8116
+ }
8117
+ prepareLocalArchive(archivePath) {
8118
+ return this.prepareArchive(archivePath, false);
8119
+ }
8120
+ prepareOwnedArchive(archivePath) {
8121
+ return this.prepareArchive(archivePath, true);
8122
+ }
8123
+ async prepareArchive(archivePath, ownsArchive) {
8124
+ await this.cleanupExpired();
8125
+ const reader = new ZipArchiveReader(archivePath);
8126
+ try {
8127
+ const entries = await reader.listEntries();
8128
+ const matches = this.resolvers.filter((resolver2) => resolver2.detect(entries));
8129
+ if (matches.length !== 1) {
8130
+ throw new ArchiveImportError(
8131
+ "error.archive_unsupported",
8132
+ matches.length === 0 ? "Unsupported archive format" : "Archive matches multiple import formats"
8133
+ );
8134
+ }
8135
+ const resolver = matches[0];
8136
+ const chats = await resolver.scan(reader);
8137
+ const createdAt = this.now();
8138
+ const sourceId = randomUUID();
8139
+ const descriptor = {
8140
+ sourceId,
8141
+ formatId: resolver.id,
8142
+ platform: resolver.platform,
8143
+ chats,
8144
+ expiresAt: createdAt + this.ttlMs
8145
+ };
8146
+ this.records.set(sourceId, {
8147
+ descriptor,
8148
+ archivePath,
8149
+ ownsArchive,
8150
+ resolver,
8151
+ lastAccessAt: createdAt
8152
+ });
8153
+ return descriptor;
8154
+ } catch (error) {
8155
+ if (ownsArchive) this.removePath(archivePath);
8156
+ throw error;
8157
+ }
8158
+ }
8159
+ /**
8160
+ * selected chat 的 JSON 物化目录只在 handler 生命周期内存在。
8161
+ * 无论数据库导入成功、失败还是抛异常,finally 都会删除它。
8162
+ */
8163
+ async withMaterializedChat(sourceId, chatId, handler) {
8164
+ const record = await this.getActiveRecord(sourceId);
8165
+ const chat = record.descriptor.chats.find((item) => item.chatId === chatId);
8166
+ if (!chat) {
8167
+ throw new ArchiveImportError(
8168
+ "error.google_chat_conversation_incomplete",
8169
+ `Archive conversation was not found: ${chatId}`
8170
+ );
8171
+ }
8172
+ const materializedDir = fs22.mkdtempSync(path17.join(this.tempRoot, `materialized-${sourceId}-`));
8173
+ try {
8174
+ const reader = new ZipArchiveReader(record.archivePath);
8175
+ const materialized = await record.resolver.materialize(reader, chat, materializedDir);
8176
+ return await handler(materialized.manifestPath);
8177
+ } finally {
8178
+ this.removePath(materializedDir);
8179
+ }
8180
+ }
8181
+ async release(sourceId) {
8182
+ const record = this.records.get(sourceId);
8183
+ if (!record) return;
8184
+ this.records.delete(sourceId);
8185
+ if (record.ownsArchive) this.removePath(record.archivePath);
8186
+ }
8187
+ async cleanupExpired(now = this.now()) {
8188
+ let removed = 0;
8189
+ for (const [sourceId, record] of this.records) {
8190
+ if (now - record.lastAccessAt < this.ttlMs) continue;
8191
+ this.records.delete(sourceId);
8192
+ this.expiredSourceIds.add(sourceId);
8193
+ if (record.ownsArchive) this.removePath(record.archivePath);
8194
+ removed++;
8195
+ }
8196
+ return removed;
8197
+ }
8198
+ async close() {
8199
+ for (const sourceId of Array.from(this.records.keys())) {
8200
+ await this.release(sourceId);
8201
+ }
8202
+ this.removePath(this.tempRoot);
8203
+ }
8204
+ async getActiveRecord(sourceId) {
8205
+ const record = this.records.get(sourceId);
8206
+ if (!record) {
8207
+ const code = this.expiredSourceIds.has(sourceId) ? "error.import_source_expired" : "error.import_source_not_found";
8208
+ throw new ArchiveImportError(code, `Archive import source is unavailable: ${sourceId}`);
8209
+ }
8210
+ const now = this.now();
8211
+ if (now - record.lastAccessAt >= this.ttlMs) {
8212
+ this.records.delete(sourceId);
8213
+ this.expiredSourceIds.add(sourceId);
8214
+ if (record.ownsArchive) this.removePath(record.archivePath);
8215
+ throw new ArchiveImportError("error.import_source_expired", `Archive import source expired: ${sourceId}`);
8216
+ }
8217
+ record.lastAccessAt = now;
8218
+ record.descriptor.expiresAt = now + this.ttlMs;
8219
+ return record;
8220
+ }
8221
+ removePath(targetPath) {
8222
+ try {
8223
+ fs22.rmSync(targetPath, { recursive: true, force: true });
8224
+ } catch {
8225
+ }
8226
+ }
8227
+ };
8228
+
8229
+ // ../../packages/node-runtime/src/logging/app-logger.ts
8230
+ import * as fs23 from "fs";
8231
+ import * as path18 from "path";
8232
+ var LEVEL_ORDER = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 };
8233
+ var MAX_SIZE_BYTES = 10 * 1024 * 1024;
8234
+ var AppLogger = class {
8235
+ logFile;
8236
+ oldLogFile;
8237
+ threshold;
8238
+ constructor(logsDir) {
8239
+ this.logFile = path18.join(logsDir, "app.log");
8240
+ this.oldLogFile = path18.join(logsDir, "app.old.log");
8241
+ this.threshold = resolveThreshold();
8242
+ }
8243
+ debug(scope, message, data) {
8244
+ this.write("DEBUG", scope, message, data);
8245
+ }
8246
+ info(scope, message, data) {
8247
+ this.write("INFO", scope, message, data);
8248
+ }
8249
+ warn(scope, message, data) {
8250
+ this.write("WARN", scope, message, data);
8251
+ }
8252
+ /** `data` may be an Error; its name/message/stack are extracted automatically. */
8253
+ error(scope, message, data) {
8254
+ this.write("ERROR", scope, message, data);
8255
+ }
8256
+ getLogPath() {
8257
+ return this.logFile;
8258
+ }
8259
+ write(level, scope, message, data) {
8260
+ if (LEVEL_ORDER[level] < LEVEL_ORDER[this.threshold]) return;
8261
+ let line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] [${scope}] ${message}`;
8262
+ try {
8263
+ const tail = formatData(data);
8264
+ if (tail) line += `
8265
+ ${tail}`;
8266
+ line += "\n";
8267
+ ensureDir2(path18.dirname(this.logFile));
8268
+ this.rotateIfNeeded();
8269
+ fs23.appendFileSync(this.logFile, line, "utf-8");
8270
+ } catch (err) {
8271
+ console.error("[AppLogger] Failed to write log:", err);
8272
+ }
8273
+ }
8274
+ // ponytail: rename-based rotation, atomic, no rewrite, ~20MB total ceiling
8275
+ rotateIfNeeded() {
8276
+ let size = 0;
8277
+ try {
8278
+ size = fs23.statSync(this.logFile).size;
8279
+ } catch {
8280
+ return;
8281
+ }
8282
+ if (size < MAX_SIZE_BYTES) return;
8283
+ fs23.renameSync(this.logFile, this.oldLogFile);
8284
+ }
8285
+ };
8286
+ function resolveThreshold() {
8287
+ const raw = (process.env.CHATLAB_LOG_LEVEL || "").toUpperCase();
8288
+ if (raw === "DEBUG" || raw === "INFO" || raw === "WARN" || raw === "ERROR") return raw;
8289
+ return "INFO";
8290
+ }
8291
+ function formatData(data) {
8292
+ if (data === void 0) return "";
8293
+ if (data instanceof Error) {
8294
+ const info = extractErrorInfo(data);
8295
+ const stack = extractErrorStack(data);
8296
+ return JSON.stringify(info) + (stack ? `
8297
+ ${stack}` : "");
8298
+ }
8299
+ if (typeof data === "string") return data;
8300
+ try {
8301
+ return JSON.stringify(data);
8302
+ } catch {
8303
+ return "[unserializable data]";
8304
+ }
8305
+ }
8306
+ function ensureDir2(dir) {
8307
+ if (!fs23.existsSync(dir)) fs23.mkdirSync(dir, { recursive: true });
8308
+ }
8309
+ var instance = null;
8310
+ function initAppLogger(logsDir) {
8311
+ instance = new AppLogger(logsDir);
8312
+ }
8313
+ var appLogger = {
8314
+ debug: (scope, message, data) => instance?.debug(scope, message, data),
8315
+ info: (scope, message, data) => instance?.info(scope, message, data),
8316
+ warn: (scope, message, data) => instance?.warn(scope, message, data),
8317
+ error: (scope, message, data) => instance?.error(scope, message, data),
8318
+ getLogPath: () => instance?.getLogPath() ?? null
8319
+ };
8320
+
8321
+ // ../../packages/node-runtime/src/node-path-provider.ts
8322
+ import * as fs25 from "fs";
8323
+ import * as os2 from "os";
8324
+ import * as path20 from "path";
6201
8325
 
6202
8326
  // ../../packages/node-runtime/src/data-dir-switch.ts
6203
- import * as fs19 from "fs";
6204
- import * as path14 from "path";
8327
+ import * as fs24 from "fs";
8328
+ import * as path19 from "path";
6205
8329
  var CHATLAB_MARKER_FILE = ".chatlab";
6206
8330
  var USER_DATA_REQUIRED_DIRS = ["databases"];
6207
8331
  var PENDING_MIGRATION_FILE = "data-dir-migration.json";
@@ -6222,15 +8346,15 @@ var DANGEROUS_PATHS = [
6222
8346
  "/Library"
6223
8347
  ];
6224
8348
  function normalizePathForCompare(input) {
6225
- const resolved = path14.resolve(input);
6226
- const normalized = path14.normalize(resolved);
8349
+ const resolved = path19.resolve(input);
8350
+ const normalized = path19.normalize(resolved);
6227
8351
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
6228
8352
  }
6229
8353
  function isSubPath(parent, child) {
6230
8354
  const parentPath = normalizePathForCompare(parent);
6231
8355
  const childPath = normalizePathForCompare(child);
6232
8356
  if (parentPath === childPath) return false;
6233
- return childPath.startsWith(`${parentPath}${path14.sep}`);
8357
+ return childPath.startsWith(`${parentPath}${path19.sep}`);
6234
8358
  }
6235
8359
  function isPathSafe(targetPath) {
6236
8360
  const normalizedTarget = targetPath.toLowerCase().replace(/\//g, "\\");
@@ -6242,37 +8366,37 @@ function isPathSafe(targetPath) {
6242
8366
  }
6243
8367
  return true;
6244
8368
  }
6245
- function ensureDir2(dirPath) {
6246
- if (!fs19.existsSync(dirPath)) {
6247
- fs19.mkdirSync(dirPath, { recursive: true });
8369
+ function ensureDir3(dirPath) {
8370
+ if (!fs24.existsSync(dirPath)) {
8371
+ fs24.mkdirSync(dirPath, { recursive: true });
6248
8372
  }
6249
8373
  }
6250
8374
  function hasChatLabUserDataStructure(entries) {
6251
8375
  return entries.includes(CHATLAB_MARKER_FILE) && USER_DATA_REQUIRED_DIRS.every((dir) => entries.includes(dir));
6252
8376
  }
6253
8377
  function hasChatLabDatabaseFiles(dirPath, entries) {
6254
- const dirEntries = entries ?? fs19.readdirSync(dirPath);
8378
+ const dirEntries = entries ?? fs24.readdirSync(dirPath);
6255
8379
  if (!dirEntries.includes("databases")) return false;
6256
- const dbDir = path14.join(dirPath, "databases");
8380
+ const dbDir = path19.join(dirPath, "databases");
6257
8381
  try {
6258
- return fs19.existsSync(dbDir) && fs19.readdirSync(dbDir).some((file) => file.endsWith(".db"));
8382
+ return fs24.existsSync(dbDir) && fs24.readdirSync(dbDir).some((file) => file.endsWith(".db"));
6259
8383
  } catch {
6260
8384
  return false;
6261
8385
  }
6262
8386
  }
6263
8387
  function isExistingUserDataDir(dirPath) {
6264
- if (!fs19.existsSync(dirPath)) return false;
8388
+ if (!fs24.existsSync(dirPath)) return false;
6265
8389
  try {
6266
- const entries = fs19.readdirSync(dirPath);
8390
+ const entries = fs24.readdirSync(dirPath);
6267
8391
  return hasChatLabUserDataStructure(entries) || hasChatLabDatabaseFiles(dirPath, entries);
6268
8392
  } catch {
6269
8393
  return false;
6270
8394
  }
6271
8395
  }
6272
8396
  function isUserDataDirSafeToUse(dirPath) {
6273
- if (!fs19.existsSync(dirPath)) return true;
8397
+ if (!fs24.existsSync(dirPath)) return true;
6274
8398
  try {
6275
- const entries = fs19.readdirSync(dirPath);
8399
+ const entries = fs24.readdirSync(dirPath);
6276
8400
  if (entries.length === 0) return true;
6277
8401
  return hasChatLabUserDataStructure(entries) || hasChatLabDatabaseFiles(dirPath, entries);
6278
8402
  } catch {
@@ -6280,26 +8404,26 @@ function isUserDataDirSafeToUse(dirPath) {
6280
8404
  }
6281
8405
  }
6282
8406
  function isDirectoryEmptyOrMissing(dirPath) {
6283
- if (!fs19.existsSync(dirPath)) return true;
8407
+ if (!fs24.existsSync(dirPath)) return true;
6284
8408
  try {
6285
- return fs19.readdirSync(dirPath).length === 0;
8409
+ return fs24.readdirSync(dirPath).length === 0;
6286
8410
  } catch {
6287
8411
  return false;
6288
8412
  }
6289
8413
  }
6290
- function copyDirMerge(src, dest, mkdir = ensureDir2, stats = { copied: 0, skipped: 0, errors: [] }) {
6291
- if (!fs19.existsSync(src)) return stats;
8414
+ function copyDirMerge(src, dest, mkdir = ensureDir3, stats = { copied: 0, skipped: 0, errors: [] }) {
8415
+ if (!fs24.existsSync(src)) return stats;
6292
8416
  try {
6293
8417
  mkdir(dest);
6294
- const entries = fs19.readdirSync(src, { withFileTypes: true });
8418
+ const entries = fs24.readdirSync(src, { withFileTypes: true });
6295
8419
  for (const entry of entries) {
6296
- const srcPath = path14.join(src, entry.name);
6297
- const destPath = path14.join(dest, entry.name);
8420
+ const srcPath = path19.join(src, entry.name);
8421
+ const destPath = path19.join(dest, entry.name);
6298
8422
  try {
6299
8423
  if (entry.isDirectory()) {
6300
8424
  copyDirMerge(srcPath, destPath, mkdir, stats);
6301
- } else if (!fs19.existsSync(destPath)) {
6302
- fs19.copyFileSync(srcPath, destPath);
8425
+ } else if (!fs24.existsSync(destPath)) {
8426
+ fs24.copyFileSync(srcPath, destPath);
6303
8427
  stats.copied++;
6304
8428
  } else {
6305
8429
  stats.skipped++;
@@ -6324,10 +8448,10 @@ function createPendingDataDirMigration(input) {
6324
8448
  }
6325
8449
  function runPendingDataDirMigration(pending, deps) {
6326
8450
  const copy = deps.copyDirMerge ?? copyDirMerge;
6327
- const mkdir = deps.ensureDir ?? ensureDir2;
8451
+ const mkdir = deps.ensureDir ?? ensureDir3;
6328
8452
  let stats = { copied: 0, skipped: 0, errors: [] };
6329
- if (pending.migrate && path14.resolve(pending.from) !== path14.resolve(pending.to)) {
6330
- if (!fs19.existsSync(pending.from)) {
8453
+ if (pending.migrate && path19.resolve(pending.from) !== path19.resolve(pending.to)) {
8454
+ if (!fs24.existsSync(pending.from)) {
6331
8455
  return {
6332
8456
  success: false,
6333
8457
  from: pending.from,
@@ -6356,7 +8480,7 @@ function runPendingDataDirMigration(pending, deps) {
6356
8480
  }
6357
8481
  deps.writeUserDataDir(pending.to);
6358
8482
  deps.clearPendingMigration();
6359
- if (pending.deleteSourceOnSuccess && path14.resolve(pending.from) !== path14.resolve(pending.to)) {
8483
+ if (pending.deleteSourceOnSuccess && path19.resolve(pending.from) !== path19.resolve(pending.to)) {
6360
8484
  deps.markPendingDeleteDir?.(pending.from);
6361
8485
  }
6362
8486
  return {
@@ -6369,13 +8493,13 @@ function runPendingDataDirMigration(pending, deps) {
6369
8493
  };
6370
8494
  }
6371
8495
  function getPendingMigrationPath(systemDir) {
6372
- return path14.join(systemDir, "settings", PENDING_MIGRATION_FILE);
8496
+ return path19.join(systemDir, "settings", PENDING_MIGRATION_FILE);
6373
8497
  }
6374
8498
  function getPendingNodeDataDirMigration(systemDir) {
6375
8499
  const filePath = getPendingMigrationPath(systemDir);
6376
- if (!fs19.existsSync(filePath)) return null;
8500
+ if (!fs24.existsSync(filePath)) return null;
6377
8501
  try {
6378
- const parsed = JSON.parse(fs19.readFileSync(filePath, "utf-8"));
8502
+ const parsed = JSON.parse(fs24.readFileSync(filePath, "utf-8"));
6379
8503
  if (!parsed.from || !parsed.to || typeof parsed.migrate !== "boolean") return null;
6380
8504
  return parsed;
6381
8505
  } catch {
@@ -6384,23 +8508,23 @@ function getPendingNodeDataDirMigration(systemDir) {
6384
8508
  }
6385
8509
  function clearPendingNodeDataDirMigration(systemDir) {
6386
8510
  const filePath = getPendingMigrationPath(systemDir);
6387
- if (fs19.existsSync(filePath)) {
6388
- fs19.unlinkSync(filePath);
8511
+ if (fs24.existsSync(filePath)) {
8512
+ fs24.unlinkSync(filePath);
6389
8513
  }
6390
8514
  }
6391
8515
  function deleteOldUserDataDirIfSafe(dirPath, currentDir, removeDir) {
6392
- if (path14.resolve(dirPath) === path14.resolve(currentDir)) return false;
8516
+ if (path19.resolve(dirPath) === path19.resolve(currentDir)) return false;
6393
8517
  if (!isPathSafe(dirPath)) return false;
6394
- if (!fs19.existsSync(dirPath)) return false;
8518
+ if (!fs24.existsSync(dirPath)) return false;
6395
8519
  if (!isExistingUserDataDir(dirPath)) return false;
6396
- const remove = removeDir ?? ((dir) => fs19.rmSync(dir, { recursive: true, force: true }));
8520
+ const remove = removeDir ?? ((dir) => fs24.rmSync(dir, { recursive: true, force: true }));
6397
8521
  remove(dirPath);
6398
8522
  return true;
6399
8523
  }
6400
8524
  function writePendingNodeDataDirMigration(systemDir, pending) {
6401
8525
  const filePath = getPendingMigrationPath(systemDir);
6402
- ensureDir2(path14.dirname(filePath));
6403
- fs19.writeFileSync(filePath, JSON.stringify(pending, null, 2), "utf-8");
8526
+ ensureDir3(path19.dirname(filePath));
8527
+ fs24.writeFileSync(filePath, JSON.stringify(pending, null, 2), "utf-8");
6404
8528
  }
6405
8529
  function createNodeDataDirSwitch(input) {
6406
8530
  if (input.envDataDir) {
@@ -6408,16 +8532,16 @@ function createNodeDataDirSwitch(input) {
6408
8532
  }
6409
8533
  const newDir = (input.targetDir?.trim() || input.defaultDir || "").trim();
6410
8534
  if (!newDir) return { success: false, error: "Data directory is required" };
6411
- if (!path14.isAbsolute(newDir)) return { success: false, error: "Data directory must be an absolute path" };
8535
+ if (!path19.isAbsolute(newDir)) return { success: false, error: "Data directory must be an absolute path" };
6412
8536
  if (!isPathSafe(newDir)) return { success: false, error: "System directories cannot be used as data directory" };
6413
8537
  const migrate = input.migrate !== false;
6414
- if (migrate && path14.resolve(input.currentDir) !== path14.resolve(newDir) && isSubPath(input.currentDir, newDir)) {
8538
+ if (migrate && path19.resolve(input.currentDir) !== path19.resolve(newDir) && isSubPath(input.currentDir, newDir)) {
6415
8539
  return { success: false, error: "Target directory cannot be inside current data directory" };
6416
8540
  }
6417
8541
  if (!isUserDataDirSafeToUse(newDir)) {
6418
8542
  return { success: false, error: "Target directory is not empty and is not a ChatLab data directory" };
6419
8543
  }
6420
- if (path14.resolve(input.currentDir) === path14.resolve(newDir)) {
8544
+ if (path19.resolve(input.currentDir) === path19.resolve(newDir)) {
6421
8545
  clearPendingNodeDataDirMigration(input.systemDir);
6422
8546
  return { success: true, from: input.currentDir, to: newDir, requiresRelaunch: false };
6423
8547
  }
@@ -6453,7 +8577,7 @@ function applyPendingNodeDataDirMigration(systemDir, deps = {}) {
6453
8577
  }
6454
8578
 
6455
8579
  // ../../packages/node-runtime/src/node-path-provider.ts
6456
- var SYSTEM_DIR = path15.join(os2.homedir(), ".chatlab");
8580
+ var SYSTEM_DIR = path20.join(os2.homedir(), ".chatlab");
6457
8581
  var _pendingElectronDataWarning = false;
6458
8582
  function hasPendingElectronDataWarning() {
6459
8583
  return _pendingElectronDataWarning;
@@ -6476,28 +8600,28 @@ var NodePathProvider = class {
6476
8600
  return this.userDataDir;
6477
8601
  }
6478
8602
  getDatabaseDir() {
6479
- return path15.join(this.userDataDir, "databases");
8603
+ return path20.join(this.userDataDir, "databases");
6480
8604
  }
6481
8605
  getVectorDir() {
6482
- return path15.join(this.userDataDir, "vector");
8606
+ return path20.join(this.userDataDir, "vector");
6483
8607
  }
6484
8608
  getAiDataDir() {
6485
- return path15.join(this.systemDir, "ai");
8609
+ return path20.join(this.systemDir, "ai");
6486
8610
  }
6487
8611
  getSettingsDir() {
6488
- return path15.join(this.systemDir, "settings");
8612
+ return path20.join(this.systemDir, "settings");
6489
8613
  }
6490
8614
  getCacheDir() {
6491
- return path15.join(this.systemDir, "cache");
8615
+ return path20.join(this.systemDir, "cache");
6492
8616
  }
6493
8617
  getTempDir() {
6494
- return path15.join(this.systemDir, "temp");
8618
+ return path20.join(this.systemDir, "temp");
6495
8619
  }
6496
8620
  getLogsDir() {
6497
- return path15.join(this.systemDir, "logs");
8621
+ return path20.join(this.systemDir, "logs");
6498
8622
  }
6499
8623
  getDownloadsDir() {
6500
- return path15.join(os2.homedir(), "Downloads");
8624
+ return path20.join(os2.homedir(), "Downloads");
6501
8625
  }
6502
8626
  /**
6503
8627
  * 确保系统目录和用户数据目录都存在
@@ -6515,13 +8639,13 @@ var NodePathProvider = class {
6515
8639
  this.getLogsDir()
6516
8640
  ];
6517
8641
  for (const dir of dirs) {
6518
- if (!fs20.existsSync(dir)) {
6519
- fs20.mkdirSync(dir, { recursive: true });
8642
+ if (!fs25.existsSync(dir)) {
8643
+ fs25.mkdirSync(dir, { recursive: true });
6520
8644
  }
6521
8645
  }
6522
- const markerPath = path15.join(this.userDataDir, ".chatlab");
6523
- if (!fs20.existsSync(markerPath)) {
6524
- fs20.writeFileSync(markerPath, "ChatLab Data Directory", "utf-8");
8646
+ const markerPath = path20.join(this.userDataDir, ".chatlab");
8647
+ if (!fs25.existsSync(markerPath)) {
8648
+ fs25.writeFileSync(markerPath, "ChatLab Data Directory", "utf-8");
6525
8649
  }
6526
8650
  }
6527
8651
  };
@@ -6547,11 +8671,14 @@ function resolveUserDataDir() {
6547
8671
  return defaultDir;
6548
8672
  }
6549
8673
  function getDefaultNodeUserDataDir() {
6550
- return path15.join(os2.homedir(), ".chatlab", "data");
8674
+ return path20.join(os2.homedir(), ".chatlab", "data");
8675
+ }
8676
+ function getSystemLogsDir() {
8677
+ return path20.join(SYSTEM_DIR, "logs");
6551
8678
  }
6552
8679
  function expandHome(filePath) {
6553
8680
  if (filePath.startsWith("~/") || filePath === "~") {
6554
- return path15.join(os2.homedir(), filePath.slice(1));
8681
+ return path20.join(os2.homedir(), filePath.slice(1));
6555
8682
  }
6556
8683
  return filePath;
6557
8684
  }
@@ -6568,12 +8695,12 @@ function createJiebaNlpProvider(dictType = "default") {
6568
8695
  }
6569
8696
 
6570
8697
  // ../../packages/node-runtime/src/cache/analytics-cache.ts
6571
- import * as fs21 from "fs";
8698
+ import * as fs26 from "fs";
6572
8699
  function getDbFileVersion(dbPath) {
6573
8700
  const parts = [];
6574
8701
  for (const p of [dbPath, `${dbPath}-wal`]) {
6575
8702
  try {
6576
- const st = fs21.statSync(p);
8703
+ const st = fs26.statSync(p);
6577
8704
  parts.push(`${Math.floor(st.mtimeMs)}:${st.size}`);
6578
8705
  } catch {
6579
8706
  parts.push("-");
@@ -6592,8 +8719,8 @@ function getOrComputeAnalysisCache(sessionId, key, queryCacheDir, version, compu
6592
8719
  }
6593
8720
 
6594
8721
  // ../../packages/node-runtime/src/preferences.ts
6595
- import * as fs22 from "fs";
6596
- import * as path16 from "path";
8722
+ import * as fs27 from "fs";
8723
+ import * as path21 from "path";
6597
8724
  var DEFAULTS = {
6598
8725
  pinnedSessionIds: [],
6599
8726
  aiPreprocessConfig: {
@@ -6639,13 +8766,13 @@ var PreferencesManager = class {
6639
8766
  filePath;
6640
8767
  cache = null;
6641
8768
  constructor(systemDir) {
6642
- this.filePath = path16.join(systemDir, "preferences.json");
8769
+ this.filePath = path21.join(systemDir, "preferences.json");
6643
8770
  }
6644
8771
  load() {
6645
8772
  if (this.cache) return this.cache;
6646
8773
  try {
6647
- if (fs22.existsSync(this.filePath)) {
6648
- const raw = fs22.readFileSync(this.filePath, "utf-8");
8774
+ if (fs27.existsSync(this.filePath)) {
8775
+ const raw = fs27.readFileSync(this.filePath, "utf-8");
6649
8776
  const parsed = JSON.parse(raw);
6650
8777
  const migrated = this.migrateLegacyDesensitizeRules(parsed, raw);
6651
8778
  this.cache = this.mergeDefaults(migrated.preferences);
@@ -6760,21 +8887,21 @@ var PreferencesManager = class {
6760
8887
  };
6761
8888
  }
6762
8889
  backupLegacyPreferences(rawContent) {
6763
- const backupDir = path16.join(path16.dirname(this.filePath), "backups");
6764
- if (!fs22.existsSync(backupDir)) {
6765
- fs22.mkdirSync(backupDir, { recursive: true });
8890
+ const backupDir = path21.join(path21.dirname(this.filePath), "backups");
8891
+ if (!fs27.existsSync(backupDir)) {
8892
+ fs27.mkdirSync(backupDir, { recursive: true });
6766
8893
  }
6767
8894
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
6768
- const backupPath = path16.join(backupDir, `preferences-pre-desensitize-groups-${timestamp}.json`);
6769
- fs22.writeFileSync(backupPath, rawContent, "utf-8");
8895
+ const backupPath = path21.join(backupDir, `preferences-pre-desensitize-groups-${timestamp}.json`);
8896
+ fs27.writeFileSync(backupPath, rawContent, "utf-8");
6770
8897
  console.info(`[Preferences] Backed up legacy desensitize rules to ${backupPath}`);
6771
8898
  }
6772
8899
  writePreferences(preferences) {
6773
- const dir = path16.dirname(this.filePath);
6774
- if (!fs22.existsSync(dir)) {
6775
- fs22.mkdirSync(dir, { recursive: true });
8900
+ const dir = path21.dirname(this.filePath);
8901
+ if (!fs27.existsSync(dir)) {
8902
+ fs27.mkdirSync(dir, { recursive: true });
6776
8903
  }
6777
- fs22.writeFileSync(this.filePath, JSON.stringify(preferences, null, 2), "utf-8");
8904
+ fs27.writeFileSync(this.filePath, JSON.stringify(preferences, null, 2), "utf-8");
6778
8905
  }
6779
8906
  /**
6780
8907
  * Deep merge: arrays are replaced (not concatenated), objects are merged.
@@ -6893,6 +9020,101 @@ function* serializeChatLabToJsonl(data) {
6893
9020
  }
6894
9021
  }
6895
9022
 
9023
+ // ../../packages/node-runtime/src/services/analytics.ts
9024
+ import * as fs28 from "fs";
9025
+ import * as path22 from "path";
9026
+ var REGIONS = {
9027
+ US: "https://us.aptabase.com",
9028
+ EU: "https://eu.aptabase.com"
9029
+ };
9030
+ var DEFAULT_DATA = { lastReportDate: null, firstReportDate: null, enabled: true };
9031
+ var AnalyticsService = class {
9032
+ dataPath;
9033
+ endpoint;
9034
+ appKey;
9035
+ appVersion;
9036
+ sessionId;
9037
+ constructor(systemDir, appKey, appVersion) {
9038
+ this.dataPath = path22.join(systemDir, "analytics.json");
9039
+ this.appKey = appKey;
9040
+ this.appVersion = appVersion;
9041
+ this.sessionId = `${Math.floor(Date.now() / 1e3)}${Math.floor(Math.random() * 1e8).toString().padStart(8, "0")}`;
9042
+ const parts = appKey.split("-");
9043
+ const base = parts.length === 3 ? REGIONS[parts[1]] : void 0;
9044
+ this.endpoint = base ? `${base}/api/v0/event` : null;
9045
+ }
9046
+ load() {
9047
+ try {
9048
+ if (fs28.existsSync(this.dataPath)) {
9049
+ return { ...DEFAULT_DATA, ...JSON.parse(fs28.readFileSync(this.dataPath, "utf-8")) };
9050
+ }
9051
+ } catch (_e) {
9052
+ }
9053
+ return { ...DEFAULT_DATA };
9054
+ }
9055
+ save(data) {
9056
+ try {
9057
+ fs28.writeFileSync(this.dataPath, JSON.stringify(data, null, 2), "utf-8");
9058
+ } catch (e) {
9059
+ console.error("[Analytics] Failed to save:", e);
9060
+ }
9061
+ }
9062
+ getEnabled() {
9063
+ return this.load().enabled;
9064
+ }
9065
+ setEnabled(enabled) {
9066
+ const data = this.load();
9067
+ data.enabled = enabled;
9068
+ this.save(data);
9069
+ }
9070
+ async track(eventName, props) {
9071
+ if (!this.endpoint) return false;
9072
+ if (!this.getEnabled()) return false;
9073
+ try {
9074
+ const resp = await fetch(this.endpoint, {
9075
+ method: "POST",
9076
+ headers: { "Content-Type": "application/json", "App-Key": this.appKey },
9077
+ body: JSON.stringify({
9078
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9079
+ sessionId: this.sessionId,
9080
+ eventName,
9081
+ systemProps: {
9082
+ isDebug: false,
9083
+ locale: "",
9084
+ osName: process.platform,
9085
+ osVersion: "",
9086
+ engineName: "Node.js",
9087
+ engineVersion: process.versions.node,
9088
+ appVersion: this.appVersion,
9089
+ sdkVersion: "chatlab@1"
9090
+ },
9091
+ props
9092
+ })
9093
+ });
9094
+ return resp.ok;
9095
+ } catch (e) {
9096
+ console.error(`[Analytics] Failed to track ${eventName}:`, e);
9097
+ return false;
9098
+ }
9099
+ }
9100
+ async trackDailyActive(props) {
9101
+ if (!this.endpoint) return;
9102
+ const data = this.load();
9103
+ if (!data.enabled) return;
9104
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9105
+ const isNew = data.firstReportDate === null;
9106
+ if (isNew) data.firstReportDate = today;
9107
+ if (data.lastReportDate === today) {
9108
+ if (isNew) this.save(data);
9109
+ return;
9110
+ }
9111
+ const tracked = await this.track(isNew ? "app_active_new" : "app_active", props);
9112
+ if (!tracked) return;
9113
+ data.lastReportDate = today;
9114
+ this.save(data);
9115
+ }
9116
+ };
9117
+
6896
9118
  // ../../packages/node-runtime/src/semantic-index/index.ts
6897
9119
  var semantic_index_exports = {};
6898
9120
  __export(semantic_index_exports, {
@@ -6952,7 +9174,7 @@ __export(semantic_index_exports, {
6952
9174
  });
6953
9175
 
6954
9176
  // ../../packages/node-runtime/src/semantic-index/worker-client.ts
6955
- import path17 from "path";
9177
+ import path23 from "path";
6956
9178
 
6957
9179
  // ../../packages/node-runtime/src/semantic-index/worker-thread-transport.ts
6958
9180
  import { Worker } from "worker_threads";
@@ -6974,22 +9196,22 @@ function createDefaultWorker(startup, entryUrlInput) {
6974
9196
  register();
6975
9197
  await import(${JSON.stringify(entryUrl.href)});
6976
9198
  `;
6977
- const options = {
9199
+ const options2 = {
6978
9200
  eval: true,
6979
9201
  type: "module",
6980
9202
  workerData: startup,
6981
9203
  execArgv: []
6982
9204
  };
6983
- return new Worker(bootstrap, options);
9205
+ return new Worker(bootstrap, options2);
6984
9206
  }
6985
9207
  var SemanticIndexWorkerThreadTransport = class {
6986
9208
  worker;
6987
9209
  pending = /* @__PURE__ */ new Map();
6988
9210
  requestId = 0;
6989
9211
  closeTimeoutMs;
6990
- constructor(options) {
6991
- this.closeTimeoutMs = options.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS;
6992
- this.worker = options.workerFactory?.() ?? createDefaultWorker(options.startup, options.workerEntryUrl);
9212
+ constructor(options2) {
9213
+ this.closeTimeoutMs = options2.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS;
9214
+ this.worker = options2.workerFactory?.() ?? createDefaultWorker(options2.startup, options2.workerEntryUrl);
6993
9215
  this.worker.on("message", (message) => this.handleMessage(message));
6994
9216
  this.worker.on("error", (error) => this.rejectAll(error));
6995
9217
  this.worker.on("exit", (code) => {
@@ -6998,8 +9220,8 @@ var SemanticIndexWorkerThreadTransport = class {
6998
9220
  }
6999
9221
  request(method, args) {
7000
9222
  const id = `si_${++this.requestId}`;
7001
- return new Promise((resolve2, reject) => {
7002
- this.pending.set(id, { resolve: resolve2, reject });
9223
+ return new Promise((resolve3, reject) => {
9224
+ this.pending.set(id, { resolve: resolve3, reject });
7003
9225
  this.worker.postMessage({ id, method, args });
7004
9226
  });
7005
9227
  }
@@ -7010,8 +9232,8 @@ var SemanticIndexWorkerThreadTransport = class {
7010
9232
  }
7011
9233
  async requestRuntimeClose() {
7012
9234
  let timeout = null;
7013
- const timeoutPromise = new Promise((resolve2) => {
7014
- timeout = setTimeout(resolve2, this.closeTimeoutMs);
9235
+ const timeoutPromise = new Promise((resolve3) => {
9236
+ timeout = setTimeout(resolve3, this.closeTimeoutMs);
7015
9237
  });
7016
9238
  try {
7017
9239
  await Promise.race([this.request("__close", []).then(() => void 0), timeoutPromise]);
@@ -7036,8 +9258,8 @@ var SemanticIndexWorkerThreadTransport = class {
7036
9258
  }
7037
9259
  }
7038
9260
  };
7039
- function createSemanticIndexWorkerThreadTransport(options) {
7040
- return new SemanticIndexWorkerThreadTransport(options);
9261
+ function createSemanticIndexWorkerThreadTransport(options2) {
9262
+ return new SemanticIndexWorkerThreadTransport(options2);
7041
9263
  }
7042
9264
 
7043
9265
  // ../../packages/node-runtime/src/semantic-index/worker-client.ts
@@ -7058,24 +9280,25 @@ var SemanticIndexWorkerClient = class {
7058
9280
  timers;
7059
9281
  resolveApiKey;
7060
9282
  writeAuthProfile;
7061
- constructor(options) {
7062
- this.configStore = options.configStore;
7063
- this.transportFactory = options.transportFactory;
7064
- this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
7065
- this.timers = options.timers ?? defaultTimers;
7066
- this.resolveApiKey = options.resolveApiKey ?? resolveApiKey;
7067
- this.writeAuthProfile = options.writeAuthProfile;
9283
+ constructor(options2) {
9284
+ this.configStore = options2.configStore;
9285
+ this.transportFactory = options2.transportFactory;
9286
+ this.idleTimeoutMs = options2.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
9287
+ this.timers = options2.timers ?? defaultTimers;
9288
+ this.resolveApiKey = options2.resolveApiKey ?? resolveApiKey;
9289
+ this.writeAuthProfile = options2.writeAuthProfile;
7068
9290
  }
7069
9291
  getConfig() {
7070
9292
  return this.configStore.get();
7071
9293
  }
7072
- async setConfig(config, options) {
9294
+ async setConfig(config, options2) {
7073
9295
  const saved = persistSemanticIndexConfig(this.configStore, config, {
7074
- apiKey: options?.apiKey,
9296
+ apiKey: options2?.apiKey,
7075
9297
  writeAuthProfile: this.writeAuthProfile
7076
9298
  });
7077
9299
  if (!saved.enabled) this.clearActiveBuildTracking();
7078
- if (!this.transport) return saved;
9300
+ const needsWorker = saved.enabled && saved.mode === "local" && this.configStore.isConfigured();
9301
+ if (!this.transport && !needsWorker) return saved;
7079
9302
  return await this.call("setConfig", [saved]);
7080
9303
  }
7081
9304
  isConfigured() {
@@ -7084,11 +9307,15 @@ var SemanticIndexWorkerClient = class {
7084
9307
  hasApiKey() {
7085
9308
  return resolveSemanticIndexApiKeySet(this.configStore.get(), this.resolveApiKey);
7086
9309
  }
9310
+ async getModelStatus() {
9311
+ if (!this.transport) return "idle";
9312
+ return this.call("getModelStatus", []);
9313
+ }
7087
9314
  enable(sessionId) {
7088
9315
  return this.call("enable", [sessionId]);
7089
9316
  }
7090
- disable(sessionId) {
7091
- return this.call("disable", [sessionId]);
9317
+ remove(sessionId) {
9318
+ return this.call("remove", [sessionId]);
7092
9319
  }
7093
9320
  async build(sessionId) {
7094
9321
  this.activeBuildSessionIds.add(sessionId);
@@ -7151,11 +9378,11 @@ var SemanticIndexWorkerClient = class {
7151
9378
  if (!this.canRunFromLocalConfig()) return false;
7152
9379
  return await this.callProbe("canSearch", [sessionId], false);
7153
9380
  }
7154
- search(sessionId, query, options) {
7155
- return this.call("search", [sessionId, query, options]);
9381
+ search(sessionId, query, options2) {
9382
+ return this.call("search", [sessionId, query, options2]);
7156
9383
  }
7157
- searchForTool(sessionId, query, options) {
7158
- return this.call("searchForTool", [sessionId, query, options]);
9384
+ searchForTool(sessionId, query, options2) {
9385
+ return this.call("searchForTool", [sessionId, query, options2]);
7159
9386
  }
7160
9387
  cleanupUnused() {
7161
9388
  return this.call("cleanupUnused", []);
@@ -7167,7 +9394,7 @@ var SemanticIndexWorkerClient = class {
7167
9394
  this.clearIdleTimer();
7168
9395
  await this.closeTransport();
7169
9396
  }
7170
- async call(method, args, options) {
9397
+ async call(method, args, options2) {
7171
9398
  const transport = this.ensureTransport();
7172
9399
  this.pendingRequests++;
7173
9400
  this.clearIdleTimer();
@@ -7175,12 +9402,12 @@ var SemanticIndexWorkerClient = class {
7175
9402
  return await transport.request(method, args);
7176
9403
  } finally {
7177
9404
  this.pendingRequests--;
7178
- if (options?.scheduleIdle !== false) this.scheduleIdleCloseIfNeeded();
9405
+ if (options2?.scheduleIdle !== false) this.scheduleIdleCloseIfNeeded();
7179
9406
  }
7180
9407
  }
7181
- async callProbe(method, args, fallback, options) {
9408
+ async callProbe(method, args, fallback, options2) {
7182
9409
  try {
7183
- return await this.call(method, args, options);
9410
+ return await this.call(method, args, options2);
7184
9411
  } catch {
7185
9412
  await this.closeFailedProbeTransport();
7186
9413
  return fallback;
@@ -7250,25 +9477,25 @@ var SemanticIndexWorkerClient = class {
7250
9477
  }
7251
9478
  }
7252
9479
  };
7253
- function createSemanticIndexWorkerClient(options) {
7254
- return new SemanticIndexWorkerClient(options);
9480
+ function createSemanticIndexWorkerClient(options2) {
9481
+ return new SemanticIndexWorkerClient(options2);
7255
9482
  }
7256
- function createSemanticIndexWorkerRuntimeClient(options) {
9483
+ function createSemanticIndexWorkerRuntimeClient(options2) {
7257
9484
  const configStore = new SemanticIndexConfigStore(
7258
- path17.join(options.pathProvider.getAiDataDir(), SEMANTIC_INDEX_CONFIG_FILE)
9485
+ path23.join(options2.pathProvider.getAiDataDir(), SEMANTIC_INDEX_CONFIG_FILE)
7259
9486
  );
7260
9487
  return createSemanticIndexWorkerClient({
7261
9488
  configStore,
7262
- idleTimeoutMs: options.idleTimeoutMs,
7263
- resolveApiKey: options.resolveApiKey,
7264
- writeAuthProfile: options.writeAuthProfile,
9489
+ idleTimeoutMs: options2.idleTimeoutMs,
9490
+ resolveApiKey: options2.resolveApiKey,
9491
+ writeAuthProfile: options2.writeAuthProfile,
7265
9492
  transportFactory: () => createSemanticIndexWorkerThreadTransport({
7266
- workerEntryUrl: options.workerEntryUrl,
9493
+ workerEntryUrl: options2.workerEntryUrl,
7267
9494
  startup: {
7268
- paths: snapshotPathProvider(options.pathProvider),
7269
- runtime: options.runtime,
7270
- nativeBinding: options.nativeBinding,
7271
- sqliteVecLoadablePath: options.sqliteVecLoadablePath
9495
+ paths: snapshotPathProvider(options2.pathProvider),
9496
+ runtime: options2.runtime,
9497
+ nativeBinding: options2.nativeBinding,
9498
+ sqliteVecLoadablePath: options2.sqliteVecLoadablePath
7272
9499
  }
7273
9500
  })
7274
9501
  });
@@ -7310,6 +9537,13 @@ export {
7310
9537
  streamParseFileInfo,
7311
9538
  analyzeIncrementalImport,
7312
9539
  incrementalImport,
9540
+ ArchiveImportError,
9541
+ validateArchiveEntryName,
9542
+ ZipArchiveReader,
9543
+ GoogleChatTakeoutResolver,
9544
+ ArchiveImportSourceManager,
9545
+ initAppLogger,
9546
+ appLogger,
7313
9547
  isExistingUserDataDir,
7314
9548
  isUserDataDirSafeToUse,
7315
9549
  isDirectoryEmptyOrMissing,
@@ -7324,6 +9558,7 @@ export {
7324
9558
  applyPendingNodeDataDirMigrationIfNeeded,
7325
9559
  NodePathProvider,
7326
9560
  getDefaultNodeUserDataDir,
9561
+ getSystemLogsDir,
7327
9562
  createJiebaNlpProvider,
7328
9563
  getDbFileVersion,
7329
9564
  getOrComputeAnalysisCache,
@@ -7331,7 +9566,8 @@ export {
7331
9566
  checkConflictsFromSources,
7332
9567
  buildMergedOutput,
7333
9568
  serializeChatLabToJsonl,
9569
+ AnalyticsService,
7334
9570
  createSemanticIndexWorkerRuntimeClient,
7335
9571
  semantic_index_exports
7336
9572
  };
7337
- //# sourceMappingURL=chunk-N3G43SCQ.mjs.map
9573
+ //# sourceMappingURL=chunk-GPF34WXV.mjs.map