@spzhongwin/skill-logger-plugin 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,2097 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // ../../node_modules/adm-zip/util/fileSystem.js
34
+ var require_fileSystem = __commonJS({
35
+ "../../node_modules/adm-zip/util/fileSystem.js"(exports) {
36
+ exports.require = function() {
37
+ var fs10 = __require("fs");
38
+ if (process.versions["electron"]) {
39
+ try {
40
+ originalFs = __require("original-fs");
41
+ if (Object.keys(originalFs).length > 0) {
42
+ fs10 = originalFs;
43
+ }
44
+ } catch (e) {
45
+ }
46
+ }
47
+ return fs10;
48
+ };
49
+ }
50
+ });
51
+
52
+ // ../../node_modules/adm-zip/util/constants.js
53
+ var require_constants = __commonJS({
54
+ "../../node_modules/adm-zip/util/constants.js"(exports, module) {
55
+ module.exports = {
56
+ /* The local file header */
57
+ LOCHDR: 30,
58
+ // LOC header size
59
+ LOCSIG: 67324752,
60
+ // "PK\003\004"
61
+ LOCVER: 4,
62
+ // version needed to extract
63
+ LOCFLG: 6,
64
+ // general purpose bit flag
65
+ LOCHOW: 8,
66
+ // compression method
67
+ LOCTIM: 10,
68
+ // modification time (2 bytes time, 2 bytes date)
69
+ LOCCRC: 14,
70
+ // uncompressed file crc-32 value
71
+ LOCSIZ: 18,
72
+ // compressed size
73
+ LOCLEN: 22,
74
+ // uncompressed size
75
+ LOCNAM: 26,
76
+ // filename length
77
+ LOCEXT: 28,
78
+ // extra field length
79
+ /* The Data descriptor */
80
+ EXTSIG: 134695760,
81
+ // "PK\007\008"
82
+ EXTHDR: 16,
83
+ // EXT header size
84
+ EXTCRC: 4,
85
+ // uncompressed file crc-32 value
86
+ EXTSIZ: 8,
87
+ // compressed size
88
+ EXTLEN: 12,
89
+ // uncompressed size
90
+ /* The central directory file header */
91
+ CENHDR: 46,
92
+ // CEN header size
93
+ CENSIG: 33639248,
94
+ // "PK\001\002"
95
+ CENVEM: 4,
96
+ // version made by
97
+ CENVER: 6,
98
+ // version needed to extract
99
+ CENFLG: 8,
100
+ // encrypt, decrypt flags
101
+ CENHOW: 10,
102
+ // compression method
103
+ CENTIM: 12,
104
+ // modification time (2 bytes time, 2 bytes date)
105
+ CENCRC: 16,
106
+ // uncompressed file crc-32 value
107
+ CENSIZ: 20,
108
+ // compressed size
109
+ CENLEN: 24,
110
+ // uncompressed size
111
+ CENNAM: 28,
112
+ // filename length
113
+ CENEXT: 30,
114
+ // extra field length
115
+ CENCOM: 32,
116
+ // file comment length
117
+ CENDSK: 34,
118
+ // volume number start
119
+ CENATT: 36,
120
+ // internal file attributes
121
+ CENATX: 38,
122
+ // external file attributes (host system dependent)
123
+ CENOFF: 42,
124
+ // LOC header offset
125
+ /* The entries in the end of central directory */
126
+ ENDHDR: 22,
127
+ // END header size
128
+ ENDSIG: 101010256,
129
+ // "PK\005\006"
130
+ ENDSUB: 8,
131
+ // number of entries on this disk
132
+ ENDTOT: 10,
133
+ // total number of entries
134
+ ENDSIZ: 12,
135
+ // central directory size in bytes
136
+ ENDOFF: 16,
137
+ // offset of first CEN header
138
+ ENDCOM: 20,
139
+ // zip file comment length
140
+ END64HDR: 20,
141
+ // zip64 END header size
142
+ END64SIG: 117853008,
143
+ // zip64 Locator signature, "PK\006\007"
144
+ END64START: 4,
145
+ // number of the disk with the start of the zip64
146
+ END64OFF: 8,
147
+ // relative offset of the zip64 end of central directory
148
+ END64NUMDISKS: 16,
149
+ // total number of disks
150
+ ZIP64SIG: 101075792,
151
+ // zip64 signature, "PK\006\006"
152
+ ZIP64HDR: 56,
153
+ // zip64 record minimum size
154
+ ZIP64LEAD: 12,
155
+ // leading bytes at the start of the record, not counted by the value stored in ZIP64SIZE
156
+ ZIP64SIZE: 4,
157
+ // zip64 size of the central directory record
158
+ ZIP64VEM: 12,
159
+ // zip64 version made by
160
+ ZIP64VER: 14,
161
+ // zip64 version needed to extract
162
+ ZIP64DSK: 16,
163
+ // zip64 number of this disk
164
+ ZIP64DSKDIR: 20,
165
+ // number of the disk with the start of the record directory
166
+ ZIP64SUB: 24,
167
+ // number of entries on this disk
168
+ ZIP64TOT: 32,
169
+ // total number of entries
170
+ ZIP64SIZB: 40,
171
+ // zip64 central directory size in bytes
172
+ ZIP64OFF: 48,
173
+ // offset of start of central directory with respect to the starting disk number
174
+ ZIP64EXTRA: 56,
175
+ // extensible data sector
176
+ /* Compression methods */
177
+ STORED: 0,
178
+ // no compression
179
+ SHRUNK: 1,
180
+ // shrunk
181
+ REDUCED1: 2,
182
+ // reduced with compression factor 1
183
+ REDUCED2: 3,
184
+ // reduced with compression factor 2
185
+ REDUCED3: 4,
186
+ // reduced with compression factor 3
187
+ REDUCED4: 5,
188
+ // reduced with compression factor 4
189
+ IMPLODED: 6,
190
+ // imploded
191
+ // 7 reserved
192
+ DEFLATED: 8,
193
+ // deflated
194
+ ENHANCED_DEFLATED: 9,
195
+ // enhanced deflated
196
+ PKWARE: 10,
197
+ // PKWare DCL imploded
198
+ // 11 reserved
199
+ BZIP2: 12,
200
+ // compressed using BZIP2
201
+ // 13 reserved
202
+ LZMA: 14,
203
+ // LZMA
204
+ // 15-17 reserved
205
+ IBM_TERSE: 18,
206
+ // compressed using IBM TERSE
207
+ IBM_LZ77: 19,
208
+ //IBM LZ77 z
209
+ /* General purpose bit flag */
210
+ FLG_ENC: 0,
211
+ // encripted file
212
+ FLG_COMP1: 1,
213
+ // compression option
214
+ FLG_COMP2: 2,
215
+ // compression option
216
+ FLG_DESC: 4,
217
+ // data descriptor
218
+ FLG_ENH: 8,
219
+ // enhanced deflation
220
+ FLG_STR: 16,
221
+ // strong encryption
222
+ FLG_LNG: 1024,
223
+ // language encoding
224
+ FLG_MSK: 4096,
225
+ // mask header values
226
+ /* Load type */
227
+ FILE: 0,
228
+ BUFFER: 1,
229
+ NONE: 2,
230
+ /* 4.5 Extensible data fields */
231
+ EF_ID: 0,
232
+ EF_SIZE: 2,
233
+ /* Header IDs */
234
+ ID_ZIP64: 1,
235
+ ID_AVINFO: 7,
236
+ ID_PFS: 8,
237
+ ID_OS2: 9,
238
+ ID_NTFS: 10,
239
+ ID_OPENVMS: 12,
240
+ ID_UNIX: 13,
241
+ ID_FORK: 14,
242
+ ID_PATCH: 15,
243
+ ID_X509_PKCS7: 20,
244
+ ID_X509_CERTID_F: 21,
245
+ ID_X509_CERTID_C: 22,
246
+ ID_STRONGENC: 23,
247
+ ID_RECORD_MGT: 24,
248
+ ID_X509_PKCS7_RL: 25,
249
+ ID_IBM1: 101,
250
+ ID_IBM2: 102,
251
+ ID_POSZIP: 18064,
252
+ EF_ZIP64_OR_32: 4294967295,
253
+ EF_ZIP64_OR_16: 65535,
254
+ EF_ZIP64_SUNCOMP: 0,
255
+ EF_ZIP64_SCOMP: 8,
256
+ EF_ZIP64_RHO: 16,
257
+ EF_ZIP64_DSN: 24
258
+ };
259
+ }
260
+ });
261
+
262
+ // ../../node_modules/adm-zip/util/errors.js
263
+ var require_errors = __commonJS({
264
+ "../../node_modules/adm-zip/util/errors.js"(exports, module) {
265
+ module.exports = {
266
+ /* Header error messages */
267
+ "INVALID_LOC": "Invalid LOC header (bad signature)",
268
+ "INVALID_CEN": "Invalid CEN header (bad signature)",
269
+ "INVALID_END": "Invalid END header (bad signature)",
270
+ /* ZipEntry error messages*/
271
+ "NO_DATA": "Nothing to decompress",
272
+ "BAD_CRC": "CRC32 checksum failed",
273
+ "FILE_IN_THE_WAY": "There is a file in the way: %s",
274
+ "UNKNOWN_METHOD": "Invalid/unsupported compression method",
275
+ /* Inflater error messages */
276
+ "AVAIL_DATA": "inflate::Available inflate data did not terminate",
277
+ "INVALID_DISTANCE": "inflate::Invalid literal/length or distance code in fixed or dynamic block",
278
+ "TO_MANY_CODES": "inflate::Dynamic block code description: too many length or distance codes",
279
+ "INVALID_REPEAT_LEN": "inflate::Dynamic block code description: repeat more than specified lengths",
280
+ "INVALID_REPEAT_FIRST": "inflate::Dynamic block code description: repeat lengths with no first length",
281
+ "INCOMPLETE_CODES": "inflate::Dynamic block code description: code lengths codes incomplete",
282
+ "INVALID_DYN_DISTANCE": "inflate::Dynamic block code description: invalid distance code lengths",
283
+ "INVALID_CODES_LEN": "inflate::Dynamic block code description: invalid literal/length code lengths",
284
+ "INVALID_STORE_BLOCK": "inflate::Stored block length did not match one's complement",
285
+ "INVALID_BLOCK_TYPE": "inflate::Invalid block type (type == 3)",
286
+ /* ADM-ZIP error messages */
287
+ "CANT_EXTRACT_FILE": "Could not extract the file",
288
+ "CANT_OVERRIDE": "Target file already exists",
289
+ "NO_ZIP": "No zip file was loaded",
290
+ "NO_ENTRY": "Entry doesn't exist",
291
+ "DIRECTORY_CONTENT_ERROR": "A directory cannot have content",
292
+ "FILE_NOT_FOUND": "File not found: %s",
293
+ "NOT_IMPLEMENTED": "Not implemented",
294
+ "INVALID_FILENAME": "Invalid filename",
295
+ "INVALID_FORMAT": "Invalid or unsupported zip format. No END header found"
296
+ };
297
+ }
298
+ });
299
+
300
+ // ../../node_modules/adm-zip/util/utils.js
301
+ var require_utils = __commonJS({
302
+ "../../node_modules/adm-zip/util/utils.js"(exports, module) {
303
+ var fs10 = require_fileSystem().require();
304
+ var pth = __require("path");
305
+ fs10.existsSync = fs10.existsSync || pth.existsSync;
306
+ module.exports = (function() {
307
+ var crcTable = [], Constants = require_constants(), Errors = require_errors(), PATH_SEPARATOR = pth.sep;
308
+ function mkdirSync(path12) {
309
+ var resolvedPath = path12.split(PATH_SEPARATOR)[0];
310
+ path12.split(PATH_SEPARATOR).forEach(function(name) {
311
+ if (!name || name.substr(-1, 1) === ":") return;
312
+ resolvedPath += PATH_SEPARATOR + name;
313
+ var stat;
314
+ try {
315
+ stat = fs10.statSync(resolvedPath);
316
+ } catch (e) {
317
+ fs10.mkdirSync(resolvedPath);
318
+ }
319
+ if (stat && stat.isFile())
320
+ throw Errors.FILE_IN_THE_WAY.replace("%s", resolvedPath);
321
+ });
322
+ }
323
+ function findSync(dir, pattern, recoursive) {
324
+ if (typeof pattern === "boolean") {
325
+ recoursive = pattern;
326
+ pattern = void 0;
327
+ }
328
+ var files = [];
329
+ fs10.readdirSync(dir).forEach(function(file) {
330
+ var path12 = pth.join(dir, file);
331
+ if (fs10.statSync(path12).isDirectory() && recoursive)
332
+ files = files.concat(findSync(path12, pattern, recoursive));
333
+ if (!pattern || pattern.test(path12)) {
334
+ files.push(pth.normalize(path12) + (fs10.statSync(path12).isDirectory() ? PATH_SEPARATOR : ""));
335
+ }
336
+ });
337
+ return files;
338
+ }
339
+ function readBigUInt64LE(buffer, index) {
340
+ var slice = Buffer.from(buffer.slice(index, index + 8));
341
+ slice.swap64();
342
+ return parseInt(`0x${slice.toString("hex")}`);
343
+ }
344
+ return {
345
+ makeDir: function(path12) {
346
+ mkdirSync(path12);
347
+ },
348
+ crc32: function(buf) {
349
+ if (typeof buf === "string") {
350
+ buf = Buffer.alloc(buf.length, buf);
351
+ }
352
+ var b = Buffer.alloc(4);
353
+ if (!crcTable.length) {
354
+ for (var n = 0; n < 256; n++) {
355
+ var c = n;
356
+ for (var k = 8; --k >= 0; )
357
+ if ((c & 1) !== 0) {
358
+ c = 3988292384 ^ c >>> 1;
359
+ } else {
360
+ c = c >>> 1;
361
+ }
362
+ if (c < 0) {
363
+ b.writeInt32LE(c, 0);
364
+ c = b.readUInt32LE(0);
365
+ }
366
+ crcTable[n] = c;
367
+ }
368
+ }
369
+ var crc = 0, off = 0, len = buf.length, c1 = ~crc;
370
+ while (--len >= 0) c1 = crcTable[(c1 ^ buf[off++]) & 255] ^ c1 >>> 8;
371
+ crc = ~c1;
372
+ b.writeInt32LE(crc & 4294967295, 0);
373
+ return b.readUInt32LE(0);
374
+ },
375
+ methodToString: function(method) {
376
+ switch (method) {
377
+ case Constants.STORED:
378
+ return "STORED (" + method + ")";
379
+ case Constants.DEFLATED:
380
+ return "DEFLATED (" + method + ")";
381
+ default:
382
+ return "UNSUPPORTED (" + method + ")";
383
+ }
384
+ },
385
+ writeFileTo: function(path12, content, overwrite, attr) {
386
+ if (fs10.existsSync(path12)) {
387
+ if (!overwrite)
388
+ return false;
389
+ var stat = fs10.statSync(path12);
390
+ if (stat.isDirectory()) {
391
+ return false;
392
+ }
393
+ }
394
+ var folder = pth.dirname(path12);
395
+ if (!fs10.existsSync(folder)) {
396
+ mkdirSync(folder);
397
+ }
398
+ var fd;
399
+ try {
400
+ fd = fs10.openSync(path12, "w", 438);
401
+ } catch (e) {
402
+ fs10.chmodSync(path12, 438);
403
+ fd = fs10.openSync(path12, "w", 438);
404
+ }
405
+ if (fd) {
406
+ try {
407
+ fs10.writeSync(fd, content, 0, content.length, 0);
408
+ } catch (e) {
409
+ throw e;
410
+ } finally {
411
+ fs10.closeSync(fd);
412
+ }
413
+ }
414
+ fs10.chmodSync(path12, attr || 438);
415
+ return true;
416
+ },
417
+ writeFileToAsync: function(path12, content, overwrite, attr, callback) {
418
+ if (typeof attr === "function") {
419
+ callback = attr;
420
+ attr = void 0;
421
+ }
422
+ fs10.exists(path12, function(exists) {
423
+ if (exists && !overwrite)
424
+ return callback(false);
425
+ fs10.stat(path12, function(err, stat) {
426
+ if (exists && stat.isDirectory()) {
427
+ return callback(false);
428
+ }
429
+ var folder = pth.dirname(path12);
430
+ fs10.exists(folder, function(exists2) {
431
+ if (!exists2)
432
+ mkdirSync(folder);
433
+ fs10.open(path12, "w", 438, function(err2, fd) {
434
+ if (err2) {
435
+ fs10.chmod(path12, 438, function() {
436
+ fs10.open(path12, "w", 438, function(err3, fd2) {
437
+ fs10.write(fd2, content, 0, content.length, 0, function() {
438
+ fs10.close(fd2, function() {
439
+ fs10.chmod(path12, attr || 438, function() {
440
+ callback(true);
441
+ });
442
+ });
443
+ });
444
+ });
445
+ });
446
+ } else {
447
+ if (fd) {
448
+ fs10.write(fd, content, 0, content.length, 0, function() {
449
+ fs10.close(fd, function() {
450
+ fs10.chmod(path12, attr || 438, function() {
451
+ callback(true);
452
+ });
453
+ });
454
+ });
455
+ } else {
456
+ fs10.chmod(path12, attr || 438, function() {
457
+ callback(true);
458
+ });
459
+ }
460
+ }
461
+ });
462
+ });
463
+ });
464
+ });
465
+ },
466
+ findFiles: function(path12) {
467
+ return findSync(path12, true);
468
+ },
469
+ getAttributes: function(path12) {
470
+ },
471
+ setAttributes: function(path12) {
472
+ },
473
+ toBuffer: function(input) {
474
+ if (Buffer.isBuffer(input)) {
475
+ return input;
476
+ } else {
477
+ if (input.length === 0) {
478
+ return Buffer.alloc(0);
479
+ }
480
+ return Buffer.from(input, "utf8");
481
+ }
482
+ },
483
+ readBigUInt64LE,
484
+ Constants,
485
+ Errors
486
+ };
487
+ })();
488
+ }
489
+ });
490
+
491
+ // ../../node_modules/adm-zip/util/fattr.js
492
+ var require_fattr = __commonJS({
493
+ "../../node_modules/adm-zip/util/fattr.js"(exports, module) {
494
+ var fs10 = require_fileSystem().require();
495
+ var pth = __require("path");
496
+ fs10.existsSync = fs10.existsSync || pth.existsSync;
497
+ module.exports = function(path12) {
498
+ var _path = path12 || "", _permissions = 0, _obj = newAttr(), _stat = null;
499
+ function newAttr() {
500
+ return {
501
+ directory: false,
502
+ readonly: false,
503
+ hidden: false,
504
+ executable: false,
505
+ mtime: 0,
506
+ atime: 0
507
+ };
508
+ }
509
+ if (_path && fs10.existsSync(_path)) {
510
+ _stat = fs10.statSync(_path);
511
+ _obj.directory = _stat.isDirectory();
512
+ _obj.mtime = _stat.mtime;
513
+ _obj.atime = _stat.atime;
514
+ _obj.executable = !!(1 & parseInt((_stat.mode & parseInt("777", 8)).toString(8)[0]));
515
+ _obj.readonly = !!(2 & parseInt((_stat.mode & parseInt("777", 8)).toString(8)[0]));
516
+ _obj.hidden = pth.basename(_path)[0] === ".";
517
+ } else {
518
+ console.warn("Invalid path: " + _path);
519
+ }
520
+ return {
521
+ get directory() {
522
+ return _obj.directory;
523
+ },
524
+ get readOnly() {
525
+ return _obj.readonly;
526
+ },
527
+ get hidden() {
528
+ return _obj.hidden;
529
+ },
530
+ get mtime() {
531
+ return _obj.mtime;
532
+ },
533
+ get atime() {
534
+ return _obj.atime;
535
+ },
536
+ get executable() {
537
+ return _obj.executable;
538
+ },
539
+ decodeAttributes: function(val) {
540
+ },
541
+ encodeAttributes: function(val) {
542
+ },
543
+ toString: function() {
544
+ return '{\n "path" : "' + _path + ',\n "isDirectory" : ' + _obj.directory + ',\n "isReadOnly" : ' + _obj.readonly + ',\n "isHidden" : ' + _obj.hidden + ',\n "isExecutable" : ' + _obj.executable + ',\n "mTime" : ' + _obj.mtime + '\n "aTime" : ' + _obj.atime + "\n}";
545
+ }
546
+ };
547
+ };
548
+ }
549
+ });
550
+
551
+ // ../../node_modules/adm-zip/util/index.js
552
+ var require_util = __commonJS({
553
+ "../../node_modules/adm-zip/util/index.js"(exports, module) {
554
+ module.exports = require_utils();
555
+ module.exports.FileSystem = require_fileSystem();
556
+ module.exports.Constants = require_constants();
557
+ module.exports.Errors = require_errors();
558
+ module.exports.FileAttr = require_fattr();
559
+ }
560
+ });
561
+
562
+ // ../../node_modules/adm-zip/headers/entryHeader.js
563
+ var require_entryHeader = __commonJS({
564
+ "../../node_modules/adm-zip/headers/entryHeader.js"(exports, module) {
565
+ var Utils = require_util();
566
+ var Constants = Utils.Constants;
567
+ module.exports = function() {
568
+ var _verMade = 10, _version = 10, _flags = 0, _method = 0, _time = 0, _crc = 0, _compressedSize = 0, _size = 0, _fnameLen = 0, _extraLen = 0, _comLen = 0, _diskStart = 0, _inattr = 0, _attr = 0, _offset = 0;
569
+ var _dataHeader = {};
570
+ function setTime(val) {
571
+ val = new Date(val);
572
+ _time = (val.getFullYear() - 1980 & 127) << 25 | val.getMonth() + 1 << 21 | val.getDate() << 16 | val.getHours() << 11 | val.getMinutes() << 5 | val.getSeconds() >> 1;
573
+ }
574
+ setTime(+/* @__PURE__ */ new Date());
575
+ return {
576
+ get made() {
577
+ return _verMade;
578
+ },
579
+ set made(val) {
580
+ _verMade = val;
581
+ },
582
+ get version() {
583
+ return _version;
584
+ },
585
+ set version(val) {
586
+ _version = val;
587
+ },
588
+ get flags() {
589
+ return _flags;
590
+ },
591
+ set flags(val) {
592
+ _flags = val;
593
+ },
594
+ get method() {
595
+ return _method;
596
+ },
597
+ set method(val) {
598
+ _method = val;
599
+ },
600
+ get time() {
601
+ return new Date(
602
+ (_time >> 25 & 127) + 1980,
603
+ (_time >> 21 & 15) - 1,
604
+ _time >> 16 & 31,
605
+ _time >> 11 & 31,
606
+ _time >> 5 & 63,
607
+ (_time & 31) << 1
608
+ );
609
+ },
610
+ set time(val) {
611
+ setTime(val);
612
+ },
613
+ get crc() {
614
+ return _crc;
615
+ },
616
+ set crc(val) {
617
+ _crc = val;
618
+ },
619
+ get compressedSize() {
620
+ return _compressedSize;
621
+ },
622
+ set compressedSize(val) {
623
+ _compressedSize = val;
624
+ },
625
+ get size() {
626
+ return _size;
627
+ },
628
+ set size(val) {
629
+ _size = val;
630
+ },
631
+ get fileNameLength() {
632
+ return _fnameLen;
633
+ },
634
+ set fileNameLength(val) {
635
+ _fnameLen = val;
636
+ },
637
+ get extraLength() {
638
+ return _extraLen;
639
+ },
640
+ set extraLength(val) {
641
+ _extraLen = val;
642
+ },
643
+ get commentLength() {
644
+ return _comLen;
645
+ },
646
+ set commentLength(val) {
647
+ _comLen = val;
648
+ },
649
+ get diskNumStart() {
650
+ return _diskStart;
651
+ },
652
+ set diskNumStart(val) {
653
+ _diskStart = val;
654
+ },
655
+ get inAttr() {
656
+ return _inattr;
657
+ },
658
+ set inAttr(val) {
659
+ _inattr = val;
660
+ },
661
+ get attr() {
662
+ return _attr;
663
+ },
664
+ set attr(val) {
665
+ _attr = val;
666
+ },
667
+ get offset() {
668
+ return _offset;
669
+ },
670
+ set offset(val) {
671
+ _offset = val;
672
+ },
673
+ get encripted() {
674
+ return (_flags & 1) === 1;
675
+ },
676
+ get entryHeaderSize() {
677
+ return Constants.CENHDR + _fnameLen + _extraLen + _comLen;
678
+ },
679
+ get realDataOffset() {
680
+ return _offset + Constants.LOCHDR + _dataHeader.fnameLen + _dataHeader.extraLen;
681
+ },
682
+ get dataHeader() {
683
+ return _dataHeader;
684
+ },
685
+ loadDataHeaderFromBinary: function(input) {
686
+ var data = input.slice(_offset, _offset + Constants.LOCHDR);
687
+ if (data.readUInt32LE(0) !== Constants.LOCSIG) {
688
+ throw new Error(Utils.Errors.INVALID_LOC);
689
+ }
690
+ _dataHeader = {
691
+ // version needed to extract
692
+ version: data.readUInt16LE(Constants.LOCVER),
693
+ // general purpose bit flag
694
+ flags: data.readUInt16LE(Constants.LOCFLG),
695
+ // compression method
696
+ method: data.readUInt16LE(Constants.LOCHOW),
697
+ // modification time (2 bytes time, 2 bytes date)
698
+ time: data.readUInt32LE(Constants.LOCTIM),
699
+ // uncompressed file crc-32 value
700
+ crc: data.readUInt32LE(Constants.LOCCRC),
701
+ // compressed size
702
+ compressedSize: data.readUInt32LE(Constants.LOCSIZ),
703
+ // uncompressed size
704
+ size: data.readUInt32LE(Constants.LOCLEN),
705
+ // filename length
706
+ fnameLen: data.readUInt16LE(Constants.LOCNAM),
707
+ // extra field length
708
+ extraLen: data.readUInt16LE(Constants.LOCEXT)
709
+ };
710
+ },
711
+ loadFromBinary: function(data) {
712
+ if (data.length !== Constants.CENHDR || data.readUInt32LE(0) !== Constants.CENSIG) {
713
+ throw new Error(Utils.Errors.INVALID_CEN);
714
+ }
715
+ _verMade = data.readUInt16LE(Constants.CENVEM);
716
+ _version = data.readUInt16LE(Constants.CENVER);
717
+ _flags = data.readUInt16LE(Constants.CENFLG);
718
+ _method = data.readUInt16LE(Constants.CENHOW);
719
+ _time = data.readUInt32LE(Constants.CENTIM);
720
+ _crc = data.readUInt32LE(Constants.CENCRC);
721
+ _compressedSize = data.readUInt32LE(Constants.CENSIZ);
722
+ _size = data.readUInt32LE(Constants.CENLEN);
723
+ _fnameLen = data.readUInt16LE(Constants.CENNAM);
724
+ _extraLen = data.readUInt16LE(Constants.CENEXT);
725
+ _comLen = data.readUInt16LE(Constants.CENCOM);
726
+ _diskStart = data.readUInt16LE(Constants.CENDSK);
727
+ _inattr = data.readUInt16LE(Constants.CENATT);
728
+ _attr = data.readUInt32LE(Constants.CENATX);
729
+ _offset = data.readUInt32LE(Constants.CENOFF);
730
+ },
731
+ dataHeaderToBinary: function() {
732
+ var data = Buffer.alloc(Constants.LOCHDR);
733
+ data.writeUInt32LE(Constants.LOCSIG, 0);
734
+ data.writeUInt16LE(_version, Constants.LOCVER);
735
+ data.writeUInt16LE(_flags, Constants.LOCFLG);
736
+ data.writeUInt16LE(_method, Constants.LOCHOW);
737
+ data.writeUInt32LE(_time, Constants.LOCTIM);
738
+ data.writeUInt32LE(_crc, Constants.LOCCRC);
739
+ data.writeUInt32LE(_compressedSize, Constants.LOCSIZ);
740
+ data.writeUInt32LE(_size, Constants.LOCLEN);
741
+ data.writeUInt16LE(_fnameLen, Constants.LOCNAM);
742
+ data.writeUInt16LE(_extraLen, Constants.LOCEXT);
743
+ return data;
744
+ },
745
+ entryHeaderToBinary: function() {
746
+ var data = Buffer.alloc(Constants.CENHDR + _fnameLen + _extraLen + _comLen);
747
+ data.writeUInt32LE(Constants.CENSIG, 0);
748
+ data.writeUInt16LE(_verMade, Constants.CENVEM);
749
+ data.writeUInt16LE(_version, Constants.CENVER);
750
+ data.writeUInt16LE(_flags, Constants.CENFLG);
751
+ data.writeUInt16LE(_method, Constants.CENHOW);
752
+ data.writeUInt32LE(_time, Constants.CENTIM);
753
+ data.writeUInt32LE(_crc, Constants.CENCRC);
754
+ data.writeUInt32LE(_compressedSize, Constants.CENSIZ);
755
+ data.writeUInt32LE(_size, Constants.CENLEN);
756
+ data.writeUInt16LE(_fnameLen, Constants.CENNAM);
757
+ data.writeUInt16LE(_extraLen, Constants.CENEXT);
758
+ data.writeUInt16LE(_comLen, Constants.CENCOM);
759
+ data.writeUInt16LE(_diskStart, Constants.CENDSK);
760
+ data.writeUInt16LE(_inattr, Constants.CENATT);
761
+ data.writeUInt32LE(_attr, Constants.CENATX);
762
+ data.writeUInt32LE(_offset, Constants.CENOFF);
763
+ data.fill(0, Constants.CENHDR);
764
+ return data;
765
+ },
766
+ toString: function() {
767
+ return '{\n "made" : ' + _verMade + ',\n "version" : ' + _version + ',\n "flags" : ' + _flags + ',\n "method" : ' + Utils.methodToString(_method) + ',\n "time" : ' + this.time + ',\n "crc" : 0x' + _crc.toString(16).toUpperCase() + ',\n "compressedSize" : ' + _compressedSize + ' bytes,\n "size" : ' + _size + ' bytes,\n "fileNameLength" : ' + _fnameLen + ',\n "extraLength" : ' + _extraLen + ' bytes,\n "commentLength" : ' + _comLen + ' bytes,\n "diskNumStart" : ' + _diskStart + ',\n "inAttr" : ' + _inattr + ',\n "attr" : ' + _attr + ',\n "offset" : ' + _offset + ',\n "entryHeaderSize" : ' + (Constants.CENHDR + _fnameLen + _extraLen + _comLen) + " bytes\n}";
768
+ }
769
+ };
770
+ };
771
+ }
772
+ });
773
+
774
+ // ../../node_modules/adm-zip/headers/mainHeader.js
775
+ var require_mainHeader = __commonJS({
776
+ "../../node_modules/adm-zip/headers/mainHeader.js"(exports, module) {
777
+ var Utils = require_util();
778
+ var Constants = Utils.Constants;
779
+ module.exports = function() {
780
+ var _volumeEntries = 0, _totalEntries = 0, _size = 0, _offset = 0, _commentLength = 0;
781
+ return {
782
+ get diskEntries() {
783
+ return _volumeEntries;
784
+ },
785
+ set diskEntries(val) {
786
+ _volumeEntries = _totalEntries = val;
787
+ },
788
+ get totalEntries() {
789
+ return _totalEntries;
790
+ },
791
+ set totalEntries(val) {
792
+ _totalEntries = _volumeEntries = val;
793
+ },
794
+ get size() {
795
+ return _size;
796
+ },
797
+ set size(val) {
798
+ _size = val;
799
+ },
800
+ get offset() {
801
+ return _offset;
802
+ },
803
+ set offset(val) {
804
+ _offset = val;
805
+ },
806
+ get commentLength() {
807
+ return _commentLength;
808
+ },
809
+ set commentLength(val) {
810
+ _commentLength = val;
811
+ },
812
+ get mainHeaderSize() {
813
+ return Constants.ENDHDR + _commentLength;
814
+ },
815
+ loadFromBinary: function(data) {
816
+ if ((data.length !== Constants.ENDHDR || data.readUInt32LE(0) !== Constants.ENDSIG) && (data.length < Constants.ZIP64HDR || data.readUInt32LE(0) !== Constants.ZIP64SIG)) {
817
+ throw new Error(Utils.Errors.INVALID_END);
818
+ }
819
+ if (data.readUInt32LE(0) === Constants.ENDSIG) {
820
+ _volumeEntries = data.readUInt16LE(Constants.ENDSUB);
821
+ _totalEntries = data.readUInt16LE(Constants.ENDTOT);
822
+ _size = data.readUInt32LE(Constants.ENDSIZ);
823
+ _offset = data.readUInt32LE(Constants.ENDOFF);
824
+ _commentLength = data.readUInt16LE(Constants.ENDCOM);
825
+ } else {
826
+ _volumeEntries = Utils.readBigUInt64LE(data, Constants.ZIP64SUB);
827
+ _totalEntries = Utils.readBigUInt64LE(data, Constants.ZIP64TOT);
828
+ _size = Utils.readBigUInt64LE(data, Constants.ZIP64SIZ);
829
+ _offset = Utils.readBigUInt64LE(data, Constants.ZIP64OFF);
830
+ _commentLength = 0;
831
+ }
832
+ },
833
+ toBinary: function() {
834
+ var b = Buffer.alloc(Constants.ENDHDR + _commentLength);
835
+ b.writeUInt32LE(Constants.ENDSIG, 0);
836
+ b.writeUInt32LE(0, 4);
837
+ b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
838
+ b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
839
+ b.writeUInt32LE(_size, Constants.ENDSIZ);
840
+ b.writeUInt32LE(_offset, Constants.ENDOFF);
841
+ b.writeUInt16LE(_commentLength, Constants.ENDCOM);
842
+ b.fill(" ", Constants.ENDHDR);
843
+ return b;
844
+ },
845
+ toString: function() {
846
+ return '{\n "diskEntries" : ' + _volumeEntries + ',\n "totalEntries" : ' + _totalEntries + ',\n "size" : ' + _size + ' bytes,\n "offset" : 0x' + _offset.toString(16).toUpperCase() + ',\n "commentLength" : 0x' + _commentLength + "\n}";
847
+ }
848
+ };
849
+ };
850
+ }
851
+ });
852
+
853
+ // ../../node_modules/adm-zip/headers/index.js
854
+ var require_headers = __commonJS({
855
+ "../../node_modules/adm-zip/headers/index.js"(exports) {
856
+ exports.EntryHeader = require_entryHeader();
857
+ exports.MainHeader = require_mainHeader();
858
+ }
859
+ });
860
+
861
+ // ../../node_modules/adm-zip/methods/deflater.js
862
+ var require_deflater = __commonJS({
863
+ "../../node_modules/adm-zip/methods/deflater.js"(exports, module) {
864
+ module.exports = function(inbuf) {
865
+ var zlib = __require("zlib");
866
+ var opts = { chunkSize: (parseInt(inbuf.length / 1024) + 1) * 1024 };
867
+ return {
868
+ deflate: function() {
869
+ return zlib.deflateRawSync(inbuf, opts);
870
+ },
871
+ deflateAsync: function(callback) {
872
+ var tmp = zlib.createDeflateRaw(opts), parts = [], total = 0;
873
+ tmp.on("data", function(data) {
874
+ parts.push(data);
875
+ total += data.length;
876
+ });
877
+ tmp.on("end", function() {
878
+ var buf = Buffer.alloc(total), written = 0;
879
+ buf.fill(0);
880
+ for (var i = 0; i < parts.length; i++) {
881
+ var part = parts[i];
882
+ part.copy(buf, written);
883
+ written += part.length;
884
+ }
885
+ callback && callback(buf);
886
+ });
887
+ tmp.end(inbuf);
888
+ }
889
+ };
890
+ };
891
+ }
892
+ });
893
+
894
+ // ../../node_modules/adm-zip/methods/inflater.js
895
+ var require_inflater = __commonJS({
896
+ "../../node_modules/adm-zip/methods/inflater.js"(exports, module) {
897
+ module.exports = function(inbuf) {
898
+ var zlib = __require("zlib");
899
+ return {
900
+ inflate: function() {
901
+ return zlib.inflateRawSync(inbuf);
902
+ },
903
+ inflateAsync: function(callback) {
904
+ var tmp = zlib.createInflateRaw(), parts = [], total = 0;
905
+ tmp.on("data", function(data) {
906
+ parts.push(data);
907
+ total += data.length;
908
+ });
909
+ tmp.on("end", function() {
910
+ var buf = Buffer.alloc(total), written = 0;
911
+ buf.fill(0);
912
+ for (var i = 0; i < parts.length; i++) {
913
+ var part = parts[i];
914
+ part.copy(buf, written);
915
+ written += part.length;
916
+ }
917
+ callback && callback(buf);
918
+ });
919
+ tmp.end(inbuf);
920
+ }
921
+ };
922
+ };
923
+ }
924
+ });
925
+
926
+ // ../../node_modules/adm-zip/methods/index.js
927
+ var require_methods = __commonJS({
928
+ "../../node_modules/adm-zip/methods/index.js"(exports) {
929
+ exports.Deflater = require_deflater();
930
+ exports.Inflater = require_inflater();
931
+ }
932
+ });
933
+
934
+ // ../../node_modules/adm-zip/zipEntry.js
935
+ var require_zipEntry = __commonJS({
936
+ "../../node_modules/adm-zip/zipEntry.js"(exports, module) {
937
+ var Utils = require_util();
938
+ var Headers = require_headers();
939
+ var Constants = Utils.Constants;
940
+ var Methods = require_methods();
941
+ module.exports = function(input) {
942
+ var _entryHeader = new Headers.EntryHeader(), _entryName = Buffer.alloc(0), _comment = Buffer.alloc(0), _isDirectory = false, uncompressedData = null, _extra = Buffer.alloc(0);
943
+ function getCompressedDataFromZip() {
944
+ if (!input || !Buffer.isBuffer(input)) {
945
+ return Buffer.alloc(0);
946
+ }
947
+ _entryHeader.loadDataHeaderFromBinary(input);
948
+ return input.slice(_entryHeader.realDataOffset, _entryHeader.realDataOffset + _entryHeader.compressedSize);
949
+ }
950
+ function crc32OK(data) {
951
+ if ((_entryHeader.flags & 8) !== 8) {
952
+ if (Utils.crc32(data) !== _entryHeader.dataHeader.crc) {
953
+ return false;
954
+ }
955
+ } else {
956
+ }
957
+ return true;
958
+ }
959
+ function decompress(async, callback, pass) {
960
+ if (typeof callback === "undefined" && typeof async === "string") {
961
+ pass = async;
962
+ async = void 0;
963
+ }
964
+ if (_isDirectory) {
965
+ if (async && callback) {
966
+ callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR);
967
+ }
968
+ return Buffer.alloc(0);
969
+ }
970
+ var compressedData = getCompressedDataFromZip();
971
+ if (compressedData.length === 0) {
972
+ if (async && callback) callback(compressedData);
973
+ return compressedData;
974
+ }
975
+ var data = Buffer.alloc(_entryHeader.size);
976
+ switch (_entryHeader.method) {
977
+ case Utils.Constants.STORED:
978
+ compressedData.copy(data);
979
+ if (!crc32OK(data)) {
980
+ if (async && callback) callback(data, Utils.Errors.BAD_CRC);
981
+ throw new Error(Utils.Errors.BAD_CRC);
982
+ } else {
983
+ if (async && callback) callback(data);
984
+ return data;
985
+ }
986
+ case Utils.Constants.DEFLATED:
987
+ var inflater = new Methods.Inflater(compressedData);
988
+ if (!async) {
989
+ var result = inflater.inflate(data);
990
+ result.copy(data, 0);
991
+ if (!crc32OK(data)) {
992
+ throw new Error(Utils.Errors.BAD_CRC + " " + _entryName.toString());
993
+ }
994
+ return data;
995
+ } else {
996
+ inflater.inflateAsync(function(result2) {
997
+ result2.copy(data, 0);
998
+ if (!crc32OK(data)) {
999
+ if (callback) callback(data, Utils.Errors.BAD_CRC);
1000
+ } else {
1001
+ if (callback) callback(data);
1002
+ }
1003
+ });
1004
+ }
1005
+ break;
1006
+ default:
1007
+ if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD);
1008
+ throw new Error(Utils.Errors.UNKNOWN_METHOD);
1009
+ }
1010
+ }
1011
+ function compress(async, callback) {
1012
+ if ((!uncompressedData || !uncompressedData.length) && Buffer.isBuffer(input)) {
1013
+ if (async && callback) callback(getCompressedDataFromZip());
1014
+ return getCompressedDataFromZip();
1015
+ }
1016
+ if (uncompressedData.length && !_isDirectory) {
1017
+ var compressedData;
1018
+ switch (_entryHeader.method) {
1019
+ case Utils.Constants.STORED:
1020
+ _entryHeader.compressedSize = _entryHeader.size;
1021
+ compressedData = Buffer.alloc(uncompressedData.length);
1022
+ uncompressedData.copy(compressedData);
1023
+ if (async && callback) callback(compressedData);
1024
+ return compressedData;
1025
+ default:
1026
+ case Utils.Constants.DEFLATED:
1027
+ var deflater = new Methods.Deflater(uncompressedData);
1028
+ if (!async) {
1029
+ var deflated = deflater.deflate();
1030
+ _entryHeader.compressedSize = deflated.length;
1031
+ return deflated;
1032
+ } else {
1033
+ deflater.deflateAsync(function(data) {
1034
+ compressedData = Buffer.alloc(data.length);
1035
+ _entryHeader.compressedSize = data.length;
1036
+ data.copy(compressedData);
1037
+ callback && callback(compressedData);
1038
+ });
1039
+ }
1040
+ deflater = null;
1041
+ break;
1042
+ }
1043
+ } else {
1044
+ if (async && callback) {
1045
+ callback(Buffer.alloc(0));
1046
+ } else {
1047
+ return Buffer.alloc(0);
1048
+ }
1049
+ }
1050
+ }
1051
+ function readUInt64LE(buffer, offset) {
1052
+ return (buffer.readUInt32LE(offset + 4) << 4) + buffer.readUInt32LE(offset);
1053
+ }
1054
+ function parseExtra(data) {
1055
+ var offset = 0;
1056
+ var signature, size, part;
1057
+ while (offset < data.length) {
1058
+ signature = data.readUInt16LE(offset);
1059
+ offset += 2;
1060
+ size = data.readUInt16LE(offset);
1061
+ offset += 2;
1062
+ part = data.slice(offset, offset + size);
1063
+ offset += size;
1064
+ if (Constants.ID_ZIP64 === signature) {
1065
+ parseZip64ExtendedInformation(part);
1066
+ }
1067
+ }
1068
+ }
1069
+ function parseZip64ExtendedInformation(data) {
1070
+ var size, compressedSize, offset, diskNumStart;
1071
+ if (data.length >= Constants.EF_ZIP64_SCOMP) {
1072
+ size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
1073
+ if (_entryHeader.size === Constants.EF_ZIP64_OR_32) {
1074
+ _entryHeader.size = size;
1075
+ }
1076
+ }
1077
+ if (data.length >= Constants.EF_ZIP64_RHO) {
1078
+ compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
1079
+ if (_entryHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
1080
+ _entryHeader.compressedSize = compressedSize;
1081
+ }
1082
+ }
1083
+ if (data.length >= Constants.EF_ZIP64_DSN) {
1084
+ offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
1085
+ if (_entryHeader.offset === Constants.EF_ZIP64_OR_32) {
1086
+ _entryHeader.offset = offset;
1087
+ }
1088
+ }
1089
+ if (data.length >= Constants.EF_ZIP64_DSN + 4) {
1090
+ diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
1091
+ if (_entryHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
1092
+ _entryHeader.diskNumStart = diskNumStart;
1093
+ }
1094
+ }
1095
+ }
1096
+ return {
1097
+ get entryName() {
1098
+ return _entryName.toString();
1099
+ },
1100
+ get rawEntryName() {
1101
+ return _entryName;
1102
+ },
1103
+ set entryName(val) {
1104
+ _entryName = Utils.toBuffer(val);
1105
+ var lastChar = _entryName[_entryName.length - 1];
1106
+ _isDirectory = lastChar === 47 || lastChar === 92;
1107
+ _entryHeader.fileNameLength = _entryName.length;
1108
+ },
1109
+ get extra() {
1110
+ return _extra;
1111
+ },
1112
+ set extra(val) {
1113
+ _extra = val;
1114
+ _entryHeader.extraLength = val.length;
1115
+ parseExtra(val);
1116
+ },
1117
+ get comment() {
1118
+ return _comment.toString();
1119
+ },
1120
+ set comment(val) {
1121
+ _comment = Utils.toBuffer(val);
1122
+ _entryHeader.commentLength = _comment.length;
1123
+ },
1124
+ get name() {
1125
+ var n = _entryName.toString();
1126
+ return _isDirectory ? n.substr(n.length - 1).split("/").pop() : n.split("/").pop();
1127
+ },
1128
+ get isDirectory() {
1129
+ return _isDirectory;
1130
+ },
1131
+ getCompressedData: function() {
1132
+ return compress(false, null);
1133
+ },
1134
+ getCompressedDataAsync: function(callback) {
1135
+ compress(true, callback);
1136
+ },
1137
+ setData: function(value) {
1138
+ uncompressedData = Utils.toBuffer(value);
1139
+ if (!_isDirectory && uncompressedData.length) {
1140
+ _entryHeader.size = uncompressedData.length;
1141
+ _entryHeader.method = Utils.Constants.DEFLATED;
1142
+ _entryHeader.crc = Utils.crc32(value);
1143
+ _entryHeader.changed = true;
1144
+ } else {
1145
+ _entryHeader.method = Utils.Constants.STORED;
1146
+ }
1147
+ },
1148
+ getData: function(pass) {
1149
+ if (_entryHeader.changed) {
1150
+ return uncompressedData;
1151
+ } else {
1152
+ return decompress(false, null, pass);
1153
+ }
1154
+ },
1155
+ getDataAsync: function(callback, pass) {
1156
+ if (_entryHeader.changed) {
1157
+ callback(uncompressedData);
1158
+ } else {
1159
+ decompress(true, callback, pass);
1160
+ }
1161
+ },
1162
+ set attr(attr) {
1163
+ _entryHeader.attr = attr;
1164
+ },
1165
+ get attr() {
1166
+ return _entryHeader.attr;
1167
+ },
1168
+ set header(data) {
1169
+ _entryHeader.loadFromBinary(data);
1170
+ },
1171
+ get header() {
1172
+ return _entryHeader;
1173
+ },
1174
+ packHeader: function() {
1175
+ var header = _entryHeader.entryHeaderToBinary();
1176
+ _entryName.copy(header, Utils.Constants.CENHDR);
1177
+ if (_entryHeader.extraLength) {
1178
+ _extra.copy(header, Utils.Constants.CENHDR + _entryName.length);
1179
+ }
1180
+ if (_entryHeader.commentLength) {
1181
+ _comment.copy(header, Utils.Constants.CENHDR + _entryName.length + _entryHeader.extraLength, _comment.length);
1182
+ }
1183
+ return header;
1184
+ },
1185
+ toString: function() {
1186
+ return '{\n "entryName" : "' + _entryName.toString() + '",\n "name" : "' + (_isDirectory ? _entryName.toString().replace(/\/$/, "").split("/").pop() : _entryName.toString().split("/").pop()) + '",\n "comment" : "' + _comment.toString() + '",\n "isDirectory" : ' + _isDirectory + ',\n "header" : ' + _entryHeader.toString().replace(/\t/mg, " ").replace(/}/mg, " }") + ',\n "compressedData" : <' + (input && input.length + " bytes buffer" || "null") + '>\n "data" : <' + (uncompressedData && uncompressedData.length + " bytes buffer" || "null") + ">\n}";
1187
+ }
1188
+ };
1189
+ };
1190
+ }
1191
+ });
1192
+
1193
+ // ../../node_modules/adm-zip/zipFile.js
1194
+ var require_zipFile = __commonJS({
1195
+ "../../node_modules/adm-zip/zipFile.js"(exports, module) {
1196
+ var ZipEntry = require_zipEntry();
1197
+ var Headers = require_headers();
1198
+ var Utils = require_util();
1199
+ module.exports = function(input, inputType) {
1200
+ var entryList = [], entryTable = {}, _comment = Buffer.alloc(0), filename = "", fs10 = Utils.FileSystem.require(), inBuffer = null, mainHeader = new Headers.MainHeader(), loadedEntries = false;
1201
+ if (inputType === Utils.Constants.FILE) {
1202
+ filename = input;
1203
+ inBuffer = fs10.readFileSync(filename);
1204
+ readMainHeader();
1205
+ } else if (inputType === Utils.Constants.BUFFER) {
1206
+ inBuffer = input;
1207
+ readMainHeader();
1208
+ } else {
1209
+ loadedEntries = true;
1210
+ }
1211
+ function iterateEntries(callback) {
1212
+ const totalEntries = mainHeader.diskEntries;
1213
+ let index = mainHeader.offset;
1214
+ for (let i = 0; i < totalEntries; i++) {
1215
+ let tmp = index;
1216
+ const entry = new ZipEntry(inBuffer);
1217
+ entry.header = inBuffer.slice(tmp, tmp += Utils.Constants.CENHDR);
1218
+ entry.entryName = inBuffer.slice(tmp, tmp += entry.header.fileNameLength);
1219
+ index += entry.header.entryHeaderSize;
1220
+ callback(entry);
1221
+ }
1222
+ }
1223
+ function readEntries() {
1224
+ loadedEntries = true;
1225
+ entryTable = {};
1226
+ entryList = new Array(mainHeader.diskEntries);
1227
+ var index = mainHeader.offset;
1228
+ for (var i = 0; i < entryList.length; i++) {
1229
+ var tmp = index, entry = new ZipEntry(inBuffer);
1230
+ entry.header = inBuffer.slice(tmp, tmp += Utils.Constants.CENHDR);
1231
+ entry.entryName = inBuffer.slice(tmp, tmp += entry.header.fileNameLength);
1232
+ if (entry.header.extraLength) {
1233
+ entry.extra = inBuffer.slice(tmp, tmp += entry.header.extraLength);
1234
+ }
1235
+ if (entry.header.commentLength)
1236
+ entry.comment = inBuffer.slice(tmp, tmp + entry.header.commentLength);
1237
+ index += entry.header.entryHeaderSize;
1238
+ entryList[i] = entry;
1239
+ entryTable[entry.entryName] = entry;
1240
+ }
1241
+ }
1242
+ function readMainHeader() {
1243
+ var i = inBuffer.length - Utils.Constants.ENDHDR, max = Math.max(0, i - 65535), n = max, endStart = inBuffer.length, endOffset = -1, commentEnd = 0;
1244
+ for (i; i >= n; i--) {
1245
+ if (inBuffer[i] !== 80) continue;
1246
+ if (inBuffer.readUInt32LE(i) === Utils.Constants.ENDSIG) {
1247
+ endOffset = i;
1248
+ commentEnd = i;
1249
+ endStart = i + Utils.Constants.ENDHDR;
1250
+ n = i - Utils.Constants.END64HDR;
1251
+ continue;
1252
+ }
1253
+ if (inBuffer.readUInt32LE(i) === Utils.Constants.END64SIG) {
1254
+ n = max;
1255
+ continue;
1256
+ }
1257
+ if (inBuffer.readUInt32LE(i) == Utils.Constants.ZIP64SIG) {
1258
+ endOffset = i;
1259
+ endStart = i + Utils.readBigUInt64LE(inBuffer, i + Utils.Constants.ZIP64SIZE) + Utils.Constants.ZIP64LEAD;
1260
+ break;
1261
+ }
1262
+ }
1263
+ if (!~endOffset)
1264
+ throw new Error(Utils.Errors.INVALID_FORMAT);
1265
+ mainHeader.loadFromBinary(inBuffer.slice(endOffset, endStart));
1266
+ if (mainHeader.commentLength) {
1267
+ _comment = inBuffer.slice(commentEnd + Utils.Constants.ENDHDR);
1268
+ }
1269
+ }
1270
+ return {
1271
+ /**
1272
+ * Returns an array of ZipEntry objects existent in the current opened archive
1273
+ * @return Array
1274
+ */
1275
+ get entries() {
1276
+ if (!loadedEntries) {
1277
+ readEntries();
1278
+ }
1279
+ return entryList;
1280
+ },
1281
+ /**
1282
+ * Archive comment
1283
+ * @return {String}
1284
+ */
1285
+ get comment() {
1286
+ return _comment.toString();
1287
+ },
1288
+ set comment(val) {
1289
+ mainHeader.commentLength = val.length;
1290
+ _comment = val;
1291
+ },
1292
+ getEntryCount: function() {
1293
+ if (!loadedEntries) {
1294
+ return mainHeader.diskEntries;
1295
+ }
1296
+ return entryList.length;
1297
+ },
1298
+ forEach: function(callback) {
1299
+ if (!loadedEntries) {
1300
+ iterateEntries(callback);
1301
+ return;
1302
+ }
1303
+ entryList.forEach(callback);
1304
+ },
1305
+ /**
1306
+ * Returns a reference to the entry with the given name or null if entry is inexistent
1307
+ *
1308
+ * @param entryName
1309
+ * @return ZipEntry
1310
+ */
1311
+ getEntry: function(entryName) {
1312
+ if (!loadedEntries) {
1313
+ readEntries();
1314
+ }
1315
+ return entryTable[entryName] || null;
1316
+ },
1317
+ /**
1318
+ * Adds the given entry to the entry list
1319
+ *
1320
+ * @param entry
1321
+ */
1322
+ setEntry: function(entry) {
1323
+ if (!loadedEntries) {
1324
+ readEntries();
1325
+ }
1326
+ entryList.push(entry);
1327
+ entryTable[entry.entryName] = entry;
1328
+ mainHeader.totalEntries = entryList.length;
1329
+ },
1330
+ /**
1331
+ * Removes the entry with the given name from the entry list.
1332
+ *
1333
+ * If the entry is a directory, then all nested files and directories will be removed
1334
+ * @param entryName
1335
+ */
1336
+ deleteEntry: function(entryName) {
1337
+ if (!loadedEntries) {
1338
+ readEntries();
1339
+ }
1340
+ var entry = entryTable[entryName];
1341
+ if (entry && entry.isDirectory) {
1342
+ var _self = this;
1343
+ this.getEntryChildren(entry).forEach(function(child) {
1344
+ if (child.entryName !== entryName) {
1345
+ _self.deleteEntry(child.entryName);
1346
+ }
1347
+ });
1348
+ }
1349
+ entryList.splice(entryList.indexOf(entry), 1);
1350
+ delete entryTable[entryName];
1351
+ mainHeader.totalEntries = entryList.length;
1352
+ },
1353
+ /**
1354
+ * Iterates and returns all nested files and directories of the given entry
1355
+ *
1356
+ * @param entry
1357
+ * @return Array
1358
+ */
1359
+ getEntryChildren: function(entry) {
1360
+ if (!loadedEntries) {
1361
+ readEntries();
1362
+ }
1363
+ if (entry.isDirectory) {
1364
+ var list = [], name = entry.entryName, len = name.length;
1365
+ entryList.forEach(function(zipEntry) {
1366
+ if (zipEntry.entryName.substr(0, len) === name) {
1367
+ list.push(zipEntry);
1368
+ }
1369
+ });
1370
+ return list;
1371
+ }
1372
+ return [];
1373
+ },
1374
+ /**
1375
+ * Returns the zip file
1376
+ *
1377
+ * @return Buffer
1378
+ */
1379
+ compressToBuffer: function() {
1380
+ if (!loadedEntries) {
1381
+ readEntries();
1382
+ }
1383
+ if (entryList.length > 1) {
1384
+ entryList.sort(function(a, b) {
1385
+ var nameA = a.entryName.toLowerCase();
1386
+ var nameB = b.entryName.toLowerCase();
1387
+ if (nameA < nameB) {
1388
+ return -1;
1389
+ }
1390
+ if (nameA > nameB) {
1391
+ return 1;
1392
+ }
1393
+ return 0;
1394
+ });
1395
+ }
1396
+ var totalSize = 0, dataBlock = [], entryHeaders = [], dindex = 0;
1397
+ mainHeader.size = 0;
1398
+ mainHeader.offset = 0;
1399
+ entryList.forEach(function(entry) {
1400
+ var compressedData = entry.getCompressedData();
1401
+ entry.header.offset = dindex;
1402
+ var dataHeader = entry.header.dataHeaderToBinary();
1403
+ var entryNameLen = entry.rawEntryName.length;
1404
+ var extra = entry.extra.toString();
1405
+ var postHeader = Buffer.alloc(entryNameLen + extra.length);
1406
+ entry.rawEntryName.copy(postHeader, 0);
1407
+ postHeader.fill(extra, entryNameLen);
1408
+ var dataLength = dataHeader.length + postHeader.length + compressedData.length;
1409
+ dindex += dataLength;
1410
+ dataBlock.push(dataHeader);
1411
+ dataBlock.push(postHeader);
1412
+ dataBlock.push(compressedData);
1413
+ var entryHeader = entry.packHeader();
1414
+ entryHeaders.push(entryHeader);
1415
+ mainHeader.size += entryHeader.length;
1416
+ totalSize += dataLength + entryHeader.length;
1417
+ });
1418
+ totalSize += mainHeader.mainHeaderSize;
1419
+ mainHeader.offset = dindex;
1420
+ dindex = 0;
1421
+ var outBuffer = Buffer.alloc(totalSize);
1422
+ dataBlock.forEach(function(content) {
1423
+ content.copy(outBuffer, dindex);
1424
+ dindex += content.length;
1425
+ });
1426
+ entryHeaders.forEach(function(content) {
1427
+ content.copy(outBuffer, dindex);
1428
+ dindex += content.length;
1429
+ });
1430
+ var mh = mainHeader.toBinary();
1431
+ if (_comment) {
1432
+ Buffer.from(_comment).copy(mh, Utils.Constants.ENDHDR);
1433
+ }
1434
+ mh.copy(outBuffer, dindex);
1435
+ return outBuffer;
1436
+ },
1437
+ toAsyncBuffer: function(onSuccess, onFail, onItemStart, onItemEnd) {
1438
+ if (!loadedEntries) {
1439
+ readEntries();
1440
+ }
1441
+ if (entryList.length > 1) {
1442
+ entryList.sort(function(a, b) {
1443
+ var nameA = a.entryName.toLowerCase();
1444
+ var nameB = b.entryName.toLowerCase();
1445
+ if (nameA > nameB) {
1446
+ return -1;
1447
+ }
1448
+ if (nameA < nameB) {
1449
+ return 1;
1450
+ }
1451
+ return 0;
1452
+ });
1453
+ }
1454
+ var totalSize = 0, dataBlock = [], entryHeaders = [], dindex = 0;
1455
+ mainHeader.size = 0;
1456
+ mainHeader.offset = 0;
1457
+ var compress = function(entryList2) {
1458
+ var self = arguments.callee;
1459
+ if (entryList2.length) {
1460
+ var entry = entryList2.pop();
1461
+ var name = entry.entryName + entry.extra.toString();
1462
+ if (onItemStart) onItemStart(name);
1463
+ entry.getCompressedDataAsync(function(compressedData) {
1464
+ if (onItemEnd) onItemEnd(name);
1465
+ entry.header.offset = dindex;
1466
+ var dataHeader = entry.header.dataHeaderToBinary();
1467
+ var postHeader;
1468
+ try {
1469
+ postHeader = Buffer.alloc(name.length, name);
1470
+ } catch (e) {
1471
+ postHeader = new Buffer(name);
1472
+ }
1473
+ var dataLength = dataHeader.length + postHeader.length + compressedData.length;
1474
+ dindex += dataLength;
1475
+ dataBlock.push(dataHeader);
1476
+ dataBlock.push(postHeader);
1477
+ dataBlock.push(compressedData);
1478
+ var entryHeader = entry.packHeader();
1479
+ entryHeaders.push(entryHeader);
1480
+ mainHeader.size += entryHeader.length;
1481
+ totalSize += dataLength + entryHeader.length;
1482
+ if (entryList2.length) {
1483
+ self(entryList2);
1484
+ } else {
1485
+ totalSize += mainHeader.mainHeaderSize;
1486
+ mainHeader.offset = dindex;
1487
+ dindex = 0;
1488
+ var outBuffer = Buffer.alloc(totalSize);
1489
+ dataBlock.forEach(function(content) {
1490
+ content.copy(outBuffer, dindex);
1491
+ dindex += content.length;
1492
+ });
1493
+ entryHeaders.forEach(function(content) {
1494
+ content.copy(outBuffer, dindex);
1495
+ dindex += content.length;
1496
+ });
1497
+ var mh = mainHeader.toBinary();
1498
+ if (_comment) {
1499
+ _comment.copy(mh, Utils.Constants.ENDHDR);
1500
+ }
1501
+ mh.copy(outBuffer, dindex);
1502
+ onSuccess(outBuffer);
1503
+ }
1504
+ });
1505
+ }
1506
+ };
1507
+ compress(entryList);
1508
+ }
1509
+ };
1510
+ };
1511
+ }
1512
+ });
1513
+
1514
+ // ../../node_modules/adm-zip/adm-zip.js
1515
+ var require_adm_zip = __commonJS({
1516
+ "../../node_modules/adm-zip/adm-zip.js"(exports, module) {
1517
+ var Utils = require_util();
1518
+ var fs10 = Utils.FileSystem.require();
1519
+ var pth = __require("path");
1520
+ fs10.existsSync = fs10.existsSync || pth.existsSync;
1521
+ var ZipEntry = require_zipEntry();
1522
+ var ZipFile = require_zipFile();
1523
+ var isWin = /^win/.test(process.platform);
1524
+ module.exports = function(input) {
1525
+ var _zip = void 0, _filename = "";
1526
+ if (input && typeof input === "string") {
1527
+ if (fs10.existsSync(input)) {
1528
+ _filename = input;
1529
+ _zip = new ZipFile(input, Utils.Constants.FILE);
1530
+ } else {
1531
+ throw new Error(Utils.Errors.INVALID_FILENAME);
1532
+ }
1533
+ } else if (input && Buffer.isBuffer(input)) {
1534
+ _zip = new ZipFile(input, Utils.Constants.BUFFER);
1535
+ } else {
1536
+ _zip = new ZipFile(null, Utils.Constants.NONE);
1537
+ }
1538
+ function sanitize(prefix, name) {
1539
+ prefix = pth.resolve(pth.normalize(prefix));
1540
+ var parts = name.split("/");
1541
+ for (var i = 0, l = parts.length; i < l; i++) {
1542
+ var path12 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
1543
+ if (path12.indexOf(prefix) === 0) {
1544
+ return path12;
1545
+ }
1546
+ }
1547
+ return pth.normalize(pth.join(prefix, pth.basename(name)));
1548
+ }
1549
+ function getEntry(entry) {
1550
+ if (entry && _zip) {
1551
+ var item;
1552
+ if (typeof entry === "string")
1553
+ item = _zip.getEntry(entry);
1554
+ if (typeof entry === "object" && typeof entry.entryName !== "undefined" && typeof entry.header !== "undefined")
1555
+ item = _zip.getEntry(entry.entryName);
1556
+ if (item) {
1557
+ return item;
1558
+ }
1559
+ }
1560
+ return null;
1561
+ }
1562
+ return {
1563
+ /**
1564
+ * Extracts the given entry from the archive and returns the content as a Buffer object
1565
+ * @param entry ZipEntry object or String with the full path of the entry
1566
+ *
1567
+ * @return Buffer or Null in case of error
1568
+ */
1569
+ readFile: function(entry) {
1570
+ var item = getEntry(entry);
1571
+ return item && item.getData() || null;
1572
+ },
1573
+ /**
1574
+ * Asynchronous readFile
1575
+ * @param entry ZipEntry object or String with the full path of the entry
1576
+ * @param callback
1577
+ *
1578
+ * @return Buffer or Null in case of error
1579
+ */
1580
+ readFileAsync: function(entry, callback) {
1581
+ var item = getEntry(entry);
1582
+ if (item) {
1583
+ item.getDataAsync(callback);
1584
+ } else {
1585
+ callback(null, "getEntry failed for:" + entry);
1586
+ }
1587
+ },
1588
+ /**
1589
+ * Extracts the given entry from the archive and returns the content as plain text in the given encoding
1590
+ * @param entry ZipEntry object or String with the full path of the entry
1591
+ * @param encoding Optional. If no encoding is specified utf8 is used
1592
+ *
1593
+ * @return String
1594
+ */
1595
+ readAsText: function(entry, encoding) {
1596
+ var item = getEntry(entry);
1597
+ if (item) {
1598
+ var data = item.getData();
1599
+ if (data && data.length) {
1600
+ return data.toString(encoding || "utf8");
1601
+ }
1602
+ }
1603
+ return "";
1604
+ },
1605
+ /**
1606
+ * Asynchronous readAsText
1607
+ * @param entry ZipEntry object or String with the full path of the entry
1608
+ * @param callback
1609
+ * @param encoding Optional. If no encoding is specified utf8 is used
1610
+ *
1611
+ * @return String
1612
+ */
1613
+ readAsTextAsync: function(entry, callback, encoding) {
1614
+ var item = getEntry(entry);
1615
+ if (item) {
1616
+ item.getDataAsync(function(data, err) {
1617
+ if (err) {
1618
+ callback(data, err);
1619
+ return;
1620
+ }
1621
+ if (data && data.length) {
1622
+ callback(data.toString(encoding || "utf8"));
1623
+ } else {
1624
+ callback("");
1625
+ }
1626
+ });
1627
+ } else {
1628
+ callback("");
1629
+ }
1630
+ },
1631
+ /**
1632
+ * Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
1633
+ *
1634
+ * @param entry
1635
+ */
1636
+ deleteFile: function(entry) {
1637
+ var item = getEntry(entry);
1638
+ if (item) {
1639
+ _zip.deleteEntry(item.entryName);
1640
+ }
1641
+ },
1642
+ /**
1643
+ * Adds a comment to the zip. The zip must be rewritten after adding the comment.
1644
+ *
1645
+ * @param comment
1646
+ */
1647
+ addZipComment: function(comment) {
1648
+ _zip.comment = comment;
1649
+ },
1650
+ /**
1651
+ * Returns the zip comment
1652
+ *
1653
+ * @return String
1654
+ */
1655
+ getZipComment: function() {
1656
+ return _zip.comment || "";
1657
+ },
1658
+ /**
1659
+ * Adds a comment to a specified zipEntry. The zip must be rewritten after adding the comment
1660
+ * The comment cannot exceed 65535 characters in length
1661
+ *
1662
+ * @param entry
1663
+ * @param comment
1664
+ */
1665
+ addZipEntryComment: function(entry, comment) {
1666
+ var item = getEntry(entry);
1667
+ if (item) {
1668
+ item.comment = comment;
1669
+ }
1670
+ },
1671
+ /**
1672
+ * Returns the comment of the specified entry
1673
+ *
1674
+ * @param entry
1675
+ * @return String
1676
+ */
1677
+ getZipEntryComment: function(entry) {
1678
+ var item = getEntry(entry);
1679
+ if (item) {
1680
+ return item.comment || "";
1681
+ }
1682
+ return "";
1683
+ },
1684
+ /**
1685
+ * Updates the content of an existing entry inside the archive. The zip must be rewritten after updating the content
1686
+ *
1687
+ * @param entry
1688
+ * @param content
1689
+ */
1690
+ updateFile: function(entry, content) {
1691
+ var item = getEntry(entry);
1692
+ if (item) {
1693
+ item.setData(content);
1694
+ }
1695
+ },
1696
+ /**
1697
+ * Adds a file from the disk to the archive
1698
+ *
1699
+ * @param localPath File to add to zip
1700
+ * @param zipPath Optional path inside the zip
1701
+ * @param zipName Optional name for the file
1702
+ */
1703
+ addLocalFile: function(localPath, zipPath, zipName) {
1704
+ if (fs10.existsSync(localPath)) {
1705
+ if (zipPath) {
1706
+ zipPath = zipPath.split("\\").join("/");
1707
+ if (zipPath.charAt(zipPath.length - 1) !== "/") {
1708
+ zipPath += "/";
1709
+ }
1710
+ } else {
1711
+ zipPath = "";
1712
+ }
1713
+ var p = localPath.split("\\").join("/").split("/").pop();
1714
+ if (zipName) {
1715
+ this.addFile(zipPath + zipName, fs10.readFileSync(localPath), "", 0);
1716
+ } else {
1717
+ this.addFile(zipPath + p, fs10.readFileSync(localPath), "", 0);
1718
+ }
1719
+ } else {
1720
+ throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
1721
+ }
1722
+ },
1723
+ /**
1724
+ * Adds a local directory and all its nested files and directories to the archive
1725
+ *
1726
+ * @param localPath
1727
+ * @param zipPath optional path inside zip
1728
+ * @param filter optional RegExp or Function if files match will
1729
+ * be included.
1730
+ */
1731
+ addLocalFolder: function(localPath, zipPath, filter) {
1732
+ if (filter === void 0) {
1733
+ filter = function() {
1734
+ return true;
1735
+ };
1736
+ } else if (filter instanceof RegExp) {
1737
+ filter = /* @__PURE__ */ (function(filter2) {
1738
+ return function(filename) {
1739
+ return filter2.test(filename);
1740
+ };
1741
+ })(filter);
1742
+ }
1743
+ if (zipPath) {
1744
+ zipPath = zipPath.split("\\").join("/");
1745
+ if (zipPath.charAt(zipPath.length - 1) !== "/") {
1746
+ zipPath += "/";
1747
+ }
1748
+ } else {
1749
+ zipPath = "";
1750
+ }
1751
+ localPath = pth.normalize(localPath);
1752
+ localPath = localPath.split("\\").join("/");
1753
+ if (localPath.charAt(localPath.length - 1) !== "/")
1754
+ localPath += "/";
1755
+ if (fs10.existsSync(localPath)) {
1756
+ var items = Utils.findFiles(localPath), self = this;
1757
+ if (items.length) {
1758
+ items.forEach(function(path12) {
1759
+ var p = path12.split("\\").join("/").replace(new RegExp(localPath.replace(/(\(|\)|\$)/g, "\\$1"), "i"), "");
1760
+ if (filter(p)) {
1761
+ if (p.charAt(p.length - 1) !== "/") {
1762
+ self.addFile(zipPath + p, fs10.readFileSync(path12), "", 0);
1763
+ } else {
1764
+ self.addFile(zipPath + p, Buffer.alloc(0), "", 0);
1765
+ }
1766
+ }
1767
+ });
1768
+ }
1769
+ } else {
1770
+ throw new Error(Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
1771
+ }
1772
+ },
1773
+ /**
1774
+ * Asynchronous addLocalFile
1775
+ * @param localPath
1776
+ * @param callback
1777
+ * @param zipPath optional path inside zip
1778
+ * @param filter optional RegExp or Function if files match will
1779
+ * be included.
1780
+ */
1781
+ addLocalFolderAsync: function(localPath, callback, zipPath, filter) {
1782
+ if (filter === void 0) {
1783
+ filter = function() {
1784
+ return true;
1785
+ };
1786
+ } else if (filter instanceof RegExp) {
1787
+ filter = /* @__PURE__ */ (function(filter2) {
1788
+ return function(filename) {
1789
+ return filter2.test(filename);
1790
+ };
1791
+ })(filter);
1792
+ }
1793
+ if (zipPath) {
1794
+ zipPath = zipPath.split("\\").join("/");
1795
+ if (zipPath.charAt(zipPath.length - 1) !== "/") {
1796
+ zipPath += "/";
1797
+ }
1798
+ } else {
1799
+ zipPath = "";
1800
+ }
1801
+ localPath = pth.normalize(localPath);
1802
+ localPath = localPath.split("\\").join("/");
1803
+ if (localPath.charAt(localPath.length - 1) !== "/")
1804
+ localPath += "/";
1805
+ var self = this;
1806
+ fs10.open(localPath, "r", function(err, fd) {
1807
+ if (err && err.code === "ENOENT") {
1808
+ callback(void 0, Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
1809
+ } else if (err) {
1810
+ callback(void 0, err);
1811
+ } else {
1812
+ var items = Utils.findFiles(localPath);
1813
+ var i = -1;
1814
+ var next = function() {
1815
+ i += 1;
1816
+ if (i < items.length) {
1817
+ var p = items[i].split("\\").join("/").replace(new RegExp(localPath.replace(/(\(|\))/g, "\\$1"), "i"), "");
1818
+ p = p.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\x20-\x7E]/g, "");
1819
+ if (filter(p)) {
1820
+ if (p.charAt(p.length - 1) !== "/") {
1821
+ fs10.readFile(items[i], function(err2, data) {
1822
+ if (err2) {
1823
+ callback(void 0, err2);
1824
+ } else {
1825
+ self.addFile(zipPath + p, data, "", 0);
1826
+ next();
1827
+ }
1828
+ });
1829
+ } else {
1830
+ self.addFile(zipPath + p, Buffer.alloc(0), "", 0);
1831
+ next();
1832
+ }
1833
+ } else {
1834
+ next();
1835
+ }
1836
+ } else {
1837
+ callback(true, void 0);
1838
+ }
1839
+ };
1840
+ next();
1841
+ }
1842
+ });
1843
+ },
1844
+ /**
1845
+ * Allows you to create a entry (file or directory) in the zip file.
1846
+ * If you want to create a directory the entryName must end in / and a null buffer should be provided.
1847
+ * Comment and attributes are optional
1848
+ *
1849
+ * @param entryName
1850
+ * @param content
1851
+ * @param comment
1852
+ * @param attr
1853
+ */
1854
+ addFile: function(entryName, content, comment, attr) {
1855
+ var entry = new ZipEntry();
1856
+ entry.entryName = entryName;
1857
+ entry.comment = comment || "";
1858
+ if (!attr) {
1859
+ if (entry.isDirectory) {
1860
+ attr = 16877 << 16 | 16;
1861
+ } else {
1862
+ attr = 420 << 16;
1863
+ }
1864
+ }
1865
+ entry.attr = attr;
1866
+ entry.setData(content);
1867
+ _zip.setEntry(entry);
1868
+ },
1869
+ /**
1870
+ * Returns an array of ZipEntry objects representing the files and folders inside the archive
1871
+ *
1872
+ * @return Array
1873
+ */
1874
+ getEntries: function() {
1875
+ if (_zip) {
1876
+ return _zip.entries;
1877
+ } else {
1878
+ return [];
1879
+ }
1880
+ },
1881
+ /**
1882
+ * Returns a ZipEntry object representing the file or folder specified by ``name``.
1883
+ *
1884
+ * @param name
1885
+ * @return ZipEntry
1886
+ */
1887
+ getEntry: function(name) {
1888
+ return getEntry(name);
1889
+ },
1890
+ getEntryCount: function() {
1891
+ return _zip.getEntryCount();
1892
+ },
1893
+ forEach: function(callback) {
1894
+ return _zip.forEach(callback);
1895
+ },
1896
+ /**
1897
+ * Extracts the given entry to the given targetPath
1898
+ * If the entry is a directory inside the archive, the entire directory and it's subdirectories will be extracted
1899
+ *
1900
+ * @param entry ZipEntry object or String with the full path of the entry
1901
+ * @param targetPath Target folder where to write the file
1902
+ * @param maintainEntryPath If maintainEntryPath is true and the entry is inside a folder, the entry folder
1903
+ * will be created in targetPath as well. Default is TRUE
1904
+ * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
1905
+ * Default is FALSE
1906
+ *
1907
+ * @return Boolean
1908
+ */
1909
+ extractEntryTo: function(entry, targetPath, maintainEntryPath, overwrite) {
1910
+ overwrite = overwrite || false;
1911
+ maintainEntryPath = typeof maintainEntryPath === "undefined" ? true : maintainEntryPath;
1912
+ var item = getEntry(entry);
1913
+ if (!item) {
1914
+ throw new Error(Utils.Errors.NO_ENTRY);
1915
+ }
1916
+ var entryName = item.entryName;
1917
+ var target = sanitize(targetPath, maintainEntryPath ? entryName : pth.basename(entryName));
1918
+ if (item.isDirectory) {
1919
+ target = pth.resolve(target, "..");
1920
+ var children = _zip.getEntryChildren(item);
1921
+ children.forEach(function(child) {
1922
+ if (child.isDirectory) return;
1923
+ var content2 = child.getData();
1924
+ if (!content2) {
1925
+ throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
1926
+ }
1927
+ var childName = sanitize(targetPath, maintainEntryPath ? child.entryName : pth.basename(child.entryName));
1928
+ Utils.writeFileTo(childName, content2, overwrite);
1929
+ });
1930
+ return true;
1931
+ }
1932
+ var content = item.getData();
1933
+ if (!content) throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
1934
+ if (fs10.existsSync(target) && !overwrite) {
1935
+ throw new Error(Utils.Errors.CANT_OVERRIDE);
1936
+ }
1937
+ Utils.writeFileTo(target, content, overwrite);
1938
+ return true;
1939
+ },
1940
+ /**
1941
+ * Test the archive
1942
+ *
1943
+ */
1944
+ test: function() {
1945
+ if (!_zip) {
1946
+ return false;
1947
+ }
1948
+ for (var entry in _zip.entries) {
1949
+ try {
1950
+ if (entry.isDirectory) {
1951
+ continue;
1952
+ }
1953
+ var content = _zip.entries[entry].getData();
1954
+ if (!content) {
1955
+ return false;
1956
+ }
1957
+ } catch (err) {
1958
+ return false;
1959
+ }
1960
+ }
1961
+ return true;
1962
+ },
1963
+ /**
1964
+ * Extracts the entire archive to the given location
1965
+ *
1966
+ * @param targetPath Target location
1967
+ * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
1968
+ * Default is FALSE
1969
+ */
1970
+ extractAllTo: function(targetPath, overwrite) {
1971
+ overwrite = overwrite || false;
1972
+ if (!_zip) {
1973
+ throw new Error(Utils.Errors.NO_ZIP);
1974
+ }
1975
+ _zip.entries.forEach(function(entry) {
1976
+ var entryName = sanitize(targetPath, entry.entryName.toString());
1977
+ if (entry.isDirectory) {
1978
+ Utils.makeDir(entryName);
1979
+ return;
1980
+ }
1981
+ var content = entry.getData();
1982
+ if (!content) {
1983
+ throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
1984
+ }
1985
+ Utils.writeFileTo(entryName, content, overwrite);
1986
+ try {
1987
+ fs10.utimesSync(entryName, entry.header.time, entry.header.time);
1988
+ } catch (err) {
1989
+ throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
1990
+ }
1991
+ });
1992
+ },
1993
+ /**
1994
+ * Asynchronous extractAllTo
1995
+ *
1996
+ * @param targetPath Target location
1997
+ * @param overwrite If the file already exists at the target path, the file will be overwriten if this is true.
1998
+ * Default is FALSE
1999
+ * @param callback
2000
+ */
2001
+ extractAllToAsync: function(targetPath, overwrite, callback) {
2002
+ if (!callback) {
2003
+ callback = function() {
2004
+ };
2005
+ }
2006
+ overwrite = overwrite || false;
2007
+ if (!_zip) {
2008
+ callback(new Error(Utils.Errors.NO_ZIP));
2009
+ return;
2010
+ }
2011
+ var entries = _zip.entries;
2012
+ var i = entries.length;
2013
+ entries.forEach(function(entry) {
2014
+ if (i <= 0) return;
2015
+ var entryName = pth.normalize(entry.entryName.toString());
2016
+ if (entry.isDirectory) {
2017
+ Utils.makeDir(sanitize(targetPath, entryName));
2018
+ if (--i === 0)
2019
+ callback(void 0);
2020
+ return;
2021
+ }
2022
+ entry.getDataAsync(function(content, err) {
2023
+ if (i <= 0) return;
2024
+ if (err) {
2025
+ callback(new Error(err));
2026
+ return;
2027
+ }
2028
+ if (!content) {
2029
+ i = 0;
2030
+ callback(new Error(Utils.Errors.CANT_EXTRACT_FILE));
2031
+ return;
2032
+ }
2033
+ Utils.writeFileToAsync(sanitize(targetPath, entryName), content, overwrite, function(succ) {
2034
+ try {
2035
+ fs10.utimesSync(pth.resolve(targetPath, entryName), entry.header.time, entry.header.time);
2036
+ } catch (err2) {
2037
+ callback(new Error("Unable to set utimes"));
2038
+ }
2039
+ if (i <= 0) return;
2040
+ if (!succ) {
2041
+ i = 0;
2042
+ callback(new Error("Unable to write"));
2043
+ return;
2044
+ }
2045
+ if (--i === 0)
2046
+ callback(void 0);
2047
+ });
2048
+ });
2049
+ });
2050
+ },
2051
+ /**
2052
+ * Writes the newly created zip file to disk at the specified location or if a zip was opened and no ``targetFileName`` is provided, it will overwrite the opened zip
2053
+ *
2054
+ * @param targetFileName
2055
+ * @param callback
2056
+ */
2057
+ writeZip: function(targetFileName, callback) {
2058
+ if (arguments.length === 1) {
2059
+ if (typeof targetFileName === "function") {
2060
+ callback = targetFileName;
2061
+ targetFileName = "";
2062
+ }
2063
+ }
2064
+ if (!targetFileName && _filename) {
2065
+ targetFileName = _filename;
2066
+ }
2067
+ if (!targetFileName) return;
2068
+ var zipData = _zip.compressToBuffer();
2069
+ if (zipData) {
2070
+ var ok = Utils.writeFileTo(targetFileName, zipData, true);
2071
+ if (typeof callback === "function") callback(!ok ? new Error("failed") : null, "");
2072
+ }
2073
+ },
2074
+ /**
2075
+ * Returns the content of the entire zip file as a Buffer object
2076
+ *
2077
+ * @return Buffer
2078
+ */
2079
+ toBuffer: function(onSuccess, onFail, onItemStart, onItemEnd) {
2080
+ this.valueOf = 2;
2081
+ if (typeof onSuccess === "function") {
2082
+ _zip.toAsyncBuffer(onSuccess, onFail, onItemStart, onItemEnd);
2083
+ return null;
2084
+ }
2085
+ return _zip.compressToBuffer();
2086
+ }
2087
+ };
2088
+ };
2089
+ }
2090
+ });
2091
+
1
2092
  // src/index.ts
