ezllm 0.0.41 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +5 -5
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -27,9 +27,9 @@ ${e.body}`:e.body).join(`
27
27
  `));return r}function ki(e){return Ei(e)!==null&&Di(e,`npm`).some(e=>m(e))}var Ai=[`.cmd`,`.bat`,`.exe`];function ji(e,t){if(t.includes(`/`)||t.includes(`\\`))return null;let n=Si?Ai.map(n=>i(e,`${t}${n}`)):[i(e,t)];return n.push(i(e,`node_modules`,`.bin`,t)),n.find(e=>m(e))??null}function Mi(e){return(Si?[e,i(e,`node_modules`,`.bin`)]:[i(e,`bin`),e]).join(n)+n}var Ni=Z(((e,t)=>{t.exports=n;function n(){this.pending=0,this.max=1/0,this.listeners=[],this.waiting=[],this.error=null}n.prototype.go=function(e){this.pending<this.max?i(this,e):this.waiting.push(e)},n.prototype.wait=function(e){this.pending===0?e(this.error):this.listeners.push(e)},n.prototype.hold=function(){return r(this)};function r(e){e.pending+=1;var t=!1;return n;function n(n){if(t)throw Error(`callback called twice`);if(t=!0,e.error=e.error||n,--e.pending,e.waiting.length>0&&e.pending<e.max)i(e,e.waiting.shift());else if(e.pending===0){var a=e.listeners;e.listeners=[],a.forEach(r)}}function r(t){t(e.error)}}function i(e,t){t(r(e))}})),Pi=Z((e=>{var t=Q(`fs`),n=Q(`util`),r=Q(`stream`),i=r.Readable,a=r.PassThrough,o=Ni(),s=Q(`events`).EventEmitter;e.BufferSlicer=u,e.FdSlicer=c,n.inherits(c,s);function c(e){s.call(this),this.fd=e,this.pend=new o,this.pend.max=1,this.refCount=0}c.prototype.read=function(e,n,r,i,a){var o=this;o.pend.go(function(s){t.read(o.fd,e,n,r,i,function(e,t,n){s(),a(e,t,n)})})},c.prototype.createReadStream=function(e){return new l(this,e)},c.prototype.ref=function(){this.refCount+=1},c.prototype.unref=function(){var e=this;if(--e.refCount,e.refCount<0)throw Error(`invalid unref`);if(e.refCount>0)return;t.close(e.fd,n);function n(t){t?e.emit(`error`,t):e.emit(`close`)}},n.inherits(l,i);function l(e,t){t||={},i.call(this,t),this.context=e,this.context.ref(),this.start=t.start||0,this.endOffset=t.end,this.pos=this.start}l.prototype._read=function(e){var n=this,r=Math.min(n._readableState.highWaterMark,e);n.endOffset!=null&&(r=Math.min(r,n.endOffset-n.pos)),r<=0?(n.push(null),this._cleanup()):n.context.pend.go(function(e){var i=Buffer.allocUnsafe(r);t.read(n.context.fd,i,0,r,n.pos,function(t,r){t?n.destroy(t):r===0?(n.push(null),n._cleanup()):(n.pos+=r,n.push(i.slice(0,r))),e()})})},l.prototype._destroy=function(e,t){this._cleanup(),t(e)},l.prototype._cleanup=function(){this.context!=null&&(this.context.unref(),this.context=null)},n.inherits(u,s);function u(e){s.call(this),this.refCount=0,this.buffer=e}u.prototype.read=function(e,t,n,r,i){if(!(0<=t&&t<=e.length))throw RangeError(`offset outside buffer: 0 <= `+t+` <= `+e.length);if(r<0)throw RangeError(`position is negative: `+r);t+n>e.length&&(n=e.length-t),r+n>this.buffer.length&&(n=this.buffer.length-r),n<=0?setImmediate(function(){i(null,0)}):(this.buffer.copy(e,t,r,r+n),setImmediate(function(){i(null,n)}))},u.prototype.createReadStream=function(e){e||={};var t=new a(e);t.start=e.start||0,t.endOffset=e.end,t.pos=t.endOffset||this.buffer.length;for(var n=this.buffer.slice(t.start,t.pos),r=65536,i=0;;){var o=i+r;if(o>=n.length){i<n.length&&t.write(n.slice(i,n.length));break}t.write(n.slice(i,o)),i=o}return t.end(),t},u.prototype.ref=function(){this.refCount+=1},u.prototype.unref=function(){if(--this.refCount,this.refCount<0)throw Error(`invalid unref`)}})),Fi=Z(((e,t)=>{var n=new Int32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117]);function r(e){let t=-1;for(let r of e)t=n[(t^r)&255]^t>>>8;return(t^-1)>>>0}t.exports=r})),Ii=Z((e=>{var t=Q(`fs`),n=Q(`zlib`),r=Pi(),i=Q(`util`),a=Q(`events`).EventEmitter,o=Q(`stream`).Transform,s=Q(`stream`).PassThrough,c=Q(`stream`).Writable,l=typeof n.crc32==`function`?n.crc32:Fi();e.openPromise=u;function u(e,t){return new Promise((n,r)=>{d(e,{...t,lazyEntries:!0},function(e,t){if(e)return r(e);n(t)})})}function d(e,n,r){typeof n==`function`&&(r=n,n=null),n??={},n.autoClose??(n.autoClose=!0),n.lazyEntries??(n.lazyEntries=!1),n.decodeStrings??(n.decodeStrings=!0),n.validateEntrySizes??(n.validateEntrySizes=!0),n.strictFileNames??(n.strictFileNames=!1),r??=M,t.open(e,`r`,function(e,i){if(e)return r(e);f(i,n,function(e,n){e&&t.close(i,M),r(e,n)})})}function f(e,n,i){typeof n==`function`&&(i=n,n=null),n??={},n.autoClose??(n.autoClose=!1),n.lazyEntries??(n.lazyEntries=!1),n.decodeStrings??(n.decodeStrings=!0),n.validateEntrySizes??(n.validateEntrySizes=!0),n.strictFileNames??(n.strictFileNames=!1),i??=M,t.fstat(e,function(t,a){if(t)return i(t);p(new r.FdSlicer(e),a.size,n,i)})}function p(e,t,n,r){typeof n==`function`&&(r=n,n=null),n??={},n.autoClose??(n.autoClose=!0),n.lazyEntries??(n.lazyEntries=!1),n.decodeStrings??(n.decodeStrings=!0);var i=!!n.decodeStrings;if(n.validateEntrySizes??(n.validateEntrySizes=!0),n.strictFileNames??(n.strictFileNames=!1),r??=M,typeof t!=`number`)throw Error(`expected totalSize parameter to be a number`);if(t>2**53-1)throw Error(`zip file too large. only file sizes up to 2^52 are supported due to JavaScript's Number type being an IEEE 754 double.`);e.ref();var a=22,o=20,s=Math.min(o+a+65535,t),c=A(s);C(e,c,0,s,t-c.length,function(l){if(l)return r(l);for(var u=s-a;u>=0;--u)if(c.readUInt32LE(u)===101010256){var d=c.subarray(u),f=d.readUInt16LE(4),p=d.readUInt16LE(10),h=d.readUInt32LE(16),g=d.readUInt16LE(20),_=d.length-a;if(g!==_)return r(Error(`Invalid comment length. Expected: `+_+`. Found: `+g+". Are there extra bytes at the end of the file? Or is the end of central dir signature `PK☺☻` in the comment?"));var v=i?O(d.subarray(22),!1):d.subarray(22);if(u-o>=0&&c.readUInt32LE(u-o)===117853008){var y=k(c.subarray(u-o,u-o+o),8),b=A(56);return C(e,b,0,b.length,y,function(a){return a?r(a):b.readUInt32LE(0)===101075792?(f=b.readUInt32LE(16),f===0?(p=k(b,32),h=k(b,48),r(null,new m(e,h,t,p,v,n.autoClose,n.lazyEntries,i,n.validateEntrySizes,n.strictFileNames))):r(Error(`multi-disk zip files are not supported: found disk number: `+f))):r(Error(`invalid zip64 end of central directory record signature`))})}return f===0?r(null,new m(e,h,t,p,v,n.autoClose,n.lazyEntries,i,n.validateEntrySizes,n.strictFileNames)):r(Error(`multi-disk zip files are not supported: found disk number: `+f))}r(Error(`End of central directory record signature not found. Either not a zip file, or file is truncated.`))})}i.inherits(m,a);function m(e,t,n,r,i,o,s,c,l,u){var d=this;a.call(d),d.reader=e,d.reader.on(`error`,function(e){g(d,e)}),d.reader.once(`close`,function(){d.emit(`close`)}),d.readEntryCursor=t,d.fileSize=n,d.entryCount=r,d.comment=i,d.entriesRead=0,d.autoClose=!!o,d.lazyEntries=!!s,d.decodeStrings=!!c,d.validateEntrySizes=!!l,d.strictFileNames=!!u,d.isOpen=!0,d.emittedError=!1,d.hasEachEntryBeenCalled=!1,d.lazyEntries||d._readEntry()}m.prototype.close=function(){this.isOpen&&(this.isOpen=!1,this.reader.unref())};function h(e,t){e.autoClose&&e.close(),g(e,t)}function g(e,t){e.emittedError||(e.emittedError=!0,e.emit(`error`,t))}m.prototype.readEntry=function(){if(!this.lazyEntries)throw Error(`readEntry() called without lazyEntries:true`);this._readEntry()},m.prototype._readEntry=function(){var e=this;if(e.entryCount===e.entriesRead)setImmediate(function(){e.autoClose&&e.close(),!e.emittedError&&e.emit(`end`)});else if(!e.emittedError){var t=A(46);C(e.reader,t,0,t.length,e.readEntryCursor,function(n){if(n)return h(e,n);if(!e.emittedError){var r=new _,i=t.readUInt32LE(0);if(i!==33639248)return h(e,Error(`invalid central directory file header signature: 0x`+i.toString(16)));if(r.versionMadeBy=t.readUInt16LE(4),r.versionNeededToExtract=t.readUInt16LE(6),r.generalPurposeBitFlag=t.readUInt16LE(8),r.compressionMethod=t.readUInt16LE(10),r.lastModFileTime=t.readUInt16LE(12),r.lastModFileDate=t.readUInt16LE(14),r.crc32=t.readUInt32LE(16),r.compressedSize=t.readUInt32LE(20),r.uncompressedSize=t.readUInt32LE(24),r.fileNameLength=t.readUInt16LE(28),r.extraFieldLength=t.readUInt16LE(30),r.fileCommentLength=t.readUInt16LE(32),r.internalFileAttributes=t.readUInt16LE(36),r.externalFileAttributes=t.readUInt32LE(38),r.relativeOffsetOfLocalHeader=t.readUInt32LE(42),r.generalPurposeBitFlag&64)return h(e,Error(`strong encryption is not supported`));e.readEntryCursor+=46,t=A(r.fileNameLength+r.extraFieldLength+r.fileCommentLength),C(e.reader,t,0,t.length,e.readEntryCursor,function(n){if(n)return h(e,n);if(!e.emittedError){r.fileNameRaw=t.subarray(0,r.fileNameLength);var i=r.fileNameLength+r.extraFieldLength;r.extraFieldRaw=t.subarray(r.fileNameLength,i),r.fileCommentRaw=t.subarray(i,i+r.fileCommentLength);try{r.extraFields=S(r.extraFieldRaw)}catch(t){return h(e,t)}if(e.decodeStrings){var a=!!(r.generalPurposeBitFlag&2048);r.fileComment=O(r.fileCommentRaw,a),r.fileName=b(r.generalPurposeBitFlag,r.fileNameRaw,r.extraFields,e.strictFileNames);var o=x(r.fileName);if(o!=null)return h(e,Error(o))}else r.fileComment=r.fileCommentRaw,r.fileName=r.fileNameRaw;r.comment=r.fileComment,e.readEntryCursor+=t.length,e.entriesRead+=1;for(var s=0;s<r.extraFields.length;s++){var c=r.extraFields[s];if(c.id===1){var l=c.data,u=0;if(r.uncompressedSize===4294967295){if(u+8>l.length)return h(e,Error(`zip64 extended information extra field does not include uncompressed size`));r.uncompressedSize=k(l,u),u+=8}if(r.compressedSize===4294967295){if(u+8>l.length)return h(e,Error(`zip64 extended information extra field does not include compressed size`));r.compressedSize=k(l,u),u+=8}if(r.relativeOffsetOfLocalHeader===4294967295){if(u+8>l.length)return h(e,Error(`zip64 extended information extra field does not include relative header offset`));r.relativeOffsetOfLocalHeader=k(l,u),u+=8}break}}if(e.validateEntrySizes&&r.compressionMethod===0){var d=r.uncompressedSize;if(r.isEncrypted()&&(d+=12),r.compressedSize!==d){var f=`compressed/uncompressed size mismatch for stored file: `+r.compressedSize+` != `+r.uncompressedSize;return h(e,Error(f))}}e.emit(`entry`,r),e.lazyEntries||e._readEntry()}})}})}},m.prototype.eachEntry=function(){let e=this;if(!e.lazyEntries)throw Error(`eachEntry() requires lazyEntries: true`);if(e.hasEachEntryBeenCalled)throw Error(`eachEntry() must only be called once per ZipFile`);e.hasEachEntryBeenCalled=!0;let t=null;e.on(`entry`,r),e.on(`end`,i),e.on(`error`,a);function n(){e.removeListener(`entry`,r),e.removeListener(`end`,i),e.removeListener(`error`,a),e.autoClose&&e.close()}function r(e){let{resolve:n}=t;t=null,n({value:e})}function i(){let{resolve:e}=t;t=null,n(),e({done:!0})}function a(e){let{reject:r}=t;t=null,n(),r(e)}return{[Symbol.asyncIterator](){return this},next(){let n=new Promise((e,n)=>{if(t!=null)throw Error(`next() called before previous Promise was resolved.`);t={resolve:e,reject:n}});return e.readEntry(),n},return(e){return n(),Promise.resolve({done:!0,value:e})},throw(e){return n(),Promise.reject(e)}}},m.prototype.openReadStream=function(e,t,n){var r=this,i=0,a=e.compressedSize;if(n??(n=t,t=null),t==null)t={};else{if(t.decodeFileData===!1){if(t.decrypt!=null)throw Error(`cannot use options.decrypt when options.decodeFileData === false`);if(t.decompress!=null)throw Error(`cannot use options.decompress when options.decodeFileData === false`)}else{if(t.decrypt!=null){if(!e.isEncrypted())throw Error(`options.decrypt can only be specified for encrypted entries. See also option decodeFileData.`);if(t.decrypt!==!1)throw Error(`invalid options.decrypt value: `+t.decrypt);if(e.isCompressed()&&t.decompress!==!1)throw Error(`entry is encrypted and compressed, and options.decompress !== false. See also option decodeFileData.`)}if(t.decompress!=null){if(!e.isCompressed())throw Error(`options.decompress can only be specified for compressed entries. See also option decodeFileData.`);if(t.decompress!==!1&&t.decompress!==!0)throw Error(`invalid options.decompress value: `+t.decompress);s=t.decompress}}if(t.start!=null){if(i=t.start,i<0)throw Error(`options.start < 0`);if(i>e.compressedSize)throw Error(`options.start > entry.compressedSize`)}if(t.end!=null){if(a=t.end,a<0)throw Error(`options.end < 0`);if(a>e.compressedSize)throw Error(`options.end > entry.compressedSize`);if(a<i)throw Error(`options.end < options.start`)}}var o=t.decodeFileData===!1||(e.compressionMethod===0||e.compressionMethod===8&&t.decompress===!1)&&(!e.isEncrypted()||t.decrypt===!1);if((t.start!=null||t.end!=null)&&!o)throw Error(`start/end range require options.decodeFileData === false for non-trivial encoded entries.`);if(!r.isOpen)return n(Error(`closed`));if(e.isEncrypted()&&!o&&t.decrypt!==!1)return n(Error(`entry is encrypted, and options.decodeFileData !== false`));var s;if(o)s=!1;else if(e.compressionMethod===8)s=t.decodeFileData!==!0;else return n(Error(`unsupported compression method: `+e.compressionMethod));r.readLocalFileHeader(e,{minimal:!0},function(t,o){if(t)return n(t);r.openReadStreamLowLevel(o.fileDataStart,e.compressedSize,i,a,s,e.uncompressedSize,n)})},m.prototype.openReadStreamLowLevel=function(e,t,r,i,a,o,s){var c=this;e+t;var l=c.reader.createReadStream({start:e+r,end:e+i}),u=l;if(a){var d=!1,f=n.createInflateRaw();l.on(`error`,function(e){setImmediate(function(){d||f.emit(`error`,e)})}),l.pipe(f),c.validateEntrySizes?(u=new w(o),f.on(`error`,function(e){setImmediate(function(){d||u.emit(`error`,e)})}),f.pipe(u)):u=f,j(u,function(){d=!0,f!==u&&f.unpipe(u),l.unpipe(f),l.destroy()})}s(null,u)},m.prototype.readLocalFileHeader=function(e,t,n){var r=this;n??(n=t,t=null),t??={},r.reader.ref();var i=A(30);C(r.reader,i,0,i.length,e.relativeOffsetOfLocalHeader,function(a){try{if(a)return n(a);var o=i.readUInt32LE(0);if(o!==67324752)return n(Error(`invalid local file header signature: 0x`+o.toString(16)));var s=i.readUInt16LE(26),c=i.readUInt16LE(28),l=e.relativeOffsetOfLocalHeader+30+s+c;if(l+e.compressedSize>r.fileSize)return n(Error(`file data overflows file bounds: `+l+` + `+e.compressedSize+` > `+r.fileSize));if(t.minimal)return n(null,{fileDataStart:l});var u=new v;u.fileDataStart=l,u.versionNeededToExtract=i.readUInt16LE(4),u.generalPurposeBitFlag=i.readUInt16LE(6),u.compressionMethod=i.readUInt16LE(8),u.lastModFileTime=i.readUInt16LE(10),u.lastModFileDate=i.readUInt16LE(12),u.crc32=i.readUInt32LE(14),u.compressedSize=i.readUInt32LE(18),u.uncompressedSize=i.readUInt32LE(22),u.fileNameLength=s,u.extraFieldLength=c,i=A(s+c),r.reader.ref(),C(r.reader,i,0,i.length,e.relativeOffsetOfLocalHeader+30,function(e){try{return e?n(e):(u.fileName=i.subarray(0,s),u.extraField=i.subarray(s),n(null,u))}finally{r.reader.unref()}})}finally{r.reader.unref()}})},m.prototype.openReadStreamPromise=function(e,t){return new Promise((n,r)=>{this.openReadStream(e,t,function(e,t){if(e)return r(e);n(t)})})},m.prototype.openReadStreamLowLevelPromise=function(e,t,n,r,i,a){return new Promise((o,s)=>{this.openReadStream(e,t,n,r,i,a,function(e,t){if(e)return s(e);o(t)})})},m.prototype.readLocalFileHeaderPromise=function(e,t){return new Promise((n,r)=>{this.readLocalFileHeader(e,t,function(e,t){if(e)return r(e);n(t)})})};function _(){}_.prototype.getLastModDate=function(e){if(e??={},!e.forceDosFormat)for(var t=0;t<this.extraFields.length;t++){var n=this.extraFields[t];if(n.id===21589){var r=n.data;if(r.length<5||!(r[0]&1))continue;var i=r.readInt32LE(1);return new Date(i*1e3)}if(n.id===10){var r=n.data;if(r.length!==32||r.readUInt16LE(4)!==1||r.readUInt16LE(6)!==24)continue;var a=(r.readUInt32LE(8)+4294967296*r.readInt32LE(12))/1e4-0xa9730b66800;return new Date(a)}}return y(this.lastModFileDate,this.lastModFileTime,e.timezone)},_.prototype.canDecodeFileData=function(){return!this.isEncrypted()&&(this.compressionMethod===0||this.compressionMethod===8)},_.prototype.isEncrypted=function(){return!!(this.generalPurposeBitFlag&1)},_.prototype.isCompressed=function(){return this.compressionMethod===8};function v(){}function y(e,t,n){var r=e&31,i=(e>>5&15)-1,a=(e>>9&127)+1980,o=0,s=(t&31)*2,c=t>>5&63,l=t>>11&31;if(n==null||n===`local`)return new Date(a,i,r,l,c,s,o);if(n===`UTC`)return new Date(Date.UTC(a,i,r,l,c,s,o));throw Error(`unrecognized options.timezone: `+options.timezone)}function b(e,t,n,r){for(var i=null,a=0;a<n.length;a++){var o=n[a];if(o.id===28789){if(o.data.length<6||o.data.readUInt8(0)!==1)continue;var s=o.data.readUInt32LE(1);if(l(t)!==s)continue;i=O(o.data.subarray(5),!0);break}}return i??=O(t,!!(e&2048)),r||(i=i.replace(/\\/g,`/`)),i}function x(e){return e.indexOf(`\\`)===-1?/^[a-zA-Z]:/.test(e)||/^\//.test(e)?`absolute path: `+e:e.split(`/`).indexOf(`..`)===-1?null:`invalid relative path: `+e:`invalid characters in fileName: `+e}function S(e){for(var t=[],n=0;n<e.length-3;){var r=e.readUInt16LE(n+0),i=e.readUInt16LE(n+2),a=n+4,o=a+i;if(o>e.length)throw Error(`extra field length exceeds extra field buffer size`);var s=e.subarray(a,o);t.push({id:r,data:s}),n=o}return t}function C(e,t,n,r,i,a){if(r===0)return setImmediate(function(){a(null,A(0))});e.read(t,n,r,i,function(e,t){if(e)return a(e);if(t<r)return a(Error(`unexpected EOF`));a()})}i.inherits(w,o);function w(e){o.call(this),this.actualByteCount=0,this.expectedByteCount=e}w.prototype._transform=function(e,t,n){if(this.actualByteCount+=e.length,this.actualByteCount>this.expectedByteCount){var r=`too many bytes in the stream. expected `+this.expectedByteCount+`. got at least `+this.actualByteCount;return n(Error(r))}n(null,e)},w.prototype._flush=function(e){if(this.actualByteCount<this.expectedByteCount){var t=`not enough bytes in the stream. expected `+this.expectedByteCount+`. got only `+this.actualByteCount;return e(Error(t))}e()},i.inherits(T,a);function T(){a.call(this),this.refCount=0}T.prototype.ref=function(){this.refCount+=1},T.prototype.unref=function(){var e=this;if(--e.refCount,e.refCount>0)return;if(e.refCount<0)throw Error(`invalid unref`);e.close(t);function t(t){if(t)return e.emit(`error`,t);e.emit(`close`)}},T.prototype.createReadStream=function(e){e??={};var t=e.start,n=e.end;if(t===n){var r=new s;return setImmediate(function(){r.end()}),r}var i=this._readStreamForRange(t,n),a=!1,o=new E(this);i.on(`error`,function(e){setImmediate(function(){a||o.emit(`error`,e)})}),j(o,function(){i.unpipe(o),o.unref(),i.destroy()});var c=new w(n-t);return o.on(`error`,function(e){setImmediate(function(){a||c.emit(`error`,e)})}),j(c,function(){a=!0,o.unpipe(c),o.destroy()}),i.pipe(o).pipe(c)},T.prototype._readStreamForRange=function(e,t){throw Error(`not implemented`)},T.prototype.read=function(e,t,n,r,i){var a=this.createReadStream({start:r,end:r+n}),o=new c,s=0;o._write=function(n,r,i){n.copy(e,t+s,0,n.length),s+=n.length,i()},o.on(`finish`,i),a.on(`error`,function(e){i(e)}),a.pipe(o)},T.prototype.close=function(e){setImmediate(e)},i.inherits(E,s);function E(e){s.call(this),this.context=e,this.context.ref(),this.unreffedYet=!1}E.prototype._flush=function(e){this.unref(),e()},E.prototype.unref=function(e){this.unreffedYet||(this.unreffedYet=!0,this.context.unref())};var D=`\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\xA0`;function O(e,t){if(t)return e.toString(`utf8`);for(var n=``,r=0;r<e.length;r++)n+=D[e[r]];return n}function k(e,t){var n=e.readUInt32LE(t);return e.readUInt32LE(t+4)*4294967296+n}var A=typeof Buffer.allocUnsafe==`function`?function(e){return Buffer.allocUnsafe(e)}:function(e){return new Buffer(e)};function j(e,t){typeof e.destroy==`function`?e._destroy=function(e,n){t(),n?.(e)}:e.destroy=t}function M(e){if(e)throw e}}))(),Li=16384,Ri=16;function zi(e,t){let n=s(e,t);if(!n.startsWith(e+c))throw Error(`zip 条目越出目标目录:${t}`);if(t.split(`/`).some(e=>e.includes(`:`)))throw Error(`zip 条目名含非法字符「:」(NTFS 数据流形态):${t}`);return n}function Bi(e){return(e.externalFileAttributes>>>16&61440)===Li||e.fileName.endsWith(`/`)?!0:!(e.versionMadeBy>>>8)&&e.externalFileAttributes===Ri}async function Vi(e,t,n){let i=s(t);h(i,{recursive:!0});let a=0,o=0,c=null,l=(e=0)=>{n?.({entries:a,bytes:o+e,current:c})},u=await(0,Ii.openPromise)(e);try{for await(let e of u.eachEntry()){if(e.fileName.startsWith(`__MACOSX/`))continue;let t=zi(i,e.fileName);if(Bi(e)){h(t,{recursive:!0}),a+=1,l();continue}h(r(t),{recursive:!0}),c=e.fileName,l();let n=0,s=await u.openReadStreamPromise(e);s.on(`data`,e=>{n+=e.length,l(n)}),await P(s,p(t)),o+=n,a+=1,c=null,l()}}finally{u.isOpen&&u.close()}}var Hi={"win32-x64":{dir:`win-x64`,ext:`zip`},"win32-arm64":{dir:`win-arm64`,ext:`zip`},"darwin-arm64":{dir:`darwin-arm64`,ext:`tar.gz`},"darwin-x64":{dir:`darwin-x64`,ext:`tar.gz`},"linux-x64":{dir:`linux-x64`,ext:`tar.gz`},"linux-arm64":{dir:`linux-arm64`,ext:`tar.gz`}},Ui=process.platform===`win32`?[[`node_modules`]]:[[`lib`,`node_modules`]],Wi=5e3,Gi=3e3;function Ki(e,t){let n=e.bytes===null?``:`,${Math.round(e.bytes/1048576)} MB`,r=e.current===null?``:`(正在 ${e.current})`;return`[ezn] 已解压 ${e.entries} 项${n}${r}(已用 ${t} 秒) ...`}function qi(e,t){let n=setInterval(()=>console.error(t()),e);return()=>clearInterval(n)}function Ji(e){return Math.round((Date.now()-e)/1e3)}var Yi=new Set([`EPERM`,`EACCES`,`EBUSY`,`ENOSPC`,`ENAMETOOLONG`,`EROFS`,`EMFILE`]);function Xi(e){let t=String(e?.code??``);return Yi.has(t)?`local`:`network`}function Zi(e){let t={local:`本机(文件/权限/安全软件)`,network:`网络`,unknown:`未识别`},n=e.mirrors.map((n,r)=>{let i=e.failures[r],a=i?.kind??`unknown`,o=i?i.error instanceof Error?i.error.message:String(i.error):`(无记录)`;return` ${r+1}. [${t[a]}] ${n}\n ${o}`}).join(`