2
- import fs7 from "node:fs";
3
- import path9 from "node:path";
2093
+ import fs9 from "node:fs";
2094
+ import path11 from "node:path";
4
2095
  import { fileURLToPath as fileURLToPath2 } from "node:url";
5
2096
  import os4 from "node:os";
6
2097
 
@@ -101,12 +2192,11 @@ var ActiveSkills = class {
101
2192
  };
102
2193
 
103
2194
  // src/updater.ts
2195
+ var import_adm_zip = __toESM(require_adm_zip(), 1);
104
2196
  import fs3 from "node:fs/promises";
105
2197
  import fsSync from "node:fs";
106
2198
  import path3 from "node:path";
107
2199
  import os2 from "node:os";
108
- import { execFile } from "node:child_process";
109
- import { promisify } from "node:util";
110
2200
  import { randomUUID, createHash } from "node:crypto";
111
2201
 
112
2202
  // src/skill-version.ts
@@ -139,14 +2229,27 @@ function parseSkillVersion(content) {
139
2229
  }
140
2230
 
141
2231
  // src/updater.ts
142
- var execFileAsync = promisify(execFile);
143
2232
  var ATTEMPT_COOLDOWN_MS = 30 * 60 * 1e3;
144
2233
  function skillIdentityHash(code, version) {
145
2234
  return createHash("sha256").update(`${code} ${code} ${version}`).digest("hex");
146
2235
  }