28
28
  `),r=new Set(e.failures.map(e=>e.kind)),i=r.size>0&&[...r].every(e=>e===`network`),a=[`Node 运行时下载失败。`,i?`所有源的失败都是网络类(不可达 / 超时 / TLS 失败)。`:`其中至少一个源是本机类失败(文件被占用、权限、磁盘空间,或被安全软件拦下)——这种情况下换源不会好转。`,`各源失败原因:`,n,``,`可尝试的恢复方式:`];return i?(a.push(` 1. 检查网络 / 代理后重试(本下载不读 http_proxy 等环境变量,需要能直连上面这些源);`),a.push(` 2. 换一个镜像源重试(**推荐入口是环境变量**,不必改任何文件):`,` Windows: set ELLM_NODE_MIRROR=https://your-mirror.example/node-dist`,` POSIX: export ELLM_NODE_MIRROR=https://your-mirror.example/node-dist`,` 目录结构需同 nodejs.org/dist(即 <mirror>/<版本>/<文件名>);`)):(a.push(` 1. 先按上面的「本机」条目处理:确认磁盘空间、把应用目录加入安全软件(360/电脑管家/Defender)信任区、`,` 或关闭其实时防护后重试;被拦下的文件也可能已被隔离/删除,删掉解压残留再试:`,` ${e.extractDir}`),a.push(` 2. 排除本机原因后若仍是网络问题,再换镜像源(**推荐入口是环境变量**):`,` Windows: set ELLM_NODE_MIRROR=https://your-mirror.example/node-dist`,` POSIX: export ELLM_NODE_MIRROR=https://your-mirror.example/node-dist`)),a.push(` 3. 手动放置:下载 ${e.filename}(见 https://nodejs.org/dist/${e.nodeVersion}/),`,` 解压到 ${e.target}(如带顶层版本目录请把其内容上移一层),`,` 确保可执行文件位于 ${e.nodePath}。`),a.join(`