147
2236
  async function systemUnzip(zipPath, destDir) {
148
2237
  await fs3.mkdir(destDir, { recursive: true });
149
- await execFileAsync("unzip", ["-o", "-q", zipPath, "-d", destDir]);
2238
+ const destRoot = path3.resolve(destDir);
2239
+ const zip = new import_adm_zip.default(zipPath);
2240
+ for (const entry of zip.getEntries()) {
2241
+ const normalizedName = entry.entryName.replace(/\\/g, "/");
2242
+ const outPath = path3.resolve(destRoot, normalizedName);
2243
+ if (outPath !== destRoot && !outPath.startsWith(destRoot + path3.sep)) {
2244
+ throw new Error(`ZIP \u5305\u542B\u975E\u6CD5\u8DEF\u5F84: ${entry.entryName}`);
2245
+ }
2246
+ if (entry.isDirectory) {
2247
+ await fs3.mkdir(outPath, { recursive: true });
2248
+ continue;
2249
+ }
2250
+ await fs3.mkdir(path3.dirname(outPath), { recursive: true });
2251
+ await fs3.writeFile(outPath, entry.getData());
2252
+ }
150
2253
  }
151
2254
  var SkillUpdater = class {
152
2255
  getConfig;
@@ -331,6 +2434,25 @@ var SkillUpdater = class {
331
2434
  }
332
2435
  return void 0;
333
2436
  }