29
29
  `)}async function Qi(e,t,n){let r=`node-${e}-${n.platform.dir}.${n.platform.ext}`,a=i(t,`node.download.tmp`),o=i(t,`node.extract.tmp`),s=()=>{b(a,{force:!0}),b(o,{recursive:!0,force:!0})},c=[];n.mirror&&c.push(n.mirror.replace(/\/+$/,``)),c.push(`https://registry.npmmirror.com/-/binary/node`,`https://nodejs.org/dist`),b(a,{force:!0}),b(o,{recursive:!0,force:!0}),h(o,{recursive:!0});let l=[];for(let t=0;t<c.length;t++){let u=c[t],d=`${u}/${e}/${r}`;console.error(`[ezn] (${t+1}/${c.length}) 正在下载 ${r}\n[ezn] 来源:${u}`);try{let e=Date.now(),t=0,r=yi.default.stream(d,{decompress:!1,timeout:{connect:3e4,response:6e4,socket:6e4}});r.on(`downloadProgress`,e=>{t=e.transferred});let c=qi(Wi,()=>`[ezn] 已下载 ${Math.round(t/1048576)} MB(已用 ${Ji(e)} 秒) ...`);try{await P(r,p(a))}finally{c()}console.error(`[ezn] 下载完成(${Math.round(x(a).size/1048576)} MB,耗时 ${Ji(e)} 秒),正在解压 ...`);let l=Date.now(),u={entries:0,bytes:null,current:null},f=qi(Gi,()=>Ki(u,Ji(l)));try{n.platform.ext===`zip`?await Vi(a,o,e=>{u=e}):await bi.x({file:a,cwd:o,onentry:e=>{u={entries:u.entries+1,bytes:null,current:e.path}}})}finally{f()}console.error(`[ezn] 解压完成(${u.entries} 项,耗时 ${Ji(l)} 秒)`);let m=v(o),h=m.length===1&&m[0]!==void 0&&x(i(o,m[0])).isDirectory()?i(o,m[0]):o;return b(a,{force:!0}),{src:h,cleanup:s}}catch(e){l.push({error:e,kind:Xi(e)}),console.error(`[ezn] 该源失败(${Xi(e)}):${e instanceof Error?e.message:String(e)}`),b(a,{force:!0}),b(o,{recursive:!0,force:!0}),h(o,{recursive:!0})}}throw s(),Error(Zi({mirrors:c,failures:l,filename:r,nodeVersion:e,target:n.target,nodePath:n.nodePath,extractDir:o}))}function $i(e,t,n,r,a){if(r.some(e=>n.length<=e.length&&n.every((t,n)=>e[n]===t))&&m(t)&&x(e).isDirectory()&&x(t).isDirectory()){for(let o of v(e))$i(i(e,o),i(t,o),[...n,o],r,a);b(e,{recursive:!0,force:!0})}else{if(m(t)){let e=`${t}.old-${a}`;y(t,e),console.error(`[ezn] 同名项已备份:${e}`)}y(e,t)}}function ea(e,t){let n=`.old-${String(t)}`,r=e=>/\.old-\d+$/.test(e)&&!e.endsWith(n),a=e=>{let t;try{t=v(e)}catch{return}for(let n of t){let t=i(e,n),o=!1;try{o=x(t).isDirectory()}catch{continue}if(o)n!==`node_modules`&&a(t);else if(r(n))try{b(t,{force:!0})}catch{console.error(`[ezn] 旧备份清理失败(可能仍被占用,下次再试):${t}`)}}};a(e)}async function ta(e,t,n={}){let a=0,o=(e,t)=>{a=Date.now();for(let n of v(e))$i(i(e,n),i(t,n),[n],Ui,a)},c=s(e),l=Ci(t),u=wi(c),d=Ti(),f=Hi[d];if(!f)throw Error(`暂不支持的平台:${d}。请手动放置 Node ${l} 到 ${c},确保可执行文件位于 ${u}(Windows 为 node.exe,Unix 为 bin/node)。`);h(c,{recursive:!0});let{src:p,cleanup:m}=await Qi(l,r(c),{target:c,nodePath:u,platform:f,mirror:n.mirror??null});try{console.error(`[ezn] 正在落位运行时文件 ...`),o(p,c)}finally{m()}a!==0&&ea(c,a),console.error(`[ezn] Node ${l} 已就绪:${c}`)}function na(e){return e!==``&&!/[\s"^&|<>()%!]/.test(e)?e:`"${e.replace(/"/g,`\\"`)}"`}function ra(e,t,n){return n?[[e,...t].map(na).join(` `),[]]:[e,[...t]]}function ia(e,t,n={}){return new Promise((r,i)=>{let a=A(e,t,{windowsHide:!0,...n}),o=null,s=null;a.stdout&&(o=``,a.stdout.on(`data`,e=>o=(o??``)+e)),a.stderr&&(s=``,a.stderr.on(`data`,e=>s=(s??``)+e)),a.on(`error`,i),a.on(`close`,(e,t)=>r({status:e,signal:t,stdout:o,stderr:s}))})}var aa=process.platform===`win32`,oa=15e3;function sa(e){return typeof e==`string`?e.trim().split(/\s+/).filter(e=>e.length>0):[...e]}var ca=class e{constructor(e,t){this.path=e,this.rt=t}get npmCliPath(){return Oi(this.rt,`npm`)}get npxCliPath(){return Oi(this.rt,`npx`)}get major(){return e.probeMajor(this.path)}resolveArgs(e,t){let n=sa(e);if(n.length===0)throw Error(`命令为空`);let r=n[0],i=n.slice(1);return r===`node`?i:r===`npm`?[this.npmCliPath,...i]:r===`npx`?[this.npxCliPath,...i]:t===null?n:[t,...n]}resolveExec(e,t){let n=sa(e);if(n.length===0)throw Error(`命令为空`);let r=n[0],i=n.slice(1),a=this.childEnv(t.env);if(r===`node`)return{file:this.path,argv:i,shell:!1,env:a};if(r===`npm`)return{file:this.path,argv:[this.npmCliPath,...i],shell:!1,env:a};if(r===`npx`)return{file:this.path,argv:[this.npxCliPath,...i],shell:!1,env:a};let o=ji(this.rt,r);if(o!==null){let e=aa&&/\.(cmd|bat)$/i.test(o),[t,n]=ra(o,i,e);return{file:t,argv:n,shell:e,env:a}}return{file:this.path,argv:n,shell:!1,env:a}}childEnv(e){let t=e??process.env;return{...t,PATH:Mi(this.rt)+(t.PATH??t.Path??``)}}execSync(e,t){let{file:n,argv:r,shell:i,env:a}=this.resolveExec(e,t??{});return j(n,r,{windowsHide:!0,encoding:`utf8`,...t,shell:i,env:a})}exec(e,t){let{file:n,argv:r,shell:i,env:a}=this.resolveExec(e,t??{});return ia(n,r,{...t,shell:i,env:a})}npmSync(e,t){return j(this.path,this.resolveArgs(e,this.npmCliPath),{windowsHide:!0,encoding:`utf8`,...t})}npm(e,t){return ia(this.path,this.resolveArgs(e,this.npmCliPath),t)}npxSync(e,t){return j(this.path,this.resolveArgs(e,this.npxCliPath),{windowsHide:!0,encoding:`utf8`,...t})}npx(e,t){return ia(this.path,this.resolveArgs(e,this.npxCliPath),t)}static probeMajor(t){return e.probe(t).major}static probe(e){try{let t=k(e,[`-v`],{encoding:`utf8`,timeout:oa,windowsHide:!0}),n=String(t).trim().match(/^v(\d+)\./);return{major:n?Number(n[1]):null,reason:n?`ok`:`unexecutable`}}catch(e){let t=e;return{major:null,reason:t.code===`ETIMEDOUT`||t.signal===`SIGTERM`?`timeout`:`unexecutable`}}}static async ensure(t,n,r={}){let a=s(t),o=Ci(n),c=Number(o.replace(/^v/,``).split(`.`)[0]),l=i(a,`node`),u=wi(l),d=r.probe??(t=>e.probe(t)),f=r.nodeBin??null;if(f){if(!m(f))throw Error(`ezn.nodeBin 指定的 Node 不存在:${f}`);let t=e.probeMajor(f);if(t===null)throw Error(`ezn.nodeBin 指定的 Node 无法执行:${f}`);return t<c&&console.error(`[ezn] 警告:ezn.nodeBin 的 Node 主版本为 ${t},低于建议值 ${c},按用户指定继续。`),console.error(`[ezn] Node 运行时(ezn.nodeBin):${f}`),new e(f,l)}if(m(u)){let{major:t,reason:n}=d(u);if(t!==null&&t>=c&&ki(l))return console.error(`[ezn] Node 运行时就绪:${u}`),new e(u,l);if(n===`timeout`)throw Error([`已有 Node 运行时探测超时(${oa/1e3} 秒内未返回),已中止——不重装。`,` 探测对象:${u}`,` 常见原因:安全软件(360 / 电脑管家 / Windows Defender 实时防护)拦下了它的执行,`,` 或正在扫描这个刚下载的可执行文件;重新下载通常同样会被拦,故这里不重试。`,` 可尝试的恢复方式:`,` 1. 把应用目录(托管运行时所在目录)加入安全软件信任区后重试;`,` 2. 临时关闭安全软件的主动防御/实时防护后重试;`," 3. 手工确认该文件可执行:在该目录执行 `node -v`,若同样超时则确认为拦截。"].join(`
30
- `));console.error(t===null?`[ezn] 已有 Node 运行时无法执行(疑似损坏),准备重新安装 ...`:t<c?`[ezn] 已有 Node 运行时主版本为 ${t},低于要求 ${c},准备重装 ...`:`[ezn] 已有 Node 运行时缺少自带 npm(上次落位可能中断),准备补齐 ...`)}return await ta(l,n,{mirror:r.mirror??null}),new e(u,l)}},la=`24`;function ua(e=U){let t={};return e.nodeMirror&&(t.mirror=e.nodeMirror),e.nodeBin&&(t.nodeBin=e.nodeBin),t}async function da(e){return(await ca.ensure(e,la,ua())).path}function fa(e=G()){return new bn(e).configure({daemonJs:Oe(),env:{ELLM_APP_DIR:e},logPrefix:ft,interpreter:e=>da(e)})}async function pa(){J(`正在启动 ezllm(常驻主进程 + 服务)...`,q.rocket),ke();let e=await fa().startChild(dt);return J(e.alreadyRunning?`服务进程已在运行(pid ${String(e.pid)})`:`服务进程已启动(pid ${String(e.pid)})`,e.alreadyRunning?q.running:q.success),{pid:e.pid,appDir:G()}}async function ma(){let e=await fa().isRunning();e&&st(`正在停止 ezllm(服务 + 常驻主进程)`);let t=await fa().shutdown();return e&&(t.stopped?ct():lt()),t}async function ha(){J(`正在重启服务(常驻主进程保留)...`,q.rocket);let e=await fa().restartChild(dt);return J(`服务进程已重新创建(pid ${String(e.pid)})`,q.success),{pid:e.pid,appDir:G()}}async function ga(){return await fa().status()}var $=`ezllm`;function _a(){U.port!==void 0&&J(`注意:--port 只对 start / install 生效(会写入配置文件);本命令不使用它。`,q.warn)}function va(){let e=G();if(!ya())throw Error(`尚未安装 ezllm(应用目录:${e})。\n 先执行:npx ezllm install\n 若已装在别处:用 --app-dir=<安装目录> 指定(或设置环境变量 ELLM_APP_DIR)。`);m(ge())||J(`注意:托管运行时(node/)未落位,本次命令由当前 CLI 执行;如需修复请重跑 npx ezllm install。`,q.warn)}function ya(){return W(G())&&m(i(ve(),`dist`,`cli.js`))}async function ba(){J(`端口已变更,需完整重启主进程才能生效:先停掉当前实例`,q.warn);let e=await ma();if(!e.stopped&&e.reason===`kill-failed`)throw Error(`停止 ezllm 失败(进程 ${String(e.pid)} 可能仍存活),已中止。\n 旧实例仍在运行时端口变更不会生效,请手工结束该进程后重试。`)}var xa=29770,Sa=1,Ca=65535,wa=`127.0.0.1`;function Ta(){try{let e=JSON.parse(_(se(),`utf-8`))?.port;return typeof e!=`number`||!Number.isInteger(e)||e<Sa||e>Ca?void 0:e}catch{return}}function Ea(){let e=(U.port!==void 0&&U.port>=Sa&&U.port<=Ca?U.port:void 0)??Ta()??xa,t=`http://${wa}:${String(e)}`;return{port:e,gateway:`${t}/v1/*`,webUi:`${t}/`}}function Da(){let e=Ea();Y(q.gateway,`网关端点`,e.gateway),Y(q.webui,`管理界面`,e.webUi)}function Oa(e){Y(q.folder,`应用目录`,G()),Y(q.status,`运行状态`,`服务进程已创建并纳管(pid ${String(e.serverPid)}${e.daemonPid?` · 主进程 pid ${String(e.daemonPid)}`:``})· 日志 ${G()}/logs`),Da()}function ka(e){F(``),Y(q.folder,`应用目录`,e.appDir),Y(q.status,`运行状态`,`服务进程 pid ${String(e.pid)}(由常驻主进程纳管)`),Da()}function Aa(e){if(!ya()){J(`${$} 尚未安装`,q.warn),F(``),Y(q.folder,`将安装到`,G()),F(``),F(`执行 npx ${$} install 开始安装。`);return}if(e===null)J(`${$} 未在运行(执行 ezllm start 启动)`,q.idle);else{let t=e.children.server??null;t?J(`${$} 正在运行(服务 pid ${String(t.pid)} · 主进程 pid ${String(e.daemonPid)})`,q.running):J(`${$} 的服务未在运行(主进程 pid ${String(e.daemonPid)} 在;执行 ezllm start 拉起)`,q.warn)}F(``),Y(q.folder,`应用目录`,G()),Da()}function ja(e){if(!e.stopped){if(e.reason===`kill-failed`){J(`${$} 停止失败:进程可能仍存活(pid ${String(e.pid)}),请检查后重试或手工结束。`,q.warn);return}J(`${$} 未在运行(可能已停止)。`,q.idle)}}var Ma={name:``,description:`显示当前运行状态(含服务端地址;只读,不启动服务)`};async function Na(){_a(),Aa(await ga()),F(``),F(`运行 ${$} --help 查看全部命令。`)}function Pa(){return{execPath:process.execPath,argv:[...process.argv],version:Te(),hosted:process.env.EZLLM_HOSTED===`1`,launchedByNpm:process.env.npm_node_execpath!==void 0}}function Fa(){let e=G(),t=ge();return{appDir:e,installed:W(e),source:ae()??null,packageDir:ve(e),nodeDir:he(),nodeExe:t,nodeExeExists:m(t),configPath:se(),configExists:m(se()),dataDir:K(),logsDir:ce(),pluginsDir:de()}}function Ia(e,t=Date.now()){if(e===null)return{daemonRunning:!1,daemonVersion:null,endpoint:null,entries:[]};let n=e=>e===null?null:Math.max(0,Math.round((t-e)/1e3)),r=[{name:`daemon`,pid:e.daemonPid,startedAt:e.startedAt,uptimeSec:n(e.startedAt)}];for(let t of Object.keys(e.children).sort()){let i=e.children[t];i&&r.push({name:t,pid:i.pid,startedAt:i.startedAt,uptimeSec:n(i.startedAt)})}return{daemonRunning:!0,daemonVersion:e.version,endpoint:e.endpoint,entries:r}}function La(e){try{let t=_(i(e,`package.json`),`utf-8`).replace(/^\uFEFF/,``);return JSON.parse(t)}catch{return null}}function Ra(){let e=La(ve());return{name:e?.name??null,version:e?.version??null,hasBin:e?.bin!==void 0}}function za(){let e=ce();return[`ezllm.out.log`,`ezllm.err.log`].map(t=>i(e,t)).filter(e=>m(e))}function Ba(){let e=process.argv[1];return e===void 0?``:r(e)}function Va(e,t=Date.now()){return{cli:Pa(),app:Fa(),process:Ia(e,t),address:Ea(),scriptDir:Ba(),hostedPackage:Ra(),logFiles:za()}}function Ha(e){let{cli:t,app:n,process:r,address:i}=e;if(J(`ezllm 诊断信息`,q.status),F(``),F(`—— CLI 层 ——`),Y(q.status,`版本`,t.version),Y(q.status,`execPath`,t.execPath),e.scriptDir!==``&&Y(q.folder,`脚本目录`,e.scriptDir),Y(q.status,`宿主侧`,t.hosted?`已转发到托管 CLI(EZLLM_HOSTED=1)`:`当前进程(npx 侧)`),Y(q.status,`拉起方式`,t.launchedByNpm?`经 npm/npx 拉起`:`直接执行(非 npm 父进程)`),Y(q.status,`argv`,t.argv.join(` `)),F(``),F(`—— 应用目录 ——`),Y(q.folder,`appDir`,n.appDir),Y(q.status,`装配状态`,n.installed?`已装配(来源 ${n.source??`未知`})`:`未装配(找不到 runtime.json 标记)`),Y(q.folder,`程序包`,e.hostedPackage.version===null?`${n.packageDir}(未读到 package.json)`:`${n.packageDir}(${e.hostedPackage.name??`?`}@${e.hostedPackage.version})`),Y(q.status,`托管运行时`,`${n.nodeDir}(${n.nodeExeExists?`node 可执行在位`:`缺 node 可执行`})`),Y(q.status,`配置文件`,n.configExists?n.configPath:`${n.configPath}(尚未创建)`),Y(q.folder,`数据目录`,n.dataDir),Y(q.folder,`日志目录`,n.logsDir),Y(q.folder,`插件目录`,n.pluginsDir),F(``),F(`—— 进程 ——`),!r.daemonRunning)Y(q.idle,`主进程`,`未在运行(执行 ezllm start 启动)`);else{Y(q.running,`主进程版本`,r.daemonVersion??`未知`),r.endpoint!==null&&Y(q.status,`控制端点`,r.endpoint);for(let e of r.entries){let t=e.uptimeSec===null?``:` · 已运行 ${String(e.uptimeSec)} 秒`;Y(q.status,e.name,`pid ${String(e.pid)}${t}`)}r.entries.length===1&&Y(q.warn,`子进程`,`无(服务未在运行或未注册)`)}e.logFiles.length>0&&Y(q.folder,`主进程日志`,e.logFiles.join(` · `)),F(``),F(`—— 访问地址 ——`),Y(q.gateway,`网关端点`,i.gateway),Y(q.webui,`管理界面`,i.webUi)}var Ua={name:`info`,description:`输出诊断信息(CLI 层 execPath、应用目录、进程与子进程、访问地址)`};async function Wa(){_a(),Ha(Va(await ga()))}function Ga(){let e=U.port;if(e===void 0)return null;let t=ke(),n;try{n=JSON.parse(_(t,`utf-8`).replace(/^\uFEFF/,``))}catch{return null}if(typeof n!=`object`||!n||Array.isArray(n))return null;let r=n,i=typeof r.port==`number`?r.port:void 0;return i===e?null:(r.port=e,Ae(t,r),{from:i,to:e})}function Ka(e){let t=e.from===void 0?`未设置`:String(e.from);return`已把端口写入配置文件:${String(e.to)}(原 ${t})→ ${se()}`}var qa={name:`start`,description:`启动 ezllm(首次会拉起常驻主进程;已在运行则显示状态)`};async function Ja(){_a(),va();let e=Ga();e!==null&&(J(Ka(e),q.success),await ga()!==null&&await ba()),ka(await pa())}var Ya={name:`stop`,description:`停止 ezllm(服务与常驻主进程一起停)`};async function Xa(){_a(),va();let e=await ma();if(!e.stopped){ja(e),e.reason===`kill-failed`&&process.exit(1);return}J(`${$} 已停止。`,q.stopped)}var Za={name:`restart`,description:`重启服务(常驻主进程不动)`};async function Qa(){_a(),va(),ka(await ha())}var $a=[a(se()).base,a(pe()).base,...me,a(he()).base,a(ue()).base],eo=[a(K()).base,a(ce()).base,a(fe()).base,a(de()).base],to=[a(se()).base,a(pe()).base,...me,a(he()).base,`data`,`logs`,`bin`,`daemon.json`,`plugin-auth.json`],no=[`.git`,`pnpm-workspace.yaml`,`src`,`package.json`];function ro(e){return e.some(e=>to.includes(e))}function io(e,t=!0){return $a.includes(e)?!0:t&&eo.includes(e)}function ao(e,t){let n=s(e);if(n===a(n).root)throw Error(`拒绝清理:应用目录解析为文件系统根(${n})。这几乎肯定是 --app-dir / ELLM_APP_DIR 配置错误。`);if(n===s(C()))throw Error(`拒绝清理:应用目录是用户主目录本身(${n}),清理会删掉整个家目录。\n 请把 --app-dir 指向一个专用子目录(如 <工程>/ezllm)。`);let r=W(n),i=r?no.filter(e=>e!==`package.json`):no,o=t.filter(e=>i.includes(e));if(o.length>0)throw Error(`拒绝清理:应用目录含源码/仓库特征(${o.join(`、`)}),疑似指向代码目录而非运行时目录。\n 当前值:${n}\n 如确要重装,请把 --app-dir 指向专用目录(如 <工程>/ezllm)后重试。`);if(!r&&t.filter(e=>to.includes(e)).length===0)throw Error(`拒绝清理:应用目录不含任何 ezllm 产物(${n}),不像被 install 装配过的目录。\n 为避免误删用户数据,已中止。`)}function oo(e,t,n=!0){let r=[],a=[];for(let o of e)io(o,n)?a.push(o):r.push(i(t,o));return{remove:r,keep:a}}function so(e={}){let t=e.appDir??G(),n=e.listDir??(e=>v(e)),r=e.remove??(e=>b(e,{recursive:!0,force:!0})),i;try{i=n(t)}catch(e){if(e.code===`ENOENT`)return{removed:[],kept:[],failed:[]};throw e}ao(t,i);let{remove:a,keep:o}=oo(i,t,e.keepUserData??!0),s=[],c=[];for(let e of a)try{r(e),s.push(e)}catch(t){let n=t.code??`UNKNOWN`;c.push({path:e,code:n})}return{removed:s,kept:o,failed:c}}var co=`.backup-`;function lo(e,n=new Date,a=m){let o=`${t(s(e))}${co}${(e=>{let t=e=>String(e).padStart(2,`0`);return`${String(e.getFullYear())}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`})(n)}`,c=r(s(e)),l=i(c,o);for(let e=2;a(l);e++)l=i(c,`${o}-${String(e)}`);return l}function uo(e,t){let n=a(he()).base,r=[],o=[];for(let a of e)a===n?o.push(a):r.push(i(t,a));return{copy:r,skipped:o}}function fo(e={}){let n=e.appDir??G(),r=e.listDir??(e=>v(e)),a=e.exists??m,o=e.copy??((e,t)=>f(e,t,{recursive:!0,force:!0})),{copy:s,skipped:c}=uo(r(n),n),l=lo(n,(e.now??(()=>new Date))(),a);if(s.length===0)return{backupDir:l,copied:[],skipped:c,empty:!0};h(l,{recursive:!0});let u=[],d=[];for(let e of s){let n=t(e);try{o(e,i(l,n)),d.push(n)}catch(t){u.push({path:e,code:t.code??`UNKNOWN`})}}if(u.length>0){let e=u.map(e=>` ${e.path}(${e.code})`).join(`
31
- `);throw Error(`${String(u.length)} 项备份失败,已中止卸载(未删除任何文件):\n${e}\n 备份目录:${l}\n 文件可能被占用(先停止 ezllm 并关闭相关程序),或改为手工复制该目录后重试。`)}return{backupDir:l,copied:d,skipped:c,empty:!1}}var po=`ezllm`;function mo(e){let t=i(e,`node`,`node_modules`,po);return[{from:`dist`,to:i(t,`dist`)},{from:`package.json`,to:i(t,`package.json`)}]}var ho=[{from:`ezllm.config.example.json`,to:`ezllm.config.example.json`},{from:`hook.example.cjs`,to:`hook.example.cjs`}],go=`*
32
- `,_o=`ezllm-runtime`;function vo(){try{let e=_(i(ve(),`package.json`),`utf-8`).replace(/^\uFEFF/,``);return JSON.parse(e)}catch{return null}}function yo(e){let t=vo();return t?.name!==`ezllm`||t.version!==e?!1:m(i(ve(),`dist`,`cli.js`))}function bo(e){let t=null;try{t=JSON.parse(_(i(Ce,`package.json`),`utf-8`))}catch{t=null}if(t?.name!==`ezllm`||t.version!==e)throw Error(`无法定位当前版本的程序包(${Ce},期望 ${po}@${e})。\n 请用发布形态运行:npx ezllm install,或 npx <解压目录>/app/cli install。`);return Ce}function xo(e,t){let n=[],r=(r,a)=>{let s=i(e,r);x(s).isDirectory()&&b(a,{recursive:!0,force:!0}),f(s,a,{recursive:!0,force:!0}),n.push(o(t,a).split(c).join(`/`))};for(let n of mo(t)){let t=i(e,n.from);if(!m(t))throw Error(`发布包内容缺失(${t})——当前运行的可能是源码形态而非发布包。\n 请用发布形态运行:npx ezllm install。`);r(n.from,n.to)}for(let n of ho){if(!m(i(e,n.from))){J(`未找到 ${n.from}(跳过,不影响运行)`,q.warn);continue}r(n.from,i(t,n.to))}return n}function So(e){for(let t of ye){let n=i(e,t);if(m(n))try{b(n,{recursive:!0,force:!0}),J(`已移除旧版产物目录(${t}/)`,q.skip)}catch(e){J(`旧版产物目录暂时无法删除(${n}):${e instanceof Error?e.message:String(e)};不影响运行,下次安装会再试。`,q.warn)}}}function Co(e,t){if(ro(t))return!0;let n=[`cli.js`,`daemon.js`,`server.js`,`plugin-host.js`,`package.json`];return ye.some(t=>{try{return v(i(e,t)).some(e=>n.includes(e))}catch{return!1}})}function wo(e){if(!m(e)||W(e))return;if(s(e)===s(Ce))throw Error(`拒绝安装:应用目录与当前运行的程序包目录相同(${e})。\n 请指定一个专用目录:npx ezllm install --app-dir=<目录>`);let t=v(e);if(t.length!==0){if(t.includes(`package.json`)){let t;try{let n=_(i(e,`package.json`),`utf-8`).replace(/^\uFEFF/,``);t=JSON.parse(n)?.name}catch{t=void 0}if(t===`ezllm`)return;throw Error(`拒绝安装:目标目录含 package.json(name=${typeof t==`string`?t:`未设置`}),不像 ezllm 的应用目录(${e})。\n 为避免覆盖你的文件,已中止。可指定其它目录:npx ezllm install --app-dir=<空目录>`)}if(ye.some(e=>t.includes(e))){if(Co(e,t))return;let n=ye.filter(e=>t.includes(e));throw Error(`拒绝安装:目标目录像是构建产物目录(含 ${n.join(`/、`)}/,${e})。\n 为避免删掉你的产物,已中止。可指定其它目录:npx ezllm install --app-dir=<空目录>`)}if(!ro(t))throw Error(`拒绝安装:目标目录已存在且非空,但不像 ezllm 的应用目录(${e})。\n 为避免覆盖你的文件,已中止。可指定其它目录:npx ezllm install --app-dir=<空目录>`)}}function To(e,t,n,r){let a={kind:_o,version:t,installedAt:new Date(n).toISOString(),source:r};S(i(e,ne),`${JSON.stringify(a,null,2)}\n`,`utf-8`)}function Eo(e){let t=i(e,`.gitignore`);m(t)||S(t,go,`utf-8`)}async function Do(e={},t={}){let n=async(e,t,n)=>{let r=await e.exec([t,`--version`,`--app-dir=${n}`]),i=`${r.stdout??``}${r.stderr??``}`.trim();return{ok:r.status===0,out:i}},r=G(),a=(t.version??Te)(),o=(t.now??Date.now)(),s=process.env.ELLM_INSTALL_SOURCE===`local`?`local`:`npm`;J(`正在安装 ezllm ...`,q.rocket),e.force||wo(r),h(r,{recursive:!0}),Eo(r),To(r,a,o,s),J(`安装位置:${r}`,q.folder);let c=ua(),l=await(t.ensureNode??((e,t)=>ca.ensure(e,t,c)))(r,`24`);J(`运行环境已就绪(Node.js 24)`,q.success),U.nodeBin!==void 0&&!m(ge())&&J(`注意:已按 --node-bin 使用外部 Node,托管运行时未落位。`,q.warn);let u=!1,d=[],f=!1;if(!e.force&&yo(a))J(`程序已安装(ezllm ${a})`,q.skip),So(r);else{let e=await(t.stop??ma)();if(f=e.stopped,!e.stopped&&e.reason===`kill-failed`)throw Error(`停止 ezllm 失败(进程 ${String(e.pid)} 可能仍存活),已中止安装。\n 进程仍存活时覆盖程序产物会失败(文件被占用),请手工结束该进程后重试。`);let n=(t.selfPkgRoot??bo)(a);if(J(`正在装配程序产物(版本 ${a})…`,q.pending),d=(t.copy??xo)(n,r),!yo(a))throw Error(`装配后未在应用目录读到 ${po}@${a}:${r}\n 请重跑 npx ezllm install --force 修复。`);So(r),J(`程序已装配(ezllm ${a})`,q.success),u=!0}let p=i(ve(),`dist`,`cli.js`),g=await(t.probe??n)(l,p,r);if(!g.ok)throw Error(`安装校验失败:程序无法启动(${p})。\n 输出:${g.out||`(无输出)`}\n 可尝试:npx ezllm install --force 重新装配。`);return F(``),J(`安装完成!`,q.success),J(`安装位置:${r}(如需卸载,执行 npx ezllm uninstall)`),F(` 同时运行多个实例时,各实例用 --port=<端口> 区分(端口会写入各自的配置文件)。`),e.noStart&&(F(``),J(`接下来这样做:`),F(` 1. 输入 npx ezllm start 启动服务`),F(` 2. 打开命令行里提示的网址,按向导完成设置`)),{appDir:r,nodePath:l.path,packageVersion:a,packageInstalled:u,copied:d,stopped:f}}async function Oo(e){let{itemPath:t}=await en({entryJs:Oe(),args:[`--app-dir=${e}`],env:Pt(),appDir:e,nodePath:await da(e)});return t}async function ko(e,t,n){let r=await(e.stop??ma)();if(!r.stopped&&r.reason===`kill-failed`)throw Error(`停止 ezllm 失败(进程 ${String(r.pid)} 可能仍存活),已中止${t}。\n 进程仍存活时${n}会删一半(文件被占用),请手工结束该进程后重试。`);return r}function Ao(e,t){if(e.failed.length!==0){J(`${String(e.failed.length)} 项未能删除(可能被占用):`,q.warn);for(let t of e.failed)F(` ${t.path}(${t.code})`);F(` ${t}`)}}async function jo(e={}){let t=()=>({status:$t,disable:e=>tn({appDir:e}),enable:e=>Oo(e)}),n=G();await ko(e,`重装`,`清理`);let r=e.autostart??t(),i=r.status(n).enabled;i&&(await r.disable(n),J(`已临时取消开机自启(装完恢复)`,q.skip));let a=async()=>{if(i)try{await r.enable(n),J(`已恢复开机自启`,q.success)}catch(e){J(`恢复开机自启失败(${e instanceof Error?e.message:String(e)}),可重跑 npx ezllm install 恢复。`,q.warn)}},o;try{o=(e.purge??so)()}catch(e){throw await a(),e}o.removed.length===0&&o.kept.length===0?J(`应用目录无可清理内容(首次安装)`,q.skip):J(`已清理应用目录(保留 ${o.kept.join(`、`)})`,q.success),Ao(o,`可重开终端后重跑 npx ezllm install 清理剩余项。`);let s;try{s=await(e.install??(e=>Do(e)))({force:!0})}catch(e){await a();let t=e instanceof Error?e.message:String(e);throw Error(`重装失败:${t}\n 应用目录已清理,但程序未装配完成,请重跑 npx ezllm install 修复。`)}return await a(),s}async function Mo(e={}){let t=G();if(await ko(e,`卸载`,`删除`),!m(t))throw Error(`应用目录不存在(${t}):尚未安装,无需卸载。\n 如需安装:npx ezllm install`);ao(t,(e.listDir??(e=>v(e)))(t));let n=e.disableAutostart??(e=>tn({appDir:e})),r=(e.autostartStatus??(e=>$t(e)))(t).enabled;r&&(await n(t),J(`已注销开机自启`,q.skip)),J(`正在备份应用目录 ...`,q.rocket);let i=(e.backup??fo)();i.empty?J(`应用目录无内容可备份(继续卸载)`,q.warn):(J(`已备份 ${String(i.copied.length)} 项到:${i.backupDir}`,q.success),i.skipped.length>0&&J(`已跳过 ${i.skipped.join(`、`)}(托管运行时,可由 npx ezllm install 重新装配)`,q.skip));let a=(e.purge??(()=>so({keepUserData:!1})))();return J(`已删除应用目录内容:${t}`,q.success),Ao(a,`可重开终端后再删,或手工删除上述路径。`),F(``),J(`卸载完成!`,q.success),i.empty||(J(`备份保留在:${i.backupDir}`),J(` 如需恢复,把备份内容复制回原目录后重跑 npx ezllm install;确认无需保留时可手工删除该备份目录。`)),{appDir:t,backupDir:i.backupDir,backedUp:i.copied,backupSkipped:i.skipped,backupEmpty:i.empty,removed:a.removed.length,failed:a.failed,autostartRemoved:r}}var No={name:`install`,description:`安装/修复运行环境(托管 Node + 程序产物),装完注册开机自启并自动启动`,options:[{flag:`--force`,description:`重装:先清空应用目录(保留配置、用户数据与 hook),再重新装配`},{flag:`--no-autostart`,description:`不注册开机自启(缺省**注册**——装完即随登录自启;用到时见 install.ts)`}]};async function Po(e){e.force?await jo():await Do({});let t=Ga();t!==null&&J(Ka(t),q.success),e.autostart!==!1&&J(`已注册开机自启:${await Oo(G())}`,q.success);let n=await ga(),r=n?.children.server??null;if(n!==null&&t===null&&r){J(`安装过程未重启它(如需重启:npx ${$} restart)`,q.skip),F(``),Oa({serverPid:r.pid,daemonPid:n.daemonPid});return}n!==null&&t!==null&&await ba(),ka(await pa())}var Fo=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;function Io(e){return Fo.test(e)}function Lo(e,t){let n=e=>String(e||``).split(`-`)[0].split(`.`).map(e=>Number(e)||0),r=n(e),i=n(t);for(let e=0;e<3;e++)if((r[e]??0)!==(i[e]??0))return(r[e]??0)>(i[e]??0);return!1}async function Ro(e,t){let n=await e.npm([`view`,po,`version`,`--registry`,t]);if(n.status!==0)throw Error(`查询最新版本失败(npm view 退出码 ${String(n.status)},源 ${t})。请检查网络与 registry 可达性。`);let r=`${n.stdout??``}`.split(`
33
- `).map(e=>e.trim()).filter(e=>e!==``),i=r[r.length-1]??``;if(!Io(i))throw Error(`查询到的最新版本串不合法(${i||`空`}),拒绝用它执行安装。`);return i}async function zo(e){return Le(t=>Ro(e,t))}function Bo(){let e=vo();return e?.name===`ezllm`&&typeof e.version==`string`&&e.version!==``?e.version:Te()}var Vo=6e5;function Ho(e,t,n=Fe){return[`install`,`-g`,`--prefix`,t,`${po}@${e}`,`--registry`,n,`--ignore-scripts`]}async function Uo(e={}){let t=async(e,t,n)=>(await e.npm(Ho(t,he(),n),{stdio:`inherit`})).status,n=()=>{let e=vo();return e?.name===`ezllm`&&typeof e.version==`string`?e.version:``},r=(e.version??Bo)(),i=je().pending??null;if(i!==null&&Date.now()-i.startedAt<Vo)return J(`已有更新在进行(目标 ${i.toVersion}),本次跳过。`,q.warn),{currentVersion:r,latestVersion:i.toVersion,updated:!1};J(`正在检查更新 ...`,q.rocket);let a=await(e.ensureNode??((e,t)=>ca.ensure(e,t,ua())))(G(),`24`),o=e.fetchLatest?{value:await e.fetchLatest(a),registry:Fe}:await zo(a),s=o.value;if(Y(q.status,`当前版本`,r),Y(q.status,`最新版本`,s),!Lo(s,r))return J(`已是最新版本,无需更新。`,q.success),{currentVersion:r,latestVersion:s,updated:!1};Me({pending:{toVersion:s,startedAt:Date.now()}});try{J(`正在安装 ${po}@${s} ...`,q.rocket);let i=await(e.installVersion??t)(a,s,o.registry);if(i!==0)throw Error(`安装 ${po}@${s} 失败(npm 退出码 ${String(i)})。\n 本次失败可能已停掉服务;用 npx ezllm start 重新启动。`);let c=n();if(c!==s)throw Error(`安装命令已执行,但应用目录的实际版本(${c||`读取失败`})与目标 ${s} 不一致。\n 服务未在新版本上重启(装配失败时可能已停止,用 npx ezllm start 启动);
30
+ `));console.error(t===null?`[ezn] 已有 Node 运行时无法执行(疑似损坏),准备重新安装 ...`:t<c?`[ezn] 已有 Node 运行时主版本为 ${t},低于要求 ${c},准备重装 ...`:`[ezn] 已有 Node 运行时缺少自带 npm(上次落位可能中断),准备补齐 ...`)}return await ta(l,n,{mirror:r.mirror??null}),new e(u,l)}},la=`24`;function ua(e=U){let t={};return e.nodeMirror&&(t.mirror=e.nodeMirror),e.nodeBin&&(t.nodeBin=e.nodeBin),t}async function da(e){return(await ca.ensure(e,la,ua())).path}function fa(e=G()){return new bn(e).configure({daemonJs:Oe(),env:{ELLM_APP_DIR:e},logPrefix:ft,interpreter:e=>da(e)})}async function pa(){J(`正在启动 ezllm(常驻主进程 + 服务)...`,q.rocket),ke();let e=await fa().startChild(dt);return J(e.alreadyRunning?`服务进程已在运行(pid ${String(e.pid)})`:`服务进程已启动(pid ${String(e.pid)})`,e.alreadyRunning?q.running:q.success),{pid:e.pid,appDir:G()}}async function ma(){let e=await fa().isRunning();e&&st(`正在停止 ezllm(服务 + 常驻主进程)`);let t=await fa().shutdown();return e&&(t.stopped?ct():lt()),t}async function ha(){J(`正在重启服务(常驻主进程保留)...`,q.rocket);let e=await fa().restartChild(dt);return J(`服务进程已重新创建(pid ${String(e.pid)})`,q.success),{pid:e.pid,appDir:G()}}async function ga(){return await fa().status()}var $=`ezllm`;function _a(){U.port!==void 0&&J(`注意:--port 只对 start / install 生效(会写入配置文件);本命令不使用它。`,q.warn)}function va(){let e=G();if(!ya())throw Error(`尚未安装 ezllm(应用目录:${e})。\n 先执行:npx ezllm install\n 若已装在别处:用 --app-dir=<安装目录> 指定(或设置环境变量 ELLM_APP_DIR)。`);m(ge())||J(`注意:托管运行时(node/)未落位,本次命令由当前 CLI 执行;如需修复请重跑 npx ezllm install。`,q.warn)}function ya(){return W(G())&&m(i(ve(),`dist`,`cli.js`))}async function ba(){J(`端口已变更,需完整重启主进程才能生效:先停掉当前实例`,q.warn);let e=await ma();if(!e.stopped&&e.reason===`kill-failed`)throw Error(`停止 ezllm 失败(进程 ${String(e.pid)} 可能仍存活),已中止。\n 旧实例仍在运行时端口变更不会生效,请手工结束该进程后重试。`)}var xa=29770,Sa=1,Ca=65535,wa=`127.0.0.1`;function Ta(){try{let e=JSON.parse(_(se(),`utf-8`))?.port;return typeof e!=`number`||!Number.isInteger(e)||e<Sa||e>Ca?void 0:e}catch{return}}function Ea(){let e=(U.port!==void 0&&U.port>=Sa&&U.port<=Ca?U.port:void 0)??Ta()??xa,t=`http://${wa}:${String(e)}`;return{port:e,gateway:`${t}/v1/*`,webUi:`${t}/`}}function Da(){let e=Ea();Y(q.gateway,`网关端点`,e.gateway),Y(q.webui,`管理界面`,e.webUi)}function Oa(e){Y(q.folder,`应用目录`,G()),Y(q.status,`运行状态`,`服务进程已创建并纳管(pid ${String(e.serverPid)}${e.daemonPid?` · 主进程 pid ${String(e.daemonPid)}`:``})· 日志 ${G()}/logs`),Da()}function ka(e){F(``),Y(q.folder,`应用目录`,e.appDir),Y(q.status,`运行状态`,`服务进程 pid ${String(e.pid)}(由常驻主进程纳管)`),Da()}function Aa(e){if(!ya()){J(`${$} 尚未安装`,q.warn),F(``),Y(q.folder,`将安装到`,G()),F(``),F(`执行 npx ${$} install 开始安装。`);return}if(e===null)J(`${$} 未在运行(执行 ezllm start 启动)`,q.idle);else{let t=e.children.server??null;t?J(`${$} 正在运行(服务 pid ${String(t.pid)} · 主进程 pid ${String(e.daemonPid)})`,q.running):J(`${$} 的服务未在运行(主进程 pid ${String(e.daemonPid)} 在;执行 ezllm start 拉起)`,q.warn)}F(``),Y(q.folder,`应用目录`,G()),Da()}function ja(e){if(!e.stopped){if(e.reason===`kill-failed`){J(`${$} 停止失败:进程可能仍存活(pid ${String(e.pid)}),请检查后重试或手工结束。`,q.warn);return}J(`${$} 未在运行(可能已停止)。`,q.idle)}}var Ma={name:``,description:`显示当前运行状态(含服务端地址;只读,不启动服务)`};async function Na(){_a(),Aa(await ga()),F(``),F(`运行 ${$} --help 查看全部命令。`)}var Pa=`EZLLM_HOSTED`,Fa=`EZLLM_CALLER_VERSION`,Ia=`EZLLM_CALLER_NODE`,La=`EZLLM_CALLER_NODE_VERSION`,Ra=`EZLLM_CALLER_JS`,za=[`install`,`uninstall`,`update`],Ba=new Set([`--app-dir`,`--port`,`--node-mirror`,`--node-bin`]);function Va(e){for(let t=0;t<e.length;t+=1){let n=e[t]??``;if(Ba.has(n)){t+=1;continue}if(!n.startsWith(`-`))return n}return``}function Ha(e=process.argv.slice(2),t=process.env){if(t.EZLLM_HOSTED===`1`)return!1;let n=G();if(za.includes(Va(e)))return!1;let r=i(ve(),`dist`,`cli.js`),a=ge();if(!W(n)||!m(r)||!m(a))return!1;let o=A(a,[r,...e],{stdio:`inherit`,env:{...t,[Pa]:`1`,[Fa]:Te(),[Ia]:process.execPath,[La]:process.version,[Ra]:process.argv[1]??``,ELLM_APP_DIR:n},windowsHide:!1});return o.on(`error`,e=>{L(`[ezllm] 转发给已安装的 CLI 失败(${a} ${r}):${e.message}`),process.exit(1)}),o.on(`exit`,(e,t)=>{process.exit(e??+!!t)}),!0}function Ua(e){return process.env[e]||null}function Wa(){return{execPath:process.execPath,nodeVersion:process.version,scriptPath:process.argv[1]??``,argv:[...process.argv],version:Te(),hosted:process.env.EZLLM_HOSTED===`1`,launchedByNpm:process.env.npm_node_execpath!==void 0,callerVersion:Ua(Fa),callerNodeExe:Ua(Ia),callerNodeVersion:Ua(La),callerJs:Ua(Ra)}}function Ga(){let e=G(),t=ge();return{appDir:e,installed:W(e),source:ae()??null,packageDir:ve(e),nodeDir:he(),nodeExe:t,nodeExeExists:m(t),configPath:se(),configExists:m(se()),dataDir:K(),logsDir:ce(),pluginsDir:de()}}function Ka(e,t=Date.now()){if(e===null)return{daemonRunning:!1,daemonVersion:null,endpoint:null,entries:[]};let n=e=>e===null?null:Math.max(0,Math.round((t-e)/1e3)),r=[{name:`daemon`,pid:e.daemonPid,startedAt:e.startedAt,uptimeSec:n(e.startedAt)}];for(let t of Object.keys(e.children).sort()){let i=e.children[t];i&&r.push({name:t,pid:i.pid,startedAt:i.startedAt,uptimeSec:n(i.startedAt)})}return{daemonRunning:!0,daemonVersion:e.version,endpoint:e.endpoint,entries:r}}function qa(e){try{let t=_(i(e,`package.json`),`utf-8`).replace(/^\uFEFF/,``);return JSON.parse(t)}catch{return null}}function Ja(){let e=qa(ve());return{name:e?.name??null,version:e?.version??null,hasBin:e?.bin!==void 0}}function Ya(){let e=ce();return[`ezllm.out.log`,`ezllm.err.log`].map(t=>i(e,t)).filter(e=>m(e))}function Xa(e,t=Date.now()){return{cli:Wa(),app:Ga(),process:Ka(e,t),address:Ea(),hostedPackage:Ja(),logFiles:Ya()}}function Za(e){let{cli:t,app:n,process:r,address:i}=e;J(`ezllm 诊断信息`,q.status),F(``),F(`—— CLI 层 ——`),(t.callerJs!==null||t.callerNodeExe!==null)&&(Y(q.status,`调用侧版本`,t.callerVersion??`未知`),Y(q.status,`调用侧 node`,`${t.callerNodeVersion??`版本未知`} · ${t.callerNodeExe??`未知`}`),Y(q.folder,`调用侧 js`,t.callerJs??`未知`));let a=t.hosted?`托管侧`:`本进程`;if(Y(q.status,`${a}版本`,t.version),Y(q.status,`${a} node`,`${t.nodeVersion} · ${t.execPath}`),t.scriptPath!==``&&Y(q.folder,`${a} js`,t.scriptPath),Y(q.status,`转发状态`,t.hosted?`已转发到托管 CLI(EZLLM_HOSTED=1)`:`未转发(就地执行)`),Y(q.status,`拉起方式`,t.launchedByNpm?`经 npm/npx 拉起`:`直接执行(非 npm 父进程)`),Y(q.status,`argv`,t.argv.join(` `)),F(``),F(`—— 应用目录 ——`),Y(q.folder,`appDir`,n.appDir),Y(q.status,`装配状态`,n.installed?`已装配(来源 ${n.source??`未知`})`:`未装配(找不到 runtime.json 标记)`),Y(q.folder,`程序包`,e.hostedPackage.version===null?`${n.packageDir}(未读到 package.json)`:`${n.packageDir}(${e.hostedPackage.name??`?`}@${e.hostedPackage.version})`),Y(q.status,`托管运行时`,`${n.nodeDir}(${n.nodeExeExists?`node 可执行在位`:`缺 node 可执行`})`),Y(q.status,`配置文件`,n.configExists?n.configPath:`${n.configPath}(尚未创建)`),Y(q.folder,`数据目录`,n.dataDir),Y(q.folder,`日志目录`,n.logsDir),Y(q.folder,`插件目录`,n.pluginsDir),F(``),F(`—— 进程 ——`),!r.daemonRunning)Y(q.idle,`主进程`,`未在运行(执行 ezllm start 启动)`);else{Y(q.running,`主进程版本`,r.daemonVersion??`未知`),r.endpoint!==null&&Y(q.status,`控制端点`,r.endpoint);for(let e of r.entries){let t=e.uptimeSec===null?``:` · 已运行 ${String(e.uptimeSec)} 秒`;Y(q.status,e.name,`pid ${String(e.pid)}${t}`)}r.entries.length===1&&Y(q.warn,`子进程`,`无(服务未在运行或未注册)`)}e.logFiles.length>0&&Y(q.folder,`主进程日志`,e.logFiles.join(` · `)),F(``),F(`—— 访问地址 ——`),Y(q.gateway,`网关端点`,i.gateway),Y(q.webui,`管理界面`,i.webUi)}var Qa={name:`info`,description:`输出诊断信息(调用侧与托管侧各自的 node / js 版本与路径、应用目录、进程与子进程、访问地址)`};async function $a(){_a(),Za(Xa(await ga()))}function eo(){let e=U.port;if(e===void 0)return null;let t=ke(),n;try{n=JSON.parse(_(t,`utf-8`).replace(/^\uFEFF/,``))}catch{return null}if(typeof n!=`object`||!n||Array.isArray(n))return null;let r=n,i=typeof r.port==`number`?r.port:void 0;return i===e?null:(r.port=e,Ae(t,r),{from:i,to:e})}function to(e){let t=e.from===void 0?`未设置`:String(e.from);return`已把端口写入配置文件:${String(e.to)}(原 ${t})→ ${se()}`}var no={name:`start`,description:`启动 ezllm(首次会拉起常驻主进程;已在运行则显示状态)`};async function ro(){_a(),va();let e=eo();e!==null&&(J(to(e),q.success),await ga()!==null&&await ba()),ka(await pa())}var io={name:`stop`,description:`停止 ezllm(服务与常驻主进程一起停)`};async function ao(){_a(),va();let e=await ma();if(!e.stopped){ja(e),e.reason===`kill-failed`&&process.exit(1);return}J(`${$} 已停止。`,q.stopped)}var oo={name:`restart`,description:`重启服务(常驻主进程不动)`};async function so(){_a(),va(),ka(await ha())}var co=[a(se()).base,a(pe()).base,...me,a(he()).base,a(ue()).base],lo=[a(K()).base,a(ce()).base,a(fe()).base,a(de()).base],uo=[a(se()).base,a(pe()).base,...me,a(he()).base,`data`,`logs`,`bin`,`daemon.json`,`plugin-auth.json`],fo=[`.git`,`pnpm-workspace.yaml`,`src`,`package.json`];function po(e){return e.some(e=>uo.includes(e))}function mo(e,t=!0){return co.includes(e)?!0:t&&lo.includes(e)}function ho(e,t){let n=s(e);if(n===a(n).root)throw Error(`拒绝清理:应用目录解析为文件系统根(${n})。这几乎肯定是 --app-dir / ELLM_APP_DIR 配置错误。`);if(n===s(C()))throw Error(`拒绝清理:应用目录是用户主目录本身(${n}),清理会删掉整个家目录。\n 请把 --app-dir 指向一个专用子目录(如 <工程>/ezllm)。`);let r=W(n),i=r?fo.filter(e=>e!==`package.json`):fo,o=t.filter(e=>i.includes(e));if(o.length>0)throw Error(`拒绝清理:应用目录含源码/仓库特征(${o.join(`、`)}),疑似指向代码目录而非运行时目录。\n 当前值:${n}\n 如确要重装,请把 --app-dir 指向专用目录(如 <工程>/ezllm)后重试。`);if(!r&&t.filter(e=>uo.includes(e)).length===0)throw Error(`拒绝清理:应用目录不含任何 ezllm 产物(${n}),不像被 install 装配过的目录。\n 为避免误删用户数据,已中止。`)}function go(e,t,n=!0){let r=[],a=[];for(let o of e)mo(o,n)?a.push(o):r.push(i(t,o));return{remove:r,keep:a}}function _o(e={}){let t=e.appDir??G(),n=e.listDir??(e=>v(e)),r=e.remove??(e=>b(e,{recursive:!0,force:!0})),i;try{i=n(t)}catch(e){if(e.code===`ENOENT`)return{removed:[],kept:[],failed:[]};throw e}ho(t,i);let{remove:a,keep:o}=go(i,t,e.keepUserData??!0),s=[],c=[];for(let e of a)try{r(e),s.push(e)}catch(t){let n=t.code??`UNKNOWN`;c.push({path:e,code:n})}return{removed:s,kept:o,failed:c}}var vo=`.backup-`;function yo(e,n=new Date,a=m){let o=`${t(s(e))}${vo}${(e=>{let t=e=>String(e).padStart(2,`0`);return`${String(e.getFullYear())}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`})(n)}`,c=r(s(e)),l=i(c,o);for(let e=2;a(l);e++)l=i(c,`${o}-${String(e)}`);return l}function bo(e,t){let n=a(he()).base,r=[],o=[];for(let a of e)a===n?o.push(a):r.push(i(t,a));return{copy:r,skipped:o}}function xo(e={}){let n=e.appDir??G(),r=e.listDir??(e=>v(e)),a=e.exists??m,o=e.copy??((e,t)=>f(e,t,{recursive:!0,force:!0})),{copy:s,skipped:c}=bo(r(n),n),l=yo(n,(e.now??(()=>new Date))(),a);if(s.length===0)return{backupDir:l,copied:[],skipped:c,empty:!0};h(l,{recursive:!0});let u=[],d=[];for(let e of s){let n=t(e);try{o(e,i(l,n)),d.push(n)}catch(t){u.push({path:e,code:t.code??`UNKNOWN`})}}if(u.length>0){let e=u.map(e=>` ${e.path}(${e.code})`).join(`
31
+ `);throw Error(`${String(u.length)} 项备份失败,已中止卸载(未删除任何文件):\n${e}\n 备份目录:${l}\n 文件可能被占用(先停止 ezllm 并关闭相关程序),或改为手工复制该目录后重试。`)}return{backupDir:l,copied:d,skipped:c,empty:!1}}var So=`ezllm`;function Co(e){let t=i(e,`node`,`node_modules`,So);return[{from:`dist`,to:i(t,`dist`)},{from:`package.json`,to:i(t,`package.json`)}]}var wo=[{from:`ezllm.config.example.json`,to:`ezllm.config.example.json`},{from:`hook.example.cjs`,to:`hook.example.cjs`}],To=`*
32
+ `,Eo=`ezllm-runtime`;function Do(){try{let e=_(i(ve(),`package.json`),`utf-8`).replace(/^\uFEFF/,``);return JSON.parse(e)}catch{return null}}function Oo(e){let t=Do();return t?.name!==`ezllm`||t.version!==e?!1:m(i(ve(),`dist`,`cli.js`))}function ko(e){let t=null;try{t=JSON.parse(_(i(Ce,`package.json`),`utf-8`))}catch{t=null}if(t?.name!==`ezllm`||t.version!==e)throw Error(`无法定位当前版本的程序包(${Ce},期望 ${So}@${e})。\n 请用发布形态运行:npx ezllm install,或 npx <解压目录>/app/cli install。`);return Ce}function Ao(e,t){let n=[],r=(r,a)=>{let s=i(e,r);x(s).isDirectory()&&b(a,{recursive:!0,force:!0}),f(s,a,{recursive:!0,force:!0}),n.push(o(t,a).split(c).join(`/`))};for(let n of Co(t)){let t=i(e,n.from);if(!m(t))throw Error(`发布包内容缺失(${t})——当前运行的可能是源码形态而非发布包。\n 请用发布形态运行:npx ezllm install。`);r(n.from,n.to)}for(let n of wo){if(!m(i(e,n.from))){J(`未找到 ${n.from}(跳过,不影响运行)`,q.warn);continue}r(n.from,i(t,n.to))}return n}function jo(e){for(let t of ye){let n=i(e,t);if(m(n))try{b(n,{recursive:!0,force:!0}),J(`已移除旧版产物目录(${t}/)`,q.skip)}catch(e){J(`旧版产物目录暂时无法删除(${n}):${e instanceof Error?e.message:String(e)};不影响运行,下次安装会再试。`,q.warn)}}}function Mo(e,t){if(po(t))return!0;let n=[`cli.js`,`daemon.js`,`server.js`,`plugin-host.js`,`package.json`];return ye.some(t=>{try{return v(i(e,t)).some(e=>n.includes(e))}catch{return!1}})}function No(e){if(!m(e)||W(e))return;if(s(e)===s(Ce))throw Error(`拒绝安装:应用目录与当前运行的程序包目录相同(${e})。\n 请指定一个专用目录:npx ezllm install --app-dir=<目录>`);let t=v(e);if(t.length!==0){if(t.includes(`package.json`)){let t;try{let n=_(i(e,`package.json`),`utf-8`).replace(/^\uFEFF/,``);t=JSON.parse(n)?.name}catch{t=void 0}if(t===`ezllm`)return;throw Error(`拒绝安装:目标目录含 package.json(name=${typeof t==`string`?t:`未设置`}),不像 ezllm 的应用目录(${e})。\n 为避免覆盖你的文件,已中止。可指定其它目录:npx ezllm install --app-dir=<空目录>`)}if(ye.some(e=>t.includes(e))){if(Mo(e,t))return;let n=ye.filter(e=>t.includes(e));throw Error(`拒绝安装:目标目录像是构建产物目录(含 ${n.join(`/、`)}/,${e})。\n 为避免删掉你的产物,已中止。可指定其它目录:npx ezllm install --app-dir=<空目录>`)}if(!po(t))throw Error(`拒绝安装:目标目录已存在且非空,但不像 ezllm 的应用目录(${e})。\n 为避免覆盖你的文件,已中止。可指定其它目录:npx ezllm install --app-dir=<空目录>`)}}function Po(e,t,n,r){let a={kind:Eo,version:t,installedAt:new Date(n).toISOString(),source:r};S(i(e,ne),`${JSON.stringify(a,null,2)}\n`,`utf-8`)}function Fo(e){let t=i(e,`.gitignore`);m(t)||S(t,To,`utf-8`)}async function Io(e={},t={}){let n=async(e,t,n)=>{let r=await e.exec([t,`--version`,`--app-dir=${n}`]),i=`${r.stdout??``}${r.stderr??``}`.trim();return{ok:r.status===0,out:i}},r=G(),a=(t.version??Te)(),o=(t.now??Date.now)(),s=process.env.ELLM_INSTALL_SOURCE===`local`?`local`:`npm`;J(`正在安装 ezllm ...`,q.rocket),e.force||No(r),h(r,{recursive:!0}),Fo(r),Po(r,a,o,s),J(`安装位置:${r}`,q.folder);let c=ua(),l=await(t.ensureNode??((e,t)=>ca.ensure(e,t,c)))(r,`24`);J(`运行环境已就绪(Node.js 24)`,q.success),U.nodeBin!==void 0&&!m(ge())&&J(`注意:已按 --node-bin 使用外部 Node,托管运行时未落位。`,q.warn);let u=!1,d=[],f=!1;if(!e.force&&Oo(a))J(`程序已安装(ezllm ${a})`,q.skip),jo(r);else{let e=await(t.stop??ma)();if(f=e.stopped,!e.stopped&&e.reason===`kill-failed`)throw Error(`停止 ezllm 失败(进程 ${String(e.pid)} 可能仍存活),已中止安装。\n 进程仍存活时覆盖程序产物会失败(文件被占用),请手工结束该进程后重试。`);let n=(t.selfPkgRoot??ko)(a);if(J(`正在装配程序产物(版本 ${a})…`,q.pending),d=(t.copy??Ao)(n,r),!Oo(a))throw Error(`装配后未在应用目录读到 ${So}@${a}:${r}\n 请重跑 npx ezllm install --force 修复。`);jo(r),J(`程序已装配(ezllm ${a})`,q.success),u=!0}let p=i(ve(),`dist`,`cli.js`),g=await(t.probe??n)(l,p,r);if(!g.ok)throw Error(`安装校验失败:程序无法启动(${p})。\n 输出:${g.out||`(无输出)`}\n 可尝试:npx ezllm install --force 重新装配。`);return F(``),J(`安装完成!`,q.success),J(`安装位置:${r}(如需卸载,执行 npx ezllm uninstall)`),F(` 同时运行多个实例时,各实例用 --port=<端口> 区分(端口会写入各自的配置文件)。`),e.noStart&&(F(``),J(`接下来这样做:`),F(` 1. 输入 npx ezllm start 启动服务`),F(` 2. 打开命令行里提示的网址,按向导完成设置`)),{appDir:r,nodePath:l.path,packageVersion:a,packageInstalled:u,copied:d,stopped:f}}async function Lo(e){let{itemPath:t}=await en({entryJs:Oe(),args:[`--app-dir=${e}`],env:Pt(),appDir:e,nodePath:await da(e)});return t}async function Ro(e,t,n){let r=await(e.stop??ma)();if(!r.stopped&&r.reason===`kill-failed`)throw Error(`停止 ezllm 失败(进程 ${String(r.pid)} 可能仍存活),已中止${t}。\n 进程仍存活时${n}会删一半(文件被占用),请手工结束该进程后重试。`);return r}function zo(e,t){if(e.failed.length!==0){J(`${String(e.failed.length)} 项未能删除(可能被占用):`,q.warn);for(let t of e.failed)F(` ${t.path}(${t.code})`);F(` ${t}`)}}async function Bo(e={}){let t=()=>({status:$t,disable:e=>tn({appDir:e}),enable:e=>Lo(e)}),n=G();await Ro(e,`重装`,`清理`);let r=e.autostart??t(),i=r.status(n).enabled;i&&(await r.disable(n),J(`已临时取消开机自启(装完恢复)`,q.skip));let a=async()=>{if(i)try{await r.enable(n),J(`已恢复开机自启`,q.success)}catch(e){J(`恢复开机自启失败(${e instanceof Error?e.message:String(e)}),可重跑 npx ezllm install 恢复。`,q.warn)}},o;try{o=(e.purge??_o)()}catch(e){throw await a(),e}o.removed.length===0&&o.kept.length===0?J(`应用目录无可清理内容(首次安装)`,q.skip):J(`已清理应用目录(保留 ${o.kept.join(`、`)})`,q.success),zo(o,`可重开终端后重跑 npx ezllm install 清理剩余项。`);let s;try{s=await(e.install??(e=>Io(e)))({force:!0})}catch(e){await a();let t=e instanceof Error?e.message:String(e);throw Error(`重装失败:${t}\n 应用目录已清理,但程序未装配完成,请重跑 npx ezllm install 修复。`)}return await a(),s}async function Vo(e={}){let t=G();if(await Ro(e,`卸载`,`删除`),!m(t))throw Error(`应用目录不存在(${t}):尚未安装,无需卸载。\n 如需安装:npx ezllm install`);ho(t,(e.listDir??(e=>v(e)))(t));let n=e.disableAutostart??(e=>tn({appDir:e})),r=(e.autostartStatus??(e=>$t(e)))(t).enabled;r&&(await n(t),J(`已注销开机自启`,q.skip)),J(`正在备份应用目录 ...`,q.rocket);let i=(e.backup??xo)();i.empty?J(`应用目录无内容可备份(继续卸载)`,q.warn):(J(`已备份 ${String(i.copied.length)} 项到:${i.backupDir}`,q.success),i.skipped.length>0&&J(`已跳过 ${i.skipped.join(`、`)}(托管运行时,可由 npx ezllm install 重新装配)`,q.skip));let a=(e.purge??(()=>_o({keepUserData:!1})))();return J(`已删除应用目录内容:${t}`,q.success),zo(a,`可重开终端后再删,或手工删除上述路径。`),F(``),J(`卸载完成!`,q.success),i.empty||(J(`备份保留在:${i.backupDir}`),J(` 如需恢复,把备份内容复制回原目录后重跑 npx ezllm install;确认无需保留时可手工删除该备份目录。`)),{appDir:t,backupDir:i.backupDir,backedUp:i.copied,backupSkipped:i.skipped,backupEmpty:i.empty,removed:a.removed.length,failed:a.failed,autostartRemoved:r}}var Ho={name:`install`,description:`安装/修复运行环境(托管 Node + 程序产物),装完注册开机自启并自动启动`,options:[{flag:`--force`,description:`重装:先清空应用目录(保留配置、用户数据与 hook),再重新装配`},{flag:`--no-autostart`,description:`不注册开机自启(缺省**注册**——装完即随登录自启;用到时见 install.ts)`}]};async function Uo(e){e.force?await Bo():await Io({});let t=eo();t!==null&&J(to(t),q.success),e.autostart!==!1&&J(`已注册开机自启:${await Lo(G())}`,q.success);let n=await ga(),r=n?.children.server??null;if(n!==null&&t===null&&r){J(`安装过程未重启它(如需重启:npx ${$} restart)`,q.skip),F(``),Oa({serverPid:r.pid,daemonPid:n.daemonPid});return}n!==null&&t!==null&&await ba(),ka(await pa())}var Wo=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;function Go(e){return Wo.test(e)}function Ko(e,t){let n=e=>String(e||``).split(`-`)[0].split(`.`).map(e=>Number(e)||0),r=n(e),i=n(t);for(let e=0;e<3;e++)if((r[e]??0)!==(i[e]??0))return(r[e]??0)>(i[e]??0);return!1}async function qo(e,t){let n=await e.npm([`view`,So,`version`,`--registry`,t]);if(n.status!==0)throw Error(`查询最新版本失败(npm view 退出码 ${String(n.status)},源 ${t})。请检查网络与 registry 可达性。`);let r=`${n.stdout??``}`.split(`
33
+ `).map(e=>e.trim()).filter(e=>e!==``),i=r[r.length-1]??``;if(!Go(i))throw Error(`查询到的最新版本串不合法(${i||`空`}),拒绝用它执行安装。`);return i}async function Jo(e){return Le(t=>qo(e,t))}function Yo(){let e=Do();return e?.name===`ezllm`&&typeof e.version==`string`&&e.version!==``?e.version:Te()}var Xo=6e5;function Zo(e,t,n=Fe){return[`install`,`-g`,`--prefix`,t,`${So}@${e}`,`--registry`,n,`--ignore-scripts`]}async function Qo(e={}){let t=async(e,t,n)=>(await e.npm(Zo(t,he(),n),{stdio:`inherit`})).status,n=()=>{let e=Do();return e?.name===`ezllm`&&typeof e.version==`string`?e.version:``},r=(e.version??Yo)(),i=je().pending??null;if(i!==null&&Date.now()-i.startedAt<Xo)return J(`已有更新在进行(目标 ${i.toVersion}),本次跳过。`,q.warn),{currentVersion:r,latestVersion:i.toVersion,updated:!1};J(`正在检查更新 ...`,q.rocket);let a=await(e.ensureNode??((e,t)=>ca.ensure(e,t,ua())))(G(),`24`),o=e.fetchLatest?{value:await e.fetchLatest(a),registry:Fe}:await Jo(a),s=o.value;if(Y(q.status,`当前版本`,r),Y(q.status,`最新版本`,s),!Ko(s,r))return J(`已是最新版本,无需更新。`,q.success),{currentVersion:r,latestVersion:s,updated:!1};Me({pending:{toVersion:s,startedAt:Date.now()}});try{J(`正在安装 ${So}@${s} ...`,q.rocket);let i=await(e.installVersion??t)(a,s,o.registry);if(i!==0)throw Error(`安装 ${So}@${s} 失败(npm 退出码 ${String(i)})。\n 本次失败可能已停掉服务;用 npx ezllm start 重新启动。`);let c=n();if(c!==s)throw Error(`安装命令已执行,但应用目录的实际版本(${c||`读取失败`})与目标 ${s} 不一致。\n 服务未在新版本上重启(装配失败时可能已停止,用 npx ezllm start 启动);
34
34
  修复:npx ezllm install --force