2437
+ /** 在解压目录里定位专家根目录;专家包根必须同时包含 AGENTS.md 和 SOUL.md。 */
2438
+ async locateExpertRoot(dir, depth) {
2439
+ if (depth > 2) return void 0;
2440
+ let entries;
2441
+ try {
2442
+ entries = await fs3.readdir(dir, { withFileTypes: true });
2443
+ } catch {
2444
+ return void 0;
2445
+ }
2446
+ const files = new Set(entries.filter((entry) => entry.isFile()).map((entry) => entry.name));
2447
+ if (files.has("AGENTS.md") && files.has("SOUL.md")) return dir;
2448
+ for (const entry of entries) {
2449
+ if (entry.isDirectory()) {
2450
+ const found = await this.locateExpertRoot(path3.join(dir, entry.name), depth + 1);
2451
+ if (found) return found;
2452
+ }
2453
+ }
2454
+ return void 0;
2455
+ }
334
2456
  /**
335
2457
  * 直接覆盖、不备份,但保证「不丢数据」:
336
2458
  * 先把新内容暂存到同级临时目录 → 旧目录改名挪开 → 新内容 rename 换入 → 删掉挪开的旧目录。
@@ -394,37 +2516,114 @@ var SkillUpdater = class {
394
2516
  });
395
2517
  }
396
2518
  }
2519
+ async installExpertZipFromUrl(url, targetDir) {
2520
+ const work = path3.join(this.tmpDir, `slp-expert-${randomUUID()}`);
2521
+ await fs3.mkdir(work, { recursive: true });
2522
+ try {
2523
+ const zipPath = path3.join(work, "pkg.zip");
2524
+ const res = await this.fetchImpl(url);
2525
+ if (!res.ok) return { success: false, message: `\u4E0B\u8F7D\u5931\u8D25: HTTP ${res.status}` };
2526
+ await fs3.writeFile(zipPath, Buffer.from(await res.arrayBuffer()));
2527
+ const staging = path3.join(work, "staging");
2528
+ await this.unzip(zipPath, staging);
2529
+ const expertRoot = await this.locateExpertRoot(staging, 0);
2530
+ if (!expertRoot) {
2531
+ return { success: false, message: "\u4E0B\u8F7D\u5305\u5185\u672A\u627E\u5230\u540C\u65F6\u542B AGENTS.md \u548C SOUL.md \u7684\u4E13\u5BB6\u6839\u76EE\u5F55" };
2532
+ }
2533
+ await this.replaceDir(expertRoot, targetDir);
2534
+ return { success: true, message: "\u5B89\u88C5\u6210\u529F" };
2535
+ } catch (err) {
2536
+ return { success: false, message: `\u6267\u884C\u51FA\u9519: ${err.message}` };
2537
+ } finally {
2538
+ await fs3.rm(work, { recursive: true, force: true }).catch(() => {
2539
+ });
2540
+ }
2541
+ }
397
2542
  async manualInstall(options) {
398
- const { code, force, targetDir } = options;
2543
+ const { code, force, targetDir, additionalTargetDirs = [], trace } = options;
399
2544
  let { url, version } = options;
400
- if (!url) {
401
- const dl = await this.fetchDownloadUrl(code, version || "latest");
402
- if (!dl?.url) {
403
- return { success: false, message: `\u65E0\u6CD5\u83B7\u53D6\u6280\u80FD ${code} \u7684\u4E0B\u8F7D\u5730\u5740` };
2545
+ const startedAt = Date.now();
2546
+ let currentStage = "install.start";
2547
+ let work;
2548
+ const emit = (stage, data) => {
2549
+ currentStage = stage;
2550
+ try {
2551
+ trace?.(stage, data);
2552
+ } catch {
404
2553
  }
405
- url = dl.url;
406
- version = dl.version || version;
407
- }
408
- const targetSkillPath = path3.join(targetDir, code);
409
- if (!force && await this.exists(targetSkillPath)) {
410
- return { success: false, message: `\u6280\u80FD ${code} \u5DF2\u5B58\u5728\u4E8E\u76EE\u6807\u76EE\u5F55` };
411
- }
412
- const work = path3.join(this.tmpDir, `slp-manual-${randomUUID()}`);
413
- await fs3.mkdir(work, { recursive: true });
2554
+ };
2555
+ emit("install.start", {
2556
+ code,
2557
+ version: version || "latest",
2558
+ force,
2559
+ hasDirectUrl: Boolean(url),
2560
+ targetCount: 1 + additionalTargetDirs.length
2561
+ });
414
2562
  try {
2563
+ if (!code || code === "." || code === ".." || code.includes("/") || code.includes("\\") || code.includes("\0") || path3.basename(code) !== code) {
2564
+ const message = `\u975E\u6CD5\u7684 Skill code: ${code}`;
2565
+ emit("install.failed", { stage: currentStage, message, elapsedMs: Date.now() - startedAt });
2566
+ return { success: false, message };
2567
+ }
2568
+ if (!url) {
2569
+ const lookupStartedAt = Date.now();
2570
+ emit("download_url.lookup.start", { code, version: version || "latest" });
2571
+ const dl = await this.fetchDownloadUrl(code, version || "latest");
2572
+ if (!dl?.url) {
2573
+ const message = `\u65E0\u6CD5\u83B7\u53D6\u6280\u80FD ${code} \u7684\u4E0B\u8F7D\u5730\u5740`;
2574
+ emit("install.failed", { stage: currentStage, message, elapsedMs: Date.now() - startedAt });
2575
+ return { success: false, message };
2576
+ }
2577
+ url = dl.url;
2578
+ version = dl.version || version;
2579
+ emit("download_url.lookup.completed", {
2580
+ version: version || "latest",
2581
+ url,
2582
+ elapsedMs: Date.now() - lookupStartedAt
2583
+ });
2584
+ }
2585
+ const targetSkillPath = path3.join(targetDir, code);
2586
+ if (!force && await this.exists(targetSkillPath)) {
2587
+ const message = `\u6280\u80FD ${code} \u5DF2\u5B58\u5728\u4E8E\u76EE\u6807\u76EE\u5F55`;
2588
+ emit("install.failed", { stage: currentStage, message, elapsedMs: Date.now() - startedAt });
2589
+ return { success: false, message };
2590
+ }
2591
+ work = path3.join(this.tmpDir, `slp-manual-${randomUUID()}`);
2592
+ await fs3.mkdir(work, { recursive: true });
415
2593
  const zipPath = path3.join(work, "pkg.zip");
2594
+ const downloadStartedAt = Date.now();
2595
+ emit("download.request.start", { url });
416
2596
  const res = await this.fetchImpl(url);
2597
+ emit("download.headers.received", {
2598
+ status: res.status,
2599
+ contentLength: res.headers?.get("content-length") || void 0,
2600
+ contentType: res.headers?.get("content-type") || void 0,
2601
+ elapsedMs: Date.now() - downloadStartedAt
2602
+ });
417
2603
  if (!res.ok) {
418
- return { success: false, message: `\u4E0B\u8F7D\u5931\u8D25: HTTP ${res.status}` };
2604
+ const message = `\u4E0B\u8F7D\u5931\u8D25: HTTP ${res.status}`;
2605
+ emit("install.failed", { stage: currentStage, message, elapsedMs: Date.now() - startedAt });
2606
+ return { success: false, message };
419
2607
  }
420
2608
  const buf = Buffer.from(await res.arrayBuffer());
2609
+ emit("download.body.completed", {
2610
+ bytes: buf.byteLength,
2611
+ elapsedMs: Date.now() - downloadStartedAt
2612
+ });
421
2613
  await fs3.writeFile(zipPath, buf);
2614
+ emit("download.file.written", { bytes: buf.byteLength });
422
2615
  const staging = path3.join(work, "staging");
2616
+ const unzipStartedAt = Date.now();
2617
+ emit("unzip.start", { extractor: "adm-zip" });
423
2618
  await this.unzip(zipPath, staging);
2619
+ emit("unzip.completed", { elapsedMs: Date.now() - unzipStartedAt });
424
2620
  const srcRoot = await this.locateSkillRoot(staging, 0);
425
2621
  if (!srcRoot) {
426
- return { success: false, message: `\u4E0B\u8F7D\u5305\u5185\u672A\u627E\u5230 SKILL.md\uFF0C\u975E\u6CD5\u7684\u6280\u80FD\u5305\u7ED3\u6784` };
2622
+ const message = `\u4E0B\u8F7D\u5305\u5185\u672A\u627E\u5230 SKILL.md\uFF0C\u975E\u6CD5\u7684\u6280\u80FD\u5305\u7ED3\u6784`;
2623
+ emit("install.failed", { stage: currentStage, message, elapsedMs: Date.now() - startedAt });
2624
+ return { success: false, message };
427
2625
  }
2626
+ emit("skill_root.located");
428
2627
  const metaPath = path3.join(srcRoot, ".meta.json");
429
2628
  if (!await this.exists(metaPath)) {
430
2629
  let parsedVersion = version || "unknown";
@@ -442,13 +2641,37 @@ var SkillUpdater = class {
442
2641
  publishedAt: Date.now()
443
2642
  }, null, 2));
444
2643
  }
445
- await this.replaceDir(srcRoot, targetSkillPath);
2644
+ const targets = [targetDir, ...additionalTargetDirs];
2645
+ for (let index = 0; index < targets.length; index += 1) {
2646
+ const rootDir = targets[index];
2647
+ const targetPath = path3.join(rootDir, code);
2648
+ const replaceStartedAt = Date.now();
2649
+ emit("target.replace.start", { targetDir: rootDir, targetIndex: index, targetCount: targets.length });
2650
+ await this.replaceDir(srcRoot, targetPath);
2651
+ emit("target.replace.completed", {
2652
+ targetDir: rootDir,
2653
+ targetIndex: index,
2654
+ targetCount: targets.length,
2655
+ elapsedMs: Date.now() - replaceStartedAt
2656
+ });
2657
+ }
2658
+ emit("install.completed", { elapsedMs: Date.now() - startedAt, targetCount: targets.length });
446
2659
  return { success: true, message: `\u6280\u80FD ${code} \u5B89\u88C5/\u66F4\u65B0\u6210\u529F` };
447
2660
  } catch (err) {
2661
+ emit("install.failed", {
2662
+ stage: currentStage,
2663
+ errorName: err?.name,
2664
+ message: err?.message || String(err),
2665
+ stack: err?.stack,
2666
+ elapsedMs: Date.now() - startedAt
2667
+ });
448
2668
  return { success: false, message: `\u6267\u884C\u51FA\u9519: ${err.message}` };
449
2669
  } finally {
450
- await fs3.rm(work, { recursive: true, force: true }).catch(() => {
451
- });
2670
+ if (work) {
2671
+ await fs3.rm(work, { recursive: true, force: true }).catch(() => {
2672
+ });
2673
+ emit("cleanup.completed", { elapsedMs: Date.now() - startedAt });
2674
+ }
452
2675
  }
453
2676
  }
454
2677
  };
@@ -822,6 +3045,9 @@ function parseCore(v) {
822
3045
  }
823
3046
  return nums.length > 0 ? nums : null;
824
3047
  }
3048
+ function isComparableVersion(v) {
3049
+ return parseCore(v) !== null;
3050
+ }
825
3051
  function compareVersions(a, b) {
826
3052
  const na = parseCore(a);
827
3053
  const nb = parseCore(b);
@@ -1275,18 +3501,18 @@ var ConfigSync = class {
1275
3501
  };
1276
3502
 
1277
3503
  // src/reporter.ts
1278
- import fs5 from "node:fs/promises";
1279
- import path6 from "node:path";
3504
+ import fs6 from "node:fs/promises";
3505
+ import path7 from "node:path";
1280
3506
 
1281
3507
  // src/identity.ts
1282
3508
  import os3 from "node:os";
1283
- import { execFile as execFile2 } from "node:child_process";
1284
- import { promisify as promisify2 } from "node:util";
1285
- var execFileAsync2 = promisify2(execFile2);
3509
+ import fs5 from "node:fs/promises";
3510
+ import path6 from "node:path";
1286
3511
  async function getGitConfigValue(key) {
1287
3512
  try {
1288
- const { stdout } = await execFileAsync2("git", ["config", "--global", key]);
1289
- return stdout.trim();
3513
+ const gitConfigPath = path6.join(os3.homedir(), ".gitconfig");
3514
+ const content = await fs5.readFile(gitConfigPath, "utf-8");
3515
+ return parseGitConfigValue(content, key);
1290
3516
  } catch {
1291
3517
  console.warn(
1292
3518
  `[skill-logger-plugin] git config --global ${key} \u672A\u8BBE\u7F6E\u3002\u53EF\u6267\u884C\uFF1Agit config --global ${key} '<value>'`
@@ -1294,6 +3520,26 @@ async function getGitConfigValue(key) {
1294
3520
  return "";
1295
3521
  }
1296
3522
  }
3523
+ function parseGitConfigValue(content, key) {
3524
+ const [section, name] = key.split(".");
3525
+ if (!section || !name) return "";
3526
+ let inTargetSection = false;
3527
+ for (const rawLine of content.split(/\r?\n/)) {
3528
+ const line = rawLine.trim();
3529
+ if (!line || line.startsWith("#") || line.startsWith(";")) continue;
3530
+ const sectionMatch = /^\[([^\]]+)\]$/.exec(line);
3531
+ if (sectionMatch) {
3532
+ inTargetSection = sectionMatch[1].trim() === section;
3533
+ continue;
3534
+ }
3535
+ if (!inTargetSection) continue;
3536
+ const kv = /^([A-Za-z0-9_.-]+)\s*=\s*(.*)$/.exec(line);
3537
+ if (kv?.[1] === name) {
3538
+ return kv[2].trim().replace(/^"|"$/g, "");
3539
+ }
3540
+ }
3541
+ return "";
3542
+ }
1297
3543
  var GitIdentityProvider = class {
1298
3544
  cached;
1299
3545
  async getIdentity() {
@@ -1345,9 +3591,9 @@ var Reporter = class {
1345
3591
  const ts = (/* @__PURE__ */ new Date()).toISOString();