35
- 如需回退:npx ${po}@${r} install --force`);return J(`正在重启以应用新版本 ...`,q.rocket),await(e.restartDaemon??(e=>fa().restartDaemon(e)))({expectVersion:s}),Me({pending:null,lastApply:{fromVersion:r,toVersion:s,updated:!0,appliedAt:Date.now()}}),J(`更新完成:${r} → ${s}`,q.success),{currentVersion:r,latestVersion:s,updated:!0}}catch(e){let t=e instanceof Error?e.message:String(e);throw Me({pending:null,lastApply:{fromVersion:r,toVersion:s,updated:!1,appliedAt:Date.now(),error:t}}),e}}var Wo={name:`update`,description:`检查并安装新版本(含常驻主进程与服务重启)`};async function Go(){va(),await Uo()}var Ko={name:`uninstall`,description:`卸载 ezllm(停服 → 注销自启 → 备份应用目录 → 删除它)`};async function qo(){await Mo()}function Jo(){let e=at(`ezllm`);e.option(`--app-dir <path>`,`应用目录(默认:用户目录下的 ~/.ezllm)`),e.option(`--port <n>`,`监听端口(配合 start / install:给定时写入配置文件)`),e.option(`--node-mirror <url>`,`托管 Node 下载镜像(引导期逃生口)`),e.option(`--node-bin <path>`,`直接用这个 node 可执行文件,跳过下载(引导期逃生口)`),e.command(Ma.name,Ma.description).action(()=>ut(Na)),e.command(Ua.name,Ua.description).action(()=>ut(Wa)),e.command(qa.name,qa.description).action(()=>ut(Ja)),e.command(Ya.name,Ya.description).action(()=>ut(Xa)),e.command(Za.name,Za.description).action(()=>ut(Qa));let t=e.command(No.name,No.description);for(let e of No.options)t.option(e.flag,e.description);return t.action(e=>ut(()=>Po(e))),e.command(Wo.name,Wo.description).action(()=>ut(Go)),e.command(Ko.name,Ko.description).action(()=>ut(qo)),e}var Yo=`EZLLM_HOSTED`,Xo=[`install`,`uninstall`,`update`],Zo=new Set([`--app-dir`,`--port`,`--node-mirror`,`--node-bin`]);function Qo(e){for(let t=0;t<e.length;t+=1){let n=e[t]??``;if(Zo.has(n)){t+=1;continue}if(!n.startsWith(`-`))return n}return``}function $o(e=process.argv.slice(2),t=process.env){if(t.EZLLM_HOSTED===`1`)return!1;let n=G();if(Xo.includes(Qo(e)))return!1;let r=i(ve(),`dist`,`cli.js`),a=ge();if(!W(n)||!m(r)||!m(a))return!1;let o=A(a,[r,...e],{stdio:`inherit`,env:{...t,[Yo]:`1`,ELLM_APP_DIR:n},windowsHide:!1});return o.on(`error`,e=>{L(`[ezllm] 转发给已安装的 CLI 失败(${a} ${r}):${e.message}`),process.exit(1)}),o.on(`exit`,(e,t)=>{process.exit(e??+!!t)}),!0}$o()||es();function es(){let e=Jo();e.help(),e.version(Te());try{e.parse()}catch(e){ot(`错误:${e instanceof Error?e.message:String(e)}`),L("运行 `ezllm --help` 查看可用命令与选项。"),process.exit(1)}}export{};
35
+ 如需回退:npx ${So}@${r} install --force`);return J(`正在重启以应用新版本 ...`,q.rocket),await(e.restartDaemon??(e=>fa().restartDaemon(e)))({expectVersion:s}),Me({pending:null,lastApply:{fromVersion:r,toVersion:s,updated:!0,appliedAt:Date.now()}}),J(`更新完成:${r} → ${s}`,q.success),{currentVersion:r,latestVersion:s,updated:!0}}catch(e){let t=e instanceof Error?e.message:String(e);throw Me({pending:null,lastApply:{fromVersion:r,toVersion:s,updated:!1,appliedAt:Date.now(),error:t}}),e}}var $o={name:`update`,description:`检查并安装新版本(含常驻主进程与服务重启)`};async function es(){va(),await Qo()}var ts={name:`uninstall`,description:`卸载 ezllm(停服 → 注销自启 → 备份应用目录 → 删除它)`};async function ns(){await Vo()}function rs(){let e=at(`ezllm`);e.option(`--app-dir <path>`,`应用目录(默认:用户目录下的 ~/.ezllm)`),e.option(`--port <n>`,`监听端口(配合 start / install:给定时写入配置文件)`),e.option(`--node-mirror <url>`,`托管 Node 下载镜像(引导期逃生口)`),e.option(`--node-bin <path>`,`直接用这个 node 可执行文件,跳过下载(引导期逃生口)`),e.command(Ma.name,Ma.description).action(()=>ut(Na)),e.command(Qa.name,Qa.description).action(()=>ut($a)),e.command(no.name,no.description).action(()=>ut(ro)),e.command(io.name,io.description).action(()=>ut(ao)),e.command(oo.name,oo.description).action(()=>ut(so));let t=e.command(Ho.name,Ho.description);for(let e of Ho.options)t.option(e.flag,e.description);return t.action(e=>ut(()=>Uo(e))),e.command($o.name,$o.description).action(()=>ut(es)),e.command(ts.name,ts.description).action(()=>ut(ns)),e}Ha()||is();function is(){let e=rs();e.help(),e.version(Te());try{e.parse()}catch(e){ot(`错误:${e instanceof Error?e.message:String(e)}`),L("运行 `ezllm --help` 查看可用命令与选项。"),process.exit(1)}}export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ezllm",
3
- "version": "0.0.41",
3
+ "version": "0.0.42",
4
4
  "description": "Self-hosted LLM gateway with admin web UI (single process, built-in process management)",
5
5
  "keywords": [
6
6
  "llm",