1346
3592
  const logLine = `[${ts}] [${level}] [skill-logger-plugin] ${msg}
1347
3593
  `;
1348
- const logDir = path6.dirname(this.paths.eventsLogPath);
1349
- await fs5.mkdir(logDir, { recursive: true });
1350
- await fs5.appendFile(path6.join(logDir, "skill-logger.err.log"), logLine);
3594
+ const logDir = path7.dirname(this.paths.eventsLogPath);
3595
+ await fs6.mkdir(logDir, { recursive: true });
3596
+ await fs6.appendFile(path7.join(logDir, "skill-logger.err.log"), logLine);
1351
3597
  if (level === "INFO" && this.isDebug) {
1352
3598
  console.log("[skill-logger-plugin/reporter]", ...args);
1353
3599
  } else if (level === "WARN" || level === "ERROR") {
@@ -1380,8 +3626,8 @@ var Reporter = class {
1380
3626
  } catch {
1381
3627
  return;
1382
3628
  }
1383
- await fs5.mkdir(path6.dirname(this.paths.eventsLogPath), { recursive: true });
1384
- await fs5.appendFile(this.paths.eventsLogPath, line + "\n");
3629
+ await fs6.mkdir(path7.dirname(this.paths.eventsLogPath), { recursive: true });
3630
+ await fs6.appendFile(this.paths.eventsLogPath, line + "\n");
1385
3631
  } catch (err) {
1386
3632
  void this.writeFallbackLog("ERROR", "\u5199\u4E8B\u4EF6\u65E5\u5FD7\u5931\u8D25", this.paths.eventsLogPath, err);
1387
3633
  }
@@ -1451,19 +3697,19 @@ var Reporter = class {
1451
3697
  void this.writeFallbackLog("WARN", "flush skipped: reportBaseUrl \u6CA1\u6709\u914D\u7F6E\uFF01\u8BF7\u68C0\u67E5 openclaw.json \u63D2\u4EF6\u914D\u7F6E\u662F\u5426\u6B63\u786E\u52A0\u8F7D\u3002");
1452
3698
  return;
1453
3699
  }
1454
- const logDir = path6.dirname(this.paths.eventsLogPath);
3700
+ const logDir = path7.dirname(this.paths.eventsLogPath);
1455
3701
  try {
1456
- await fs5.access(this.paths.eventsLogPath);
3702
+ await fs6.access(this.paths.eventsLogPath);
1457
3703
  const timestamp = Date.now();
1458
- const rotatedPath = path6.join(logDir, `events.${timestamp}.jsonl`);
1459
- await fs5.rename(this.paths.eventsLogPath, rotatedPath);
1460
- this.debug(`Rotated active log to ${path6.basename(rotatedPath)}`);
3704
+ const rotatedPath = path7.join(logDir, `events.${timestamp}.jsonl`);
3705
+ await fs6.rename(this.paths.eventsLogPath, rotatedPath);
3706
+ this.debug(`Rotated active log to ${path7.basename(rotatedPath)}`);
1461
3707
  } catch {
1462
3708
  }
1463
3709
  let files = [];
1464
3710
  try {
1465
- const dirEntries = await fs5.readdir(logDir);
1466
- files = dirEntries.filter((f) => f.startsWith("events.") && f.endsWith(".jsonl") && f !== "events.jsonl").map((f) => path6.join(logDir, f));
3711
+ const dirEntries = await fs6.readdir(logDir);
3712
+ files = dirEntries.filter((f) => f.startsWith("events.") && f.endsWith(".jsonl") && f !== "events.jsonl").map((f) => path7.join(logDir, f));
1467
3713
  } catch {
1468
3714
  return;
1469
3715
  }
@@ -1476,10 +3722,10 @@ var Reporter = class {
1476
3722
  const url = config.reportBaseUrl.replace(/\/$/, "") + "/skill_report/batch";
1477
3723
  for (const filePath of files) {
1478
3724
  try {
1479
- const content = await fs5.readFile(filePath, "utf-8");
3725
+ const content = await fs6.readFile(filePath, "utf-8");
1480
3726
  const lines = this.linesOf(content);
1481
3727
  if (lines.length === 0) {
1482
- await fs5.unlink(filePath);
3728
+ await fs6.unlink(filePath);
1483
3729
  continue;
1484
3730
  }
1485
3731
  let cursor = 0;
@@ -1508,8 +3754,8 @@ var Reporter = class {
1508
3754
  if (config.authToken) headers.Authorization = config.authToken;
1509
3755
  const res = await this.fetchImpl(url, { method: "POST", headers, body });
1510
3756
  if (!res.ok) {
1511
- const errBody = await res.text().catch(() => "\u65E0\u6CD5\u8BFB\u53D6\u54CD\u5E94\u4F53");
1512
- await this.writeFallbackLog("ERROR", `\u6279\u91CF\u4E0A\u62A5\u5931\u8D25 (\u6587\u4EF6 ${path6.basename(filePath)}), HTTP`, res.status, "\u670D\u52A1\u7AEF\u8FD4\u56DE\u4FE1\u606F:", errBody);
3757
+ const errBody = await res.text?.().catch(() => "\u65E0\u6CD5\u8BFB\u53D6\u54CD\u5E94\u4F53") ?? "\u65E0\u6CD5\u8BFB\u53D6\u54CD\u5E94\u4F53";
3758
+ await this.writeFallbackLog("ERROR", `\u6279\u91CF\u4E0A\u62A5\u5931\u8D25 (\u6587\u4EF6 ${path7.basename(filePath)}), HTTP`, res.status, "\u670D\u52A1\u7AEF\u8FD4\u56DE\u4FE1\u606F:", errBody);
1513
3759
  if (res.status === 400 || res.status === 413 || res.status === 422) {
1514
3760
  await this.writeFallbackLog("WARN", `\u62A5\u6587\u88AB\u670D\u52A1\u5668\u6C38\u4E45\u62D2\u7EDD\uFF0C\u4E22\u5F03\u8BE5\u6279\u6B21\u4EE5\u91CA\u653E\u961F\u5217`);
1515
3761
  cursor += slice.length;
@@ -1518,17 +3764,17 @@ var Reporter = class {
1518
3764
  allSuccess = false;
1519
3765
  break;
1520
3766
  }
1521
- this.debug(`Successfully reported batch of ${events.length} events from ${path6.basename(filePath)}`);
3767
+ this.debug(`Successfully reported batch of ${events.length} events from ${path7.basename(filePath)}`);
1522
3768
  cursor += slice.length;
1523
3769
  }
1524
3770
  if (allSuccess) {
1525
- await fs5.unlink(filePath);
1526
- this.debug(`Deleted fully processed file: ${path6.basename(filePath)}`);
3771
+ await fs6.unlink(filePath);
3772
+ this.debug(`Deleted fully processed file: ${path7.basename(filePath)}`);
1527
3773
  } else {
1528
- this.debug(`File ${path6.basename(filePath)} partially failed. Keeping it for next flush.`);
3774
+ this.debug(`File ${path7.basename(filePath)} partially failed. Keeping it for next flush.`);
1529
3775
  }
1530
3776
  } catch (err) {
1531
- await this.writeFallbackLog("ERROR", `\u5904\u7406\u6587\u4EF6 ${path6.basename(filePath)} \u5F02\u5E38:`, err);
3777
+ await this.writeFallbackLog("ERROR", `\u5904\u7406\u6587\u4EF6 ${path7.basename(filePath)} \u5F02\u5E38:`, err);
1532
3778
  }
1533
3779
  }
1534
3780
  } catch (err) {
@@ -1539,29 +3785,303 @@ var Reporter = class {
1539
3785
  }
1540
3786
  };
1541
3787
 
3788
+ // src/expert-skill-layout.ts
3789
+ import fs7 from "node:fs/promises";
3790
+ import path8 from "node:path";
3791
+ import { randomUUID as randomUUID2 } from "node:crypto";
3792
+ var ASSISTANT_WORKSPACE_RE = /^workspace-assistant-\d{5,}$/;
3793
+ var REPAIR_RESIDUE_RE = /^\.(.+)\.repair-(old|new)-(.+)$/;
3794
+ async function lstatOrUndefined(filePath) {
3795
+ try {
3796
+ return await fs7.lstat(filePath);
3797
+ } catch (error) {
3798
+ if (error?.code === "ENOENT") return void 0;
3799
+ throw error;
3800
+ }
3801
+ }
3802
+ async function isRegularFile(filePath) {
3803
+ const stat = await lstatOrUndefined(filePath);
3804
+ return Boolean(stat?.isFile() && !stat.isSymbolicLink());
3805
+ }
3806
+ async function removeRealDirectory(dirPath) {
3807
+ const stat = await lstatOrUndefined(dirPath);
3808
+ if (!stat) return;
3809
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
3810
+ throw new Error(`\u62D2\u7EDD\u6E05\u7406\u975E\u771F\u5B9E\u76EE\u5F55: ${dirPath}`);
3811
+ }
3812
+ await fs7.rm(dirPath, { recursive: true });
3813
+ }
3814
+ async function removeNestedDirectoryIfPresent(dirPath) {
3815
+ const stat = await lstatOrUndefined(dirPath);
3816
+ if (!stat) return;
3817
+ if (stat.isSymbolicLink()) throw new Error(`\u62D2\u7EDD\u6E05\u7406\u7B26\u53F7\u94FE\u63A5: ${dirPath}`);
3818
+ if (stat.isDirectory()) await fs7.rm(dirPath, { recursive: true });
3819
+ }
3820
+ async function recoverRepairResidues(skillsRoot, entries, result) {
3821
+ const groups = /* @__PURE__ */ new Map();
3822
+ for (const entry of entries) {
3823
+ const match2 = REPAIR_RESIDUE_RE.exec(entry.name);
3824
+ if (!match2) continue;
3825
+ const group = groups.get(match2[1]) ?? { old: [], stage: [] };
3826
+ group[match2[2] === "old" ? "old" : "stage"].push(path8.join(skillsRoot, entry.name));
3827
+ groups.set(match2[1], group);
3828
+ }
3829
+ for (const [code, group] of groups) {
3830
+ const targetDir = path8.join(skillsRoot, code);
3831
+ try {
3832
+ const targetStat = await lstatOrUndefined(targetDir);
3833
+ if (targetStat?.isSymbolicLink() || targetStat && !targetStat.isDirectory()) {
3834
+ throw new Error(`\u89C4\u8303\u8DEF\u5F84\u4E0D\u662F\u53EF\u5B89\u5168\u64CD\u4F5C\u7684\u771F\u5B9E\u76EE\u5F55: ${targetDir}`);
3835
+ }
3836
+ group.old.sort().reverse();
3837
+ if (!targetStat && group.old.length > 0) {
3838
+ const restore = group.old.shift();
3839
+ const restoreStat = await lstatOrUndefined(restore);
3840
+ if (!restoreStat?.isDirectory() || restoreStat.isSymbolicLink()) {
3841
+ throw new Error(`\u62D2\u7EDD\u4ECE\u975E\u771F\u5B9E\u76EE\u5F55\u6062\u590D: ${restore}`);
3842
+ }
3843
+ await fs7.rename(restore, targetDir);
3844
+ }
3845
+ if (await lstatOrUndefined(targetDir)) {
3846
+ for (const residue of [...group.old, ...group.stage]) {
3847
+ await removeRealDirectory(residue);
3848
+ }
3849
+ }
3850
+ } catch (error) {
3851
+ result.errors.push({ path: targetDir, message: error?.message || String(error) });
3852
+ }
3853
+ }
3854
+ }
3855
+ async function promoteNestedSkill(sourceDir, targetDir) {
3856
+ const parent = path8.dirname(targetDir);
3857
+ const tag = `${Date.now()}-${randomUUID2().slice(0, 8)}`;
3858
+ const stage = path8.join(parent, `.${path8.basename(targetDir)}.repair-new-${tag}`);
3859
+ const old = path8.join(parent, `.${path8.basename(targetDir)}.repair-old-${tag}`);
3860
+ let movedOld = false;
3861
+ try {
3862
+ await fs7.cp(sourceDir, stage, { recursive: true });
3863
+ await removeNestedDirectoryIfPresent(path8.join(stage, path8.basename(targetDir)));
3864
+ await fs7.rename(targetDir, old);
3865
+ movedOld = true;
3866
+ await fs7.rename(stage, targetDir);
3867
+ } catch (error) {
3868
+ const rollbackErrors = [];
3869
+ try {
3870
+ await removeRealDirectory(stage);
3871
+ } catch (cleanupError) {
3872
+ rollbackErrors.push(`\u6E05\u7406\u6682\u5B58\u76EE\u5F55\u5931\u8D25: ${cleanupError?.message || String(cleanupError)}`);
3873
+ }
3874
+ if (movedOld) {
3875
+ try {
3876
+ await fs7.rename(old, targetDir);
3877
+ } catch (restoreError) {
3878
+ rollbackErrors.push(`\u6062\u590D\u65E7\u76EE\u5F55\u5931\u8D25: ${restoreError?.message || String(restoreError)}`);
3879
+ }
3880
+ }
3881
+ if (rollbackErrors.length > 0) {
3882
+ throw new Error(`${error?.message || String(error)}; ${rollbackErrors.join("; ")}`);
3883
+ }
3884
+ throw error;
3885
+ }
3886
+ await removeRealDirectory(old);
3887
+ }
3888
+ async function repairNestedExpertSkillLayouts(openclawRoot) {
3889
+ const result = {
3890
+ scannedWorkspaces: 0,
3891
+ repaired: [],
3892
+ skipped: [],
3893
+ errors: []
3894
+ };
3895
+ let workspaceEntries;
3896
+ try {
3897
+ workspaceEntries = await fs7.readdir(openclawRoot, { withFileTypes: true });
3898
+ } catch (error) {
3899
+ result.errors.push({ path: openclawRoot, message: error?.message || String(error) });
3900
+ return result;
3901
+ }
3902
+ for (const workspaceEntry of workspaceEntries) {
3903
+ if (!workspaceEntry.isDirectory() || !ASSISTANT_WORKSPACE_RE.test(workspaceEntry.name)) continue;
3904
+ result.scannedWorkspaces += 1;
3905
+ const skillsRoot = path8.join(openclawRoot, workspaceEntry.name, ".user", "skills");
3906
+ let skillEntries;
3907
+ try {
3908
+ skillEntries = await fs7.readdir(skillsRoot, { withFileTypes: true });
3909
+ await recoverRepairResidues(skillsRoot, skillEntries, result);
3910
+ skillEntries = await fs7.readdir(skillsRoot, { withFileTypes: true });
3911
+ } catch (error) {
3912
+ if (error?.code !== "ENOENT") {
3913
+ result.errors.push({ path: skillsRoot, message: error?.message || String(error) });
3914
+ }
3915
+ continue;
3916
+ }
3917
+ for (const skillEntry of skillEntries) {
3918
+ if (!skillEntry.isDirectory() || skillEntry.name.startsWith(".")) continue;
3919
+ const outerDir = path8.join(skillsRoot, skillEntry.name);
3920
+ try {
3921
+ const candidates = [];
3922
+ const outerHasSkill = await isRegularFile(path8.join(outerDir, "SKILL.md"));
3923
+ if (outerHasSkill) {
3924
+ const version = await readSkillVersion(outerDir);
3925
+ if (!version) {
3926
+ result.skipped.push(outerDir);
3927
+ continue;
3928
+ }
3929
+ candidates.push({ dir: outerDir, version });
3930
+ }
3931
+ let cursor = outerDir;
3932
+ let nestedCount = 0;
3933
+ while (true) {
3934
+ const nestedDir = path8.join(cursor, skillEntry.name);
3935
+ const nestedStat = await lstatOrUndefined(nestedDir);
3936
+ if (!nestedStat) break;
3937
+ if (nestedStat.isSymbolicLink()) {
3938
+ throw new Error(`\u62D2\u7EDD\u8DDF\u968F\u540C\u540D\u7B26\u53F7\u94FE\u63A5: ${nestedDir}`);
3939
+ }
3940
+ if (!nestedStat.isDirectory()) break;
3941
+ cursor = nestedDir;
3942
+ const skillMd = path8.join(nestedDir, "SKILL.md");
3943
+ const skillStat = await lstatOrUndefined(skillMd);
3944
+ if (skillStat?.isSymbolicLink()) {
3945
+ throw new Error(`\u62D2\u7EDD\u8BFB\u53D6\u7B26\u53F7\u94FE\u63A5 SKILL.md: ${skillMd}`);
3946
+ }
3947
+ if (!skillStat?.isFile()) continue;
3948
+ nestedCount += 1;
3949
+ const version = await readSkillVersion(nestedDir);
3950
+ if (!version) {
3951
+ result.skipped.push(outerDir);
3952
+ candidates.length = 0;
3953
+ break;
3954
+ }
3955
+ candidates.push({ dir: nestedDir, version });
3956
+ }
3957
+ if (nestedCount === 0 || candidates.length === 0) continue;
3958
+ if (candidates.some((candidate) => !isComparableVersion(candidate.version))) {
3959
+ result.skipped.push(outerDir);
3960
+ continue;
3961
+ }
3962
+ let source = candidates[0];
3963
+ for (const candidate of candidates.slice(1)) {
3964
+ if (compareVersions(candidate.version, source.version) >= 0) source = candidate;
3965
+ }
3966
+ if (source.dir === outerDir) {
3967
+ result.skipped.push(outerDir);
3968
+ continue;
3969
+ }
3970
+ await promoteNestedSkill(source.dir, outerDir);
3971
+ result.repaired.push(outerDir);
3972
+ } catch (error) {
3973
+ result.errors.push({ path: outerDir, message: error?.message || String(error) });
3974
+ }
3975
+ }
3976
+ }
3977
+ return result;
3978
+ }
3979
+
1542
3980
  // src/ws-client.ts
1543
3981
  import WebSocket from "ws";
1544
- import path7 from "path";
1545
- import fs6 from "fs/promises";
3982
+ import path9 from "path";
3983
+ import fs8 from "fs/promises";
3984
+ import { DatabaseSync } from "node:sqlite";
1546
3985
  var HEARTBEAT_INTERVAL_MS = 3e4;
1547
3986
  var HEARTBEAT_ACK_TIMEOUT_MS = 75e3;
1548
3987
  var AGENT_SCAN_INTERVAL_MS = 3 * 60 * 1e3;
1549
- var ASSISTANT_WORKSPACE_PREFIX = "workspace-assistant-";
1550
3988
  var ASSISTANT_AGENT_PREFIX = "assistant-";
1551
3989
  var ASSISTANT_WORKSPACE_ID_RE = /^\d{5,}$/;
1552
- function parseAssistantWorkspaceAgentId(entryName) {
1553
- if (!entryName.startsWith(ASSISTANT_WORKSPACE_PREFIX)) return void 0;
1554
- const suffix = entryName.slice(ASSISTANT_WORKSPACE_PREFIX.length);
1555
- if (!ASSISTANT_WORKSPACE_ID_RE.test(suffix)) return void 0;
1556
- return `${ASSISTANT_AGENT_PREFIX}${suffix}`;
3990
+ function enabledAgentIdsFromAccounts(config) {
3991
+ if (!config || typeof config !== "object") return [];
3992
+ const channels = config.channels;
3993
+ if (!channels || typeof channels !== "object") return [];
3994
+ const cworkConfig = channels.xg_cwork_im;
3995
+ if (!cworkConfig || typeof cworkConfig !== "object") return [];
3996
+ const accounts = cworkConfig.accounts;
3997
+ if (!accounts || typeof accounts !== "object" || Array.isArray(accounts)) return [];
3998
+ const agentIds = /* @__PURE__ */ new Set();
3999
+ for (const account of Object.values(accounts)) {
4000
+ if (!account || typeof account !== "object" || account.enabled === false) continue;
4001
+ if (typeof account.agentId !== "string") continue;
4002
+ const agentId = account.agentId.trim();
4003
+ if (agentId) agentIds.add(agentId);
4004
+ }
4005
+ return [...agentIds];
4006
+ }
4007
+ function resolveSkillInstallTarget(config, userId) {
4008
+ if (!config || typeof config !== "object") throw new Error("openclaw.json \u914D\u7F6E\u65E0\u6548");
4009
+ const root = config;
4010
+ const accounts = root.channels?.xg_cwork_im?.accounts;
4011
+ if (!accounts || typeof accounts !== "object" || Array.isArray(accounts)) {
4012
+ throw new Error(`\u672A\u627E\u5230 userId=${userId} \u7684 xg_cwork_im account`);
4013
+ }
4014
+ const matched = Object.entries(accounts).filter(([, account2]) => account2 && typeof account2 === "object" && account2.agentId === userId);
4015
+ if (matched.length !== 1) {
4016
+ throw new Error(matched.length > 1 ? `userId=${userId} \u5B58\u5728\u591A\u4E2A xg_cwork_im account\uFF0C\u65E0\u6CD5\u786E\u5B9A\u5B89\u88C5\u76EE\u5F55` : `\u672A\u627E\u5230 userId=${userId} \u7684 xg_cwork_im account`);
4017
+ }
4018
+ const [accountId, account] = matched[0];
4019
+ if (account.enabled === false) throw new Error(`userId=${userId} \u5BF9\u5E94 Agent \u5DF2\u7981\u7528`);
4020
+ const bindingAccountIds = /* @__PURE__ */ new Set([accountId, userId]);
4021
+ const bindings = Array.isArray(root.bindings) ? root.bindings : [];
4022
+ const binding = bindings.find((item) => {
4023
+ if (!item || typeof item !== "object") return false;
4024
+ const candidate = item;
4025
+ return candidate.match?.channel === "xg_cwork_im" && typeof candidate.match.accountId === "string" && bindingAccountIds.has(candidate.match.accountId) && typeof candidate.agentId === "string" && candidate.agentId.length > 0;
4026
+ });
4027
+ const localAgentId = typeof binding?.agentId === "string" ? binding.agentId : userId;
4028
+ const list = Array.isArray(root.agents?.list) ? root.agents.list : [];
4029
+ const agent = list.find(
4030
+ (item) => Boolean(item) && typeof item === "object" && item.id === localAgentId
4031
+ );
4032
+ if (!agent) throw new Error(`\u672A\u627E\u5230\u672C\u5730 Agent \u914D\u7F6E: ${localAgentId}`);
4033
+ const workspace = typeof agent.workspace === "string" ? agent.workspace : root.agents?.defaults?.workspace;
4034
+ if (typeof workspace !== "string" || !workspace.trim()) {
4035
+ throw new Error(`\u672C\u5730 Agent ${localAgentId} \u672A\u914D\u7F6E workspace`);
4036
+ }
4037
+ return { skillsDir: path9.join(workspace, "skills"), localAgentId };
1557
4038
  }
1558
4039
  function normalizeAssistantUserId(userId) {
1559
- const safeUserId = path7.basename(userId);
4040
+ const safeUserId = path9.basename(userId);
1560
4041
  if (safeUserId !== userId) return void 0;
1561
4042
  const pureId = safeUserId.startsWith(ASSISTANT_AGENT_PREFIX) ? safeUserId.slice(ASSISTANT_AGENT_PREFIX.length) : safeUserId;
1562
4043
  if (!ASSISTANT_WORKSPACE_ID_RE.test(pureId)) return void 0;
1563
4044
  return pureId;
1564
4045
  }
4046
+ function normalizeCommandCode(code) {
4047
+ if (typeof code !== "string" || code.length === 0 || code === "." || code === "..") return void 0;
4048
+ if (code.includes("/") || code.includes("\\") || code.includes("\0")) return void 0;
4049
+ if (path9.basename(code) !== code) return void 0;
4050
+ return code;
4051
+ }
4052
+ function shouldSyncBuiltInTemplate(action, isBuiltIn) {
4053
+ return action === "UPDATE_SKILL" && isBuiltIn === true;
4054
+ }
4055
+ function resolveGatewaySkillTarget(home = openclawHome()) {
4056
+ return path9.join(home, "skills");
4057
+ }
4058
+ function isGatewaySkillCommand(action, installScope) {
4059
+ return installScope === "gateway" && ["INSTALL_SKILL", "UPDATE_SKILL", "UNINSTALL_SKILL"].includes(String(action || ""));
4060
+ }
4061
+ async function findInstalledExpertSkillsRoot(rootPath, pureId, code) {
4062
+ const skillsRoot = path9.join(rootPath, `workspace-assistant-${pureId}`, ".user", "skills");
4063
+ try {
4064
+ const stat = await fs8.stat(path9.join(skillsRoot, code));
4065
+ return stat.isDirectory() ? skillsRoot : void 0;
4066
+ } catch {
4067
+ return void 0;
4068
+ }
4069
+ }
4070
+ function defaultOpenclawSqlitePath() {
4071
+ return path9.join(openclawHome(), "state", "openclaw.sqlite");
4072
+ }
4073
+ function readCronJobsByAgentId(agentId, sqlitePath = defaultOpenclawSqlitePath(), onError) {
4074
+ let db;
4075
+ try {
4076
+ db = new DatabaseSync(sqlitePath, { readOnly: true });
4077
+ return db.prepare("SELECT * FROM cron_jobs WHERE agent_id = ?").all(agentId);
4078
+ } catch (err) {
4079
+ onError?.(err);
4080
+ return [];
4081
+ } finally {
4082
+ db?.close();
4083
+ }
4084
+ }
1565
4085
  var GatewayWsClient = class {
1566
4086
  ws = null;
1567
4087
  options;
@@ -1588,16 +4108,35 @@ var GatewayWsClient = class {
1588
4108
  }
1589
4109
  }
1590
4110
  logLine += "\n";
1591
- const logsDir = path7.join(openclawHome(), "logs");
1592
- fs6.mkdir(logsDir, { recursive: true }).then(() => {
1593
- const logPath = path7.join(logsDir, "skill-logger.err");
1594
- fs6.appendFile(logPath, logLine).catch(() => {
4111
+ const logsDir = path9.join(openclawHome(), "logs");
4112
+ fs8.mkdir(logsDir, { recursive: true }).then(() => {
4113
+ const logPath = path9.join(logsDir, "skill-logger.err");
4114
+ fs8.appendFile(logPath, logLine).catch(() => {
1595
4115
  });
1596
4116
  }).catch(() => {
1597
4117
  });
1598
4118
  } catch (e) {
1599
4119
  }
1600
4120
  }
4121
+ createInstallTrace(context) {
4122
+ return (stage, data) => {
4123
+ this.appendLogToFile(stage === "install.failed" ? "ERROR" : "INFO", "Install", stage, {
4124
+ ...context,
4125
+ ...data
4126
+ });
4127
+ };
4128
+ }
4129
+ /** 普通 Skill 的所有读写操作共用这一个配置驱动的寻址入口。 */
4130
+ async resolveRegularSkillTarget(userId) {
4131
+ const configPath = path9.join(openclawHome(), "openclaw.json");
4132
+ let config;
4133
+ try {
4134
+ config = JSON.parse(await fs8.readFile(configPath, "utf-8"));
4135
+ } catch (err) {
4136
+ throw new Error(`\u65E0\u6CD5\u8BFB\u53D6 openclaw.json: ${err?.message || String(err)}`);
4137
+ }
4138
+ return resolveSkillInstallTarget(config, userId).skillsDir;
4139
+ }
1601
4140
  constructor(options) {
1602
4141
  this.options = options;
1603
4142
  }
@@ -1693,26 +4232,26 @@ var GatewayWsClient = class {
1693
4232
  }
1694
4233
  });
1695
4234
  }
1696
- /**
1697
- * 扫描 OpenClaw 根目录下的 workspace-assistant-{userId} 目录。
1698
- * userId 必须是至少 5 位数字。
1699
- */
4235
+ /** 从 openclaw.json 的 xg_cwork_im accounts 读取当前启用的 agent。 */
1700
4236
  async scanAndReportAgents(isInitialReport) {
1701
4237
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
1702
4238
  try {
1703
- const rootPath = openclawHome();
1704
- let entries = [];
4239
+ const configPath = path9.join(openclawHome(), "openclaw.json");
4240
+ let rawConfig;
1705
4241
  try {
1706
- entries = await fs6.readdir(rootPath);
4242
+ rawConfig = await fs8.readFile(configPath, "utf-8");
1707
4243
  } catch (e) {
1708
- this.appendLogToFile("WARN", "AgentScan", "OpenClaw home is not readable; skipping this scan cycle", e);
4244
+ this.appendLogToFile("WARN", "AgentScan", "OpenClaw config is not readable; skipping this scan cycle", e);
1709
4245
  return;
1710
4246
  }
1711
- const newAgentIds = /* @__PURE__ */ new Set();
1712
- for (const entry of entries) {
1713
- const agentId = parseAssistantWorkspaceAgentId(entry);
1714
- if (agentId) newAgentIds.add(agentId);
4247
+ let config;
4248
+ try {
4249
+ config = JSON.parse(rawConfig);
4250
+ } catch (e) {
4251
+ this.appendLogToFile("WARN", "AgentScan", "OpenClaw config is invalid JSON; skipping this scan cycle", e);
4252
+ return;
1715
4253
  }
4254
+ const newAgentIds = new Set(enabledAgentIdsFromAccounts(config));
1716
4255
  let changed = false;
1717
4256
  if (newAgentIds.size !== this.currentAgentIds.size) {
1718
4257
  changed = true;
@@ -1820,7 +4359,8 @@ var GatewayWsClient = class {
1820
4359
  gatewayId: this.options.gatewayId,
1821
4360
  agentIds: Array.from(this.currentAgentIds),
1822
4361
  clientTime: Date.now(),
1823
- supportsBatch: true
4362
+ supportsBatch: true,
4363
+ supportsGatewaySkillScope: true
1824
4364
  }, "Heartbeat");
1825
4365
  }
1826
4366
  sendClientHeartbeat() {
@@ -1849,22 +4389,57 @@ var GatewayWsClient = class {
1849
4389
  * 核心指令分发中心:完全跳过沙盒,基于 userId 直接进行底层物理文件操作
1850
4390
  */
1851
4391
  async handleMessage(msg) {
1852
- const { action, userId, code, url, force, version, replyId } = msg;
1853
- this.appendLogToFile("INFO", "Command", `Received WS message`, { action, userId, code, version, replyId });
1854
- if (!action || !userId) {
1855
- this.appendLogToFile("WARN", "Command", `Message dropped: missing action or userId`, msg);
4392
+ const { action, userId, code, url, force, version, replyId, isBuiltIn, installScope } = msg;
4393
+ this.appendLogToFile("INFO", "Command", `Received WS message`, {
4394
+ action,
4395
+ userId,
4396
+ code,
4397
+ version,
4398
+ replyId,
4399
+ isBuiltIn,
4400
+ installScope,
4401
+ hasDirectUrl: Boolean(url)
4402
+ });
4403
+ if (!action) {
4404
+ this.appendLogToFile("WARN", "Command", `Message dropped: missing action`, msg);
4405
+ return;
4406
+ }
4407
+ if (action === "GET_CRON_JOBS_BY_AGENT_ID") {
4408
+ const agentId = typeof msg.agent_id === "string" ? msg.agent_id : typeof msg.agentId === "string" ? msg.agentId : userId;
4409
+ if (!agentId) {
4410
+ this.reply(replyId, { success: false, message: "Missing agent_id parameter", action });
4411
+ return;
4412
+ }
4413
+ try {
4414
+ const data = readCronJobsByAgentId(agentId, defaultOpenclawSqlitePath(), (err) => {
4415
+ this.appendLogToFile("WARN", "Command", `GET_CRON_JOBS_BY_AGENT_ID sqlite lookup skipped`, err);
4416
+ });
4417
+ this.reply(replyId, { success: true, data, action });
4418
+ } catch (err) {
4419
+ this.appendLogToFile("ERROR", "Command", `GET_CRON_JOBS_BY_AGENT_ID threw`, err);
4420
+ this.reply(replyId, { success: false, message: err.message, action });
4421
+ }
1856
4422
  return;
1857
4423
  }
1858
- const safeCode = code ? path7.basename(code) : void 0;
1859
- const pureId = normalizeAssistantUserId(userId);
1860
- if (!pureId) {
4424
+ if (!userId) {
4425
+ this.appendLogToFile("WARN", "Command", `Message dropped: missing userId`, msg);
4426
+ return;
4427
+ }
4428
+ const safeCode = normalizeCommandCode(code);
4429
+ if (code !== void 0 && !safeCode) {
4430
+ this.reply(replyId, { success: false, message: `Invalid code: ${String(code)}`, action });
4431
+ return;
4432
+ }
4433
+ const gatewaySkillCommand = isGatewaySkillCommand(action, installScope);
4434
+ const pureId = gatewaySkillCommand ? void 0 : normalizeAssistantUserId(userId);
4435
+ if (!gatewaySkillCommand && !pureId) {
1861
4436
  this.reply(replyId, { success: false, message: `Invalid userId: ${userId}`, action });
1862
4437
  return;
1863
4438
  }
1864
- const targetDir = path7.join(openclawHome(), `workspace-assistant-${pureId}`, "skills");
1865
4439
  try {
1866
4440
  if (action === "INSTALL_SKILL") {
1867
4441
  if (!safeCode) throw new Error("Missing code parameter");
4442
+ const targetDir = gatewaySkillCommand ? resolveGatewaySkillTarget() : await this.resolveRegularSkillTarget(userId);
1868
4443
  console.log(`[skill-logger-plugin][WS] Executing INSTALL for user ${userId}, code: ${safeCode}`);
1869
4444
  this.appendLogToFile("INFO", "Command", `INSTALL_SKILL received`, { userId, code: safeCode, version });
1870
4445
  const result = await this.options.updater.manualInstall({
@@ -1872,109 +4447,163 @@ var GatewayWsClient = class {
1872
4447
  url,
1873
4448
  version,
1874
4449
  force: force !== false,
1875
- targetDir
4450
+ targetDir,
4451
+ trace: this.createInstallTrace({ action, replyId, userId, code: safeCode })
4452
+ });
4453
+ this.reply(replyId, {
4454
+ success: result.success,
4455
+ message: result.message,
4456
+ action,
4457
+ data: { code: safeCode, version, installScope: gatewaySkillCommand ? "gateway" : "agent" }
1876
4458
  });
1877
- this.reply(replyId, { success: result.success, message: result.message, action });
1878
4459
  } else if (action === "UNINSTALL_SKILL") {
1879
4460
  if (!safeCode) throw new Error("Missing code parameter");
4461
+ const targetDir = gatewaySkillCommand ? resolveGatewaySkillTarget() : await this.resolveRegularSkillTarget(userId);
1880
4462
  console.log(`[skill-logger-plugin][WS] Executing UNINSTALL for user ${userId}, code: ${safeCode}`);
1881
4463
  this.appendLogToFile("INFO", "Command", `UNINSTALL_SKILL received`, { userId, code: safeCode });
1882
- const skillPath = path7.join(targetDir, safeCode);
1883
- await fs6.rm(skillPath, { recursive: true, force: true });
1884
- this.reply(replyId, { success: true, message: `Skill ${safeCode} removed`, action });
4464
+ const skillPath = path9.join(targetDir, safeCode);
4465
+ await fs8.rm(skillPath, { recursive: true, force: true });
4466
+ this.reply(replyId, {
4467
+ success: true,
4468
+ message: `Skill ${safeCode} removed`,
4469
+ action,
4470
+ data: { code: safeCode, installScope: gatewaySkillCommand ? "gateway" : "agent", removed: true }
4471
+ });
1885
4472
  } else if (action === "LIST_SKILLS") {
1886
- let list = [];
1887
- let targetDirExists = false;
1888
- try {
1889
- const targetStat = await fs6.stat(targetDir);
1890
- targetDirExists = targetStat.isDirectory();
1891
- } catch (err) {
1892
- if (err?.code !== "ENOENT") throw err;
1893
- }
1894
- if (!targetDirExists) {
1895
- throw new Error(`Target skills directory does not exist: ${targetDir}`);
1896
- }
1897
- const entries = await fs6.readdir(targetDir, { withFileTypes: true });
1898
- const dirs = entries.filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith("."));
1899
- for (const e of dirs) {
1900
- const skillDir = path7.join(targetDir, e.name);
1901
- const skillMdPath = path7.join(skillDir, "SKILL.md");
4473
+ const regularTargetDir = await this.resolveRegularSkillTarget(userId);
4474
+ const skillsByCode = /* @__PURE__ */ new Map();
4475
+ const sources = [
4476
+ { dir: regularTargetDir, gatewayBuiltIn: false },
4477
+ { dir: resolveGatewaySkillTarget(), gatewayBuiltIn: true }
4478
+ ];
4479
+ for (const source of sources) {
4480
+ let entries;
1902
4481
  try {
1903
- const stat = await fs6.stat(skillMdPath);
1904
- if (!stat.isFile()) continue;
4482
+ entries = await fs8.readdir(source.dir, { withFileTypes: true });
1905
4483
  } catch (err) {
1906
- continue;
4484
+ if (err?.code === "ENOENT") continue;
4485
+ throw err;
1907
4486
  }
1908
- const metaPath = path7.join(skillDir, ".meta.json");
1909
- let isPlatform = false;
1910
- let isBuiltIn = e.isSymbolicLink();
1911
- let metaData = null;
1912
- let name = e.name;
1913
- let description = "";
1914
- let skillVersion = "";
1915
- try {
1916
- const mdContent = await fs6.readFile(skillMdPath, "utf8");
1917
- const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(mdContent)?.[1] ?? "";
1918
- const parsedName = /(^|\n)name:\s*(.+)/.exec(fm)?.[2]?.trim();
1919
- if (parsedName) name = parsedName;
1920
- const descMatch = /(^|\n)description:\s*(?:>\s*\n\s*)?(.*?)(?=\n[a-z]+:|\n---|$)/is.exec(fm);
1921
- if (descMatch && descMatch[2]) {
1922
- description = descMatch[2].replace(/\n\s+/g, " ").trim();
4487
+ const dirs = entries.filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith("."));
4488
+ for (const e of dirs) {
4489
+ const skillDir = path9.join(source.dir, e.name);
4490
+ const skillMdPath = path9.join(skillDir, "SKILL.md");
4491
+ try {
4492
+ const stat = await fs8.stat(skillMdPath);
4493
+ if (!stat.isFile()) continue;
4494
+ } catch {
4495
+ continue;
1923
4496
  }
1924
- } catch (err) {
1925
- }
1926
- try {
1927
- const metaContent = await fs6.readFile(metaPath, "utf8");
1928
- const parsed = JSON.parse(metaContent);
1929
- if (parsed) {
1930
- if (parsed.ownerId === "CMS" || parsed.ownerId === "CMS_COMPAT") isPlatform = true;
1931
- if (parsed.isBuiltIn === true || parsed.ownerId === "built-in") isBuiltIn = true;
1932
- metaData = parsed;
4497
+ const metaPath = path9.join(skillDir, ".meta.json");
4498
+ let isPlatform = source.gatewayBuiltIn;
4499
+ let isBuiltIn2 = source.gatewayBuiltIn || e.isSymbolicLink();
4500
+ let metaData = null;
4501
+ let name = e.name;
4502
+ let description = "";
4503
+ let skillVersion = "";
4504
+ try {
4505
+ const mdContent = await fs8.readFile(skillMdPath, "utf8");
4506
+ const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(mdContent)?.[1] ?? "";
4507
+ const parsedName = /(^|\n)name:\s*(.+)/.exec(fm)?.[2]?.trim();
4508
+ if (parsedName) name = parsedName;
4509
+ const descMatch = /(^|\n)description:\s*(?:>\s*\n\s*)?(.*?)(?=\n[a-z]+:|\n---|$)/is.exec(fm);
4510
+ if (descMatch?.[2]) description = descMatch[2].replace(/\n\s+/g, " ").trim();
4511
+ } catch {
4512
+ }
4513
+ try {
4514
+ const parsed = JSON.parse(await fs8.readFile(metaPath, "utf8"));
4515
+ if (parsed) {
4516
+ if (parsed.ownerId === "CMS" || parsed.ownerId === "CMS_COMPAT") isPlatform = true;
4517
+ if (parsed.isBuiltIn === true || parsed.ownerId === "built-in") isBuiltIn2 = true;
4518
+ metaData = parsed;
4519
+ }
4520
+ } catch {
4521
+ }
4522
+ const resolvedVersion = await readSkillVersion(skillDir);
4523
+ if (resolvedVersion) skillVersion = resolvedVersion;
4524
+ if (isPlatform) {
4525
+ skillsByCode.set(e.name, {
4526
+ code: e.name,
4527
+ isPlatform: true,
4528
+ isBuiltIn: isBuiltIn2,
4529
+ version: skillVersion,
4530
+ name,
4531
+ description,
4532
+ publishedAt: metaData?.publishedAt
4533
+ });
4534
+ } else {
4535
+ skillsByCode.set(e.name, {
4536
+ code: e.name,
4537
+ isPlatform: false,
4538
+ isBuiltIn: isBuiltIn2,
4539
+ version: skillVersion,
4540
+ name,
4541
+ description
4542
+ });
1933
4543
  }
1934
- } catch (err) {
1935
- }
1936
- const resolvedVersion = await readSkillVersion(skillDir);
1937
- if (resolvedVersion) skillVersion = resolvedVersion;
1938
- if (isPlatform) {
1939
- list.push({
1940
- code: e.name,
1941
- isPlatform: true,
1942
- isBuiltIn,
1943
- version: skillVersion,
1944
- name,
1945
- description,
1946
- publishedAt: metaData?.publishedAt
1947
- });
1948
- } else {
1949
- list.push({
1950
- code: e.name,
1951
- isPlatform: false,
1952
- isBuiltIn,
1953
- version: skillVersion,
1954
- name,
1955
- description
1956
- });
1957
4544
  }
1958
4545
  }
1959
- this.reply(replyId, { success: true, data: list, action });
4546
+ this.reply(replyId, { success: true, data: [...skillsByCode.values()], action });
1960
4547
  } else if (action === "UPDATE_SKILL") {
1961
4548
  if (!safeCode) throw new Error("Missing code parameter");
1962
4549
  const delayMs = Math.random() * 5e3;
4550
+ const syncBuiltInTemplate = !gatewaySkillCommand && shouldSyncBuiltInTemplate(action, isBuiltIn);
1963
4551
  console.log(`[skill-logger-plugin][WS] Scheduled UPDATE for user ${userId}, code: ${safeCode} in ${Math.round(delayMs)}ms`);
1964
- this.appendLogToFile("INFO", "Command", `Scheduled UPDATE_SKILL`, { userId, code: safeCode, version, delayMs: Math.round(delayMs) });
4552
+ this.appendLogToFile("INFO", "Command", `Scheduled UPDATE_SKILL`, {
4553
+ userId,
4554
+ code: safeCode,
4555
+ version,
4556
+ isBuiltIn,
4557
+ installScope,
4558
+ syncBuiltInTemplate,
4559
+ delayMs: Math.round(delayMs)
4560
+ });
1965
4561
  setTimeout(async () => {
1966
4562
  try {
1967
- await this.options.updater.manualInstall({
4563
+ const targetDir = gatewaySkillCommand ? resolveGatewaySkillTarget() : await this.resolveRegularSkillTarget(userId);
4564
+ const additionalTargetDirs = syncBuiltInTemplate ? [path9.join(openclawHome(), "workspace-xgjk-assistant-template", "skills")] : [];
4565
+ const userSkillRoot = pureId ? await findInstalledExpertSkillsRoot(openclawHome(), pureId, safeCode) : void 0;
4566
+ if (userSkillRoot) additionalTargetDirs.push(userSkillRoot);
4567
+ const result = await this.options.updater.manualInstall({
1968
4568
  code: safeCode,
1969
4569
  url,
1970
4570
  version,
1971
4571
  force: true,
1972
- targetDir
4572
+ targetDir,
4573
+ additionalTargetDirs,
4574
+ trace: this.createInstallTrace({
4575
+ action,
4576
+ replyId,
4577
+ userId,
4578
+ code: safeCode,
4579
+ isBuiltIn,
4580
+ syncBuiltInTemplate
4581
+ })
4582
+ });
4583
+ this.appendLogToFile(result.success ? "INFO" : "ERROR", "Command", `UPDATE_SKILL completed`, {
4584
+ userId,
4585
+ code: safeCode,
4586
+ replyId,
4587
+ success: result.success,
4588
+ message: result.message,
4589
+ syncBuiltInTemplate
1973
4590
  });
1974
4591
  if (replyId) {
1975
- this.reply(replyId, { success: true, message: `Skill ${safeCode} updated successfully`, action });
4592
+ this.reply(replyId, {
4593
+ success: result.success,
4594
+ message: result.message,
4595
+ action,
4596
+ data: { code: safeCode, version, installScope: gatewaySkillCommand ? "gateway" : "agent" }
4597
+ });
1976
4598
  }
1977
4599
  } catch (e) {
4600
+ this.appendLogToFile("ERROR", "Command", `UPDATE_SKILL threw`, {
4601
+ userId,
4602
+ code: safeCode,
4603
+ replyId,
4604
+ message: e?.message || String(e),
4605
+ stack: e?.stack
4606
+ });
1978
4607
  if (replyId) this.reply(replyId, { success: false, message: e.message, action });
1979
4608
  }
1980
4609
  }, delayMs);
@@ -1983,28 +4612,52 @@ var GatewayWsClient = class {
1983
4612
  const { name, version: version2, downloadUrl, skills } = msg;
1984
4613
  console.log(`[skill-logger-plugin][WS] Executing INSTALL_EXPERT for user ${userId}, code: ${safeCode}`);
1985
4614
  this.appendLogToFile("INFO", "Command", `INSTALL_EXPERT received`, { userId, code: safeCode, version: version2, downloadUrl });
1986
- const userSkillRoot = path7.join(openclawHome(), `workspace-assistant-${pureId}`, ".user");
1987
- const expertTarget = path7.join(userSkillRoot, "experts", safeCode);
1988
- await fs6.mkdir(path7.dirname(expertTarget), { recursive: true });
1989
- const expertResult = await this.options.updater.installZipFromUrl(downloadUrl, expertTarget);
1990
- if (!expertResult.success) {
1991
- throw new Error(`\u4E13\u5BB6\u5B89\u88C5\u5931\u8D25: ${expertResult.message}`);
1992
- }
1993
- const skillTargetRoot = path7.join(userSkillRoot, "skills");
1994
- await fs6.mkdir(skillTargetRoot, { recursive: true });
4615
+ const userSkillRoot = path9.join(openclawHome(), `workspace-assistant-${pureId}`, ".user");
4616
+ const expertTarget = path9.join(userSkillRoot, "experts", safeCode);
4617
+ let skipInstall = false;
4618
+ const metaPath = path9.join(expertTarget, ".meta.json");
4619
+ try {
4620
+ const raw = await fs8.readFile(metaPath, "utf-8");
4621
+ const existing = JSON.parse(raw);
4622
+ if (existing.version && existing.version === (version2 || "1.0.0")) {
4623
+ skipInstall = true;
4624
+ }
4625
+ } catch {
4626
+ }
4627
+ if (!skipInstall) {
4628
+ await fs8.mkdir(path9.dirname(expertTarget), { recursive: true });
4629
+ const expertResult = await this.options.updater.installExpertZipFromUrl(downloadUrl, expertTarget);
4630
+ if (!expertResult.success) {
4631
+ throw new Error(`\u4E13\u5BB6\u5B89\u88C5\u5931\u8D25: ${expertResult.message}`);
4632
+ }
4633
+ }
4634
+ const meta = { code: safeCode, name, version: version2 || "1.0.0", installedAt: Date.now() };
4635
+ await fs8.writeFile(metaPath, JSON.stringify(meta, null, 2));
4636
+ const skillTargetRoot = path9.join(userSkillRoot, "skills");
4637
+ await fs8.mkdir(skillTargetRoot, { recursive: true });
1995
4638
  const skillResults = [];
1996
4639
  if (Array.isArray(skills)) {
1997
4640
  for (const sk of skills) {
1998
- if (!sk.code || !sk.downloadUrl) {
1999
- skillResults.push(`${sk.code || "unknown"}: \u7F3A\u5C11\u4E0B\u8F7D\u5730\u5740`);
4641
+ const skillCode = normalizeCommandCode(sk?.code);
4642
+ if (!skillCode) {
4643
+ skillResults.push(`${String(sk?.code || "unknown")}: \u5931\u8D25 - \u975E\u6CD5\u7684 Skill code`);
4644
+ continue;
4645
+ }
4646
+ if (!sk.downloadUrl) {
4647
+ skillResults.push(`${skillCode}: \u5931\u8D25 - \u7F3A\u5C11\u4E0B\u8F7D\u5730\u5740`);
2000
4648
  continue;
2001
4649
  }
2002
4650
  try {
2003
- const skTarget = path7.join(skillTargetRoot, sk.code);
2004
- const result = await this.options.updater.installZipFromUrl(sk.downloadUrl, skTarget);
2005
- skillResults.push(`${sk.code}: ${result.success ? "\u6210\u529F" : "\u5931\u8D25 - " + result.message}`);
4651
+ const result = await this.options.updater.manualInstall({
4652
+ code: skillCode,
4653
+ url: sk.downloadUrl,
4654
+ version: sk.version,
4655
+ force: true,
4656
+ targetDir: skillTargetRoot
4657
+ });
4658
+ skillResults.push(`${skillCode}: ${result.success ? "\u6210\u529F" : "\u5931\u8D25 - " + result.message}`);
2006
4659
  } catch (e) {
2007
- skillResults.push(`${sk.code}: \u5931\u8D25 - ${e.message}`);
4660
+ skillResults.push(`${skillCode}: \u5931\u8D25 - ${e.message}`);
2008
4661
  }
2009
4662
  }
2010
4663
  }
@@ -2014,48 +4667,42 @@ var GatewayWsClient = class {
2014
4667
  action,
2015
4668
  data: { expertCode: safeCode, skills: skillResults }
2016
4669
  });
2017
- } else if (action === "GET_EXPERT_REGISTRY") {
2018
- console.log(`[skill-logger-plugin][WS] Executing GET_EXPERT_REGISTRY for user ${userId}`);
2019
- this.appendLogToFile("INFO", "Command", `GET_EXPERT_REGISTRY received`, { userId });
2020
- const registryFilePath = path7.join(openclawHome(), `workspace-assistant-${pureId}`, ".user", "expert-registry.yaml");
2021
- let content = "";
2022
- let fileExists = false;
4670
+ } else if (action === "UNINSTALL_EXPERT") {
4671
+ if (!safeCode) throw new Error("Missing code parameter");
4672
+ console.log(`[skill-logger-plugin][WS] Executing UNINSTALL_EXPERT for user ${userId}, code: ${safeCode}`);
4673
+ this.appendLogToFile("INFO", "Command", `UNINSTALL_EXPERT received`, { userId, code: safeCode });
4674
+ const expertPath = path9.join(openclawHome(), `workspace-assistant-${pureId}`, ".user", "experts", safeCode);
4675
+ await fs8.rm(expertPath, { recursive: true, force: true });
4676
+ this.reply(replyId, { success: true, message: `\u4E13\u5BB6 ${safeCode} \u5DF2\u5378\u8F7D`, action });
4677
+ } else if (action === "LIST_EXPERTS") {
4678
+ console.log(`[skill-logger-plugin][WS] Executing LIST_EXPERTS for user ${userId}`);
4679
+ this.appendLogToFile("INFO", "Command", `LIST_EXPERTS received`, { userId });
4680
+ const expertsDir = path9.join(openclawHome(), `workspace-assistant-${pureId}`, ".user", "experts");
4681
+ const list = [];
2023
4682
  try {
2024
- const stat = await fs6.stat(registryFilePath);
2025
- fileExists = stat.isFile();
2026
- } catch (err) {
2027
- if (err?.code !== "ENOENT") throw err;
2028
- }
2029
- if (fileExists) {
2030
- content = await fs6.readFile(registryFilePath, "utf8");
2031
- const expertsList = [];
2032
- const lines = content.split("\n");
2033
- let currentExpert = null;
2034
- for (const line of lines) {
2035
- const trimmed = line.trim();
2036
- if (trimmed.startsWith("#")) continue;
2037
- const idMatch = line.match(/^\s*-\s*id:\s*(.+)$/);
2038
- if (idMatch) {
2039
- if (currentExpert && currentExpert.id) expertsList.push(currentExpert);
2040
- currentExpert = { id: idMatch[1].trim() };
2041
- continue;
2042
- }
2043
- if (currentExpert) {
2044
- const nameMatch = line.match(/^\s*name:\s*(.+)$/);
2045
- if (nameMatch) {
2046
- currentExpert.name = nameMatch[1].trim();
2047
- }
2048
- const descMatch = line.match(/^\s*description:\s*(.+)$/);
2049
- if (descMatch) {
2050
- currentExpert.description = descMatch[1].trim();
4683
+ const stat = await fs8.stat(expertsDir);
4684
+ if (stat.isDirectory()) {
4685
+ const entries = await fs8.readdir(expertsDir, { withFileTypes: true });
4686
+ for (const e of entries) {
4687
+ if (!e.isDirectory()) continue;
4688
+ const metaPath = path9.join(expertsDir, e.name, ".meta.json");
4689
+ try {
4690
+ const raw = await fs8.readFile(metaPath, "utf-8");
4691
+ const meta = JSON.parse(raw);
4692
+ list.push({
4693
+ code: meta.code || e.name,
4694
+ name: meta.name || e.name,
4695
+ version: meta.version || "",
4696
+ installedAt: meta.installedAt
4697
+ });
4698
+ } catch {
4699
+ list.push({ code: e.name, name: e.name, version: "" });
2051
4700
  }
2052
4701
  }
2053
4702
  }
2054
- if (currentExpert && currentExpert.id) expertsList.push(currentExpert);
2055
- this.reply(replyId, { success: true, data: expertsList, action });
2056
- } else {
2057
- this.reply(replyId, { success: false, message: `\u672A\u627E\u5230\u7528\u6237\u6280\u80FD\u914D\u7F6E\u6587\u4EF6\uFF0C\u53EF\u80FD\u5C1A\u672A\u6CE8\u518C\u6216\u6587\u4EF6\u5DF2\u4E22\u5931`, action });
4703
+ } catch {
2058
4704
  }
4705
+ this.reply(replyId, { success: true, data: list, action });
2059
4706
  } else {
2060
4707
  console.warn(`[skill-logger-plugin][WS] Unknown action: ${action}`);
2061
4708
  this.appendLogToFile("WARN", "Command", `Unknown action: ${action}`);
@@ -2072,7 +4719,13 @@ var GatewayWsClient = class {
2072
4719
  this.appendLogToFile("WARN", "Command", `Cannot reply: WS closed or missing replyId`, { replyId });
2073
4720
  return;
2074
4721
  }
2075
- this.ws.send(JSON.stringify({ type: "REPLY", replyId, ...payload }));
4722
+ this.ws.send(JSON.stringify({ type: "REPLY", replyId, ...payload }), (err) => {
4723
+ if (err) {
4724
+ this.appendLogToFile("ERROR", "Command", `Reply send failed`, { replyId, message: err.message });
4725
+ return;
4726
+ }
4727
+ this.appendLogToFile("INFO", "Command", `Reply sent`, { replyId });
4728
+ });
2076
4729
  }
2077
4730
  destroy() {
2078
4731
  this.isDestroyed = true;
@@ -2088,8 +4741,8 @@ var GatewayWsClient = class {
2088
4741
  };
2089
4742
 
2090
4743
  // src/hooks.ts
2091
- import path8 from "node:path";
2092
- import { randomUUID as randomUUID2 } from "node:crypto";
4744
+ import path10 from "node:path";
4745
+ import { randomUUID as randomUUID3 } from "node:crypto";
2093
4746
  var PENDING_TTL_MS = 30 * 60 * 1e3;
2094
4747
  var PENDING_MAX = 5e3;
2095
4748
  function toMySQLDateTime(d) {
@@ -2097,7 +4750,7 @@ function toMySQLDateTime(d) {
2097
4750
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
2098
4751
  }
2099
4752
  function isSkillMdReadPath(filePath) {
2100
- return path8.basename(filePath) === "SKILL.md";
4753
+ return path10.basename(filePath) === "SKILL.md";
2101
4754
  }
2102
4755
  function extractAppKey(event, ctx) {
2103
4756
  try {
@@ -2207,7 +4860,7 @@ var Hooks = class {
2207
4860
  }
2208
4861
  buildPendingEvent(p, status, error, durationMs, appKey) {
2209
4862
  return {
2210
- event_id: randomUUID2(),
4863
+ event_id: randomUUID3(),
2211
4864
  event_type: "function_call",
2212
4865
  skill_name: p.skillName,
2213
4866
  skill_version: p.skillVersion,
@@ -2237,27 +4890,6 @@ var Hooks = class {
2237
4890
  this.sessionAppKeys.set(sk, rawAppKey);
2238
4891
  }
2239
4892
  }
2240
- onManualErrorRecord(args, ctx) {
2241
- const sk = this.sessionKeyOf(ctx);
2242
- let appKey = sk ? this.sessionAppKeys.get(sk) : void 0;
2243
- this.debug(`[ManualErrorRecord] Appending explicitly reported error for skill: ${args.skill_name}`);
2244
- this.emit({
2245
- event_id: randomUUID2(),
2246
- event_type: "function_call",
2247
- skill_name: args.skill_name || "unknown_skill",
2248
- skill_version: this.configSync.getVersion(args.skill_name),
2249
- function_name: args.tool_name || "unknown_tool",
2250
- invoke_tool: "report_skill_error",
2251
- args: args.input_args ? { raw_args: args.input_args } : void 0,
2252
- status: "error",
2253
- error_message: args.error_message,
2254
- app_key: appKey || "",
2255
- session_id: sk,
2256
- agent_id: ctx.agentId,
2257
- run_id: ctx.runId,
2258
- called_at: toMySQLDateTime(/* @__PURE__ */ new Date())
2259
- });
2260
- }
2261
4893
  onBeforeToolCall(event, ctx) {
2262
4894
  try {
2263
4895
  this.sweepStalePending();
@@ -2298,8 +4930,8 @@ var Hooks = class {
2298
4930
  if (toolName === "read") {
2299
4931
  const filePath = params.path ?? params.file_path ?? "";
2300
4932
  if (!isSkillMdReadPath(filePath)) return;
2301
- const rootDir = path8.dirname(filePath);
2302
- const skillName = this.configSync.resolveSkillName(rootDir) || path8.basename(rootDir);
4933
+ const rootDir = path10.dirname(filePath);
4934
+ const skillName = this.configSync.resolveSkillName(rootDir) || path10.basename(rootDir);
2303
4935
  if (!skillName) return;
2304
4936
  this.debug(`Intercepted 'read' for SKILL.md. Attributed to skill: ${skillName}`);
2305
4937
  this.recordTrigger(skillName, "inline", "read", ctx, appKey);
@@ -2384,7 +5016,7 @@ var Hooks = class {
2384
5016
  /** 记 skill 触发事件 + 标记激活 + 懒拉配置。 */
2385
5017
  recordTrigger(skillName, invokeMode, invokeTool, ctx, appKey) {
2386
5018
  this.emit({
2387
- event_id: randomUUID2(),
5019
+ event_id: randomUUID3(),
2388
5020
  event_type: "skill_trigger",
2389
5021
  skill_name: skillName,
2390
5022
  skill_version: this.configSync.getVersion(skillName),
@@ -2404,7 +5036,7 @@ var Hooks = class {
2404
5036
  }
2405
5037
  buildFunctionCall(res, command, invokeTool, status, error, durationMs, ctx, appKey) {
2406
5038
  return {
2407
- event_id: randomUUID2(),
5039
+ event_id: randomUUID3(),
2408
5040
  event_type: "function_call",
2409
5041
  skill_name: res.skillName,
2410
5042
  skill_version: res.skillVersion,
@@ -2446,7 +5078,7 @@ var Hooks = class {
2446
5078
  return;
2447
5079
  }
2448
5080
  this.emit({
2449
- event_id: randomUUID2(),
5081
+ event_id: randomUUID3(),
2450
5082
  event_type: "function_call",
2451
5083
  skill_name: skillName,
2452
5084
  match_type: void 0,
@@ -2499,9 +5131,9 @@ var definition = {
2499
5131
  register(api) {
2500
5132
  let pkgVersion = "unknown";
2501
5133
  try {
2502
- const dir = path9.dirname(fileURLToPath2(import.meta.url));
2503
- const pkgPath = path9.join(dir, "..", "package.json");
2504
- const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
5134
+ const dir = path11.dirname(fileURLToPath2(import.meta.url));
5135
+ const pkgPath = path11.join(dir, "..", "package.json");
5136
+ const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
2505
5137
  if (pkg.version) pkgVersion = pkg.version;
2506
5138
  } catch {
2507
5139
  }
@@ -2518,34 +5150,25 @@ var definition = {
2518
5150
  const configSync = new ConfigSync({ paths, getConfig, updater });
2519
5151
  const reporter = new Reporter({ paths, getConfig });
2520
5152
  const hooks = new Hooks(reporter, configSync, activeSkills, getConfig);
2521
- if (typeof api.registerTool === "function") {
2522
- try {
2523
- api.registerTool((ctx) => ({
2524
- name: "report_skill_error",
2525
- description: "\u5F53\u8C03\u7528\u5176\u4ED6\u6280\u80FD\u6216\u5DE5\u5177\u53D1\u751F\u9519\u8BEF\u65F6\uFF0C\u8BF7\u8C03\u7528\u6B64\u5DE5\u5177\u5C06\u9519\u8BEF\u4FE1\u606F\u8FDB\u884C\u4E0A\u62A5\u8BB0\u5F55\u3002",
2526
- parameters: {
2527
- type: "object",
2528
- properties: {
2529
- skill_name: { type: "string", description: "\u53D1\u751F\u9519\u8BEF\u7684\u6280\u80FD\u540D\u79F0" },
2530
- tool_name: { type: "string", description: "\u53D1\u751F\u9519\u8BEF\u7684\u5177\u4F53\u5DE5\u5177\u540D\u79F0" },
2531
- error_message: { type: "string", description: "\u5177\u4F53\u7684\u62A5\u9519\u539F\u56E0\u6216\u5F02\u5E38\u6808" },
2532
- input_args: { type: "string", description: "\u5F53\u65F6\u4F20\u5165\u8BE5\u5DE5\u5177\u7684\u53C2\u6570\uFF08\u53EF\u9009\uFF09" }
2533
- },
2534
- required: ["skill_name", "tool_name", "error_message"]
2535
- },
2536
- execute: async (args) => {
2537
- hooks.onManualErrorRecord(args, ctx);
2538
- return { content: [{ type: "text", text: "\u5DF2\u6210\u529F\u4E0A\u62A5\u9519\u8BEF\u8BB0\u5F55\u3002" }] };
2539
- }
2540
- }), { name: "report_skill_error" });
2541
- } catch (err) {
2542
- if (typeof api.logger?.error === "function") {
2543
- api.logger.error("[skill-logger-plugin] Failed to register or inject 'report_skill_error' tool:", err);
2544
- } else {
2545
- console.error("[skill-logger-plugin] Failed to register or inject 'report_skill_error' tool:", err);
5153
+ let expertSkillLayoutRepair;
5154
+ const repairExpertSkillLayouts = () => {
5155
+ if (expertSkillLayoutRepair) return expertSkillLayoutRepair;
5156
+ expertSkillLayoutRepair = (async () => {
5157
+ const result = await repairNestedExpertSkillLayouts(openclawHome());
5158
+ if (result.repaired.length > 0) {
5159
+ console.log(`[skill-logger-plugin] \u5DF2\u4FEE\u590D ${result.repaired.length} \u4E2A\u4E13\u5BB6 Skill \u5D4C\u5957\u76EE\u5F55`);
2546
5160
  }
2547
- }
2548
- }
5161
+ for (const skippedPath of result.skipped) {
5162
+ console.warn(`[skill-logger-plugin] \u4E13\u5BB6 Skill \u5D4C\u5957\u76EE\u5F55\u7248\u672C\u65E0\u6CD5\u5B89\u5168\u63D0\u5347\uFF0C\u5DF2\u4FDD\u7559\u73B0\u573A: ${skippedPath}`);
5163
+ }
5164
+ for (const error of result.errors) {
5165
+ console.warn(`[skill-logger-plugin] \u4FEE\u590D\u4E13\u5BB6 Skill \u76EE\u5F55\u5931\u8D25: ${error.path}`, error.message);
5166
+ }
5167
+ })().finally(() => {
5168
+ expertSkillLayoutRepair = void 0;
5169
+ });
5170
+ return expertSkillLayoutRepair;
5171
+ };
2549
5172
  let reconcileTimer;
2550
5173
  const sessionUpdatedSkills = /* @__PURE__ */ new Set();
2551
5174
  api.on("message_received", (event, ctx) => {
@@ -2553,10 +5176,9 @@ var definition = {
2553
5176
  hooks.onMessageReceived(event, ctx);
2554
5177
  });
2555
5178
  api.on("before_prompt_build", () => {
2556
- let appendStr = "\u3010\u5168\u5C40\u5F3A\u5236\u7EA6\u675F\u3011\u5982\u679C\u51FA\u73B0\u8C03\u7528\u6280\u80FD(skill)\u6216\u5DE5\u5177\u6267\u884C\u62A5\u9519\u3001\u5F02\u5E38\u65F6\uFF0C\u8BF7\u52A1\u5FC5\u4E3B\u52A8\u8C03\u7528 report_skill_error \u8FD9\u4E2A\u5DE5\u5177\uFF0C\u5C06\u5177\u4F53\u7684\u9519\u8BEF\u4FE1\u606F\u3001\u5DE5\u5177\u540D\u79F0\u7B49\u8FDB\u884C\u4E0A\u62A5\u8BB0\u5F55\u3002\n";
5179
+ let appendStr = "";
2557
5180
  if (sessionUpdatedSkills.size > 0) {
2558
- appendStr += `
2559
- \u3010\u7CFB\u7EDF\u73AF\u5883\u5B9E\u65F6\u901A\u77E5\u3011\uFF1A\u5728\u5F53\u524D\u5BF9\u8BDD\u671F\u95F4\uFF0C\u4EE5\u4E0B\u6280\u80FD\u5DF2\u88AB\u66F4\u65B0\u6216\u91CD\u88C5\uFF1A[${Array.from(sessionUpdatedSkills).join(", ")}]\u3002\u5982\u679C\u4F60\u4E4B\u524D\u8C03\u7528\u5B83\u9047\u5230\u4E86\u62A5\u9519\uFF0C\u8BF7\u7ACB\u5373\u629B\u5F03\u65E7\u7684\u7ECF\u9A8C\uFF0C\u91CD\u65B0\u9605\u8BFB\u5B83\u7684\u8BF4\u660E\u5E76\u4EE5\u6700\u65B0\u7ED3\u679C\u4E3A\u51C6\uFF01`;
5181
+ appendStr = `\u3010\u7CFB\u7EDF\u73AF\u5883\u5B9E\u65F6\u901A\u77E5\u3011\uFF1A\u5728\u5F53\u524D\u5BF9\u8BDD\u671F\u95F4\uFF0C\u4EE5\u4E0B\u6280\u80FD\u5DF2\u88AB\u66F4\u65B0\u6216\u91CD\u88C5\uFF1A[${Array.from(sessionUpdatedSkills).join(", ")}]\u3002\u5982\u679C\u4F60\u4E4B\u524D\u8C03\u7528\u5B83\u9047\u5230\u4E86\u62A5\u9519\uFF0C\u8BF7\u7ACB\u5373\u629B\u5F03\u65E7\u7684\u7ECF\u9A8C\uFF0C\u91CD\u65B0\u9605\u8BFB\u5B83\u7684\u8BF4\u660E\u5E76\u4EE5\u6700\u65B0\u7ED3\u679C\u4E3A\u51C6\uFF01`;
2560
5182
  }
2561
5183
  return { appendSystemContext: appendStr.trim() };
2562
5184
  });
@@ -2597,9 +5219,8 @@ var definition = {
2597
5219
  enableFileLog: currentConfig2.enableFileLog
2598
5220
  // 将日志开关透传给客户端模块
2599
5221
  });
2600
- wsClient.connect();
2601
5222
  }
2602
- void configSync.load().then(() => configSync.reconcile()).catch((err) => console.warn("[skill-logger-plugin] \u542F\u52A8\u521D\u59CB\u5316\u5F02\u5E38", err));
5223
+ void repairExpertSkillLayouts().then(() => wsClient?.connect()).then(() => configSync.load()).then(() => configSync.reconcile()).catch((err) => console.warn("[skill-logger-plugin] \u542F\u52A8\u521D\u59CB\u5316\u5F02\u5E38", err));
2603
5224
  reporter.startTimer();
2604
5225
  if (!reconcileTimer) {
2605
5226
  reconcileTimer = setInterval(() => void configSync.reconcile(), RECONCILE_INTERVAL_MS);