@blueharford/scrypted-spatial-awareness 0.6.11 → 0.6.13
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/main.nodejs.js +1 -1
- package/dist/main.nodejs.js.map +1 -1
- package/dist/plugin.zip +0 -0
- package/out/main.nodejs.js +50 -33
- package/out/main.nodejs.js.map +1 -1
- package/out/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/alerts/alert-manager.ts +2 -1
- package/src/core/tracking-engine.ts +54 -30
package/dist/main.nodejs.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*! For license information please see main.nodejs.js.LICENSE.txt */
|
|
2
|
-
(()=>{var e={128(e,t){"use strict";function n(e){const t=e.split("/");for(let e=0;e<t.length;e++)if("+"!==t[e]){if("#"===t[e])return e===t.length-1;if(-1!==t[e].indexOf("+")||-1!==t[e].indexOf("#"))return!1}return!0}Object.defineProperty(t,"__esModule",{value:!0}),t.validateTopic=n,t.validateTopics=function(e){if(0===e.length)return"empty_topic_list";for(let t=0;t<e.length;t++)if(!n(e[t]))return e[t];return null}},181(e){"use strict";e.exports=require("buffer")},277(e,t,n){"use strict";const{ArrayIsArray:i,ArrayPrototypeIncludes:r,ArrayPrototypeJoin:o,ArrayPrototypeMap:s,NumberIsInteger:a,NumberIsNaN:c,NumberMAX_SAFE_INTEGER:l,NumberMIN_SAFE_INTEGER:d,NumberParseInt:u,ObjectPrototypeHasOwnProperty:p,RegExpPrototypeExec:h,String:f,StringPrototypeToUpperCase:g,StringPrototypeTrim:m}=n(4134),{hideStackFrames:y,codes:{ERR_SOCKET_BAD_PORT:b,ERR_INVALID_ARG_TYPE:v,ERR_INVALID_ARG_VALUE:S,ERR_OUT_OF_RANGE:_,ERR_UNKNOWN_SIGNAL:w}}=n(6371),{normalizeEncoding:k}=n(7760),{isAsyncFunction:I,isArrayBufferView:x}=n(7760).types,C={};const E=/^[0-7]+$/;const T=y((e,t,n=d,i=l)=>{if("number"!=typeof e)throw new v(t,"number",e);if(!a(e))throw new _(t,"an integer",e);if(e<n||e>i)throw new _(t,`>= ${n} && <= ${i}`,e)}),O=y((e,t,n=-2147483648,i=2147483647)=>{if("number"!=typeof e)throw new v(t,"number",e);if(!a(e))throw new _(t,"an integer",e);if(e<n||e>i)throw new _(t,`>= ${n} && <= ${i}`,e)}),P=y((e,t,n=!1)=>{if("number"!=typeof e)throw new v(t,"number",e);if(!a(e))throw new _(t,"an integer",e);const i=n?1:0,r=4294967295;if(e<i||e>r)throw new _(t,`>= ${i} && <= ${r}`,e)});function A(e,t){if("string"!=typeof e)throw new v(t,"string",e)}const R=y((e,t,n)=>{if(!r(n,e)){const i=o(s(n,e=>"string"==typeof e?`'${e}'`:f(e)),", ");throw new S(t,e,"must be one of: "+i)}});function M(e,t){if("boolean"!=typeof e)throw new v(t,"boolean",e)}function L(e,t,n){return null!=e&&p(e,t)?e[t]:n}const N=y((e,t,n=null)=>{const r=L(n,"allowArray",!1),o=L(n,"allowFunction",!1);if(!L(n,"nullable",!1)&&null===e||!r&&i(e)||"object"!=typeof e&&(!o||"function"!=typeof e))throw new v(t,"Object",e)}),D=y((e,t)=>{if(null!=e&&"object"!=typeof e&&"function"!=typeof e)throw new v(t,"a dictionary",e)}),B=y((e,t,n=0)=>{if(!i(e))throw new v(t,"Array",e);if(e.length<n){throw new S(t,e,`must be longer than ${n}`)}});const j=y((e,t="buffer")=>{if(!x(e))throw new v(t,["Buffer","TypedArray","DataView"],e)});const $=y((e,t)=>{if(void 0!==e&&(null===e||"object"!=typeof e||!("aborted"in e)))throw new v(t,"AbortSignal",e)}),F=y((e,t)=>{if("function"!=typeof e)throw new v(t,"Function",e)}),U=y((e,t)=>{if("function"!=typeof e||I(e))throw new v(t,"Function",e)}),z=y((e,t)=>{if(void 0!==e)throw new v(t,"undefined",e)});const V=/^(?:<[^>]*>)(?:\s*;\s*[^;"\s]+(?:=(")?[^;"\s]*\1)?)*$/;function W(e,t){if("undefined"==typeof e||!h(V,e))throw new S(t,e,'must be an array or string of format "</styles.css>; rel=preload; as=style"')}e.exports={isInt32:function(e){return e===(0|e)},isUint32:function(e){return e===e>>>0},parseFileMode:function(e,t,n){if("undefined"==typeof e&&(e=n),"string"==typeof e){if(null===h(E,e))throw new S(t,e,"must be a 32-bit unsigned integer or an octal string");e=u(e,8)}return P(e,t),e},validateArray:B,validateStringArray:function(e,t){B(e,t);for(let n=0;n<e.length;n++)A(e[n],`${t}[${n}]`)},validateBooleanArray:function(e,t){B(e,t);for(let n=0;n<e.length;n++)M(e[n],`${t}[${n}]`)},validateAbortSignalArray:function(e,t){B(e,t);for(let n=0;n<e.length;n++){const i=e[n],r=`${t}[${n}]`;if(null==i)throw new v(r,"AbortSignal",i);$(i,r)}},validateBoolean:M,validateBuffer:j,validateDictionary:D,validateEncoding:function(e,t){const n=k(t),i=e.length;if("hex"===n&&i%2!=0)throw new S("encoding",t,`is invalid for data of length ${i}`)},validateFunction:F,validateInt32:O,validateInteger:T,validateNumber:function(e,t,n=void 0,i){if("number"!=typeof e)throw new v(t,"number",e);if(null!=n&&e<n||null!=i&&e>i||(null!=n||null!=i)&&c(e))throw new _(t,`${null!=n?`>= ${n}`:""}${null!=n&&null!=i?" && ":""}${null!=i?`<= ${i}`:""}`,e)},validateObject:N,validateOneOf:R,validatePlainFunction:U,validatePort:function(e,t="Port",n=!0){if("number"!=typeof e&&"string"!=typeof e||"string"==typeof e&&0===m(e).length||+e!==+e>>>0||e>65535||0===e&&!n)throw new b(t,e,n);return 0|e},validateSignalName:function(e,t="signal"){if(A(e,t),void 0===C[e]){if(void 0!==C[g(e)])throw new w(e+" (signals must use all capital letters)");throw new w(e)}},validateString:A,validateUint32:P,validateUndefined:z,validateUnion:function(e,t,n){if(!r(n,e))throw new v(t,`('${o(n,"|")}')`,e)},validateAbortSignal:$,validateLinkHeaderValue:function(e){if("string"==typeof e)return W(e,"hints"),e;if(i(e)){const t=e.length;let n="";if(0===t)return n;for(let i=0;i<t;i++){const r=e[i];W(r,"hints"),n+=r,i!==t-1&&(n+=", ")}return n}throw new S("hints",e,'must be an array or string of format "</styles.css>; rel=preload; as=style"')}}},321(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.ADDRESS_BOUNDARY=void 0,t.groupPossibilities=a,t.padGroup=c,t.simpleRegularExpression=function(e){const t=[];e.forEach((e,n)=>{0===parseInt(e,16)&&t.push(n)});const n=t.map(t=>e.map((e,n)=>{if(n===t){const t=0===n||n===s.GROUPS-1?":":"";return a([c(e),t])}return c(e)}).join(":"));return n.push(e.map(c).join(":")),a(n)},t.possibleElisions=function(e,t,n){const i=t?"":":",r=n?"":":",o=[];t||n||o.push("::");t&&n&&o.push("");(n&&!t||!n&&t)&&o.push(":");o.push(`${i}(:0{1,4}){1,${e-1}}`),o.push(`(0{1,4}:){1,${e-1}}${r}`),o.push(`(0{1,4}:){${e-1}}0{1,4}`);for(let t=1;t<e-1;t++)for(let n=1;n<e-t;n++)o.push(`(0{1,4}:){${n}}:(0{1,4}:){${e-n-t-1}}0{1,4}`);return a(o)};const s=o(n(8914));function a(e){return`(${e.join("|")})`}function c(e){return e.length<4?`0{0,${4-e.length}}${e}`:e}t.ADDRESS_BOUNDARY="[^A-Fa-f0-9:]"},345(e,t,n){"use strict";const{StringPrototypeSlice:i,SymbolIterator:r,TypedArrayPrototypeSet:o,Uint8Array:s}=n(4134),{Buffer:a}=n(181),{inspect:c}=n(7760);e.exports=class{constructor(){this.head=null,this.tail=null,this.length=0}push(e){const t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length}unshift(e){const t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length}shift(){if(0===this.length)return;const e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}clear(){this.head=this.tail=null,this.length=0}join(e){if(0===this.length)return"";let t=this.head,n=""+t.data;for(;null!==(t=t.next);)n+=e+t.data;return n}concat(e){if(0===this.length)return a.alloc(0);const t=a.allocUnsafe(e>>>0);let n=this.head,i=0;for(;n;)o(t,n.data,i),i+=n.data.length,n=n.next;return t}consume(e,t){const n=this.head.data;if(e<n.length){const t=n.slice(0,e);return this.head.data=n.slice(e),t}return e===n.length?this.shift():t?this._getString(e):this._getBuffer(e)}first(){return this.head.data}*[r](){for(let e=this.head;e;e=e.next)yield e.data}_getString(e){let t="",n=this.head,r=0;do{const o=n.data;if(!(e>o.length)){e===o.length?(t+=o,++r,n.next?this.head=n.next:this.head=this.tail=null):(t+=i(o,0,e),this.head=n,n.data=i(o,e));break}t+=o,e-=o.length,++r}while(null!==(n=n.next));return this.length-=r,t}_getBuffer(e){const t=a.allocUnsafe(e),n=e;let i=this.head,r=0;do{const a=i.data;if(!(e>a.length)){e===a.length?(o(t,a,n-e),++r,i.next?this.head=i.next:this.head=this.tail=null):(o(t,new s(a.buffer,a.byteOffset,e),n-e),this.head=i,i.data=a.slice(e));break}o(t,a,n-e),e-=a.length,++r}while(null!==(i=i.next));return this.length-=r,t}[Symbol.for("nodejs.util.inspect.custom")](e,t){return c(this,{...t,depth:0,customInspect:!1})}}},397(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_TRAINING_CONFIG=void 0,t.createTrainingSession=function(e){const t=Date.now();return{id:`training-${t}-${Math.random().toString(36).substr(2,9)}`,state:"idle",startedAt:t,updatedAt:t,trainerName:e,visits:[],transits:[],landmarks:[],overlaps:[],structures:[],stats:{totalDuration:0,camerasVisited:0,transitsRecorded:0,landmarksMarked:0,overlapsDetected:0,structuresMarked:0,averageTransitTime:0,coveragePercentage:0}}},t.calculateTrainingStats=function(e,t){const n=new Set(e.visits.map(e=>e.cameraId)),i=e.transits.map(e=>e.transitSeconds),r=i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0;return{totalDuration:(e.completedAt||Date.now())-e.startedAt,camerasVisited:n.size,transitsRecorded:e.transits.length,landmarksMarked:e.landmarks.length,overlapsDetected:e.overlaps.length,structuresMarked:e.structures.length,averageTransitTime:Math.round(r),coveragePercentage:t>0?Math.round(n.size/t*100):0}},t.DEFAULT_TRAINING_CONFIG={minDetectionConfidence:.7,maxTransitWait:120,autoDetectOverlaps:!0,autoSuggestLandmarks:!0,minOverlapDuration:2}},441(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createTrackedObject=function(e,t,n){return{globalId:e,className:t.detection.className,label:t.detection.label,sightings:[t],journey:[],firstSeen:t.timestamp,lastSeen:t.timestamp,activeOnCameras:[t.cameraId],entryCamera:n?t.cameraId:void 0,entryCameraName:n?t.cameraName:void 0,hasExited:!1,totalDwellTime:0,state:"active",visualDescriptor:t.embedding,bestThumbnailId:t.detectionId}},t.addSighting=function(e,t){e.sightings.push(t),e.lastSeen=t.timestamp,e.activeOnCameras.includes(t.cameraId)||e.activeOnCameras.push(t.cameraId);t.embedding&&!e.visualDescriptor&&(e.visualDescriptor=t.embedding);t.detectionId&&t.confidence>.8&&(e.bestThumbnailId=t.detectionId);t.detection.label&&!e.label&&(e.label=t.detection.label)},t.addJourneySegment=function(e,t){e.journey.push(t),e.activeOnCameras=e.activeOnCameras.filter(e=>e!==t.fromCameraId),e.activeOnCameras.includes(t.toCameraId)||e.activeOnCameras.push(t.toCameraId)},t.calculateDwellTime=function(e){return 0===e.sightings.length?0:e.lastSeen-e.firstSeen},t.getLastCamera=function(e){return 0===e.sightings.length?void 0:e.sightings[e.sightings.length-1].cameraId},t.getLastSighting=function(e){return 0===e.sightings.length?void 0:e.sightings[e.sightings.length-1]},t.getJourneySummary=function(e){const t=[];e.entryCamera&&t.push(e.entryCameraName||e.entryCamera);for(const n of e.journey)t.includes(n.toCameraName||n.toCameraId)||t.push(n.toCameraName||n.toCameraId);e.exitCamera&&!t.includes(e.exitCameraName||e.exitCamera)&&t.push(e.exitCameraName||e.exitCamera);return t.join(" → ")}},465(e,t){"use strict";function n(e){return e.replace(/(0+)/g,'<span class="zero">$1</span>')}function i(e){return e.replace(/^(0+)/,'<span class="zero">$1</span>')}Object.defineProperty(t,"__esModule",{value:!0}),t.spanAllZeroes=n,t.spanAll=function(e,t=0){return e.split("").map((e,i)=>`<span class="digit value-${e} position-${i+t}">${n(e)}</span>`).join("")},t.spanLeadingZeroes=function(e){return e.split(":").map(e=>i(e)).join(":")},t.simpleGroup=function(e,t=0){return e.split(":").map((e,n)=>/group-v4/.test(e)?e:`<span class="hover-group group-${n+t}">${i(e)}</span>`)}},495(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=n(1021),o=i(n(3497)),s=n(4723);t.default=(e,t)=>{e.log("_handleConnack");const{options:n}=e,i=5===n.protocolVersion?t.reasonCode:t.returnCode;if(clearTimeout(e.connackTimer),delete e.topicAliasSend,t.properties){if(t.properties.topicAliasMaximum){if(t.properties.topicAliasMaximum>65535)return void e.emit("error",new Error("topicAliasMaximum from broker is out of range"));t.properties.topicAliasMaximum>0&&(e.topicAliasSend=new o.default(t.properties.topicAliasMaximum))}t.properties.serverKeepAlive&&n.keepalive&&(n.keepalive=t.properties.serverKeepAlive),t.properties.maximumPacketSize&&(n.properties||(n.properties={}),n.properties.maximumPacketSize=t.properties.maximumPacketSize)}if(0===i)e.reconnecting=!1,e._onConnect(t);else if(i>0){const t=new s.ErrorWithReasonCode(`Connection refused: ${r.ReasonCodes[i]}`,i);e.emit("error",t),e.options.reconnectOnConnackError&&e._cleanUp(!0)}}},576(e){e.exports=class{constructor(){this.cmd=null,this.retain=!1,this.qos=0,this.dup=!1,this.length=-1,this.topic=null,this.payload=null}}},579(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=class{nextId;constructor(){this.nextId=Math.max(1,Math.floor(65535*Math.random()))}allocate(){const e=this.nextId++;return 65536===this.nextId&&(this.nextId=1),e}getLastAllocated(){return 1===this.nextId?65535:this.nextId-1}register(e){return!0}deallocate(e){}clear(){}}},597(e,t,n){"use strict";const{kForOnEventAttribute:i,kListener:r}=n(2614),o=Symbol("kCode"),s=Symbol("kData"),a=Symbol("kError"),c=Symbol("kMessage"),l=Symbol("kReason"),d=Symbol("kTarget"),u=Symbol("kType"),p=Symbol("kWasClean");class h{constructor(e){this[d]=null,this[u]=e}get target(){return this[d]}get type(){return this[u]}}Object.defineProperty(h.prototype,"target",{enumerable:!0}),Object.defineProperty(h.prototype,"type",{enumerable:!0});class f extends h{constructor(e,t={}){super(e),this[o]=void 0===t.code?0:t.code,this[l]=void 0===t.reason?"":t.reason,this[p]=void 0!==t.wasClean&&t.wasClean}get code(){return this[o]}get reason(){return this[l]}get wasClean(){return this[p]}}Object.defineProperty(f.prototype,"code",{enumerable:!0}),Object.defineProperty(f.prototype,"reason",{enumerable:!0}),Object.defineProperty(f.prototype,"wasClean",{enumerable:!0});class g extends h{constructor(e,t={}){super(e),this[a]=void 0===t.error?null:t.error,this[c]=void 0===t.message?"":t.message}get error(){return this[a]}get message(){return this[c]}}Object.defineProperty(g.prototype,"error",{enumerable:!0}),Object.defineProperty(g.prototype,"message",{enumerable:!0});class m extends h{constructor(e,t={}){super(e),this[s]=void 0===t.data?null:t.data}get data(){return this[s]}}Object.defineProperty(m.prototype,"data",{enumerable:!0});const y={addEventListener(e,t,n={}){for(const o of this.listeners(e))if(!n[i]&&o[r]===t&&!o[i])return;let o;if("message"===e)o=function(e,n){const i=new m("message",{data:n?e:e.toString()});i[d]=this,b(t,this,i)};else if("close"===e)o=function(e,n){const i=new f("close",{code:e,reason:n.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});i[d]=this,b(t,this,i)};else if("error"===e)o=function(e){const n=new g("error",{error:e,message:e.message});n[d]=this,b(t,this,n)};else{if("open"!==e)return;o=function(){const e=new h("open");e[d]=this,b(t,this,e)}}o[i]=!!n[i],o[r]=t,n.once?this.once(e,o):this.on(e,o)},removeEventListener(e,t){for(const n of this.listeners(e))if(n[r]===t&&!n[i]){this.removeListener(e,n);break}}};function b(e,t,n){"object"==typeof e&&e.handleEvent?e.handleEvent.call(e,n):e.call(t,n)}e.exports={CloseEvent:f,ErrorEvent:g,Event:h,EventTarget:y,MessageEvent:m}},720(e,t,n){const i=n(9291);e.exports.NumberAllocator=i},736(e,t,n){e.exports=function(e){function t(e){let n,r,o,s=null;function a(...e){if(!a.enabled)return;const i=a,r=Number(new Date),o=r-(n||r);i.diff=o,i.prev=n,i.curr=r,n=r,e[0]=t.coerce(e[0]),"string"!=typeof e[0]&&e.unshift("%O");let s=0;e[0]=e[0].replace(/%([a-zA-Z%])/g,(n,r)=>{if("%%"===n)return"%";s++;const o=t.formatters[r];if("function"==typeof o){const t=e[s];n=o.call(i,t),e.splice(s,1),s--}return n}),t.formatArgs.call(i,e);(i.log||t.log).apply(i,e)}return a.namespace=e,a.useColors=t.useColors(),a.color=t.selectColor(e),a.extend=i,a.destroy=t.destroy,Object.defineProperty(a,"enabled",{enumerable:!0,configurable:!1,get:()=>null!==s?s:(r!==t.namespaces&&(r=t.namespaces,o=t.enabled(e)),o),set:e=>{s=e}}),"function"==typeof t.init&&t.init(a),a}function i(e,n){const i=t(this.namespace+("undefined"==typeof n?":":n)+e);return i.log=this.log,i}function r(e,t){let n=0,i=0,r=-1,o=0;for(;n<e.length;)if(i<t.length&&(t[i]===e[n]||"*"===t[i]))"*"===t[i]?(r=i,o=n,i++):(n++,i++);else{if(-1===r)return!1;i=r+1,o++,n=o}for(;i<t.length&&"*"===t[i];)i++;return i===t.length}return t.debug=t,t.default=t,t.coerce=function(e){if(e instanceof Error)return e.stack||e.message;return e},t.disable=function(){const e=[...t.names,...t.skips.map(e=>"-"+e)].join(",");return t.enable(""),e},t.enable=function(e){t.save(e),t.namespaces=e,t.names=[],t.skips=[];const n=("string"==typeof e?e:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(const e of n)"-"===e[0]?t.skips.push(e.slice(1)):t.names.push(e)},t.enabled=function(e){for(const n of t.skips)if(r(e,n))return!1;for(const n of t.names)if(r(e,n))return!0;return!1},t.humanize=n(6585),t.destroy=function(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")},Object.keys(e).forEach(n=>{t[n]=e[n]}),t.names=[],t.skips=[],t.formatters={},t.selectColor=function(e){let n=0;for(let t=0;t<e.length;t++)n=(n<<5)-n+e.charCodeAt(t),n|=0;return t.colors[Math.abs(n)%t.colors.length]},t.enable(t.load()),t}},778(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=i(n(9278)),o=i(n(5753)),s=i(n(6968)),a=(0,o.default)("mqttjs:tcp");t.default=(e,t)=>{if(t.port=t.port||1883,t.hostname=t.hostname||t.host||"localhost",t.socksProxy)return(0,s.default)(t.hostname,t.port,t.socksProxy,{timeout:t.socksTimeout});const{port:n,path:i}=t,o=t.hostname;return a("port %d and host %s",n,o),r.default.createConnection({port:n,host:o,path:i})}},823(e,t,n){"use strict";const i=globalThis.AbortController||n(6584).AbortController,{codes:{ERR_INVALID_ARG_VALUE:r,ERR_INVALID_ARG_TYPE:o,ERR_MISSING_ARGS:s,ERR_OUT_OF_RANGE:a},AbortError:c}=n(6371),{validateAbortSignal:l,validateInteger:d,validateObject:u}=n(277),p=n(4134).Symbol("kWeak"),h=n(4134).Symbol("kResistStopPropagation"),{finished:f}=n(6238),g=n(7830),{addAbortSignalNoValidate:m}=n(4147),{isWritable:y,isNodeStream:b}=n(6115),{deprecate:v}=n(7760),{ArrayPrototypePush:S,Boolean:_,MathFloor:w,Number:k,NumberIsNaN:I,Promise:x,PromiseReject:C,PromiseResolve:E,PromisePrototypeThen:T,Symbol:O}=n(4134),P=O("kEmpty"),A=O("kEof");function R(e,t){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal");let i=1;null!=(null==t?void 0:t.concurrency)&&(i=w(t.concurrency));let r=i-1;return null!=(null==t?void 0:t.highWaterMark)&&(r=w(t.highWaterMark)),d(i,"options.concurrency",1),d(r,"options.highWaterMark",0),r+=i,async function*(){const o=n(7760).AbortSignalAny([null==t?void 0:t.signal].filter(_)),s=this,a=[],l={signal:o};let d,u,p=!1,h=0;function f(){p=!0,g()}function g(){h-=1,m()}function m(){u&&!p&&h<i&&a.length<r&&(u(),u=null)}!async function(){try{for await(let t of s){if(p)return;if(o.aborted)throw new c;try{if(t=e(t,l),t===P)continue;t=E(t)}catch(e){t=C(e)}h+=1,T(t,g,f),a.push(t),d&&(d(),d=null),!p&&(a.length>=r||h>=i)&&await new x(e=>{u=e})}a.push(A)}catch(e){const t=C(e);T(t,g,f),a.push(t)}finally{p=!0,d&&(d(),d=null)}}();try{for(;;){for(;a.length>0;){const e=await a[0];if(e===A)return;if(o.aborted)throw new c;e!==P&&(yield e),a.shift(),m()}await new x(e=>{d=e})}}finally{p=!0,u&&(u(),u=null)}}.call(this)}async function M(e,t=void 0){for await(const n of L.call(this,e,t))return!0;return!1}function L(e,t){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);return R.call(this,async function(t,n){return await e(t,n)?t:P},t)}class N extends s{constructor(){super("reduce"),this.message="Reduce of an empty stream requires an initial value"}}function D(e){if(e=k(e),I(e))return 0;if(e<0)throw new a("number",">= 0",e);return e}e.exports.streamReturningOperators={asIndexedPairs:v(function(e=void 0){return null!=e&&u(e,"options"),null!=(null==e?void 0:e.signal)&&l(e.signal,"options.signal"),async function*(){let t=0;for await(const i of this){var n;if(null!=e&&null!==(n=e.signal)&&void 0!==n&&n.aborted)throw new c({cause:e.signal.reason});yield[t++,i]}}.call(this)},"readable.asIndexedPairs will be removed in a future version."),drop:function(e,t=void 0){return null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal"),e=D(e),async function*(){var n;if(null!=t&&null!==(n=t.signal)&&void 0!==n&&n.aborted)throw new c;for await(const n of this){var i;if(null!=t&&null!==(i=t.signal)&&void 0!==i&&i.aborted)throw new c;e--<=0&&(yield n)}}.call(this)},filter:L,flatMap:function(e,t){const n=R.call(this,e,t);return async function*(){for await(const e of n)yield*e}.call(this)},map:R,take:function(e,t=void 0){return null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal"),e=D(e),async function*(){var n;if(null!=t&&null!==(n=t.signal)&&void 0!==n&&n.aborted)throw new c;for await(const n of this){var i;if(null!=t&&null!==(i=t.signal)&&void 0!==i&&i.aborted)throw new c;if(e-- >0&&(yield n),e<=0)return}}.call(this)},compose:function(e,t){if(null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal"),b(e)&&!y(e))throw new r("stream",e,"must be writable");const n=g(this,e);return null!=t&&t.signal&&m(t.signal,n),n}},e.exports.promiseReturningOperators={every:async function(e,t=void 0){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);return!await M.call(this,async(...t)=>!await e(...t),t)},forEach:async function(e,t){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);for await(const n of R.call(this,async function(t,n){return await e(t,n),P},t));},reduce:async function(e,t,n){var r;if("function"!=typeof e)throw new o("reducer",["Function","AsyncFunction"],e);null!=n&&u(n,"options"),null!=(null==n?void 0:n.signal)&&l(n.signal,"options.signal");let s=arguments.length>1;if(null!=n&&null!==(r=n.signal)&&void 0!==r&&r.aborted){const e=new c(void 0,{cause:n.signal.reason});throw this.once("error",()=>{}),await f(this.destroy(e)),e}const a=new i,d=a.signal;if(null!=n&&n.signal){const e={once:!0,[p]:this,[h]:!0};n.signal.addEventListener("abort",()=>a.abort(),e)}let g=!1;try{for await(const i of this){var m;if(g=!0,null!=n&&null!==(m=n.signal)&&void 0!==m&&m.aborted)throw new c;s?t=await e(t,i,{signal:d}):(t=i,s=!0)}if(!g&&!s)throw new N}finally{a.abort()}return t},toArray:async function(e){null!=e&&u(e,"options"),null!=(null==e?void 0:e.signal)&&l(e.signal,"options.signal");const t=[];for await(const i of this){var n;if(null!=e&&null!==(n=e.signal)&&void 0!==n&&n.aborted)throw new c(void 0,{cause:e.signal.reason});S(t,i)}return t},some:M,find:async function(e,t){for await(const n of L.call(this,e,t))return n}}},837(e,t){"use strict";function n(e){return e.toString(16).padStart(2,"0")}Object.defineProperty(t,"__esModule",{value:!0}),t.isInSubnet=function(e){if(this.subnetMask<e.subnetMask)return!1;if(this.mask(e.subnetMask)===e.mask())return!0;return!1},t.isCorrect=function(e){return function(){return this.addressMinusSuffix===this.correctForm()&&(this.subnetMask===e&&!this.parsedSubnet||this.parsedSubnet===String(this.subnetMask))}},t.numberToPaddedHex=n,t.stringToPaddedHex=function(e){return n(parseInt(e,10))},t.testBit=function(e,t){const{length:n}=e;if(t>n)return!1;const i=n-t;return"1"===e.substring(i,i+1)}},857(e){"use strict";e.exports=require("os")},914(e,t,n){"use strict";const{Duplex:i}=n(2203),{randomFillSync:r}=n(6982),o=n(2971),{EMPTY_BUFFER:s,kWebSocket:a,NOOP:c}=n(2614),{isBlob:l,isValidStatusCode:d}=n(5880),{mask:u,toBuffer:p}=n(3338),h=Symbol("kByteLength"),f=Buffer.alloc(4),g=8192;let m,y=g;class b{constructor(e,t,n){this._extensions=t||{},n&&(this._generateMask=n,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=0,this.onerror=c,this[a]=void 0}static frame(e,t){let n,i,o=!1,s=2,a=!1;t.mask&&(n=t.maskBuffer||f,t.generateMask?t.generateMask(n):(y===g&&(void 0===m&&(m=Buffer.alloc(g)),r(m,0,g),y=0),n[0]=m[y++],n[1]=m[y++],n[2]=m[y++],n[3]=m[y++]),a=0===(n[0]|n[1]|n[2]|n[3]),s=6),"string"==typeof e?i=t.mask&&!a||void 0===t[h]?(e=Buffer.from(e)).length:t[h]:(i=e.length,o=t.mask&&t.readOnly&&!a);let c=i;i>=65536?(s+=8,c=127):i>125&&(s+=2,c=126);const l=Buffer.allocUnsafe(o?i+s:s);return l[0]=t.fin?128|t.opcode:t.opcode,t.rsv1&&(l[0]|=64),l[1]=c,126===c?l.writeUInt16BE(i,2):127===c&&(l[2]=l[3]=0,l.writeUIntBE(i,4,6)),t.mask?(l[1]|=128,l[s-4]=n[0],l[s-3]=n[1],l[s-2]=n[2],l[s-1]=n[3],a?[l,e]:o?(u(e,n,l,s,i),[l]):(u(e,n,e,0,i),[l,e])):[l,e]}close(e,t,n,i){let r;if(void 0===e)r=s;else{if("number"!=typeof e||!d(e))throw new TypeError("First argument must be a valid error code number");if(void 0!==t&&t.length){const n=Buffer.byteLength(t);if(n>123)throw new RangeError("The message must not be greater than 123 bytes");r=Buffer.allocUnsafe(2+n),r.writeUInt16BE(e,0),"string"==typeof t?r.write(t,2):r.set(t,2)}else r=Buffer.allocUnsafe(2),r.writeUInt16BE(e,0)}const o={[h]:r.length,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};0!==this._state?this.enqueue([this.dispatch,r,!1,o,i]):this.sendFrame(b.frame(r,o),i)}ping(e,t,n){let i,r;if("string"==typeof e?(i=Buffer.byteLength(e),r=!1):l(e)?(i=e.size,r=!1):(i=(e=p(e)).length,r=p.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");const o={[h]:i,fin:!0,generateMask:this._generateMask,mask:t,maskBuffer:this._maskBuffer,opcode:9,readOnly:r,rsv1:!1};l(e)?0!==this._state?this.enqueue([this.getBlobData,e,!1,o,n]):this.getBlobData(e,!1,o,n):0!==this._state?this.enqueue([this.dispatch,e,!1,o,n]):this.sendFrame(b.frame(e,o),n)}pong(e,t,n){let i,r;if("string"==typeof e?(i=Buffer.byteLength(e),r=!1):l(e)?(i=e.size,r=!1):(i=(e=p(e)).length,r=p.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");const o={[h]:i,fin:!0,generateMask:this._generateMask,mask:t,maskBuffer:this._maskBuffer,opcode:10,readOnly:r,rsv1:!1};l(e)?0!==this._state?this.enqueue([this.getBlobData,e,!1,o,n]):this.getBlobData(e,!1,o,n):0!==this._state?this.enqueue([this.dispatch,e,!1,o,n]):this.sendFrame(b.frame(e,o),n)}send(e,t,n){const i=this._extensions[o.extensionName];let r,s,a=t.binary?2:1,c=t.compress;"string"==typeof e?(r=Buffer.byteLength(e),s=!1):l(e)?(r=e.size,s=!1):(r=(e=p(e)).length,s=p.readOnly),this._firstFragment?(this._firstFragment=!1,c&&i&&i.params[i._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(c=r>=i._threshold),this._compress=c):(c=!1,a=0),t.fin&&(this._firstFragment=!0);const d={[h]:r,fin:t.fin,generateMask:this._generateMask,mask:t.mask,maskBuffer:this._maskBuffer,opcode:a,readOnly:s,rsv1:c};l(e)?0!==this._state?this.enqueue([this.getBlobData,e,this._compress,d,n]):this.getBlobData(e,this._compress,d,n):0!==this._state?this.enqueue([this.dispatch,e,this._compress,d,n]):this.dispatch(e,this._compress,d,n)}getBlobData(e,t,n,i){this._bufferedBytes+=n[h],this._state=2,e.arrayBuffer().then(e=>{if(this._socket.destroyed){const e=new Error("The socket was closed while the blob was being read");return void process.nextTick(v,this,e,i)}this._bufferedBytes-=n[h];const r=p(e);t?this.dispatch(r,t,n,i):(this._state=0,this.sendFrame(b.frame(r,n),i),this.dequeue())}).catch(e=>{process.nextTick(S,this,e,i)})}dispatch(e,t,n,i){if(!t)return void this.sendFrame(b.frame(e,n),i);const r=this._extensions[o.extensionName];this._bufferedBytes+=n[h],this._state=1,r.compress(e,n.fin,(e,t)=>{if(this._socket.destroyed){return void v(this,new Error("The socket was closed while data was being compressed"),i)}this._bufferedBytes-=n[h],this._state=0,n.readOnly=!1,this.sendFrame(b.frame(t,n),i),this.dequeue()})}dequeue(){for(;0===this._state&&this._queue.length;){const e=this._queue.shift();this._bufferedBytes-=e[3][h],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][h],this._queue.push(e)}sendFrame(e,t){2===e.length?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],t),this._socket.uncork()):this._socket.write(e[0],t)}}function v(e,t,n){"function"==typeof n&&n(t);for(let n=0;n<e._queue.length;n++){const i=e._queue[n],r=i[i.length-1];"function"==typeof r&&r(t)}}function S(e,t,n){v(e,t,n),e.onerror(t)}e.exports=b},1021(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ReasonCodes=void 0;const i=n(4723);t.ReasonCodes={0:"",1:"Unacceptable protocol version",2:"Identifier rejected",3:"Server unavailable",4:"Bad username or password",5:"Not authorized",16:"No matching subscribers",17:"No subscription existed",128:"Unspecified error",129:"Malformed Packet",130:"Protocol Error",131:"Implementation specific error",132:"Unsupported Protocol Version",133:"Client Identifier not valid",134:"Bad User Name or Password",135:"Not authorized",136:"Server unavailable",137:"Server busy",138:"Banned",139:"Server shutting down",140:"Bad authentication method",141:"Keep Alive timeout",142:"Session taken over",143:"Topic Filter invalid",144:"Topic Name invalid",145:"Packet identifier in use",146:"Packet Identifier not found",147:"Receive Maximum exceeded",148:"Topic Alias invalid",149:"Packet too large",150:"Message rate too high",151:"Quota exceeded",152:"Administrative action",153:"Payload format invalid",154:"Retain not supported",155:"QoS not supported",156:"Use another server",157:"Server moved",158:"Shared Subscriptions not supported",159:"Connection rate exceeded",160:"Maximum connect time",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"};t.default=(e,n)=>{const{messageId:r}=n,o=n.cmd;let s=null;const a=e.outgoing[r]?e.outgoing[r].cb:null;let c=null;if(a){switch(e.log("_handleAck :: packet type",o),o){case"pubcomp":case"puback":{const o=n.reasonCode;o&&o>0&&16!==o?(c=new i.ErrorWithReasonCode(`Publish error: ${t.ReasonCodes[o]}`,o),e._removeOutgoingAndStoreMessage(r,()=>{a(c,n)})):e._removeOutgoingAndStoreMessage(r,a);break}case"pubrec":{s={cmd:"pubrel",qos:2,messageId:r};const o=n.reasonCode;o&&o>0&&16!==o?(c=new i.ErrorWithReasonCode(`Publish error: ${t.ReasonCodes[o]}`,o),e._removeOutgoingAndStoreMessage(r,()=>{a(c,n)})):e._sendPacket(s);break}case"suback":{delete e.outgoing[r],e.messageIdProvider.deallocate(r);const i=n.granted;for(let n=0;n<i.length;n++){const o=i[n];if(128&o){c=new Error(`Subscribe error: ${t.ReasonCodes[o]}`),c.code=o;const n=e.messageIdToTopic[r];n&&n.forEach(t=>{delete e._resubscribeTopics[t]})}}delete e.messageIdToTopic[r],e._invokeStoreProcessingQueue(),a(c,n);break}case"unsuback":delete e.outgoing[r],e.messageIdProvider.deallocate(r),e._invokeStoreProcessingQueue(),a(null,n);break;default:e.emit("error",new Error("unrecognized packet type"))}e.disconnecting&&0===Object.keys(e.outgoing).length&&e.emit("outgoingEmpty")}else e.log("_handleAck :: Server sent an ack in error. Ignoring.")}},1060(e,t,n){"use strict";const i=n(4434),r=n(5692),o=n(8611),s=n(9278),a=n(4756),{randomBytes:c,createHash:l}=n(6982),{Duplex:d,Readable:u}=n(2203),{URL:p}=n(7016),h=n(2971),f=n(6286),g=n(914),{isBlob:m}=n(5880),{BINARY_TYPES:y,EMPTY_BUFFER:b,GUID:v,kForOnEventAttribute:S,kListener:_,kStatusCode:w,kWebSocket:k,NOOP:I}=n(2614),{EventTarget:{addEventListener:x,removeEventListener:C}}=n(597),{format:E,parse:T}=n(5926),{toBuffer:O}=n(3338),P=Symbol("kAborted"),A=[8,13],R=["CONNECTING","OPEN","CLOSING","CLOSED"],M=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;class L extends i{constructor(e,t,n){super(),this._binaryType=y[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=b,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=L.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,null!==e?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,void 0===t?t=[]:Array.isArray(t)||("object"==typeof t&&null!==t?(n=t,t=[]):t=[t]),N(this,e,t,n)):(this._autoPong=n.autoPong,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){y.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,t,n){const i=new f({allowSynchronousEvents:n.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation}),r=new g(e,this._extensions,n.generateMask);this._receiver=i,this._sender=r,this._socket=e,i[k]=this,r[k]=this,e[k]=this,i.on("conclude",U),i.on("drain",z),i.on("error",V),i.on("message",H),i.on("ping",q),i.on("pong",G),r.onerror=Z,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),t.length>0&&e.unshift(t),e.on("close",Q),e.on("data",Y),e.on("end",X),e.on("error",ee),this._readyState=L.OPEN,this.emit("open")}emitClose(){if(!this._socket)return this._readyState=L.CLOSED,void this.emit("close",this._closeCode,this._closeMessage);this._extensions[h.extensionName]&&this._extensions[h.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=L.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,t){if(this.readyState!==L.CLOSED){if(this.readyState===L.CONNECTING){const e="WebSocket was closed before the connection was established";return void $(this,this._req,e)}this.readyState!==L.CLOSING?(this._readyState=L.CLOSING,this._sender.close(e,t,!this._isServer,e=>{e||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),J(this)):this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end()}}pause(){this.readyState!==L.CONNECTING&&this.readyState!==L.CLOSED&&(this._paused=!0,this._socket.pause())}ping(e,t,n){if(this.readyState===L.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");"function"==typeof e?(n=e,e=t=void 0):"function"==typeof t&&(n=t,t=void 0),"number"==typeof e&&(e=e.toString()),this.readyState===L.OPEN?(void 0===t&&(t=!this._isServer),this._sender.ping(e||b,t,n)):F(this,e,n)}pong(e,t,n){if(this.readyState===L.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");"function"==typeof e?(n=e,e=t=void 0):"function"==typeof t&&(n=t,t=void 0),"number"==typeof e&&(e=e.toString()),this.readyState===L.OPEN?(void 0===t&&(t=!this._isServer),this._sender.pong(e||b,t,n)):F(this,e,n)}resume(){this.readyState!==L.CONNECTING&&this.readyState!==L.CLOSED&&(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,t,n){if(this.readyState===L.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if("function"==typeof t&&(n=t,t={}),"number"==typeof e&&(e=e.toString()),this.readyState!==L.OPEN)return void F(this,e,n);const i={binary:"string"!=typeof e,mask:!this._isServer,compress:!0,fin:!0,...t};this._extensions[h.extensionName]||(i.compress=!1),this._sender.send(e||b,i,n)}terminate(){if(this.readyState!==L.CLOSED){if(this.readyState===L.CONNECTING){const e="WebSocket was closed before the connection was established";return void $(this,this._req,e)}this._socket&&(this._readyState=L.CLOSING,this._socket.destroy())}}}function N(e,t,n,i){const s={allowSynchronousEvents:!0,autoPong:!0,protocolVersion:A[1],maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...i,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(e._autoPong=s.autoPong,!A.includes(s.protocolVersion))throw new RangeError(`Unsupported protocol version: ${s.protocolVersion} (supported versions: ${A.join(", ")})`);let a;if(t instanceof p)a=t;else try{a=new p(t)}catch(e){throw new SyntaxError(`Invalid URL: ${t}`)}"http:"===a.protocol?a.protocol="ws:":"https:"===a.protocol&&(a.protocol="wss:"),e._url=a.href;const d="wss:"===a.protocol,u="ws+unix:"===a.protocol;let f;if("ws:"===a.protocol||d||u?u&&!a.pathname?f="The URL's pathname is empty":a.hash&&(f="The URL contains a fragment identifier"):f='The URL\'s protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"',f){const t=new SyntaxError(f);if(0===e._redirects)throw t;return void D(e,t)}const g=d?443:80,m=c(16).toString("base64"),y=d?r.request:o.request,b=new Set;let S,_;if(s.createConnection=s.createConnection||(d?j:B),s.defaultPort=s.defaultPort||g,s.port=a.port||g,s.host=a.hostname.startsWith("[")?a.hostname.slice(1,-1):a.hostname,s.headers={...s.headers,"Sec-WebSocket-Version":s.protocolVersion,"Sec-WebSocket-Key":m,Connection:"Upgrade",Upgrade:"websocket"},s.path=a.pathname+a.search,s.timeout=s.handshakeTimeout,s.perMessageDeflate&&(S=new h(!0!==s.perMessageDeflate?s.perMessageDeflate:{},!1,s.maxPayload),s.headers["Sec-WebSocket-Extensions"]=E({[h.extensionName]:S.offer()})),n.length){for(const e of n){if("string"!=typeof e||!M.test(e)||b.has(e))throw new SyntaxError("An invalid or duplicated subprotocol was specified");b.add(e)}s.headers["Sec-WebSocket-Protocol"]=n.join(",")}if(s.origin&&(s.protocolVersion<13?s.headers["Sec-WebSocket-Origin"]=s.origin:s.headers.Origin=s.origin),(a.username||a.password)&&(s.auth=`${a.username}:${a.password}`),u){const e=s.path.split(":");s.socketPath=e[0],s.path=e[1]}if(s.followRedirects){if(0===e._redirects){e._originalIpc=u,e._originalSecure=d,e._originalHostOrSocketPath=u?s.socketPath:a.host;const t=i&&i.headers;if(i={...i,headers:{}},t)for(const[e,n]of Object.entries(t))i.headers[e.toLowerCase()]=n}else if(0===e.listenerCount("redirect")){const t=u?!!e._originalIpc&&s.socketPath===e._originalHostOrSocketPath:!e._originalIpc&&a.host===e._originalHostOrSocketPath;(!t||e._originalSecure&&!d)&&(delete s.headers.authorization,delete s.headers.cookie,t||delete s.headers.host,s.auth=void 0)}s.auth&&!i.headers.authorization&&(i.headers.authorization="Basic "+Buffer.from(s.auth).toString("base64")),_=e._req=y(s),e._redirects&&e.emit("redirect",e.url,_)}else _=e._req=y(s);s.timeout&&_.on("timeout",()=>{$(e,_,"Opening handshake has timed out")}),_.on("error",t=>{null===_||_[P]||(_=e._req=null,D(e,t))}),_.on("response",r=>{const o=r.headers.location,a=r.statusCode;if(o&&s.followRedirects&&a>=300&&a<400){if(++e._redirects>s.maxRedirects)return void $(e,_,"Maximum redirects exceeded");let r;_.abort();try{r=new p(o,t)}catch(t){const n=new SyntaxError(`Invalid URL: ${o}`);return void D(e,n)}N(e,r,n,i)}else e.emit("unexpected-response",_,r)||$(e,_,`Unexpected server response: ${r.statusCode}`)}),_.on("upgrade",(t,n,i)=>{if(e.emit("upgrade",t),e.readyState!==L.CONNECTING)return;_=e._req=null;const r=t.headers.upgrade;if(void 0===r||"websocket"!==r.toLowerCase())return void $(e,n,"Invalid Upgrade header");const o=l("sha1").update(m+v).digest("base64");if(t.headers["sec-websocket-accept"]!==o)return void $(e,n,"Invalid Sec-WebSocket-Accept header");const a=t.headers["sec-websocket-protocol"];let c;if(void 0!==a?b.size?b.has(a)||(c="Server sent an invalid subprotocol"):c="Server sent a subprotocol but none was requested":b.size&&(c="Server sent no subprotocol"),c)return void $(e,n,c);a&&(e._protocol=a);const d=t.headers["sec-websocket-extensions"];if(void 0!==d){if(!S){return void $(e,n,"Server sent a Sec-WebSocket-Extensions header but no extension was requested")}let t;try{t=T(d)}catch(t){return void $(e,n,"Invalid Sec-WebSocket-Extensions header")}const i=Object.keys(t);if(1!==i.length||i[0]!==h.extensionName){return void $(e,n,"Server indicated an extension that was not requested")}try{S.accept(t[h.extensionName])}catch(t){return void $(e,n,"Invalid Sec-WebSocket-Extensions header")}e._extensions[h.extensionName]=S}e.setSocket(n,i,{allowSynchronousEvents:s.allowSynchronousEvents,generateMask:s.generateMask,maxPayload:s.maxPayload,skipUTF8Validation:s.skipUTF8Validation})}),s.finishRequest?s.finishRequest(_,e):_.end()}function D(e,t){e._readyState=L.CLOSING,e._errorEmitted=!0,e.emit("error",t),e.emitClose()}function B(e){return e.path=e.socketPath,s.connect(e)}function j(e){return e.path=void 0,e.servername||""===e.servername||(e.servername=s.isIP(e.host)?"":e.host),a.connect(e)}function $(e,t,n){e._readyState=L.CLOSING;const i=new Error(n);Error.captureStackTrace(i,$),t.setHeader?(t[P]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(D,e,i)):(t.destroy(i),t.once("error",e.emit.bind(e,"error")),t.once("close",e.emitClose.bind(e)))}function F(e,t,n){if(t){const n=m(t)?t.size:O(t).length;e._socket?e._sender._bufferedBytes+=n:e._bufferedAmount+=n}if(n){const t=new Error(`WebSocket is not open: readyState ${e.readyState} (${R[e.readyState]})`);process.nextTick(n,t)}}function U(e,t){const n=this[k];n._closeFrameReceived=!0,n._closeMessage=t,n._closeCode=e,void 0!==n._socket[k]&&(n._socket.removeListener("data",Y),process.nextTick(K,n._socket),1005===e?n.close():n.close(e,t))}function z(){const e=this[k];e.isPaused||e._socket.resume()}function V(e){const t=this[k];void 0!==t._socket[k]&&(t._socket.removeListener("data",Y),process.nextTick(K,t._socket),t.close(e[w])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e))}function W(){this[k].emitClose()}function H(e,t){this[k].emit("message",e,t)}function q(e){const t=this[k];t._autoPong&&t.pong(e,!this._isServer,I),t.emit("ping",e)}function G(e){this[k].emit("pong",e)}function K(e){e.resume()}function Z(e){const t=this[k];t.readyState!==L.CLOSED&&(t.readyState===L.OPEN&&(t._readyState=L.CLOSING,J(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e)))}function J(e){e._closeTimer=setTimeout(e._socket.destroy.bind(e._socket),3e4)}function Q(){const e=this[k];let t;this.removeListener("close",Q),this.removeListener("data",Y),this.removeListener("end",X),e._readyState=L.CLOSING,this._readableState.endEmitted||e._closeFrameReceived||e._receiver._writableState.errorEmitted||null===(t=e._socket.read())||e._receiver.write(t),e._receiver.end(),this[k]=void 0,clearTimeout(e._closeTimer),e._receiver._writableState.finished||e._receiver._writableState.errorEmitted?e.emitClose():(e._receiver.on("error",W),e._receiver.on("finish",W))}function Y(e){this[k]._receiver.write(e)||this.pause()}function X(){const e=this[k];e._readyState=L.CLOSING,e._receiver.end(),this.end()}function ee(){const e=this[k];this.removeListener("error",ee),this.on("error",I),e&&(e._readyState=L.CLOSING,this.destroy())}Object.defineProperty(L,"CONNECTING",{enumerable:!0,value:R.indexOf("CONNECTING")}),Object.defineProperty(L.prototype,"CONNECTING",{enumerable:!0,value:R.indexOf("CONNECTING")}),Object.defineProperty(L,"OPEN",{enumerable:!0,value:R.indexOf("OPEN")}),Object.defineProperty(L.prototype,"OPEN",{enumerable:!0,value:R.indexOf("OPEN")}),Object.defineProperty(L,"CLOSING",{enumerable:!0,value:R.indexOf("CLOSING")}),Object.defineProperty(L.prototype,"CLOSING",{enumerable:!0,value:R.indexOf("CLOSING")}),Object.defineProperty(L,"CLOSED",{enumerable:!0,value:R.indexOf("CLOSED")}),Object.defineProperty(L.prototype,"CLOSED",{enumerable:!0,value:R.indexOf("CLOSED")}),["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(e=>{Object.defineProperty(L.prototype,e,{enumerable:!0})}),["open","error","close","message"].forEach(e=>{Object.defineProperty(L.prototype,`on${e}`,{enumerable:!0,get(){for(const t of this.listeners(e))if(t[S])return t[_];return null},set(t){for(const t of this.listeners(e))if(t[S]){this.removeListener(e,t);break}"function"==typeof t&&this.addEventListener(e,t,{[S]:!0})}})}),L.prototype.addEventListener=x,L.prototype.removeEventListener=C,e.exports=L},1278(e,t,n){t.parser=n(3079).parser,t.generate=n(2535),t.writeToStream=n(3132)},1554(e,t){"use strict";function n(e,t){return e.cameras.find(e=>e.deviceId===t)}function i(e,t){return e.landmarks?.find(e=>e.id===t)}function r(e,t,n){return e.connections.filter(e=>e.fromCameraId===t&&e.toCameraId===n||e.bidirectional&&e.fromCameraId===n&&e.toCameraId===t)[0]}function o(e,t){const r=n(e,t);return r?.context?.visibleLandmarks?r.context.visibleLandmarks.map(t=>i(e,t)).filter(e=>void 0!==e):[]}function s(e,t){const n=t.x-e.x,i=t.y-e.y;return Math.sqrt(n*n+i*i)}Object.defineProperty(t,"__esModule",{value:!0}),t.ZONE_TYPE_COLORS=t.LANDMARK_TEMPLATES=void 0,t.createEmptyTopology=function(){return{version:"2.0",cameras:[],connections:[],landmarks:[],relationships:[],globalZones:[]}},t.findCamera=n,t.findLandmark=i,t.findConnectionsFrom=function(e,t){return e.connections.filter(e=>e.fromCameraId===t||e.bidirectional&&e.toCameraId===t)},t.findConnection=r,t.getEntryPoints=function(e){return e.cameras.filter(e=>e.isEntryPoint)},t.getExitPoints=function(e){return e.cameras.filter(e=>e.isExitPoint)},t.getLandmarksVisibleFromCamera=o,t.getCamerasWithLandmarkVisibility=function(e,t){return e.cameras.filter(e=>e.context?.visibleLandmarks?.includes(t))},t.getAdjacentLandmarks=function(e,t){const n=i(e,t);return n?.adjacentTo?n.adjacentTo.map(t=>i(e,t)).filter(e=>void 0!==e):[]},t.calculateDistance=s,t.inferRelationships=function(e,t=50){const n=[],i=[];for(const t of e.cameras)t.floorPlanPosition&&i.push({id:t.deviceId,position:t.floorPlanPosition,type:"camera"});for(const t of e.landmarks||[])i.push({id:t.id,position:t.position,type:"landmark"});for(let e=0;e<i.length;e++)for(let r=e+1;r<i.length;r++){const o=s(i[e].position,i[r].position);o<=t&&n.push({id:`auto_${i[e].id}_${i[r].id}`,type:o<=t/2?"adjacent":"near",entityA:i[e].id,entityB:i[r].id,autoInferred:!0})}return n},t.generateTopologyDescription=function(e){const t=[];e.property?.description&&t.push(`Property: ${e.property.description}`);e.property?.frontFacing&&t.push(`Front of property faces ${e.property.frontFacing}.`);if(e.landmarks?.length>0){t.push("\nLandmarks on property:");for(const n of e.landmarks||[]){let e=`- ${n.name} (${n.type})`;n.description&&(e+=`: ${n.description}`),n.isEntryPoint&&(e+=" [Entry point]"),n.isExitPoint&&(e+=" [Exit point]"),t.push(e)}}if(e.cameras.length>0){t.push("\nCamera coverage:");for(const n of e.cameras){let r=`- ${n.name}`;if(n.context?.mountLocation&&(r+=` (mounted at ${n.context.mountLocation})`),n.context?.coverageDescription&&(r+=`: ${n.context.coverageDescription}`),n.isEntryPoint&&(r+=" [Watches entry point]"),n.isExitPoint&&(r+=" [Watches exit point]"),n.context?.visibleLandmarks&&n.context.visibleLandmarks.length>0){const t=n.context.visibleLandmarks.map(t=>i(e,t)?.name).filter(Boolean);t.length>0&&(r+=` Can see: ${t.join(", ")}`)}t.push(r)}}if(e.connections.length>0){t.push("\nMovement paths:");for(const i of e.connections){const r=n(e,i.fromCameraId),o=n(e,i.toCameraId);if(r&&o){let e=`- ${r.name} → ${o.name}`;i.name&&(e+=` (${i.name})`),e+=` [${i.transitTime.min/1e3}-${i.transitTime.max/1e3}s transit]`,i.bidirectional&&(e+=" [bidirectional]"),t.push(e)}}}return t.join("\n")},t.generateMovementContext=function(e,t,s,a){const c=n(e,t),l=n(e,s),d=r(e,t,s);if(!c||!l)return`${a} moving between cameras`;const u=[];u.push(`Origin: ${c.name}`),c.context?.coverageDescription&&u.push(` Coverage: ${c.context.coverageDescription}`);u.push(`Destination: ${l.name}`),l.context?.coverageDescription&&u.push(` Coverage: ${l.context.coverageDescription}`);if(d&&(d.name&&u.push(`Path: ${d.name}`),d.pathLandmarks&&d.pathLandmarks.length>0)){const t=d.pathLandmarks.map(t=>i(e,t)?.name).filter(Boolean);t.length>0&&u.push(`Passing: ${t.join(" → ")}`)}const p=o(e,s);p.length>0&&u.push(`Near: ${p.map(e=>e.name).join(", ")}`);return u.join("\n")},t.LANDMARK_TEMPLATES=[{type:"structure",suggestions:["House","Garage","Shed","Porch","Deck","Patio","Gazebo","Pool House"]},{type:"feature",suggestions:["Mailbox","Tree","Firepit","Pool","Hot Tub","Garden","Fountain","Flagpole"]},{type:"boundary",suggestions:["Front Fence","Back Fence","Side Fence","Hedge","Wall","Property Line"]},{type:"access",suggestions:["Driveway","Front Walkway","Back Walkway","Front Door","Back Door","Side Door","Gate","Stairs"]},{type:"vehicle",suggestions:["Car Parking","Boat","RV Pad","Motorcycle Spot"]},{type:"neighbor",suggestions:["Neighbor's House","Neighbor's Driveway","Neighbor's Yard"]},{type:"zone",suggestions:["Front Yard","Back Yard","Side Yard","Courtyard"]},{type:"street",suggestions:["Street","Sidewalk","Alley","Cul-de-sac"]}],t.ZONE_TYPE_COLORS={yard:"rgba(76, 175, 80, 0.3)",driveway:"rgba(158, 158, 158, 0.3)",street:"rgba(96, 96, 96, 0.3)",patio:"rgba(255, 152, 0, 0.3)",walkway:"rgba(121, 85, 72, 0.3)",parking:"rgba(189, 189, 189, 0.3)",garden:"rgba(139, 195, 74, 0.3)",pool:"rgba(33, 150, 243, 0.3)",garage:"rgba(117, 117, 117, 0.3)",entrance:"rgba(233, 30, 99, 0.3)",custom:"rgba(156, 39, 176, 0.3)"}},1676(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)},c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.ReasonCodes=t.KeepaliveManager=t.UniqueMessageIdProvider=t.DefaultMessageIdProvider=t.Store=t.MqttClient=t.connectAsync=t.connect=t.Client=void 0;const l=c(n(9777));t.MqttClient=l.default;const d=c(n(579));t.DefaultMessageIdProvider=d.default;const u=c(n(2099));t.UniqueMessageIdProvider=u.default;const p=c(n(7969));t.Store=p.default;const h=s(n(2793));t.connect=h.default,Object.defineProperty(t,"connectAsync",{enumerable:!0,get:function(){return h.connectAsync}});const f=c(n(3175));t.KeepaliveManager=f.default,t.Client=l.default,a(n(9777),t),a(n(4723),t);var g=n(1021);Object.defineProperty(t,"ReasonCodes",{enumerable:!0,get:function(){return g.ReasonCodes}})},1711(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TRAINING_HTML=void 0,t.TRAINING_HTML='<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">\n <meta name="apple-mobile-web-app-capable" content="yes">\n <meta name="mobile-web-app-capable" content="yes">\n <title>Spatial Awareness - Training Mode</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }\n html, body { height: 100%; overflow: hidden; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n background: #121212;\n color: rgba(255,255,255,0.87);\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n }\n\n /* Header */\n .header {\n background: rgba(255,255,255,0.03);\n padding: 12px 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-bottom: 1px solid rgba(255,255,255,0.08);\n }\n .header h1 { font-size: 16px; font-weight: 500; }\n .header-status {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n }\n .status-badge {\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n text-transform: uppercase;\n }\n .status-badge.idle { background: rgba(255,255,255,0.1); color: rgba(255,255,255,0.6); }\n .status-badge.active { background: #4fc3f7; color: #000; animation: pulse 2s infinite; }\n .status-badge.paused { background: #ffb74d; color: #000; }\n .status-badge.completed { background: #81c784; color: #000; }\n @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }\n\n /* Main content area */\n .main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 12px;\n overflow-y: auto;\n gap: 12px;\n }\n\n /* Camera detection card */\n .detection-card {\n background: rgba(255,255,255,0.03);\n border-radius: 8px;\n padding: 16px;\n border: 1px solid rgba(255,255,255,0.08);\n transition: all 0.3s;\n }\n .detection-card.detecting {\n border-color: #4fc3f7;\n background: rgba(79, 195, 247, 0.1);\n }\n .detection-card.in-transit {\n border-color: #ffb74d;\n background: rgba(255, 183, 77, 0.1);\n }\n\n .detection-icon {\n width: 64px;\n height: 64px;\n border-radius: 8px;\n background: rgba(255,255,255,0.05);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 12px;\n font-size: 28px;\n }\n .detection-card.detecting .detection-icon {\n background: #4fc3f7;\n animation: detectPulse 1.5s infinite;\n }\n @keyframes detectPulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.03); }\n }\n\n .detection-title {\n font-size: 18px;\n font-weight: 500;\n text-align: center;\n margin-bottom: 4px;\n }\n .detection-subtitle {\n font-size: 13px;\n color: rgba(255,255,255,0.5);\n text-align: center;\n }\n .detection-confidence {\n margin-top: 8px;\n text-align: center;\n font-size: 12px;\n color: rgba(255,255,255,0.4);\n }\n\n /* Transit timer */\n .transit-timer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 12px;\n padding: 10px;\n background: rgba(0,0,0,0.2);\n border-radius: 6px;\n }\n .transit-timer-icon { font-size: 18px; }\n .transit-timer-text { font-size: 16px; font-weight: 500; }\n .transit-timer-from { font-size: 12px; color: rgba(255,255,255,0.5); }\n\n /* Stats grid */\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n }\n .stat-item {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 12px 8px;\n text-align: center;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .stat-value {\n font-size: 24px;\n font-weight: 500;\n color: #4fc3f7;\n }\n .stat-label {\n font-size: 10px;\n color: rgba(255,255,255,0.4);\n text-transform: uppercase;\n margin-top: 2px;\n }\n\n /* Progress bar */\n .progress-section {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 12px;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .progress-header {\n display: flex;\n justify-content: space-between;\n margin-bottom: 8px;\n font-size: 13px;\n }\n .progress-bar {\n height: 6px;\n background: rgba(255,255,255,0.1);\n border-radius: 3px;\n overflow: hidden;\n }\n .progress-fill {\n height: 100%;\n background: #4fc3f7;\n border-radius: 3px;\n transition: width 0.5s;\n }\n\n /* Suggestions */\n .suggestions-section {\n background: rgba(79, 195, 247, 0.08);\n border: 1px solid rgba(79, 195, 247, 0.2);\n border-radius: 6px;\n padding: 12px;\n }\n .suggestions-title {\n font-size: 11px;\n text-transform: uppercase;\n color: #4fc3f7;\n margin-bottom: 6px;\n font-weight: 500;\n }\n .suggestion-item {\n font-size: 13px;\n padding: 6px 0;\n border-bottom: 1px solid rgba(255,255,255,0.05);\n color: rgba(255,255,255,0.7);\n }\n .suggestion-item:last-child { border-bottom: none; }\n .suggestion-item::before {\n content: "→ ";\n color: #4fc3f7;\n }\n\n /* Action buttons */\n .action-buttons {\n display: flex;\n gap: 8px;\n padding: 8px 0;\n }\n .btn {\n flex: 1;\n padding: 14px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n }\n .btn:active { transform: scale(0.98); }\n .btn-primary { background: #4fc3f7; color: #000; }\n .btn-secondary { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.87); }\n .btn-danger { background: #ef5350; color: #fff; }\n .btn-warning { background: #ffb74d; color: #000; }\n .btn:disabled { opacity: 0.4; cursor: not-allowed; }\n\n /* Full-width button */\n .btn-full { flex: none; width: 100%; }\n\n /* Mark landmark/structure panel */\n .mark-panel {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 16px;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .mark-panel-title {\n font-size: 14px;\n font-weight: 500;\n margin-bottom: 12px;\n }\n .mark-type-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 6px;\n margin-bottom: 12px;\n }\n .mark-type-btn {\n padding: 10px 6px;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n background: transparent;\n color: rgba(255,255,255,0.7);\n font-size: 10px;\n text-align: center;\n cursor: pointer;\n transition: all 0.2s;\n }\n .mark-type-btn.selected {\n border-color: #4fc3f7;\n background: rgba(79, 195, 247, 0.15);\n color: #fff;\n }\n .mark-type-btn .icon { font-size: 18px; margin-bottom: 2px; display: block; }\n\n /* Input field */\n .input-group { margin-bottom: 12px; }\n .input-group label {\n display: block;\n font-size: 12px;\n color: rgba(255,255,255,0.5);\n margin-bottom: 4px;\n }\n .input-group input {\n width: 100%;\n padding: 12px;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n background: rgba(0,0,0,0.2);\n color: #fff;\n font-size: 14px;\n }\n .input-group input:focus {\n outline: none;\n border-color: #4fc3f7;\n }\n\n /* History list */\n .history-section {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 12px;\n max-height: 180px;\n overflow-y: auto;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .history-title {\n font-size: 13px;\n font-weight: 500;\n margin-bottom: 8px;\n display: flex;\n justify-content: space-between;\n }\n .history-item {\n padding: 8px;\n border-bottom: 1px solid rgba(255,255,255,0.05);\n font-size: 13px;\n }\n .history-item:last-child { border-bottom: none; }\n .history-item-time {\n font-size: 10px;\n color: rgba(255,255,255,0.4);\n }\n .history-item-camera { color: #4fc3f7; font-weight: 500; }\n .history-item-transit { color: #ffb74d; }\n\n /* Bottom action bar */\n .bottom-bar {\n background: rgba(255,255,255,0.03);\n padding: 12px 16px;\n padding-bottom: max(12px, env(safe-area-inset-bottom));\n border-top: 1px solid rgba(255,255,255,0.08);\n }\n\n /* Tabs */\n .tabs {\n display: flex;\n background: rgba(0,0,0,0.2);\n border-radius: 6px;\n padding: 3px;\n margin-bottom: 12px;\n }\n .tab {\n flex: 1;\n padding: 10px;\n border: none;\n background: transparent;\n color: rgba(255,255,255,0.5);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.2s;\n }\n .tab.active {\n background: rgba(255,255,255,0.08);\n color: rgba(255,255,255,0.87);\n }\n\n /* Tab content */\n .tab-content { display: none; }\n .tab-content.active { display: block; }\n\n /* Apply results modal */\n .modal-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0,0,0,0.85);\n z-index: 100;\n align-items: center;\n justify-content: center;\n padding: 16px;\n }\n .modal-overlay.active { display: flex; }\n .modal {\n background: #1e1e1e;\n border-radius: 8px;\n padding: 20px;\n max-width: 360px;\n width: 100%;\n border: 1px solid rgba(255,255,255,0.1);\n }\n .modal h2 { font-size: 18px; margin-bottom: 12px; font-weight: 500; }\n .modal-result-item {\n display: flex;\n justify-content: space-between;\n padding: 8px 0;\n border-bottom: 1px solid rgba(255,255,255,0.08);\n font-size: 13px;\n }\n .modal-result-value { color: #4fc3f7; font-weight: 500; }\n .modal-buttons { display: flex; gap: 8px; margin-top: 16px; }\n\n /* Idle state */\n .idle-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 32px 16px;\n }\n .idle-icon {\n font-size: 56px;\n margin-bottom: 16px;\n opacity: 0.7;\n }\n .idle-title {\n font-size: 20px;\n font-weight: 500;\n margin-bottom: 8px;\n }\n .idle-desc {\n font-size: 14px;\n color: rgba(255,255,255,0.5);\n max-width: 280px;\n line-height: 1.5;\n }\n .idle-instructions {\n margin-top: 24px;\n text-align: left;\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 16px;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .idle-instructions h3 {\n font-size: 12px;\n margin-bottom: 10px;\n color: #4fc3f7;\n font-weight: 500;\n }\n .idle-instructions ol {\n padding-left: 18px;\n font-size: 13px;\n line-height: 1.8;\n color: rgba(255,255,255,0.6);\n }\n </style>\n</head>\n<body>\n <div class="header">\n <h1>Training Mode</h1>\n <div class="header-status">\n <span class="status-badge" id="status-badge">Idle</span>\n </div>\n </div>\n\n \x3c!-- Idle State --\x3e\n <div class="main-content" id="idle-content">\n <div class="idle-content">\n <div class="idle-icon">🚶</div>\n <div class="idle-title">Train Your System</div>\n <div class="idle-desc">Walk around your property to teach the system about camera positions, transit times, and landmarks.</div>\n\n <div class="idle-instructions">\n <h3>How it works:</h3>\n <ol>\n <li>Tap <strong>Start Training</strong> below</li>\n <li>Walk to each camera on your property</li>\n <li>The system detects you automatically</li>\n <li>Mark landmarks as you encounter them</li>\n <li>End training when you\'re done</li>\n </ol>\n </div>\n </div>\n\n <div class="bottom-bar">\n <button class="btn btn-primary btn-full" onclick="startTraining()">\n ▶ Start Training\n </button>\n </div>\n </div>\n\n \x3c!-- Active Training State --\x3e\n <div class="main-content" id="active-content" style="display: none;">\n \x3c!-- Detection Card --\x3e\n <div class="detection-card" id="detection-card">\n <div class="detection-icon" id="detection-icon">👤</div>\n <div class="detection-title" id="detection-title">Waiting for detection...</div>\n <div class="detection-subtitle" id="detection-subtitle">Walk to any camera to begin</div>\n <div class="detection-confidence" id="detection-confidence"></div>\n\n <div class="transit-timer" id="transit-timer" style="display: none;">\n <span class="transit-timer-icon">⏱</span>\n <span class="transit-timer-text" id="transit-time">0s</span>\n <span class="transit-timer-from" id="transit-from"></span>\n </div>\n </div>\n\n \x3c!-- Tabs --\x3e\n <div class="tabs">\n <button class="tab active" onclick="switchTab(\'status\')">Status</button>\n <button class="tab" onclick="switchTab(\'mark\')">Mark</button>\n <button class="tab" onclick="switchTab(\'history\')">History</button>\n </div>\n\n \x3c!-- Status Tab --\x3e\n <div class="tab-content active" id="tab-status">\n \x3c!-- Stats --\x3e\n <div class="stats-grid">\n <div class="stat-item">\n <div class="stat-value" id="stat-cameras">0</div>\n <div class="stat-label">Cameras</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="stat-transits">0</div>\n <div class="stat-label">Transits</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="stat-landmarks">0</div>\n <div class="stat-label">Landmarks</div>\n </div>\n </div>\n\n \x3c!-- Progress --\x3e\n <div class="progress-section" style="margin-top: 15px;">\n <div class="progress-header">\n <span>Coverage</span>\n <span id="progress-percent">0%</span>\n </div>\n <div class="progress-bar">\n <div class="progress-fill" id="progress-fill" style="width: 0%"></div>\n </div>\n </div>\n\n \x3c!-- Suggestions --\x3e\n <div class="suggestions-section" style="margin-top: 15px;" id="suggestions-section">\n <div class="suggestions-title">Suggestions</div>\n <div id="suggestions-list">\n <div class="suggestion-item">Start walking to a camera</div>\n </div>\n </div>\n </div>\n\n \x3c!-- Mark Tab --\x3e\n <div class="tab-content" id="tab-mark">\n <div class="mark-panel">\n <div class="mark-panel-title">Mark a Landmark</div>\n <div class="mark-type-grid" id="landmark-type-grid">\n <button class="mark-type-btn selected" data-type="mailbox" onclick="selectLandmarkType(\'mailbox\')">\n <span class="icon">📬</span>\n Mailbox\n </button>\n <button class="mark-type-btn" data-type="garage" onclick="selectLandmarkType(\'garage\')">\n <span class="icon">🏠</span>\n Garage\n </button>\n <button class="mark-type-btn" data-type="shed" onclick="selectLandmarkType(\'shed\')">\n <span class="icon">🏚</span>\n Shed\n </button>\n <button class="mark-type-btn" data-type="tree" onclick="selectLandmarkType(\'tree\')">\n <span class="icon">🌳</span>\n Tree\n </button>\n <button class="mark-type-btn" data-type="gate" onclick="selectLandmarkType(\'gate\')">\n <span class="icon">🚪</span>\n Gate\n </button>\n <button class="mark-type-btn" data-type="driveway" onclick="selectLandmarkType(\'driveway\')">\n <span class="icon">🛣</span>\n Driveway\n </button>\n <button class="mark-type-btn" data-type="pool" onclick="selectLandmarkType(\'pool\')">\n <span class="icon">🏊</span>\n Pool\n </button>\n <button class="mark-type-btn" data-type="other" onclick="selectLandmarkType(\'other\')">\n <span class="icon">📍</span>\n Other\n </button>\n </div>\n\n <div class="input-group">\n <label>Landmark Name</label>\n <input type="text" id="landmark-name" placeholder="e.g., Front Mailbox">\n </div>\n\n <button class="btn btn-primary btn-full" onclick="markLandmark()">\n 📍 Mark Landmark Here\n </button>\n </div>\n </div>\n\n \x3c!-- History Tab --\x3e\n <div class="tab-content" id="tab-history">\n <div class="history-section">\n <div class="history-title">\n <span>Recent Activity</span>\n <span id="history-count">0 events</span>\n </div>\n <div id="history-list">\n <div class="history-item" style="color: rgba(255,255,255,0.4); text-align: center;">\n No activity yet\n </div>\n </div>\n </div>\n </div>\n\n \x3c!-- Bottom Actions --\x3e\n <div class="bottom-bar">\n <div class="action-buttons">\n <button class="btn btn-warning" id="pause-btn" onclick="togglePause()">\n ⏸ Pause\n </button>\n <button class="btn btn-danger" onclick="endTraining()">\n ⏹ End\n </button>\n </div>\n </div>\n </div>\n\n \x3c!-- Completed State --\x3e\n <div class="main-content" id="completed-content" style="display: none;">\n <div class="idle-content">\n <div class="idle-icon">✅</div>\n <div class="idle-title">Training Complete!</div>\n <div class="idle-desc">Review the results and apply them to your topology.</div>\n </div>\n\n \x3c!-- Final Stats --\x3e\n <div class="stats-grid">\n <div class="stat-item">\n <div class="stat-value" id="final-cameras">0</div>\n <div class="stat-label">Cameras</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-transits">0</div>\n <div class="stat-label">Transits</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-landmarks">0</div>\n <div class="stat-label">Landmarks</div>\n </div>\n </div>\n\n <div class="stats-grid" style="margin-top: 10px;">\n <div class="stat-item">\n <div class="stat-value" id="final-overlaps">0</div>\n <div class="stat-label">Overlaps</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-avg-transit">0s</div>\n <div class="stat-label">Avg Transit</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-coverage">0%</div>\n <div class="stat-label">Coverage</div>\n </div>\n </div>\n\n <div class="bottom-bar" style="margin-top: auto;">\n <div class="action-buttons">\n <button class="btn btn-secondary" onclick="resetTraining()">\n ↻ Start Over\n </button>\n <button class="btn btn-primary" onclick="applyTraining()">\n ✓ Apply Results\n </button>\n </div>\n </div>\n </div>\n\n \x3c!-- Apply Results Modal --\x3e\n <div class="modal-overlay" id="results-modal">\n <div class="modal">\n <h2>Training Applied!</h2>\n <div id="results-content">\n <div class="modal-result-item">\n <span>Connections Created</span>\n <span class="modal-result-value" id="result-connections">0</span>\n </div>\n <div class="modal-result-item">\n <span>Connections Updated</span>\n <span class="modal-result-value" id="result-updated">0</span>\n </div>\n <div class="modal-result-item">\n <span>Landmarks Added</span>\n <span class="modal-result-value" id="result-landmarks">0</span>\n </div>\n <div class="modal-result-item">\n <span>Zones Created</span>\n <span class="modal-result-value" id="result-zones">0</span>\n </div>\n </div>\n <div class="modal-buttons">\n <button class="btn btn-secondary" style="flex: 1;" onclick="closeResultsModal()">Close</button>\n <button class="btn btn-primary" style="flex: 1;" onclick="openEditor()">Open Editor</button>\n </div>\n </div>\n </div>\n\n <script>\n let trainingState = \'idle\'; // idle, active, paused, completed\n let session = null;\n let pollInterval = null;\n let transitInterval = null;\n let selectedLandmarkType = \'mailbox\';\n let historyItems = [];\n\n // Initialize\n async function init() {\n // Check if there\'s an existing session\n const status = await fetchTrainingStatus();\n if (status && (status.state === \'active\' || status.state === \'paused\')) {\n session = status;\n trainingState = status.state;\n updateUI();\n startPolling();\n }\n }\n\n // API calls\n async function fetchTrainingStatus() {\n try {\n const response = await fetch(\'../api/training/status\');\n if (response.ok) {\n return await response.json();\n }\n } catch (e) { console.error(\'Failed to fetch status:\', e); }\n return null;\n }\n\n async function startTraining() {\n try {\n const response = await fetch(\'../api/training/start\', { method: \'POST\' });\n if (response.ok) {\n session = await response.json();\n trainingState = \'active\';\n updateUI();\n startPolling();\n addHistoryItem(\'Training started\', \'start\');\n }\n } catch (e) {\n console.error(\'Failed to start training:\', e);\n alert(\'Failed to start training. Please try again.\');\n }\n }\n\n async function togglePause() {\n const endpoint = trainingState === \'active\' ? \'pause\' : \'resume\';\n try {\n const response = await fetch(\'../api/training/\' + endpoint, { method: \'POST\' });\n if (response.ok) {\n trainingState = trainingState === \'active\' ? \'paused\' : \'active\';\n updateUI();\n addHistoryItem(\'Training \' + (trainingState === \'paused\' ? \'paused\' : \'resumed\'), \'control\');\n }\n } catch (e) { console.error(\'Failed to toggle pause:\', e); }\n }\n\n async function endTraining() {\n if (!confirm(\'End training session?\')) return;\n try {\n const response = await fetch(\'../api/training/end\', { method: \'POST\' });\n if (response.ok) {\n session = await response.json();\n trainingState = \'completed\';\n stopPolling();\n updateUI();\n }\n } catch (e) { console.error(\'Failed to end training:\', e); }\n }\n\n async function applyTraining() {\n try {\n const response = await fetch(\'../api/training/apply\', { method: \'POST\' });\n if (response.ok) {\n const result = await response.json();\n document.getElementById(\'result-connections\').textContent = result.connectionsCreated;\n document.getElementById(\'result-updated\').textContent = result.connectionsUpdated;\n document.getElementById(\'result-landmarks\').textContent = result.landmarksAdded;\n document.getElementById(\'result-zones\').textContent = result.zonesCreated;\n document.getElementById(\'results-modal\').classList.add(\'active\');\n }\n } catch (e) {\n console.error(\'Failed to apply training:\', e);\n alert(\'Failed to apply training results.\');\n }\n }\n\n function closeResultsModal() {\n document.getElementById(\'results-modal\').classList.remove(\'active\');\n }\n\n function openEditor() {\n window.location.href = \'../ui/editor\';\n }\n\n function resetTraining() {\n trainingState = \'idle\';\n session = null;\n historyItems = [];\n updateUI();\n }\n\n async function markLandmark() {\n const name = document.getElementById(\'landmark-name\').value.trim();\n if (!name) {\n alert(\'Please enter a landmark name\');\n return;\n }\n\n const currentCameraId = session?.currentCamera?.id;\n const visibleFromCameras = currentCameraId ? [currentCameraId] : [];\n\n try {\n const response = await fetch(\'../api/training/landmark\', {\n method: \'POST\',\n headers: { \'Content-Type\': \'application/json\' },\n body: JSON.stringify({\n name,\n type: selectedLandmarkType,\n visibleFromCameras,\n position: { x: 50, y: 50 }, // Will be refined when applied\n })\n });\n if (response.ok) {\n document.getElementById(\'landmark-name\').value = \'\';\n addHistoryItem(\'Marked: \' + name + \' (\' + selectedLandmarkType + \')\', \'landmark\');\n // Refresh status\n const status = await fetchTrainingStatus();\n if (status) {\n session = status;\n updateStatsUI();\n }\n }\n } catch (e) { console.error(\'Failed to mark landmark:\', e); }\n }\n\n function selectLandmarkType(type) {\n selectedLandmarkType = type;\n document.querySelectorAll(\'.mark-type-btn\').forEach(btn => {\n btn.classList.toggle(\'selected\', btn.dataset.type === type);\n });\n }\n\n // Polling\n function startPolling() {\n if (pollInterval) clearInterval(pollInterval);\n pollInterval = setInterval(async () => {\n const status = await fetchTrainingStatus();\n if (status) {\n session = status;\n updateDetectionUI();\n updateStatsUI();\n updateSuggestionsUI();\n }\n }, 1000);\n }\n\n function stopPolling() {\n if (pollInterval) {\n clearInterval(pollInterval);\n pollInterval = null;\n }\n if (transitInterval) {\n clearInterval(transitInterval);\n transitInterval = null;\n }\n }\n\n // UI Updates\n function updateUI() {\n // Show/hide content sections\n document.getElementById(\'idle-content\').style.display = trainingState === \'idle\' ? \'flex\' : \'none\';\n document.getElementById(\'active-content\').style.display = (trainingState === \'active\' || trainingState === \'paused\') ? \'flex\' : \'none\';\n document.getElementById(\'completed-content\').style.display = trainingState === \'completed\' ? \'flex\' : \'none\';\n\n // Update status badge\n const badge = document.getElementById(\'status-badge\');\n badge.textContent = trainingState.charAt(0).toUpperCase() + trainingState.slice(1);\n badge.className = \'status-badge \' + trainingState;\n\n // Update pause button\n const pauseBtn = document.getElementById(\'pause-btn\');\n if (pauseBtn) {\n pauseBtn.innerHTML = trainingState === \'paused\' ? \'▶ Resume\' : \'⏸ Pause\';\n }\n\n // Update completed stats\n if (trainingState === \'completed\' && session) {\n document.getElementById(\'final-cameras\').textContent = session.stats?.camerasVisited || 0;\n document.getElementById(\'final-transits\').textContent = session.stats?.transitsRecorded || 0;\n document.getElementById(\'final-landmarks\').textContent = session.stats?.landmarksMarked || 0;\n document.getElementById(\'final-overlaps\').textContent = session.stats?.overlapsDetected || 0;\n document.getElementById(\'final-avg-transit\').textContent = (session.stats?.averageTransitTime || 0) + \'s\';\n document.getElementById(\'final-coverage\').textContent = (session.stats?.coveragePercentage || 0) + \'%\';\n }\n }\n\n function updateDetectionUI() {\n if (!session) return;\n\n const card = document.getElementById(\'detection-card\');\n const icon = document.getElementById(\'detection-icon\');\n const title = document.getElementById(\'detection-title\');\n const subtitle = document.getElementById(\'detection-subtitle\');\n const confidence = document.getElementById(\'detection-confidence\');\n const transitTimer = document.getElementById(\'transit-timer\');\n\n if (session.currentCamera) {\n // Detected on a camera\n card.className = \'detection-card detecting\';\n icon.textContent = \'📷\';\n title.textContent = session.currentCamera.name;\n subtitle.textContent = \'You are visible on this camera\';\n confidence.textContent = \'Confidence: \' + Math.round(session.currentCamera.confidence * 100) + \'%\';\n transitTimer.style.display = \'none\';\n\n // Check for new camera detection to add to history\n const lastHistoryCamera = historyItems.find(h => h.type === \'camera\');\n if (!lastHistoryCamera || lastHistoryCamera.cameraId !== session.currentCamera.id) {\n addHistoryItem(\'Detected on: \' + session.currentCamera.name, \'camera\', session.currentCamera.id);\n }\n } else if (session.activeTransit) {\n // In transit\n card.className = \'detection-card in-transit\';\n icon.textContent = \'🚶\';\n title.textContent = \'In Transit\';\n subtitle.textContent = \'Walking to next camera...\';\n confidence.textContent = \'\';\n transitTimer.style.display = \'flex\';\n document.getElementById(\'transit-from\').textContent = \'from \' + session.activeTransit.fromCameraName;\n\n // Start transit timer if not already running\n if (!transitInterval) {\n transitInterval = setInterval(() => {\n if (session?.activeTransit) {\n document.getElementById(\'transit-time\').textContent = session.activeTransit.elapsedSeconds + \'s\';\n }\n }, 1000);\n }\n } else {\n // Waiting\n card.className = \'detection-card\';\n icon.textContent = \'👤\';\n title.textContent = \'Waiting for detection...\';\n subtitle.textContent = \'Walk to any camera to begin\';\n confidence.textContent = \'\';\n transitTimer.style.display = \'none\';\n\n if (transitInterval) {\n clearInterval(transitInterval);\n transitInterval = null;\n }\n }\n }\n\n function updateStatsUI() {\n if (!session?.stats) return;\n\n document.getElementById(\'stat-cameras\').textContent = session.stats.camerasVisited;\n document.getElementById(\'stat-transits\').textContent = session.stats.transitsRecorded;\n document.getElementById(\'stat-landmarks\').textContent = session.stats.landmarksMarked;\n document.getElementById(\'progress-percent\').textContent = session.stats.coveragePercentage + \'%\';\n document.getElementById(\'progress-fill\').style.width = session.stats.coveragePercentage + \'%\';\n }\n\n function updateSuggestionsUI() {\n if (!session?.suggestions || session.suggestions.length === 0) return;\n\n const list = document.getElementById(\'suggestions-list\');\n list.innerHTML = session.suggestions.map(s =>\n \'<div class="suggestion-item">\' + s + \'</div>\'\n ).join(\'\');\n }\n\n function addHistoryItem(text, type, cameraId) {\n const time = new Date().toLocaleTimeString();\n historyItems.unshift({ text, type, time, cameraId });\n if (historyItems.length > 50) historyItems.pop();\n\n const list = document.getElementById(\'history-list\');\n document.getElementById(\'history-count\').textContent = historyItems.length + \' events\';\n\n list.innerHTML = historyItems.map(item => {\n let className = \'\';\n if (item.type === \'camera\') className = \'history-item-camera\';\n if (item.type === \'transit\') className = \'history-item-transit\';\n return \'<div class="history-item"><span class="\' + className + \'">\' + item.text + \'</span>\' +\n \'<div class="history-item-time">\' + item.time + \'</div></div>\';\n }).join(\'\');\n }\n\n function switchTab(tabName) {\n document.querySelectorAll(\'.tab\').forEach(tab => {\n tab.classList.toggle(\'active\', tab.textContent.toLowerCase() === tabName);\n });\n document.querySelectorAll(\'.tab-content\').forEach(content => {\n content.classList.toggle(\'active\', content.id === \'tab-\' + tabName);\n });\n }\n\n // Initialize on load\n init();\n <\/script>\n</body>\n</html>'},1722(e,t,n){"use strict";const i=n(4434),r=n(8611),{Duplex:o}=n(2203),{createHash:s}=n(6982),a=n(5926),c=n(2971),l=n(8237),d=n(1060),{GUID:u,kWebSocket:p}=n(2614),h=/^[+/0-9A-Za-z]{22}==$/;function f(e){e._state=2,e.emit("close")}function g(){this.destroy()}function m(e,t,n,i){n=n||r.STATUS_CODES[t],i={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(n),...i},e.once("finish",e.destroy),e.end(`HTTP/1.1 ${t} ${r.STATUS_CODES[t]}\r\n`+Object.keys(i).map(e=>`${e}: ${i[e]}`).join("\r\n")+"\r\n\r\n"+n)}function y(e,t,n,i,r,o){if(e.listenerCount("wsClientError")){const i=new Error(r);Error.captureStackTrace(i,y),e.emit("wsClientError",i,n,t)}else m(n,i,r,o)}e.exports=class extends i{constructor(e,t){if(super(),null==(e={allowSynchronousEvents:!0,autoPong:!0,maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:d,...e}).port&&!e.server&&!e.noServer||null!=e.port&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(null!=e.port?(this._server=r.createServer((e,t)=>{const n=r.STATUS_CODES[426];t.writeHead(426,{"Content-Length":n.length,"Content-Type":"text/plain"}),t.end(n)}),this._server.listen(e.port,e.host,e.backlog,t)):e.server&&(this._server=e.server),this._server){const e=this.emit.bind(this,"connection");this._removeListeners=function(e,t){for(const n of Object.keys(t))e.on(n,t[n]);return function(){for(const n of Object.keys(t))e.removeListener(n,t[n])}}(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(t,n,i)=>{this.handleUpgrade(t,n,i,e)}})}!0===e.perMessageDeflate&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=0}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(2===this._state)return e&&this.once("close",()=>{e(new Error("The server is not running"))}),void process.nextTick(f,this);if(e&&this.once("close",e),1!==this._state)if(this._state=1,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients&&this.clients.size?this._shouldEmitClose=!0:process.nextTick(f,this);else{const e=this._server;this._removeListeners(),this._removeListeners=this._server=null,e.close(()=>{f(this)})}}shouldHandle(e){if(this.options.path){const t=e.url.indexOf("?");if((-1!==t?e.url.slice(0,t):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,t,n,i){t.on("error",g);const r=e.headers["sec-websocket-key"],o=e.headers.upgrade,s=+e.headers["sec-websocket-version"];if("GET"!==e.method){return void y(this,e,t,405,"Invalid HTTP method")}if(void 0===o||"websocket"!==o.toLowerCase()){return void y(this,e,t,400,"Invalid Upgrade header")}if(void 0===r||!h.test(r)){return void y(this,e,t,400,"Missing or invalid Sec-WebSocket-Key header")}if(13!==s&&8!==s){return void y(this,e,t,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"})}if(!this.shouldHandle(e))return void m(t,400);const d=e.headers["sec-websocket-protocol"];let u=new Set;if(void 0!==d)try{u=l.parse(d)}catch(n){return void y(this,e,t,400,"Invalid Sec-WebSocket-Protocol header")}const p=e.headers["sec-websocket-extensions"],f={};if(this.options.perMessageDeflate&&void 0!==p){const n=new c(this.options.perMessageDeflate,!0,this.options.maxPayload);try{const e=a.parse(p);e[c.extensionName]&&(n.accept(e[c.extensionName]),f[c.extensionName]=n)}catch(n){return void y(this,e,t,400,"Invalid or unacceptable Sec-WebSocket-Extensions header")}}if(this.options.verifyClient){const o={origin:e.headers[""+(8===s?"sec-websocket-origin":"origin")],secure:!(!e.socket.authorized&&!e.socket.encrypted),req:e};if(2===this.options.verifyClient.length)return void this.options.verifyClient(o,(o,s,a,c)=>{if(!o)return m(t,s||401,a,c);this.completeUpgrade(f,r,u,e,t,n,i)});if(!this.options.verifyClient(o))return m(t,401)}this.completeUpgrade(f,r,u,e,t,n,i)}completeUpgrade(e,t,n,i,r,o,l){if(!r.readable||!r.writable)return r.destroy();if(r[p])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>0)return m(r,503);const d=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${s("sha1").update(t+u).digest("base64")}`],h=new this.options.WebSocket(null,void 0,this.options);if(n.size){const e=this.options.handleProtocols?this.options.handleProtocols(n,i):n.values().next().value;e&&(d.push(`Sec-WebSocket-Protocol: ${e}`),h._protocol=e)}if(e[c.extensionName]){const t=e[c.extensionName].params,n=a.format({[c.extensionName]:[t]});d.push(`Sec-WebSocket-Extensions: ${n}`),h._extensions=e}this.emit("headers",d,i),r.write(d.concat("\r\n").join("\r\n")),r.removeListener("error",g),h.setSocket(r,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(h),h.on("close",()=>{this.clients.delete(h),this._shouldEmitClose&&!this.clients.size&&process.nextTick(f,this)})),l(h,i)}}},1725(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(181),r={INVALID_ENCODING:"Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.",INVALID_SMARTBUFFER_SIZE:"Invalid size provided. Size must be a valid integer greater than zero.",INVALID_SMARTBUFFER_BUFFER:"Invalid Buffer provided in SmartBufferOptions.",INVALID_SMARTBUFFER_OBJECT:"Invalid SmartBufferOptions object supplied to SmartBuffer constructor or factory methods.",INVALID_OFFSET:"An invalid offset value was provided.",INVALID_OFFSET_NON_NUMBER:"An invalid offset value was provided. A numeric value is required.",INVALID_LENGTH:"An invalid length value was provided.",INVALID_LENGTH_NON_NUMBER:"An invalid length value was provived. A numeric value is required.",INVALID_TARGET_OFFSET:"Target offset is beyond the bounds of the internal SmartBuffer data.",INVALID_TARGET_LENGTH:"Specified length value moves cursor beyong the bounds of the internal SmartBuffer data.",INVALID_READ_BEYOND_BOUNDS:"Attempted to read beyond the bounds of the managed data.",INVALID_WRITE_BEYOND_BOUNDS:"Attempted to write beyond the bounds of the managed data."};function o(e){return"number"==typeof e&&isFinite(e)&&function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}(e)}function s(e,t){if("number"!=typeof e)throw new Error(t?r.INVALID_OFFSET_NON_NUMBER:r.INVALID_LENGTH_NON_NUMBER);if(!o(e)||e<0)throw new Error(t?r.INVALID_OFFSET:r.INVALID_LENGTH)}t.ERRORS=r,t.checkEncoding=function(e){if(!i.Buffer.isEncoding(e))throw new Error(r.INVALID_ENCODING)},t.isFiniteInteger=o,t.checkLengthValue=function(e){s(e,!1)},t.checkOffsetValue=function(e){s(e,!0)},t.checkTargetOffset=function(e,t){if(e<0||e>t.length)throw new Error(r.INVALID_TARGET_OFFSET)},t.bigIntAndBufferInt64Check=function(e){if("undefined"==typeof BigInt)throw new Error("Platform does not support JS BigInt type.");if("undefined"==typeof i.Buffer.prototype[e])throw new Error(`Platform does not support Buffer.prototype.${e}.`)}},2017(e,t,n){try{var i=n(9023);if("function"!=typeof i.inherits)throw"";e.exports=i.inherits}catch(t){e.exports=n(6698)}},2018(e){"use strict";e.exports=require("tty")},2099(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(720);t.default=class{numberAllocator;lastId;constructor(){this.numberAllocator=new i.NumberAllocator(1,65535)}allocate(){return this.lastId=this.numberAllocator.alloc(),this.lastId}getLastAllocated(){return this.lastId}register(e){return this.numberAllocator.use(e)}deallocate(e){this.numberAllocator.free(e)}clear(){this.numberAllocator.clear()}}},2203(e){"use strict";e.exports=require("stream")},2250(e){"use strict";e.exports=require("dns")},2437(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.AddressError=void 0;class n extends Error{constructor(e,t){super(e),this.name="AddressError",this.parseMessage=t}}t.AddressError=n},2535(e,t,n){const i=n(3132),{EventEmitter:r}=n(4434),{Buffer:o}=n(181);class s extends r{constructor(){super(),this._array=new Array(20),this._i=0}write(e){return this._array[this._i++]=e,!0}concat(){let e=0;const t=new Array(this._array.length),n=this._array;let i,r=0;for(i=0;i<n.length&&void 0!==n[i];i++)"string"!=typeof n[i]?t[i]=n[i].length:t[i]=o.byteLength(n[i]),e+=t[i];const s=o.allocUnsafe(e);for(i=0;i<n.length&&void 0!==n[i];i++)"string"!=typeof n[i]?(n[i].copy(s,r),r+=t[i]):(s.write(n[i],r),r+=t[i]);return s}destroy(e){e&&this.emit("error",e)}}e.exports=function(e,t){const n=new s;return i(e,n,t),n.concat()}},2613(e){"use strict";e.exports=require("assert")},2614(e){"use strict";const t=["nodebuffer","arraybuffer","fragments"],n="undefined"!=typeof Blob;n&&t.push("blob"),e.exports={BINARY_TYPES:t,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:n,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}},2635(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BufferedDuplex=void 0,t.writev=o;const i=n(4478),r=n(181);function o(e,t){const n=new Array(e.length);for(let t=0;t<e.length;t++)"string"==typeof e[t].chunk?n[t]=r.Buffer.from(e[t].chunk,"utf8"):n[t]=e[t].chunk;this._write(r.Buffer.concat(n),"binary",t)}class s extends i.Duplex{socket;proxy;isSocketOpen;writeQueue;constructor(e,t,n){super({objectMode:!0}),this.proxy=t,this.socket=n,this.writeQueue=[],e.objectMode||(this._writev=o.bind(this)),this.isSocketOpen=!1,this.proxy.on("data",e=>{!this.destroyed&&this.readable&&this.push(e)})}_read(e){this.proxy.read(e)}_write(e,t,n){this.isSocketOpen?this.writeToProxy(e,t,n):this.writeQueue.push({chunk:e,encoding:t,cb:n})}_final(e){this.writeQueue=[],this.proxy.end(e)}_destroy(e,t){this.writeQueue=[],this.proxy.destroy(),t(e)}socketReady(){this.emit("connect"),this.isSocketOpen=!0,this.processWriteQueue()}writeToProxy(e,t,n){!1===this.proxy.write(e,t)?this.proxy.once("drain",n):n()}processWriteQueue(){for(;this.writeQueue.length>0;){const{chunk:e,encoding:t,cb:n}=this.writeQueue.shift();this.writeToProxy(e,t,n)}}}t.BufferedDuplex=s},2639(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=class{aliasToTopic;max;length;constructor(e){this.aliasToTopic={},this.max=e}put(e,t){return!(0===t||t>this.max)&&(this.aliasToTopic[t]=e,this.length=Object.keys(this.aliasToTopic).length,!0)}getTopicByAlias(e){return this.aliasToTopic[e]}clear(){this.aliasToTopic={}}}},2778(e,t,n){"use strict";const i=n(181),r=n(4478),o=n(2635);let s,a,c,l=!1;t.A=(e,t)=>{if(t.hostname=t.hostname||t.host,!t.hostname)throw new Error("Could not determine host. Specify host manually.");const n="MQIsdp"===t.protocolId&&3===t.protocolVersion?"mqttv3.1":"mqtt";!function(e){e.hostname||(e.hostname="localhost"),e.path||(e.path="/"),e.wsOptions||(e.wsOptions={})}(t);const d=function(e,t){const n="alis"===e.protocol?"wss":"ws";let i=`${n}://${e.hostname}${e.path}`;return e.port&&80!==e.port&&443!==e.port&&(i=`${n}://${e.hostname}:${e.port}${e.path}`),"function"==typeof e.transformWsUrl&&(i=e.transformWsUrl(i,e,t)),i}(t,e);return s=t.my,s.connectSocket({url:d,protocols:n}),a=function(){const e=new r.Transform;return e._write=(e,t,n)=>{s.sendSocketMessage({data:e.buffer,success(){n()},fail(){n(new Error)}})},e._flush=e=>{s.closeSocket({success(){e()}})},e}(),c=new o.BufferedDuplex(t,a,s),l||(l=!0,s.onSocketOpen(()=>{c.socketReady()}),s.onSocketMessage(e=>{if("string"==typeof e.data){const t=i.Buffer.from(e.data,"base64");a.push(t)}else{const t=new FileReader;t.addEventListener("load",()=>{t.result instanceof ArrayBuffer?a.push(i.Buffer.from(t.result)):a.push(i.Buffer.from(t.result,"utf-8"))}),t.readAsArrayBuffer(e.data)}}),s.onSocketClose(()=>{c.end(),c.destroy()}),s.onSocketError(e=>{c.destroy(e)})),c}},2793(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.connectAsync=function(e,t,n=!0){return new Promise((i,r)=>{const o=d(e,t),s={connect:e=>{a(),i(o)},end:()=>{a(),i(o)},error:e=>{a(),o.end(),r(e)}};function a(){Object.keys(s).forEach(e=>{o.off(e,s[e])})}!1===n&&(s.close=()=>{s.error(new Error("Couldn't connect to server"))}),Object.keys(s).forEach(e=>{o.on(e,s[e])})})};const r=i(n(5753)),o=i(n(7016)),s=i(n(9777)),a=i(n(6887));"function"!=typeof process?.nextTick&&(process.nextTick=setImmediate);const c=(0,r.default)("mqttjs");let l=null;function d(e,t){if(c("connecting to an MQTT broker..."),"object"!=typeof e||t||(t=e,e=""),t=t||{},e&&"string"==typeof e){const n=o.default.parse(e,!0),i={};if(null!=n.port&&(i.port=Number(n.port)),i.host=n.hostname,i.query=n.query,i.auth=n.auth,i.protocol=n.protocol,i.path=n.path,!(t={...i,...t}).protocol)throw new Error("Missing protocol");t.protocol=t.protocol.replace(/:$/,"")}if(t.unixSocket=t.unixSocket||t.protocol?.includes("+unix"),t.unixSocket?t.protocol=t.protocol.replace("+unix",""):t.protocol?.startsWith("ws")||t.protocol?.startsWith("wx")||delete t.path,function(e){let t;if(e.auth)if(t=e.auth.match(/^(.+):(.+)$/),t){const[,n,i]=t;e.username=n,e.password=i}else e.username=e.auth}(t),t.query&&"string"==typeof t.query.clientId&&(t.clientId=t.query.clientId),a.default||t.unixSocket?t.socksProxy=void 0:void 0===t.socksProxy&&"undefined"!=typeof process&&(t.socksProxy=process.env.MQTTJS_SOCKS_PROXY),t.cert&&t.key){if(!t.protocol)throw new Error("Missing secure protocol key");if(-1===["mqtts","wss","wxs","alis"].indexOf(t.protocol))switch(t.protocol){case"mqtt":t.protocol="mqtts";break;case"ws":t.protocol="wss";break;case"wx":t.protocol="wxs";break;case"ali":t.protocol="alis";break;default:throw new Error(`Unknown protocol for secure connection: "${t.protocol}"!`)}}if(l||(l={},a.default||t.forceNativeWebSocket?(l.ws=n(8203).browserStreamBuilder,l.wss=n(8203).browserStreamBuilder,l.wx=n(5670).A,l.wxs=n(5670).A,l.ali=n(2778).A,l.alis=n(2778).A):(l.ws=n(8203).streamBuilder,l.wss=n(8203).streamBuilder,l.mqtt=n(778).default,l.tcp=n(778).default,l.ssl=n(3936).default,l.tls=l.ssl,l.mqtts=n(3936).default)),!l[t.protocol]){const e=-1!==["mqtts","wss"].indexOf(t.protocol);t.protocol=["mqtt","mqtts","ws","wss","wx","wxs","ali","alis"].filter((t,n)=>(!e||n%2!=0)&&"function"==typeof l[t])[0]}if(!1===t.clean&&!t.clientId)throw new Error("Missing clientId for unclean clients");t.protocol&&(t.defaultProtocol=t.protocol);const i=new s.default(function(e){return t.servers&&(e._reconnectCount&&e._reconnectCount!==t.servers.length||(e._reconnectCount=0),t.host=t.servers[e._reconnectCount].host,t.port=t.servers[e._reconnectCount].port,t.protocol=t.servers[e._reconnectCount].protocol?t.servers[e._reconnectCount].protocol:t.defaultProtocol,t.hostname=t.host,e._reconnectCount++),c("calling streambuilder for",t.protocol),l[t.protocol](e,t)},t);return i.on("error",()=>{}),i}t.default=d},2839(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Address4=void 0;const s=o(n(837)),a=o(n(9576)),c=n(2437);class l{constructor(e){this.groups=a.GROUPS,this.parsedAddress=[],this.parsedSubnet="",this.subnet="/32",this.subnetMask=32,this.v4=!0,this.isCorrect=s.isCorrect(a.BITS),this.isInSubnet=s.isInSubnet,this.address=e;const t=a.RE_SUBNET_STRING.exec(e);if(t){if(this.parsedSubnet=t[0].replace("/",""),this.subnetMask=parseInt(this.parsedSubnet,10),this.subnet=`/${this.subnetMask}`,this.subnetMask<0||this.subnetMask>a.BITS)throw new c.AddressError("Invalid subnet mask.");e=e.replace(a.RE_SUBNET_STRING,"")}this.addressMinusSuffix=e,this.parsedAddress=this.parse(e)}static isValid(e){try{return new l(e),!0}catch(e){return!1}}parse(e){const t=e.split(".");if(!e.match(a.RE_ADDRESS))throw new c.AddressError("Invalid IPv4 address.");return t}correctForm(){return this.parsedAddress.map(e=>parseInt(e,10)).join(".")}static fromHex(e){const t=e.replace(/:/g,"").padStart(8,"0"),n=[];let i;for(i=0;i<8;i+=2){const e=t.slice(i,i+2);n.push(parseInt(e,16))}return new l(n.join("."))}static fromInteger(e){return l.fromHex(e.toString(16))}static fromArpa(e){const t=e.replace(/(\.in-addr\.arpa)?\.$/,"").split(".").reverse().join(".");return new l(t)}toHex(){return this.parsedAddress.map(e=>s.stringToPaddedHex(e)).join(":")}toArray(){return this.parsedAddress.map(e=>parseInt(e,10))}toGroup6(){const e=[];let t;for(t=0;t<a.GROUPS;t+=2)e.push(`${s.stringToPaddedHex(this.parsedAddress[t])}${s.stringToPaddedHex(this.parsedAddress[t+1])}`);return e.join(":")}bigInt(){return BigInt(`0x${this.parsedAddress.map(e=>s.stringToPaddedHex(e)).join("")}`)}_startAddress(){return BigInt(`0b${this.mask()+"0".repeat(a.BITS-this.subnetMask)}`)}startAddress(){return l.fromBigInt(this._startAddress())}startAddressExclusive(){const e=BigInt("1");return l.fromBigInt(this._startAddress()+e)}_endAddress(){return BigInt(`0b${this.mask()+"1".repeat(a.BITS-this.subnetMask)}`)}endAddress(){return l.fromBigInt(this._endAddress())}endAddressExclusive(){const e=BigInt("1");return l.fromBigInt(this._endAddress()-e)}static fromBigInt(e){return l.fromHex(e.toString(16))}static fromByteArray(e){if(4!==e.length)throw new c.AddressError("IPv4 addresses require exactly 4 bytes");for(let t=0;t<e.length;t++)if(!Number.isInteger(e[t])||e[t]<0||e[t]>255)throw new c.AddressError("All bytes must be integers between 0 and 255");return this.fromUnsignedByteArray(e)}static fromUnsignedByteArray(e){if(4!==e.length)throw new c.AddressError("IPv4 addresses require exactly 4 bytes");const t=e.join(".");return new l(t)}mask(e){return void 0===e&&(e=this.subnetMask),this.getBitsBase2(0,e)}getBitsBase2(e,t){return this.binaryZeroPad().slice(e,t)}reverseForm(e){e||(e={});const t=this.correctForm().split(".").reverse().join(".");return e.omitSuffix?t:`${t}.in-addr.arpa.`}isMulticast(){return this.isInSubnet(new l("224.0.0.0/4"))}binaryZeroPad(){return this.bigInt().toString(2).padStart(a.BITS,"0")}groupForV6(){const e=this.parsedAddress;return this.address.replace(a.RE_ADDRESS,`<span class="hover-group group-v4 group-6">${e.slice(0,2).join(".")}</span>.<span class="hover-group group-v4 group-7">${e.slice(2,4).join(".")}</span>`)}}t.Address4=l},2846(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TrackingZone=void 0;const i=n(7562),r=n(6117);class o extends i.ScryptedDeviceBase{trackingState;plugin;config={type:"entry",cameras:[]};storageSettings=new r.StorageSettings(this,{zoneType:{title:"Zone Type",type:"string",choices:["entry","exit","dwell","restricted"],defaultValue:"entry",description:"Type of zone for alerting purposes"},cameras:{title:"Cameras",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${i.ScryptedInterface.ObjectDetector}')`,description:"Cameras that make up this zone"},dwellThreshold:{title:"Dwell Time Threshold (seconds)",type:"number",defaultValue:60,description:"For dwell zones: alert if object stays longer than this"},trackClasses:{title:"Track Object Types",type:"string",multiple:!0,choices:["person","car","vehicle","animal","package"],description:"Object types to monitor in this zone (empty = all)"}});constructor(e,t,n){super(t),this.plugin=e,this.trackingState=n,this.loadConfig(),n.onStateChange(()=>this.evaluateZone()),this.evaluateZone()}loadConfig(){try{const e=this.storage.getItem("zoneConfig");e&&(this.config=JSON.parse(e))}catch(e){this.console.error("Failed to load zone config:",e)}}saveConfig(){try{this.storage.setItem("zoneConfig",JSON.stringify(this.config))}catch(e){this.console.error("Failed to save zone config:",e)}}configure(e){this.config={...this.config,...e},this.saveConfig(),this.evaluateZone()}evaluateZone(){const e=this.getCameraIds();if(0===e.length)return this.occupied=!1,void(this.motionDetected=!1);const t=this.storageSettings.values.trackClasses||[];let n=!1,i=!1;const r=Date.now();for(const o of e){const e=this.trackingState.getObjectsOnCamera(o);for(const s of e){if(t.length>0&&!t.includes(s.className))continue;n=!0;s.sightings.filter(e=>e.cameraId===o&&r-e.timestamp<5e3).some(e=>e.detection.movement?.moving)&&(i=!0)}}this.occupied=n,this.motionDetected=i}getCameraIds(){const e=this.storageSettings.values.cameras;return Array.isArray(e)?e:e?[e]:this.config.cameras||[]}getObjectsInZone(){const e=this.getCameraIds(),t=this.storageSettings.values.trackClasses||[],n=[],i=new Set;for(const r of e)for(const e of this.trackingState.getObjectsOnCamera(r))i.has(e.globalId)||(i.add(e.globalId),(0===t.length||t.includes(e.className))&&n.push(e));return n}async getSettings(){const e=await this.storageSettings.getSettings(),t=this.getObjectsInZone();return e.push({key:"currentStatus",title:"Current Status",type:"string",readonly:!0,value:this.occupied?`Occupied: ${t.length} object${1!==t.length?"s":""}`:"Empty",group:"Status"}),t.length>0&&e.push({key:"objectsList",title:"Objects in Zone",type:"string",readonly:!0,value:t.map(e=>`${e.className}${e.label?` (${e.label})`:""}`).join(", "),group:"Status"}),e}async putSetting(e,t){await this.storageSettings.putSetting(e,t),this.config.type=this.storageSettings.values.zoneType||"entry",this.config.cameras=this.getCameraIds(),this.config.dwellThreshold=1e3*(this.storageSettings.values.dwellThreshold||60),this.saveConfig(),this.evaluateZone()}}t.TrackingZone=o},2860(e){"use strict";e.exports={version:"5.14.1"}},2861(e,t,n){var i=n(181),r=i.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return r(e,t,n)}r.from&&r.alloc&&r.allocUnsafe&&r.allocUnsafeSlow?e.exports=i:(o(i,t),t.Buffer=s),s.prototype=Object.create(r.prototype),o(r,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return r(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var i=r(e);return void 0!==t?"string"==typeof n?i.fill(t,n):i.fill(t):i.fill(0),i},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return i.SlowBuffer(e)}},2881(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_DISCOVERY_STATUS=t.RATE_LIMIT_WARNING_THRESHOLD=t.DEFAULT_DISCOVERY_CONFIG=void 0,t.DEFAULT_DISCOVERY_CONFIG={discoveryIntervalHours:0,autoAcceptThreshold:.85,minLandmarkConfidence:.6,minConnectionConfidence:.5},t.RATE_LIMIT_WARNING_THRESHOLD=1,t.DEFAULT_DISCOVERY_STATUS={isRunning:!1,isScanning:!1,lastScanTime:null,nextScanTime:null,camerasAnalyzed:0,pendingSuggestions:0}},2971(e,t,n){"use strict";const i=n(3106),r=n(3338),o=n(4759),{kStatusCode:s}=n(2614),a=Buffer[Symbol.species],c=Buffer.from([0,0,255,255]),l=Symbol("permessage-deflate"),d=Symbol("total-length"),u=Symbol("callback"),p=Symbol("buffers"),h=Symbol("error");let f;function g(e){this[p].push(e),this[d]+=e.length}function m(e){this[d]+=e.length,this[l]._maxPayload<1||this[d]<=this[l]._maxPayload?this[p].push(e):(this[h]=new RangeError("Max payload size exceeded"),this[h].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[h][s]=1009,this.removeListener("data",m),this.reset())}function y(e){this[l]._inflate=null,this[h]?this[u](this[h]):(e[s]=1007,this[u](e))}e.exports=class{constructor(e,t,n){if(this._maxPayload=0|n,this._options=e||{},this._threshold=void 0!==this._options.threshold?this._options.threshold:1024,this._isServer=!!t,this._deflate=null,this._inflate=null,this.params=null,!f){const e=void 0!==this._options.concurrencyLimit?this._options.concurrencyLimit:10;f=new o(e)}}static get extensionName(){return"permessage-deflate"}offer(){const e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:null==this._options.clientMaxWindowBits&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){const e=this._deflate[u];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){const t=this._options,n=e.find(e=>!(!1===t.serverNoContextTakeover&&e.server_no_context_takeover||e.server_max_window_bits&&(!1===t.serverMaxWindowBits||"number"==typeof t.serverMaxWindowBits&&t.serverMaxWindowBits>e.server_max_window_bits)||"number"==typeof t.clientMaxWindowBits&&!e.client_max_window_bits));if(!n)throw new Error("None of the extension offers can be accepted");return t.serverNoContextTakeover&&(n.server_no_context_takeover=!0),t.clientNoContextTakeover&&(n.client_no_context_takeover=!0),"number"==typeof t.serverMaxWindowBits&&(n.server_max_window_bits=t.serverMaxWindowBits),"number"==typeof t.clientMaxWindowBits?n.client_max_window_bits=t.clientMaxWindowBits:!0!==n.client_max_window_bits&&!1!==t.clientMaxWindowBits||delete n.client_max_window_bits,n}acceptAsClient(e){const t=e[0];if(!1===this._options.clientNoContextTakeover&&t.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(t.client_max_window_bits){if(!1===this._options.clientMaxWindowBits||"number"==typeof this._options.clientMaxWindowBits&&t.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"')}else"number"==typeof this._options.clientMaxWindowBits&&(t.client_max_window_bits=this._options.clientMaxWindowBits);return t}normalizeParams(e){return e.forEach(e=>{Object.keys(e).forEach(t=>{let n=e[t];if(n.length>1)throw new Error(`Parameter "${t}" must have only a single value`);if(n=n[0],"client_max_window_bits"===t){if(!0!==n){const e=+n;if(!Number.isInteger(e)||e<8||e>15)throw new TypeError(`Invalid value for parameter "${t}": ${n}`);n=e}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${t}": ${n}`)}else if("server_max_window_bits"===t){const e=+n;if(!Number.isInteger(e)||e<8||e>15)throw new TypeError(`Invalid value for parameter "${t}": ${n}`);n=e}else{if("client_no_context_takeover"!==t&&"server_no_context_takeover"!==t)throw new Error(`Unknown parameter "${t}"`);if(!0!==n)throw new TypeError(`Invalid value for parameter "${t}": ${n}`)}e[t]=n})}),e}decompress(e,t,n){f.add(i=>{this._decompress(e,t,(e,t)=>{i(),n(e,t)})})}compress(e,t,n){f.add(i=>{this._compress(e,t,(e,t)=>{i(),n(e,t)})})}_decompress(e,t,n){const o=this._isServer?"client":"server";if(!this._inflate){const e=`${o}_max_window_bits`,t="number"!=typeof this.params[e]?i.Z_DEFAULT_WINDOWBITS:this.params[e];this._inflate=i.createInflateRaw({...this._options.zlibInflateOptions,windowBits:t}),this._inflate[l]=this,this._inflate[d]=0,this._inflate[p]=[],this._inflate.on("error",y),this._inflate.on("data",m)}this._inflate[u]=n,this._inflate.write(e),t&&this._inflate.write(c),this._inflate.flush(()=>{const e=this._inflate[h];if(e)return this._inflate.close(),this._inflate=null,void n(e);const i=r.concat(this._inflate[p],this._inflate[d]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[d]=0,this._inflate[p]=[],t&&this.params[`${o}_no_context_takeover`]&&this._inflate.reset()),n(null,i)})}_compress(e,t,n){const o=this._isServer?"server":"client";if(!this._deflate){const e=`${o}_max_window_bits`,t="number"!=typeof this.params[e]?i.Z_DEFAULT_WINDOWBITS:this.params[e];this._deflate=i.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:t}),this._deflate[d]=0,this._deflate[p]=[],this._deflate.on("data",g)}this._deflate[u]=n,this._deflate.write(e),this._deflate.flush(i.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let e=r.concat(this._deflate[p],this._deflate[d]);t&&(e=new a(e.buffer,e.byteOffset,e.length-4)),this._deflate[u]=null,this._deflate[d]=0,this._deflate[p]=[],t&&this.params[`${o}_no_context_takeover`]&&this._deflate.reset(),n(null,e)})}}},3079(e,t,n){const i=n(4829),{EventEmitter:r}=n(4434),o=n(576),s=n(5399),a=n(5753)("mqtt-packet:parser");class c extends r{constructor(){super(),this.parser=this.constructor.parser}static parser(e){return this instanceof c?(this.settings=e||{},this._states=["_parseHeader","_parseLength","_parsePayload","_newPacket"],this._resetState(),this):(new c).parser(e)}_resetState(){a("_resetState: resetting packet, error, _list, and _stateCounter"),this.packet=new o,this.error=null,this._list=i(),this._stateCounter=0}parse(e){for(this.error&&this._resetState(),this._list.append(e),a("parse: current state: %s",this._states[this._stateCounter]);(-1!==this.packet.length||this._list.length>0)&&this[this._states[this._stateCounter]]()&&!this.error;)this._stateCounter++,a("parse: state complete. _stateCounter is now: %d",this._stateCounter),a("parse: packet.length: %d, buffer list length: %d",this.packet.length,this._list.length),this._stateCounter>=this._states.length&&(this._stateCounter=0);return a("parse: exited while loop. packet: %d, buffer list length: %d",this.packet.length,this._list.length),this._list.length}_parseHeader(){const e=this._list.readUInt8(0),t=e>>s.CMD_SHIFT;this.packet.cmd=s.types[t];const n=15&e,i=s.requiredHeaderFlags[t];return null!=i&&n!==i?this._emitError(new Error(s.requiredHeaderFlagsErrors[t])):(this.packet.retain=0!==(e&s.RETAIN_MASK),this.packet.qos=e>>s.QOS_SHIFT&s.QOS_MASK,this.packet.qos>2?this._emitError(new Error("Packet must not have both QoS bits set to 1")):(this.packet.dup=0!==(e&s.DUP_MASK),a("_parseHeader: packet: %o",this.packet),this._list.consume(1),!0))}_parseLength(){const e=this._parseVarByteNum(!0);return e&&(this.packet.length=e.value,this._list.consume(e.bytes)),a("_parseLength %d",e.value),!!e}_parsePayload(){a("_parsePayload: payload %O",this._list);let e=!1;if(0===this.packet.length||this._list.length>=this.packet.length){switch(this._pos=0,this.packet.cmd){case"connect":this._parseConnect();break;case"connack":this._parseConnack();break;case"publish":this._parsePublish();break;case"puback":case"pubrec":case"pubrel":case"pubcomp":this._parseConfirmation();break;case"subscribe":this._parseSubscribe();break;case"suback":this._parseSuback();break;case"unsubscribe":this._parseUnsubscribe();break;case"unsuback":this._parseUnsuback();break;case"pingreq":case"pingresp":break;case"disconnect":this._parseDisconnect();break;case"auth":this._parseAuth();break;default:this._emitError(new Error("Not supported"))}e=!0}return a("_parsePayload complete result: %s",e),e}_parseConnect(){let e,t,n,i;a("_parseConnect");const r={},o=this.packet,c=this._parseString();if(null===c)return this._emitError(new Error("Cannot parse protocolId"));if("MQTT"!==c&&"MQIsdp"!==c)return this._emitError(new Error("Invalid protocolId"));if(o.protocolId=c,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(o.protocolVersion=this._list.readUInt8(this._pos),o.protocolVersion>=128&&(o.bridgeMode=!0,o.protocolVersion=o.protocolVersion-128),3!==o.protocolVersion&&4!==o.protocolVersion&&5!==o.protocolVersion)return this._emitError(new Error("Invalid protocol version"));if(this._pos++,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(1&this._list.readUInt8(this._pos))return this._emitError(new Error("Connect flag bit 0 must be 0, but got 1"));r.username=this._list.readUInt8(this._pos)&s.USERNAME_MASK,r.password=this._list.readUInt8(this._pos)&s.PASSWORD_MASK,r.will=this._list.readUInt8(this._pos)&s.WILL_FLAG_MASK;const l=!!(this._list.readUInt8(this._pos)&s.WILL_RETAIN_MASK),d=(this._list.readUInt8(this._pos)&s.WILL_QOS_MASK)>>s.WILL_QOS_SHIFT;if(r.will)o.will={},o.will.retain=l,o.will.qos=d;else{if(l)return this._emitError(new Error("Will Retain Flag must be set to zero when Will Flag is set to 0"));if(d)return this._emitError(new Error("Will QoS must be set to zero when Will Flag is set to 0"))}if(o.clean=0!==(this._list.readUInt8(this._pos)&s.CLEAN_SESSION_MASK),this._pos++,o.keepalive=this._parseNum(),-1===o.keepalive)return this._emitError(new Error("Packet too short"));if(5===o.protocolVersion){const e=this._parseProperties();Object.getOwnPropertyNames(e).length&&(o.properties=e)}const u=this._parseString();if(null===u)return this._emitError(new Error("Packet too short"));if(o.clientId=u,a("_parseConnect: packet.clientId: %s",o.clientId),r.will){if(5===o.protocolVersion){const e=this._parseProperties();Object.getOwnPropertyNames(e).length&&(o.will.properties=e)}if(e=this._parseString(),null===e)return this._emitError(new Error("Cannot parse will topic"));if(o.will.topic=e,a("_parseConnect: packet.will.topic: %s",o.will.topic),t=this._parseBuffer(),null===t)return this._emitError(new Error("Cannot parse will payload"));o.will.payload=t,a("_parseConnect: packet.will.paylaod: %s",o.will.payload)}if(r.username){if(i=this._parseString(),null===i)return this._emitError(new Error("Cannot parse username"));o.username=i,a("_parseConnect: packet.username: %s",o.username)}if(r.password){if(n=this._parseBuffer(),null===n)return this._emitError(new Error("Cannot parse password"));o.password=n}return this.settings=o,a("_parseConnect: complete"),o}_parseConnack(){a("_parseConnack");const e=this.packet;if(this._list.length<1)return null;const t=this._list.readUInt8(this._pos++);if(t>1)return this._emitError(new Error("Invalid connack flags, bits 7-1 must be set to 0"));if(e.sessionPresent=!!(t&s.SESSIONPRESENT_MASK),5===this.settings.protocolVersion)this._list.length>=2?e.reasonCode=this._list.readUInt8(this._pos++):e.reasonCode=0;else{if(this._list.length<2)return null;e.returnCode=this._list.readUInt8(this._pos++)}if(-1===e.returnCode||-1===e.reasonCode)return this._emitError(new Error("Cannot parse return code"));if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}a("_parseConnack: complete")}_parsePublish(){a("_parsePublish");const e=this.packet;if(e.topic=this._parseString(),null===e.topic)return this._emitError(new Error("Cannot parse topic"));if(!(e.qos>0)||this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}e.payload=this._list.slice(this._pos,e.length),a("_parsePublish: payload from buffer list: %o",e.payload)}}_parseSubscribe(){a("_parseSubscribe");const e=this.packet;let t,n,i,r,o,c,l;if(e.subscriptions=[],this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}if(e.length<=0)return this._emitError(new Error("Malformed subscribe, no payload specified"));for(;this._pos<e.length;){if(t=this._parseString(),null===t)return this._emitError(new Error("Cannot parse topic"));if(this._pos>=e.length)return this._emitError(new Error("Malformed Subscribe Payload"));if(n=this._parseByte(),5===this.settings.protocolVersion){if(192&n)return this._emitError(new Error("Invalid subscribe topic flag bits, bits 7-6 must be 0"))}else if(252&n)return this._emitError(new Error("Invalid subscribe topic flag bits, bits 7-2 must be 0"));if(i=n&s.SUBSCRIBE_OPTIONS_QOS_MASK,i>2)return this._emitError(new Error("Invalid subscribe QoS, must be <= 2"));if(c=0!==(n>>s.SUBSCRIBE_OPTIONS_NL_SHIFT&s.SUBSCRIBE_OPTIONS_NL_MASK),o=0!==(n>>s.SUBSCRIBE_OPTIONS_RAP_SHIFT&s.SUBSCRIBE_OPTIONS_RAP_MASK),r=n>>s.SUBSCRIBE_OPTIONS_RH_SHIFT&s.SUBSCRIBE_OPTIONS_RH_MASK,r>2)return this._emitError(new Error("Invalid retain handling, must be <= 2"));l={topic:t,qos:i},5===this.settings.protocolVersion?(l.nl=c,l.rap=o,l.rh=r):this.settings.bridgeMode&&(l.rh=0,l.rap=!0,l.nl=!0),a("_parseSubscribe: push subscription `%s` to subscription",l),e.subscriptions.push(l)}}}_parseSuback(){a("_parseSuback");const e=this.packet;if(this.packet.granted=[],this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}if(e.length<=0)return this._emitError(new Error("Malformed suback, no payload specified"));for(;this._pos<this.packet.length;){const e=this._list.readUInt8(this._pos++);if(5===this.settings.protocolVersion){if(!s.MQTT5_SUBACK_CODES[e])return this._emitError(new Error("Invalid suback code"))}else if(e>2&&128!==e)return this._emitError(new Error("Invalid suback QoS, must be 0, 1, 2 or 128"));this.packet.granted.push(e)}}}_parseUnsubscribe(){a("_parseUnsubscribe");const e=this.packet;if(e.unsubscriptions=[],this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}if(e.length<=0)return this._emitError(new Error("Malformed unsubscribe, no payload specified"));for(;this._pos<e.length;){const t=this._parseString();if(null===t)return this._emitError(new Error("Cannot parse topic"));a("_parseUnsubscribe: push topic `%s` to unsubscriptions",t),e.unsubscriptions.push(t)}}}_parseUnsuback(){a("_parseUnsuback");const e=this.packet;if(!this._parseMessageId())return this._emitError(new Error("Cannot parse messageId"));if((3===this.settings.protocolVersion||4===this.settings.protocolVersion)&&2!==e.length)return this._emitError(new Error("Malformed unsuback, payload length must be 2"));if(e.length<=0)return this._emitError(new Error("Malformed unsuback, no payload specified"));if(5===this.settings.protocolVersion){const t=this._parseProperties();for(Object.getOwnPropertyNames(t).length&&(e.properties=t),e.granted=[];this._pos<this.packet.length;){const e=this._list.readUInt8(this._pos++);if(!s.MQTT5_UNSUBACK_CODES[e])return this._emitError(new Error("Invalid unsuback code"));this.packet.granted.push(e)}}}_parseConfirmation(){a("_parseConfirmation: packet.cmd: `%s`",this.packet.cmd);const e=this.packet;if(this._parseMessageId(),5===this.settings.protocolVersion){if(e.length>2){switch(e.reasonCode=this._parseByte(),this.packet.cmd){case"puback":case"pubrec":if(!s.MQTT5_PUBACK_PUBREC_CODES[e.reasonCode])return this._emitError(new Error("Invalid "+this.packet.cmd+" reason code"));break;case"pubrel":case"pubcomp":if(!s.MQTT5_PUBREL_PUBCOMP_CODES[e.reasonCode])return this._emitError(new Error("Invalid "+this.packet.cmd+" reason code"))}a("_parseConfirmation: packet.reasonCode `%d`",e.reasonCode)}else e.reasonCode=0;if(e.length>3){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}}return!0}_parseDisconnect(){const e=this.packet;if(a("_parseDisconnect"),5===this.settings.protocolVersion){this._list.length>0?(e.reasonCode=this._parseByte(),s.MQTT5_DISCONNECT_CODES[e.reasonCode]||this._emitError(new Error("Invalid disconnect reason code"))):e.reasonCode=0;const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}return a("_parseDisconnect result: true"),!0}_parseAuth(){a("_parseAuth");const e=this.packet;if(5!==this.settings.protocolVersion)return this._emitError(new Error("Not supported auth packet for this version MQTT"));if(e.reasonCode=this._parseByte(),!s.MQTT5_AUTH_CODES[e.reasonCode])return this._emitError(new Error("Invalid auth reason code"));const t=this._parseProperties();return Object.getOwnPropertyNames(t).length&&(e.properties=t),a("_parseAuth: result: true"),!0}_parseMessageId(){const e=this.packet;return e.messageId=this._parseNum(),null===e.messageId?(this._emitError(new Error("Cannot parse messageId")),!1):(a("_parseMessageId: packet.messageId %d",e.messageId),!0)}_parseString(e){const t=this._parseNum(),n=t+this._pos;if(-1===t||n>this._list.length||n>this.packet.length)return null;const i=this._list.toString("utf8",this._pos,n);return this._pos+=t,a("_parseString: result: %s",i),i}_parseStringPair(){return a("_parseStringPair"),{name:this._parseString(),value:this._parseString()}}_parseBuffer(){const e=this._parseNum(),t=e+this._pos;if(-1===e||t>this._list.length||t>this.packet.length)return null;const n=this._list.slice(this._pos,t);return this._pos+=e,a("_parseBuffer: result: %o",n),n}_parseNum(){if(this._list.length-this._pos<2)return-1;const e=this._list.readUInt16BE(this._pos);return this._pos+=2,a("_parseNum: result: %s",e),e}_parse4ByteNum(){if(this._list.length-this._pos<4)return-1;const e=this._list.readUInt32BE(this._pos);return this._pos+=4,a("_parse4ByteNum: result: %s",e),e}_parseVarByteNum(e){a("_parseVarByteNum");let t,n=0,i=1,r=0,o=!1;const c=this._pos?this._pos:0;for(;n<4&&c+n<this._list.length;){if(t=this._list.readUInt8(c+n++),r+=i*(t&s.VARBYTEINT_MASK),i*=128,0===(t&s.VARBYTEINT_FIN_MASK)){o=!0;break}if(this._list.length<=n)break}return!o&&4===n&&this._list.length>=n&&this._emitError(new Error("Invalid variable byte integer")),c&&(this._pos+=n),o=!!o&&(e?{bytes:n,value:r}:r),a("_parseVarByteNum: result: %o",o),o}_parseByte(){let e;return this._pos<this._list.length&&(e=this._list.readUInt8(this._pos),this._pos++),a("_parseByte: result: %o",e),e}_parseByType(e){switch(a("_parseByType: type: %s",e),e){case"byte":return 0!==this._parseByte();case"int8":return this._parseByte();case"int16":return this._parseNum();case"int32":return this._parse4ByteNum();case"var":return this._parseVarByteNum();case"string":return this._parseString();case"pair":return this._parseStringPair();case"binary":return this._parseBuffer()}}_parseProperties(){a("_parseProperties");const e=this._parseVarByteNum(),t=this._pos+e,n={};for(;this._pos<t;){const e=this._parseByte();if(!e)return this._emitError(new Error("Cannot parse property code type")),!1;const t=s.propertiesCodes[e];if(!t)return this._emitError(new Error("Unknown property")),!1;if("userProperties"===t){n[t]||(n[t]=Object.create(null));const e=this._parseByType(s.propertiesTypes[t]);if(n[t][e.name])if(Array.isArray(n[t][e.name]))n[t][e.name].push(e.value);else{const i=n[t][e.name];n[t][e.name]=[i],n[t][e.name].push(e.value)}else n[t][e.name]=e.value;continue}n[t]?(Array.isArray(n[t])||(n[t]=[n[t]]),n[t].push(this._parseByType(s.propertiesTypes[t]))):n[t]=this._parseByType(s.propertiesTypes[t])}return n}_newPacket(){return a("_newPacket"),this.packet&&(this._list.consume(this.packet.length),a("_newPacket: parser emit packet: packet.cmd: %s, packet.payload: %s, packet.length: %d",this.packet.cmd,this.packet.payload,this.packet.length),this.emit("packet",this.packet)),a("_newPacket: new packet"),this.packet=new o,this._pos=0,!0}_emitError(e){a("_emitError",e),this.error=e,this.emit("error",e)}}e.exports=c},3095(e,t,n){"use strict";const{ArrayPrototypePop:i,Promise:r}=n(4134),{isIterable:o,isNodeStream:s,isWebStream:a}=n(6115),{pipelineImpl:c}=n(7758),{finished:l}=n(6238);n(5506),e.exports={finished:l,pipeline:function(...e){return new r((t,n)=>{let r,l;const d=e[e.length-1];if(d&&"object"==typeof d&&!s(d)&&!o(d)&&!a(d)){const t=i(e);r=t.signal,l=t.end}c(e,(e,i)=>{e?n(e):t(i)},{signal:r,end:l})})}}},3106(e){"use strict";e.exports=require("zlib")},3132(e,t,n){const i=n(5399),{Buffer:r}=n(181),o=r.allocUnsafe(0),s=r.from([0]),a=n(6172),c=n(3225).nextTick,l=n(5753)("mqtt-packet:writeToStream"),d=a.cache,u=a.generateNumber,p=a.generateCache,h=a.genBufVariableByteInt,f=a.generate4ByteBuffer;let g=k,m=!0;function y(e,t,n){switch(l("generate called"),t.cork&&(t.cork(),c(b,t)),m&&(m=!1,p()),l("generate: packet.cmd: %s",e.cmd),e.cmd){case"connect":return function(e,t){const n=e||{},o=n.protocolId||"MQTT";let s=n.protocolVersion||4;const a=n.will;let c=n.clean;const l=n.keepalive||0,d=n.clientId||"",u=n.username,p=n.password,h=n.properties;void 0===c&&(c=!0);let f,m,y=0;if(!o||"string"!=typeof o&&!r.isBuffer(o))return t.destroy(new Error("Invalid protocolId")),!1;y+=o.length+2;if(3!==s&&4!==s&&5!==s)return t.destroy(new Error("Invalid protocol version")),!1;y+=1;if(("string"==typeof d||r.isBuffer(d))&&(d||s>=4)&&(d||c))y+=r.byteLength(d)+2;else{if(s<4)return t.destroy(new Error("clientId must be supplied before 3.1.1")),!1;if(1*c==0)return t.destroy(new Error("clientId must be given if cleanSession set to 0")),!1}if("number"!=typeof l||l<0||l>65535||l%1!=0)return t.destroy(new Error("Invalid keepalive")),!1;y+=2;if(y+=1,5===s){if(f=C(t,h),!f)return!1;y+=f.length}if(a){if("object"!=typeof a)return t.destroy(new Error("Invalid will")),!1;if(!a.topic||"string"!=typeof a.topic)return t.destroy(new Error("Invalid will topic")),!1;if(y+=r.byteLength(a.topic)+2,y+=2,a.payload){if(!(a.payload.length>=0))return t.destroy(new Error("Invalid will payload")),!1;"string"==typeof a.payload?y+=r.byteLength(a.payload):y+=a.payload.length}if(m={},5===s){if(m=C(t,a.properties),!m)return!1;y+=m.length}}let b=!1;if(null!=u){if(!A(u))return t.destroy(new Error("Invalid username")),!1;b=!0,y+=r.byteLength(u)+2}if(null!=p){if(!b)return t.destroy(new Error("Username is required to use password")),!1;if(!A(p))return t.destroy(new Error("Invalid password")),!1;y+=P(p)+2}t.write(i.CONNECT_HEADER),S(t,y),x(t,o),n.bridgeMode&&(s+=128);t.write(131===s?i.VERSION131:132===s?i.VERSION132:4===s?i.VERSION4:5===s?i.VERSION5:i.VERSION3);let v=0;v|=null!=u?i.USERNAME_MASK:0,v|=null!=p?i.PASSWORD_MASK:0,v|=a&&a.retain?i.WILL_RETAIN_MASK:0,v|=a&&a.qos?a.qos<<i.WILL_QOS_SHIFT:0,v|=a?i.WILL_FLAG_MASK:0,v|=c?i.CLEAN_SESSION_MASK:0,t.write(r.from([v])),g(t,l),5===s&&f.write();x(t,d),a&&(5===s&&m.write(),_(t,a.topic),x(t,a.payload));null!=u&&x(t,u);null!=p&&x(t,p);return!0}(e,t);case"connack":return function(e,t,n){const o=n?n.protocolVersion:4,a=e||{},c=5===o?a.reasonCode:a.returnCode,l=a.properties;let d=2;if("number"!=typeof c)return t.destroy(new Error("Invalid return code")),!1;let u=null;if(5===o){if(u=C(t,l),!u)return!1;d+=u.length}t.write(i.CONNACK_HEADER),S(t,d),t.write(a.sessionPresent?i.SESSIONPRESENT_HEADER:s),t.write(r.from([c])),null!=u&&u.write();return!0}(e,t,n);case"publish":return function(e,t,n){l("publish: packet: %o",e);const s=n?n.protocolVersion:4,a=e||{},c=a.qos||0,d=a.retain?i.RETAIN_MASK:0,u=a.topic,p=a.payload||o,h=a.messageId,f=a.properties;let m=0;if("string"==typeof u)m+=r.byteLength(u)+2;else{if(!r.isBuffer(u))return t.destroy(new Error("Invalid topic")),!1;m+=u.length+2}r.isBuffer(p)?m+=p.length:m+=r.byteLength(p);if(c&&"number"!=typeof h)return t.destroy(new Error("Invalid messageId")),!1;c&&(m+=2);let y=null;if(5===s){if(y=C(t,f),!y)return!1;m+=y.length}t.write(i.PUBLISH_HEADER[c][a.dup?1:0][d?1:0]),S(t,m),g(t,P(u)),t.write(u),c>0&&g(t,h);null!=y&&y.write();return l("publish: payload: %o",p),t.write(p)}(e,t,n);case"puback":case"pubrec":case"pubrel":case"pubcomp":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.cmd||"puback",c=s.messageId,l=s.dup&&"pubrel"===a?i.DUP_MASK:0;let d=0;const u=s.reasonCode,p=s.properties;let h=5===o?3:2;"pubrel"===a&&(d=1);if("number"!=typeof c)return t.destroy(new Error("Invalid messageId")),!1;let f=null;if(5===o&&"object"==typeof p){if(f=E(t,p,n,h),!f)return!1;h+=f.length}t.write(i.ACKS[a][d][l][0]),3===h&&(h+=0!==u?1:-1);S(t,h),g(t,c),5===o&&2!==h&&t.write(r.from([u]));null!==f?f.write():4===h&&t.write(r.from([0]));return!0}(e,t,n);case"subscribe":return function(e,t,n){l("subscribe: packet: ");const o=n?n.protocolVersion:4,s=e||{},a=s.dup?i.DUP_MASK:0,c=s.messageId,d=s.subscriptions,u=s.properties;let p=0;if("number"!=typeof c)return t.destroy(new Error("Invalid messageId")),!1;p+=2;let h=null;if(5===o){if(h=C(t,u),!h)return!1;p+=h.length}if("object"!=typeof d||!d.length)return t.destroy(new Error("Invalid subscriptions")),!1;for(let e=0;e<d.length;e+=1){const n=d[e].topic,i=d[e].qos;if("string"!=typeof n)return t.destroy(new Error("Invalid subscriptions - invalid topic")),!1;if("number"!=typeof i)return t.destroy(new Error("Invalid subscriptions - invalid qos")),!1;if(5===o){if("boolean"!=typeof(d[e].nl||!1))return t.destroy(new Error("Invalid subscriptions - invalid No Local")),!1;if("boolean"!=typeof(d[e].rap||!1))return t.destroy(new Error("Invalid subscriptions - invalid Retain as Published")),!1;const n=d[e].rh||0;if("number"!=typeof n||n>2)return t.destroy(new Error("Invalid subscriptions - invalid Retain Handling")),!1}p+=r.byteLength(n)+2+1}l("subscribe: writing to stream: %o",i.SUBSCRIBE_HEADER),t.write(i.SUBSCRIBE_HEADER[1][a?1:0][0]),S(t,p),g(t,c),null!==h&&h.write();let f=!0;for(const e of d){const n=e.topic,s=e.qos,a=+e.nl,c=+e.rap,l=e.rh;let d;_(t,n),d=i.SUBSCRIBE_OPTIONS_QOS[s],5===o&&(d|=a?i.SUBSCRIBE_OPTIONS_NL:0,d|=c?i.SUBSCRIBE_OPTIONS_RAP:0,d|=l?i.SUBSCRIBE_OPTIONS_RH[l]:0),f=t.write(r.from([d]))}return f}(e,t,n);case"suback":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.messageId,c=s.granted,l=s.properties;let d=0;if("number"!=typeof a)return t.destroy(new Error("Invalid messageId")),!1;d+=2;if("object"!=typeof c||!c.length)return t.destroy(new Error("Invalid qos vector")),!1;for(let e=0;e<c.length;e+=1){if("number"!=typeof c[e])return t.destroy(new Error("Invalid qos vector")),!1;d+=1}let u=null;if(5===o){if(u=E(t,l,n,d),!u)return!1;d+=u.length}t.write(i.SUBACK_HEADER),S(t,d),g(t,a),null!==u&&u.write();return t.write(r.from(c))}(e,t,n);case"unsubscribe":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.messageId,c=s.dup?i.DUP_MASK:0,l=s.unsubscriptions,d=s.properties;let u=0;if("number"!=typeof a)return t.destroy(new Error("Invalid messageId")),!1;u+=2;if("object"!=typeof l||!l.length)return t.destroy(new Error("Invalid unsubscriptions")),!1;for(let e=0;e<l.length;e+=1){if("string"!=typeof l[e])return t.destroy(new Error("Invalid unsubscriptions")),!1;u+=r.byteLength(l[e])+2}let p=null;if(5===o){if(p=C(t,d),!p)return!1;u+=p.length}t.write(i.UNSUBSCRIBE_HEADER[1][c?1:0][0]),S(t,u),g(t,a),null!==p&&p.write();let h=!0;for(let e=0;e<l.length;e++)h=_(t,l[e]);return h}(e,t,n);case"unsuback":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.messageId,c=s.dup?i.DUP_MASK:0,l=s.granted,d=s.properties,u=s.cmd,p=0;let h=2;if("number"!=typeof a)return t.destroy(new Error("Invalid messageId")),!1;if(5===o){if("object"!=typeof l||!l.length)return t.destroy(new Error("Invalid qos vector")),!1;for(let e=0;e<l.length;e+=1){if("number"!=typeof l[e])return t.destroy(new Error("Invalid qos vector")),!1;h+=1}}let f=null;if(5===o){if(f=E(t,d,n,h),!f)return!1;h+=f.length}t.write(i.ACKS[u][p][c][0]),S(t,h),g(t,a),null!==f&&f.write();5===o&&t.write(r.from(l));return!0}(e,t,n);case"pingreq":case"pingresp":return function(e,t){return t.write(i.EMPTY[e.cmd])}(e,t);case"disconnect":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.reasonCode,c=s.properties;let l=5===o?1:0,d=null;if(5===o){if(d=E(t,c,n,l),!d)return!1;l+=d.length}t.write(r.from([i.codes.disconnect<<4])),S(t,l),5===o&&t.write(r.from([a]));null!==d&&d.write();return!0}(e,t,n);case"auth":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.reasonCode,c=s.properties;let l=5===o?1:0;5!==o&&t.destroy(new Error("Invalid mqtt version for auth packet"));const d=E(t,c,n,l);if(!d)return!1;l+=d.length,t.write(r.from([i.codes.auth<<4])),S(t,l),t.write(r.from([a])),null!==d&&d.write();return!0}(e,t,n);default:return t.destroy(new Error("Unknown command")),!1}}function b(e){e.uncork()}Object.defineProperty(y,"cacheNumbers",{get:()=>g===k,set(e){e?(d&&0!==Object.keys(d).length||(m=!0),g=k):(m=!1,g=I)}});const v={};function S(e,t){if(t>i.VARBYTEINT_MAX)return e.destroy(new Error(`Invalid variable byte integer: ${t}`)),!1;let n=v[t];return n||(n=h(t),t<16384&&(v[t]=n)),l("writeVarByteInt: writing to stream: %o",n),e.write(n)}function _(e,t){const n=r.byteLength(t);return g(e,n),l("writeString: %s",t),e.write(t,"utf8")}function w(e,t,n){_(e,t),_(e,n)}function k(e,t){return l("writeNumberCached: number: %d",t),l("writeNumberCached: %o",d[t]),e.write(d[t])}function I(e,t){const n=u(t);return l("writeNumberGenerated: %o",n),e.write(n)}function x(e,t){"string"==typeof t?_(e,t):t?(g(e,t.length),e.write(t)):g(e,0)}function C(e,t){if("object"!=typeof t||null!=t.length)return{length:1,write(){O(e,{},0)}};let n=0;function o(t,n){let o=0;switch(i.propertiesTypes[t]){case"byte":if("boolean"!=typeof n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=2;break;case"int8":if("number"!=typeof n||n<0||n>255)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=2;break;case"binary":if(n&&null===n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=1+r.byteLength(n)+2;break;case"int16":if("number"!=typeof n||n<0||n>65535)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=3;break;case"int32":if("number"!=typeof n||n<0||n>4294967295)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=5;break;case"var":if("number"!=typeof n||n<0||n>268435455)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=1+r.byteLength(h(n));break;case"string":if("string"!=typeof n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=3+r.byteLength(n.toString());break;case"pair":if("object"!=typeof n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=Object.getOwnPropertyNames(n).reduce((e,t)=>{const i=n[t];return Array.isArray(i)?e+=i.reduce((e,n)=>e+=3+r.byteLength(t.toString())+2+r.byteLength(n.toString()),0):e+=3+r.byteLength(t.toString())+2+r.byteLength(n[t].toString()),e},0);break;default:return e.destroy(new Error(`Invalid property ${t}: ${n}`)),!1}return o}if(t)for(const e in t){let i=0,r=0;const s=t[e];if(void 0!==s){if(Array.isArray(s))for(let t=0;t<s.length;t++){if(r=o(e,s[t]),!r)return!1;i+=r}else{if(r=o(e,s),!r)return!1;i=r}if(!i)return!1;n+=i}}return{length:r.byteLength(h(n))+n,write(){O(e,t,n)}}}function E(e,t,n,i){const r=["reasonString","userProperties"],o=n&&n.properties&&n.properties.maximumPacketSize?n.properties.maximumPacketSize:0;let s=C(e,t);if(o)for(;i+s.length>o;){const n=r.shift();if(!n||!t[n])return!1;delete t[n],s=C(e,t)}return s}function T(e,t,n){switch(i.propertiesTypes[t]){case"byte":e.write(r.from([i.properties[t]])),e.write(r.from([+n]));break;case"int8":e.write(r.from([i.properties[t]])),e.write(r.from([n]));break;case"binary":e.write(r.from([i.properties[t]])),x(e,n);break;case"int16":e.write(r.from([i.properties[t]])),g(e,n);break;case"int32":e.write(r.from([i.properties[t]])),function(e,t){const n=f(t);l("write4ByteNumber: %o",n),e.write(n)}(e,n);break;case"var":e.write(r.from([i.properties[t]])),S(e,n);break;case"string":e.write(r.from([i.properties[t]])),_(e,n);break;case"pair":Object.getOwnPropertyNames(n).forEach(o=>{const s=n[o];Array.isArray(s)?s.forEach(n=>{e.write(r.from([i.properties[t]])),w(e,o.toString(),n.toString())}):(e.write(r.from([i.properties[t]])),w(e,o.toString(),s.toString()))});break;default:return e.destroy(new Error(`Invalid property ${t} value: ${n}`)),!1}}function O(e,t,n){S(e,n);for(const n in t)if(Object.prototype.hasOwnProperty.call(t,n)&&null!=t[n]){const i=t[n];if(Array.isArray(i))for(let t=0;t<i.length;t++)T(e,n,i[t]);else T(e,n,i)}}function P(e){return e?e instanceof r?e.length:r.byteLength(e):0}function A(e){return"string"==typeof e||e instanceof r}e.exports=y},3141(e,t,n){"use strict";var i=n(2861).Buffer,r=i.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function o(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(i.isEncoding===r||!r(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=l,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=d,this.end=u,t=3;break;default:return this.write=p,void(this.end=h)}this.lastNeed=0,this.lastTotal=0,this.lastChar=i.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,n=function(e,t){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var i=n.charCodeAt(n.length-1);if(i>=55296&&i<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function l(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function d(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function u(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function p(e){return e.toString(this.encoding)}function h(e){return e&&e.length?this.write(e):""}t.StringDecoder=o,o.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||""},o.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},o.prototype.text=function(e,t){var n=function(e,t,n){var i=t.length-1;if(i<n)return 0;var r=s(t[i]);if(r>=0)return r>0&&(e.lastNeed=r-1),r;if(--i<n||-2===r)return 0;if(r=s(t[i]),r>=0)return r>0&&(e.lastNeed=r-2),r;if(--i<n||-2===r)return 0;if(r=s(t[i]),r>=0)return r>0&&(2===r?r=0:e.lastNeed=r-3),r;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var i=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,i),e.toString("utf8",t,i)},o.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},3175(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=i(n(7732));t.default=class{_keepalive;timerId;timer;destroyed=!1;counter;client;_keepaliveTimeoutTimestamp;_intervalEvery;get keepaliveTimeoutTimestamp(){return this._keepaliveTimeoutTimestamp}get intervalEvery(){return this._intervalEvery}get keepalive(){return this._keepalive}constructor(e,t){this.client=e,this.timer="object"==typeof t&&"set"in t&&"clear"in t?t:(0,r.default)(t),this.setKeepalive(e.options.keepalive)}clear(){this.timerId&&(this.timer.clear(this.timerId),this.timerId=null)}setKeepalive(e){if(e*=1e3,isNaN(e)||e<=0||e>2147483647)throw new Error(`Keepalive value must be an integer between 0 and 2147483647. Provided value is ${e}`);this._keepalive=e,this.reschedule(),this.client.log(`KeepaliveManager: set keepalive to ${e}ms`)}destroy(){this.clear(),this.destroyed=!0}reschedule(){if(this.destroyed)return;this.clear(),this.counter=0;const e=Math.ceil(1.5*this._keepalive);this._keepaliveTimeoutTimestamp=Date.now()+e,this._intervalEvery=Math.ceil(this._keepalive/2),this.timerId=this.timer.set(()=>{this.destroyed||(this.counter+=1,2===this.counter?this.client.sendPing():this.counter>2&&this.client.onKeepaliveTimeout())},this._intervalEvery)}}},3225(e){"use strict";"undefined"==typeof process||!process.version||0===process.version.indexOf("v0.")||0===process.version.indexOf("v1.")&&0!==process.version.indexOf("v1.8.")?e.exports={nextTick:function(e,t,n,i){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var r,o,s=arguments.length;switch(s){case 0:case 1:return process.nextTick(e);case 2:return process.nextTick(function(){e.call(null,t)});case 3:return process.nextTick(function(){e.call(null,t,n)});case 4:return process.nextTick(function(){e.call(null,t,n,i)});default:for(r=new Array(s-1),o=0;o<r.length;)r[o++]=arguments[o];return process.nextTick(function(){e.apply(null,r)})}}}:e.exports=process},3338(e,t,n){"use strict";const{EMPTY_BUFFER:i}=n(2614),r=Buffer[Symbol.species];function o(e,t,n,i,r){for(let o=0;o<r;o++)n[i+o]=e[o]^t[3&o]}function s(e,t){for(let n=0;n<e.length;n++)e[n]^=t[3&n]}if(e.exports={concat:function(e,t){if(0===e.length)return i;if(1===e.length)return e[0];const n=Buffer.allocUnsafe(t);let o=0;for(let t=0;t<e.length;t++){const i=e[t];n.set(i,o),o+=i.length}return o<t?new r(n.buffer,n.byteOffset,o):n},mask:o,toArrayBuffer:function(e){return e.length===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.length)},toBuffer:function e(t){if(e.readOnly=!0,Buffer.isBuffer(t))return t;let n;return t instanceof ArrayBuffer?n=new r(t):ArrayBuffer.isView(t)?n=new r(t.buffer,t.byteOffset,t.byteLength):(n=Buffer.from(t),e.readOnly=!1),n},unmask:s},!process.env.WS_NO_BUFFER_UTIL)try{const t=n(Object(function(){var e=new Error("Cannot find module 'bufferutil'");throw e.code="MODULE_NOT_FOUND",e}()));e.exports.mask=function(e,n,i,r,s){s<48?o(e,n,i,r,s):t.mask(e,n,i,r,s)},e.exports.unmask=function(e,n){e.length<32?s(e,n):t.unmask(e,n)}}catch(e){}},3339(e){"use strict";e.exports=require("module")},3370(e,t,n){"use strict";const{ObjectDefineProperties:i,ObjectGetOwnPropertyDescriptor:r,ObjectKeys:o,ObjectSetPrototypeOf:s}=n(4134);e.exports=l;const a=n(7576),c=n(8584);s(l.prototype,a.prototype),s(l,a);{const e=o(c.prototype);for(let t=0;t<e.length;t++){const n=e[t];l.prototype[n]||(l.prototype[n]=c.prototype[n])}}function l(e){if(!(this instanceof l))return new l(e);a.call(this,e),c.call(this,e),e?(this.allowHalfOpen=!1!==e.allowHalfOpen,!1===e.readable&&(this._readableState.readable=!1,this._readableState.ended=!0,this._readableState.endEmitted=!0),!1===e.writable&&(this._writableState.writable=!1,this._writableState.ending=!0,this._writableState.ended=!0,this._writableState.finished=!0)):this.allowHalfOpen=!0}let d,u;function p(){return void 0===d&&(d={}),d}i(l.prototype,{writable:{__proto__:null,...r(c.prototype,"writable")},writableHighWaterMark:{__proto__:null,...r(c.prototype,"writableHighWaterMark")},writableObjectMode:{__proto__:null,...r(c.prototype,"writableObjectMode")},writableBuffer:{__proto__:null,...r(c.prototype,"writableBuffer")},writableLength:{__proto__:null,...r(c.prototype,"writableLength")},writableFinished:{__proto__:null,...r(c.prototype,"writableFinished")},writableCorked:{__proto__:null,...r(c.prototype,"writableCorked")},writableEnded:{__proto__:null,...r(c.prototype,"writableEnded")},writableNeedDrain:{__proto__:null,...r(c.prototype,"writableNeedDrain")},destroyed:{__proto__:null,get(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set(e){this._readableState&&this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}}),l.fromWeb=function(e,t){return p().newStreamDuplexFromReadableWritablePair(e,t)},l.toWeb=function(e){return p().newReadableWritablePairFromDuplex(e)},l.from=function(e){return u||(u=n(6706)),u(e,"body")}},3497(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(4966),r=n(720);t.default=class{aliasToTopic;topicToAlias;max;numberAllocator;length;constructor(e){e>0&&(this.aliasToTopic=new i.LRUCache({max:e}),this.topicToAlias={},this.numberAllocator=new r.NumberAllocator(1,e),this.max=e,this.length=0)}put(e,t){if(0===t||t>this.max)return!1;const n=this.aliasToTopic.get(t);return n&&delete this.topicToAlias[n],this.aliasToTopic.set(t,e),this.topicToAlias[e]=t,this.numberAllocator.use(t),this.length=this.aliasToTopic.size,!0}getTopicByAlias(e){return this.aliasToTopic.get(e)}getAliasByTopic(e){const t=this.topicToAlias[e];return"undefined"!=typeof t&&this.aliasToTopic.get(t),t}clear(){this.aliasToTopic.clear(),this.topicToAlias={},this.numberAllocator.clear(),this.length=0}getLruAlias(){const e=this.numberAllocator.firstVacant();return e||[...this.aliasToTopic.keys()][this.aliasToTopic.size-1]}}},3719(e,t,n){"use strict";n(1060);const{Duplex:i}=n(2203);function r(e){e.emit("close")}function o(){!this.destroyed&&this._writableState.finished&&this.destroy()}function s(e){this.removeListener("error",s),this.destroy(),0===this.listenerCount("error")&&this.emit("error",e)}e.exports=function(e,t){let n=!0;const a=new i({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return e.on("message",function(t,n){const i=!n&&a._readableState.objectMode?t.toString():t;a.push(i)||e.pause()}),e.once("error",function(e){a.destroyed||(n=!1,a.destroy(e))}),e.once("close",function(){a.destroyed||a.push(null)}),a._destroy=function(t,i){if(e.readyState===e.CLOSED)return i(t),void process.nextTick(r,a);let o=!1;e.once("error",function(e){o=!0,i(e)}),e.once("close",function(){o||i(t),process.nextTick(r,a)}),n&&e.terminate()},a._final=function(t){e.readyState!==e.CONNECTING?null!==e._socket&&(e._socket._writableState.finished?(t(),a._readableState.endEmitted&&a.destroy()):(e._socket.once("finish",function(){t()}),e.close())):e.once("open",function(){a._final(t)})},a._read=function(){e.isPaused&&e.resume()},a._write=function(t,n,i){e.readyState!==e.CONNECTING?e.send(t,i):e.once("open",function(){a._write(t,n,i)})},a.on("end",o),a.on("error",s),a}},3763(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shuffleArray=t.SocksClientError=void 0;class n extends Error{constructor(e,t){super(e),this.options=t}}t.SocksClientError=n,t.shuffleArray=function(e){for(let t=e.length-1;t>0;t--){const n=Math.floor(Math.random()*(t+1));[e[t],e[n]]=[e[n],e[t]]}}},3874(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EDITOR_HTML=void 0,t.EDITOR_HTML="<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Spatial Awareness - Topology Editor</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, sans-serif; background: #1a1a2e; color: #eee; min-height: 100vh; }\n .container { display: flex; height: 100vh; }\n .sidebar { width: 300px; background: #16213e; border-right: 1px solid #0f3460; display: flex; flex-direction: column; overflow: hidden; }\n .sidebar-header { padding: 20px; border-bottom: 1px solid #0f3460; }\n .sidebar-header h1 { font-size: 18px; font-weight: 600; margin-bottom: 5px; }\n .sidebar-header p { font-size: 12px; color: #888; }\n .sidebar-content { flex: 1; overflow-y: auto; padding: 15px; }\n .section { margin-bottom: 20px; }\n .section-title { font-size: 12px; font-weight: 600; text-transform: uppercase; color: #888; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }\n .btn { background: #0f3460; color: #fff; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 13px; transition: background 0.2s; }\n .btn:hover { background: #1a4a7a; }\n .btn-primary { background: #e94560; }\n .btn-primary:hover { background: #ff6b6b; }\n .btn-small { padding: 4px 8px; font-size: 11px; }\n .camera-item, .connection-item { background: #0f3460; border-radius: 6px; padding: 12px; margin-bottom: 8px; cursor: pointer; transition: background 0.2s; }\n .camera-item:hover, .connection-item:hover { background: #1a4a7a; }\n .camera-item.selected, .connection-item.selected { outline: 2px solid #e94560; }\n .camera-name { font-weight: 500; margin-bottom: 4px; }\n .camera-info { font-size: 11px; color: #888; }\n .editor { flex: 1; display: flex; flex-direction: column; overflow: hidden; }\n .toolbar { background: #16213e; border-bottom: 1px solid #0f3460; padding: 10px 20px; display: flex; gap: 10px; align-items: center; }\n .toolbar-group { display: flex; gap: 5px; padding-right: 15px; border-right: 1px solid #0f3460; margin-right: 5px; }\n .toolbar-group:last-child { border-right: none; }\n .canvas-container { flex: 1; position: relative; overflow: hidden; background: #0f0f1a; }\n #floor-plan-canvas { position: absolute; top: 0; left: 0; }\n .canvas-placeholder { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #666; }\n .canvas-placeholder h2 { margin-bottom: 15px; }\n .properties-panel { width: 280px; background: #16213e; border-left: 1px solid #0f3460; overflow-y: auto; padding: 15px; }\n .properties-panel h3 { font-size: 14px; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #0f3460; }\n .form-group { margin-bottom: 15px; }\n .form-group label { display: block; font-size: 12px; color: #888; margin-bottom: 5px; }\n .form-group input, .form-group select { width: 100%; padding: 8px 10px; background: #0f3460; border: 1px solid #1a4a7a; border-radius: 4px; color: #fff; font-size: 13px; }\n .form-group input:focus, .form-group select:focus { outline: none; border-color: #e94560; }\n .checkbox-group { display: flex; align-items: center; gap: 8px; }\n .checkbox-group input[type=\"checkbox\"] { width: auto; }\n .transit-time-inputs { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }\n .transit-time-inputs input { text-align: center; }\n .transit-time-labels { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; font-size: 10px; color: #666; text-align: center; }\n .modal-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.7); z-index: 1000; align-items: center; justify-content: center; }\n .modal-overlay.active { display: flex; }\n .modal { background: #16213e; border-radius: 8px; padding: 25px; max-width: 500px; width: 90%; max-height: 80vh; overflow-y: auto; }\n .modal h2 { margin-bottom: 20px; }\n .modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }\n .upload-zone { border: 2px dashed #0f3460; border-radius: 8px; padding: 40px; text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s; }\n .upload-zone:hover { border-color: #e94560; background: rgba(233, 69, 96, 0.1); }\n .upload-zone input { display: none; }\n .status-bar { background: #0f3460; padding: 8px 20px; font-size: 12px; color: #888; display: flex; justify-content: space-between; }\n .status-indicator { display: flex; align-items: center; gap: 6px; }\n .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #4caf50; }\n .status-dot.warning { background: #ff9800; }\n .status-dot.error { background: #f44336; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"sidebar\">\n <div class=\"sidebar-header\">\n <h1>Spatial Awareness</h1>\n <p>Topology Editor</p>\n </div>\n <div class=\"sidebar-content\">\n <div class=\"section\" style=\"background: #1a3a5c; margin: -10px -15px 10px -15px; padding: 15px;\">\n <div class=\"section-title\" style=\"margin-bottom: 10px;\">\n <span>Floor Plan Scale</span>\n </div>\n <div style=\"display: flex; gap: 10px; align-items: center;\">\n <input type=\"number\" id=\"scale-input\" value=\"5\" min=\"1\" max=\"50\" style=\"width: 60px; padding: 6px; background: #0f3460; border: 1px solid #1a4a7a; border-radius: 4px; color: #fff;\" onchange=\"updateScale(this.value)\">\n <span style=\"font-size: 12px; color: #888;\">pixels per foot</span>\n <button class=\"btn btn-small\" onclick=\"openScaleHelper()\" style=\"margin-left: auto;\">Help</button>\n </div>\n <div style=\"font-size: 11px; color: #666; margin-top: 8px;\">\n Tip: If your floor plan is 800px wide and represents 80ft, scale = 10 px/ft\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Cameras</span>\n <button class=\"btn btn-small\" onclick=\"openAddCameraModal()\">+ Add</button>\n </div>\n <div id=\"camera-list\">\n <div class=\"camera-item\" style=\"color: #666; text-align: center; cursor: default;\">No cameras configured</div>\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Connections</span>\n <button class=\"btn btn-small\" onclick=\"openAddConnectionModal()\">+ Add</button>\n </div>\n <div id=\"connection-list\">\n <div class=\"connection-item\" style=\"color: #666; text-align: center; cursor: default;\">No connections configured</div>\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Landmarks</span>\n <button class=\"btn btn-small\" onclick=\"openAddLandmarkModal()\">+ Add</button>\n </div>\n <div id=\"landmark-list\">\n <div class=\"landmark-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No landmarks configured</div>\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Zones</span>\n <button class=\"btn btn-small\" onclick=\"setTool('zone')\" style=\"background: #2e7d32;\">+ Draw</button>\n </div>\n <div id=\"zone-list\">\n <div class=\"zone-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No zones drawn</div>\n </div>\n </div>\n <div class=\"section\" id=\"suggestions-section\" style=\"display: none;\">\n <div class=\"section-title\">\n <span>AI Suggestions</span>\n <button class=\"btn btn-small\" onclick=\"loadSuggestions()\">Refresh</button>\n </div>\n <div id=\"suggestions-list\"></div>\n </div>\n <div class=\"section\" id=\"connection-suggestions-section\" style=\"display: none;\">\n <div class=\"section-title\">\n <span>Connection Suggestions</span>\n <button class=\"btn btn-small\" onclick=\"loadConnectionSuggestions()\">Refresh</button>\n </div>\n <div id=\"connection-suggestions-list\"></div>\n </div>\n <div class=\"section\" id=\"discovery-section\">\n <div class=\"section-title\">\n <span>Auto-Discovery</span>\n <button class=\"btn btn-small btn-primary\" id=\"scan-now-btn\" onclick=\"runDiscoveryScan()\">Scan Now</button>\n </div>\n <div id=\"discovery-status\" style=\"font-size: 11px; color: #888; margin-bottom: 8px;\">\n <span id=\"discovery-status-text\">Position cameras first, then scan</span>\n </div>\n <div id=\"discovery-suggestions-list\"></div>\n </div>\n <div class=\"section\" id=\"live-tracking-section\">\n <div class=\"section-title\">\n <span>Live Tracking</span>\n <label class=\"checkbox-group\" style=\"font-size: 11px; font-weight: normal; text-transform: none;\">\n <input type=\"checkbox\" id=\"live-tracking-toggle\" onchange=\"toggleLiveTracking(this.checked)\">\n Enable\n </label>\n </div>\n <div id=\"live-tracking-list\" style=\"max-height: 150px; overflow-y: auto;\"></div>\n </div>\n </div>\n </div>\n <div class=\"editor\">\n <div class=\"toolbar\">\n <div class=\"toolbar-group\">\n <button class=\"btn\" onclick=\"uploadFloorPlan()\">Upload Image</button>\n <button class=\"btn\" onclick=\"useBlankCanvas()\">Blank Canvas</button>\n </div>\n <div class=\"toolbar-group\">\n <button class=\"btn\" id=\"tool-select\" onclick=\"setTool('select')\">Select</button>\n <button class=\"btn\" id=\"tool-wall\" onclick=\"setTool('wall')\">Draw Wall</button>\n <button class=\"btn\" id=\"tool-room\" onclick=\"setTool('room')\">Draw Room</button>\n <button class=\"btn\" id=\"tool-zone\" onclick=\"setTool('zone')\" style=\"background: #2e7d32;\">Draw Zone</button>\n <button class=\"btn\" id=\"tool-camera\" onclick=\"setTool('camera')\">Place Camera</button>\n <button class=\"btn\" id=\"tool-landmark\" onclick=\"setTool('landmark')\">Place Landmark</button>\n <button class=\"btn\" id=\"tool-connect\" onclick=\"setTool('connect')\">Connect</button>\n </div>\n <div class=\"toolbar-group\">\n <button class=\"btn\" onclick=\"clearDrawings()\">Clear Drawings</button>\n <button class=\"btn\" onclick=\"clearAllTopology()\" style=\"background: #dc2626;\">Delete All</button>\n </div>\n <div class=\"toolbar-group\">\n <button class=\"btn btn-primary\" onclick=\"saveTopology()\">Save</button>\n </div>\n </div>\n <div class=\"canvas-container\">\n <canvas id=\"floor-plan-canvas\"></canvas>\n <div class=\"canvas-placeholder\" id=\"canvas-placeholder\">\n <h2>Floor Plan Editor</h2>\n <p>Upload an image or use a blank canvas to draw your floor plan</p>\n <br>\n <div style=\"display: flex; gap: 15px; justify-content: center;\">\n <button class=\"btn btn-primary\" onclick=\"uploadFloorPlan()\">Upload Image</button>\n <button class=\"btn\" onclick=\"useBlankCanvas()\">Use Blank Canvas</button>\n </div>\n </div>\n </div>\n <div class=\"status-bar\">\n <div class=\"status-indicator\">\n <div class=\"status-dot\" id=\"status-dot\"></div>\n <span id=\"status-text\">Ready</span>\n </div>\n <div>\n <span id=\"camera-count\">0</span> cameras | <span id=\"connection-count\">0</span> connections | <span id=\"landmark-count\">0</span> landmarks\n </div>\n </div>\n </div>\n <div class=\"properties-panel\" id=\"properties-panel\">\n <h3>Properties</h3>\n <p style=\"color: #666; font-size: 13px;\">Select a camera or connection to edit its properties.</p>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-camera-modal\">\n <div class=\"modal\">\n <h2>Add Camera</h2>\n <div class=\"form-group\">\n <label>Camera Device</label>\n <select id=\"camera-device-select\"><option value=\"\">Loading cameras...</option></select>\n </div>\n <div class=\"form-group\">\n <label>Display Name</label>\n <input type=\"text\" id=\"camera-name-input\" placeholder=\"e.g., Front Door Camera\">\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"camera-entry-checkbox\">\n Entry Point (objects can enter property here)\n </label>\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"camera-exit-checkbox\">\n Exit Point (objects can exit property here)\n </label>\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('add-camera-modal')\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"addCamera()\">Add Camera</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-connection-modal\">\n <div class=\"modal\">\n <h2>Add Connection</h2>\n <div class=\"form-group\">\n <label>Connection Name</label>\n <input type=\"text\" id=\"connection-name-input\" placeholder=\"e.g., Driveway to Front Door\">\n </div>\n <div class=\"form-group\">\n <label>From Camera</label>\n <select id=\"connection-from-select\"></select>\n </div>\n <div class=\"form-group\">\n <label>To Camera</label>\n <select id=\"connection-to-select\"></select>\n </div>\n <div class=\"form-group\">\n <label>Transit Time (seconds)</label>\n <div class=\"transit-time-inputs\">\n <input type=\"number\" id=\"transit-min\" placeholder=\"Min\" value=\"3\">\n <input type=\"number\" id=\"transit-typical\" placeholder=\"Typical\" value=\"10\">\n <input type=\"number\" id=\"transit-max\" placeholder=\"Max\" value=\"30\">\n </div>\n <div class=\"transit-time-labels\">\n <span>Minimum</span>\n <span>Typical</span>\n <span>Maximum</span>\n </div>\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"connection-bidirectional\" checked>\n Bidirectional (works both ways)\n </label>\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('add-connection-modal')\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"addConnection()\">Add Connection</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"upload-modal\">\n <div class=\"modal\">\n <h2>Upload Floor Plan</h2>\n <div class=\"upload-zone\" onclick=\"document.getElementById('floor-plan-input').click()\">\n <p>Click to select an image<br><small>PNG, JPG, or SVG</small></p>\n <input type=\"file\" id=\"floor-plan-input\" accept=\"image/*\" onchange=\"handleFloorPlanUpload(event)\">\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('upload-modal')\">Cancel</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-landmark-modal\">\n <div class=\"modal\">\n <h2>Add Landmark</h2>\n <div class=\"form-group\">\n <label>Landmark Type</label>\n <select id=\"landmark-type-select\" onchange=\"updateLandmarkSuggestions()\">\n <option value=\"structure\">Structure (House, Garage, Shed)</option>\n <option value=\"feature\">Feature (Mailbox, Tree, Pool)</option>\n <option value=\"boundary\">Boundary (Fence, Wall, Hedge)</option>\n <option value=\"access\">Access (Driveway, Walkway, Gate)</option>\n <option value=\"vehicle\">Vehicle (Parking, Boat, RV)</option>\n <option value=\"neighbor\">Neighbor (House, Driveway)</option>\n <option value=\"zone\">Zone (Front Yard, Back Yard)</option>\n <option value=\"street\">Street (Street, Sidewalk, Alley)</option>\n </select>\n </div>\n <div class=\"form-group\">\n <label>Quick Templates</label>\n <div id=\"landmark-templates\" style=\"display: flex; flex-wrap: wrap; gap: 5px;\"></div>\n </div>\n <div class=\"form-group\">\n <label>Name</label>\n <input type=\"text\" id=\"landmark-name-input\" placeholder=\"e.g., Front Porch, Red Shed\">\n </div>\n <div class=\"form-group\">\n <label>Description (optional)</label>\n <input type=\"text\" id=\"landmark-desc-input\" placeholder=\"Brief description for AI context\">\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"landmark-entry-checkbox\">\n Entry Point (people can enter property here)\n </label>\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"landmark-exit-checkbox\">\n Exit Point (people can exit property here)\n </label>\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('add-landmark-modal')\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"addLandmark()\">Add Landmark</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-zone-modal\">\n <div class=\"modal\">\n <h2>Create Zone</h2>\n <p style=\"color: #888; margin-bottom: 15px; font-size: 13px;\">Click points on the canvas to draw a polygon. Double-click or press Enter to finish.</p>\n <div class=\"form-group\">\n <label>Zone Name</label>\n <input type=\"text\" id=\"zone-name-input\" placeholder=\"e.g., Front Yard\">\n </div>\n <div class=\"form-group\">\n <label>Zone Type</label>\n <select id=\"zone-type-select\">\n <option value=\"yard\">Yard</option>\n <option value=\"driveway\">Driveway</option>\n <option value=\"street\">Street</option>\n <option value=\"patio\">Patio/Deck</option>\n <option value=\"walkway\">Walkway</option>\n <option value=\"parking\">Parking</option>\n <option value=\"garden\">Garden</option>\n <option value=\"pool\">Pool Area</option>\n <option value=\"garage\">Garage</option>\n <option value=\"entrance\">Entrance</option>\n <option value=\"custom\">Custom</option>\n </select>\n </div>\n <div class=\"form-group\">\n <label>Description (optional)</label>\n <input type=\"text\" id=\"zone-desc-input\" placeholder=\"e.g., Main front lawn area\">\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"cancelZoneDrawing()\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"startZoneDrawing()\">Start Drawing</button>\n </div>\n </div>\n </div>\n\n <script>\n let topology = { version: '2.0', cameras: [], connections: [], globalZones: [], landmarks: [], relationships: [], floorPlan: null, drawings: [] };\n let selectedItem = null;\n let currentTool = 'select';\n let floorPlanImage = null;\n let availableCameras = [];\n let landmarkTemplates = [];\n let pendingSuggestions = [];\n let connectionSuggestions = [];\n let liveTrackingData = { objects: [], timestamp: 0 };\n let liveTrackingEnabled = false;\n let liveTrackingInterval = null;\n let selectedJourneyId = null;\n let journeyPath = null;\n let isDrawing = false;\n let drawStart = null;\n let currentDrawing = null;\n let blankCanvasMode = false;\n\n // Floor plan scale: pixels per foot (default assumes ~5 pixels per foot for a typical floor plan)\n // User can adjust this by setting the scale\n let floorPlanScale = 5; // pixels per foot\n\n // Helper functions for scale conversion\n function feetToPixels(feet) { return feet * floorPlanScale; }\n function pixelsToFeet(pixels) { return pixels / floorPlanScale; }\n\n // Zone drawing state\n let zoneDrawingMode = false;\n let currentZonePoints = [];\n let pendingZoneConfig = null;\n\n // Zone colors by type\n const ZONE_COLORS = {\n yard: 'rgba(76, 175, 80, 0.3)',\n driveway: 'rgba(158, 158, 158, 0.3)',\n street: 'rgba(96, 96, 96, 0.3)',\n patio: 'rgba(255, 152, 0, 0.3)',\n walkway: 'rgba(121, 85, 72, 0.3)',\n parking: 'rgba(189, 189, 189, 0.3)',\n garden: 'rgba(139, 195, 74, 0.3)',\n pool: 'rgba(33, 150, 243, 0.3)',\n garage: 'rgba(117, 117, 117, 0.3)',\n entrance: 'rgba(233, 30, 99, 0.3)',\n custom: 'rgba(156, 39, 176, 0.3)',\n };\n const ZONE_STROKE_COLORS = {\n yard: '#4caf50',\n driveway: '#9e9e9e',\n street: '#606060',\n patio: '#ff9800',\n walkway: '#795548',\n parking: '#bdbdbd',\n garden: '#8bc34a',\n pool: '#2196f3',\n garage: '#757575',\n entrance: '#e91e63',\n custom: '#9c27b0',\n };\n\n const canvas = document.getElementById('floor-plan-canvas');\n const ctx = canvas.getContext('2d');\n\n async function init() {\n await loadTopology();\n await loadAvailableCameras();\n await loadLandmarkTemplates();\n await loadSuggestions();\n await loadConnectionSuggestions();\n await loadDiscoveryStatus();\n await loadDiscoverySuggestions();\n resizeCanvas();\n render();\n updateUI();\n }\n\n async function loadTopology() {\n try {\n const response = await fetch('../api/topology');\n if (response.ok) {\n topology = await response.json();\n if (!topology.drawings) topology.drawings = [];\n // Load floor plan scale if saved\n if (topology.floorPlanScale) {\n floorPlanScale = topology.floorPlanScale;\n const scaleInput = document.getElementById('scale-input');\n if (scaleInput) scaleInput.value = floorPlanScale;\n }\n // Load floor plan from separate storage (handles legacy imageData in topology too)\n if (topology.floorPlan?.imageData) {\n // Legacy: imageData was stored in topology\n await loadFloorPlanImage(topology.floorPlan.imageData);\n } else if (topology.floorPlan?.type === 'blank') {\n blankCanvasMode = true;\n } else {\n // Always try to load from floor-plan endpoint (handles uploaded and missing cases)\n try {\n const fpResponse = await fetch('../api/floor-plan');\n if (fpResponse.ok) {\n const fpData = await fpResponse.json();\n if (fpData.imageData) {\n await loadFloorPlanImage(fpData.imageData);\n // Update topology reference if not set\n if (!topology.floorPlan || topology.floorPlan.type !== 'uploaded') {\n topology.floorPlan = { type: 'uploaded', width: floorPlanImage.width, height: floorPlanImage.height };\n }\n }\n }\n } catch (err) { console.error('Failed to load floor plan:', err); }\n }\n }\n } catch (e) { console.error('Failed to load topology:', e); }\n }\n\n async function loadAvailableCameras() {\n try {\n const response = await fetch('../api/cameras');\n if (response.ok) {\n availableCameras = await response.json();\n } else {\n availableCameras = [];\n }\n } catch (e) {\n console.error('Failed to load cameras:', e);\n availableCameras = [];\n }\n updateCameraSelects();\n }\n\n async function loadLandmarkTemplates() {\n try {\n const response = await fetch('../api/landmark-templates');\n if (response.ok) {\n const data = await response.json();\n landmarkTemplates = data.templates || [];\n }\n } catch (e) { console.error('Failed to load landmark templates:', e); }\n }\n\n async function loadSuggestions() {\n try {\n const response = await fetch('../api/landmark-suggestions');\n if (response.ok) {\n const data = await response.json();\n pendingSuggestions = data.suggestions || [];\n updateSuggestionsUI();\n }\n } catch (e) { console.error('Failed to load suggestions:', e); }\n }\n\n function updateSuggestionsUI() {\n const section = document.getElementById('suggestions-section');\n const list = document.getElementById('suggestions-list');\n if (pendingSuggestions.length === 0) {\n section.style.display = 'none';\n return;\n }\n section.style.display = 'block';\n list.innerHTML = pendingSuggestions.map(s =>\n '<div class=\"camera-item\" style=\"display: flex; justify-content: space-between; align-items: center;\">' +\n '<div><div class=\"camera-name\">' + s.landmark.name + '</div>' +\n '<div class=\"camera-info\">' + s.landmark.type + ' - ' + Math.round((s.landmark.aiConfidence || 0) * 100) + '% confidence</div></div>' +\n '<div style=\"display: flex; gap: 5px;\">' +\n '<button class=\"btn btn-small btn-primary\" onclick=\"acceptSuggestion(\\'' + s.id + '\\')\">Accept</button>' +\n '<button class=\"btn btn-small\" onclick=\"rejectSuggestion(\\'' + s.id + '\\')\">Reject</button>' +\n '</div></div>'\n ).join('');\n }\n\n async function acceptSuggestion(id) {\n try {\n const response = await fetch('../api/landmark-suggestions/' + id + '/accept', { method: 'POST' });\n if (response.ok) {\n const data = await response.json();\n if (data.landmark) {\n topology.landmarks.push(data.landmark);\n updateUI();\n render();\n }\n await loadSuggestions();\n setStatus('Landmark accepted', 'success');\n }\n } catch (e) { console.error('Failed to accept suggestion:', e); }\n }\n\n async function rejectSuggestion(id) {\n try {\n await fetch('../api/landmark-suggestions/' + id + '/reject', { method: 'POST' });\n await loadSuggestions();\n setStatus('Suggestion rejected', 'success');\n } catch (e) { console.error('Failed to reject suggestion:', e); }\n }\n\n // ==================== Connection Suggestions ====================\n async function loadConnectionSuggestions() {\n try {\n const response = await fetch('../api/connection-suggestions');\n if (response.ok) {\n const data = await response.json();\n connectionSuggestions = data.suggestions || [];\n updateConnectionSuggestionsUI();\n }\n } catch (e) { console.error('Failed to load connection suggestions:', e); }\n }\n\n function updateConnectionSuggestionsUI() {\n const section = document.getElementById('connection-suggestions-section');\n const list = document.getElementById('connection-suggestions-list');\n if (connectionSuggestions.length === 0) {\n section.style.display = 'none';\n return;\n }\n section.style.display = 'block';\n list.innerHTML = connectionSuggestions.map(s =>\n '<div class=\"camera-item\" style=\"display: flex; justify-content: space-between; align-items: center;\">' +\n '<div><div class=\"camera-name\">' + s.fromCameraName + ' → ' + s.toCameraName + '</div>' +\n '<div class=\"camera-info\">' + Math.round(s.suggestedTransitTime.typical / 1000) + 's typical, ' +\n Math.round(s.confidence * 100) + '% confidence</div></div>' +\n '<div style=\"display: flex; gap: 5px;\">' +\n '<button class=\"btn btn-small btn-primary\" onclick=\"acceptConnectionSuggestion(\\'' + s.id + '\\')\">Accept</button>' +\n '<button class=\"btn btn-small\" onclick=\"rejectConnectionSuggestion(\\'' + s.id + '\\')\">Reject</button>' +\n '</div></div>'\n ).join('');\n }\n\n async function acceptConnectionSuggestion(id) {\n try {\n const response = await fetch('../api/connection-suggestions/' + encodeURIComponent(id) + '/accept', { method: 'POST' });\n if (response.ok) {\n const data = await response.json();\n if (data.connection) {\n topology.connections.push(data.connection);\n updateUI();\n render();\n }\n await loadConnectionSuggestions();\n setStatus('Connection accepted', 'success');\n }\n } catch (e) { console.error('Failed to accept connection suggestion:', e); }\n }\n\n async function rejectConnectionSuggestion(id) {\n try {\n await fetch('../api/connection-suggestions/' + encodeURIComponent(id) + '/reject', { method: 'POST' });\n await loadConnectionSuggestions();\n setStatus('Connection suggestion rejected', 'success');\n } catch (e) { console.error('Failed to reject connection suggestion:', e); }\n }\n\n // ==================== Auto-Discovery ====================\n let discoverySuggestions = [];\n let discoveryStatus = { isScanning: false, lastScanTime: null, pendingSuggestions: 0 };\n\n async function loadDiscoveryStatus() {\n try {\n const response = await fetch('../api/discovery/status');\n if (response.ok) {\n discoveryStatus = await response.json();\n updateDiscoveryStatusUI();\n }\n } catch (e) { console.error('Failed to load discovery status:', e); }\n }\n\n async function loadDiscoverySuggestions() {\n try {\n const response = await fetch('../api/discovery/suggestions');\n if (response.ok) {\n const data = await response.json();\n discoverySuggestions = data.suggestions || [];\n updateDiscoverySuggestionsUI();\n }\n } catch (e) { console.error('Failed to load discovery suggestions:', e); }\n }\n\n function updateDiscoveryStatusUI() {\n const statusText = document.getElementById('discovery-status-text');\n const scanBtn = document.getElementById('scan-now-btn');\n\n if (discoveryStatus.isScanning) {\n statusText.textContent = 'Scanning cameras...';\n scanBtn.disabled = true;\n scanBtn.textContent = 'Scanning...';\n } else if (discoveryStatus.lastScanTime) {\n const ago = Math.round((Date.now() - discoveryStatus.lastScanTime) / 1000 / 60);\n const agoStr = ago < 1 ? 'just now' : ago + 'm ago';\n statusText.textContent = 'Last scan: ' + agoStr + ' | ' + discoveryStatus.pendingSuggestions + ' suggestions';\n scanBtn.disabled = false;\n scanBtn.textContent = 'Scan Now';\n } else {\n statusText.textContent = 'Not scanned yet';\n scanBtn.disabled = false;\n scanBtn.textContent = 'Scan Now';\n }\n }\n\n function updateDiscoverySuggestionsUI() {\n const list = document.getElementById('discovery-suggestions-list');\n if (discoverySuggestions.length === 0) {\n list.innerHTML = '<div style=\"color: #666; font-size: 11px; text-align: center; padding: 8px;\">No pending suggestions</div>';\n return;\n }\n list.innerHTML = discoverySuggestions.map(s => {\n const name = s.type === 'landmark' ? s.landmark?.name : (s.type === 'connection' ? s.connection?.via : s.zone?.name);\n const typeLabel = s.type === 'landmark' ? s.landmark?.type : s.type;\n return '<div class=\"camera-item\" style=\"display: flex; justify-content: space-between; align-items: center; padding: 8px;\">' +\n '<div><div class=\"camera-name\" style=\"font-size: 12px;\">' + (name || 'Unknown') + '</div>' +\n '<div class=\"camera-info\">' + typeLabel + ' - ' + Math.round(s.confidence * 100) + '% confidence</div></div>' +\n '<div style=\"display: flex; gap: 4px;\">' +\n '<button class=\"btn btn-small btn-primary\" onclick=\"acceptDiscoverySuggestion(\\'' + s.id + '\\')\">✓</button>' +\n '<button class=\"btn btn-small\" onclick=\"rejectDiscoverySuggestion(\\'' + s.id + '\\')\">✗</button>' +\n '</div></div>';\n }).join('');\n }\n\n let scanPollingInterval = null;\n\n async function runDiscoveryScan() {\n // Check if cameras are positioned on the floor plan\n const positionedCameras = topology.cameras.filter(c => c.floorPlanPosition);\n if (positionedCameras.length === 0) {\n alert('Please position at least one camera on the floor plan before running discovery.\\n\\nSteps:\\n1. Click \"Place Camera\" in the toolbar\\n2. Click on the floor plan where the camera is located\\n3. Select the camera from the dropdown\\n4. Drag the rotation handle to set its direction\\n5. Then run discovery to detect zones and connections');\n return;\n }\n\n const scanBtn = document.getElementById('scan-now-btn');\n const statusText = document.getElementById('discovery-status-text');\n scanBtn.disabled = true;\n scanBtn.textContent = 'Scanning...';\n setStatus('Starting discovery scan...', 'warning');\n\n // Start polling for live status updates\n let camerasDone = 0;\n scanPollingInterval = setInterval(async () => {\n try {\n const statusResp = await fetch('../api/discovery/status');\n if (statusResp.ok) {\n const status = await statusResp.json();\n if (status.isScanning) {\n statusText.textContent = 'Scanning: ' + status.camerasAnalyzed + ' cameras analyzed...';\n // Check for new suggestions during scan\n if (status.pendingSuggestions > camerasDone) {\n camerasDone = status.pendingSuggestions;\n await loadDiscoverySuggestions();\n }\n }\n }\n } catch (e) { /* ignore polling errors */ }\n }, 1000);\n\n try {\n const response = await fetch('../api/discovery/scan', { method: 'POST' });\n if (response.ok) {\n const result = await response.json();\n discoveryStatus = result.status || discoveryStatus;\n discoverySuggestions = result.suggestions || [];\n updateDiscoveryStatusUI();\n updateDiscoverySuggestionsUI();\n setStatus('Discovery scan complete: ' + discoverySuggestions.length + ' suggestions found', 'success');\n\n // Also reload topology to get any auto-accepted items\n await loadTopology();\n updateUI();\n render();\n } else {\n const error = await response.json();\n setStatus('Scan failed: ' + (error.error || 'Unknown error'), 'error');\n }\n } catch (e) {\n console.error('Discovery scan failed:', e);\n setStatus('Discovery scan failed', 'error');\n } finally {\n // Stop polling\n if (scanPollingInterval) {\n clearInterval(scanPollingInterval);\n scanPollingInterval = null;\n }\n scanBtn.disabled = false;\n scanBtn.textContent = 'Scan Now';\n }\n }\n\n async function acceptDiscoverySuggestion(id) {\n try {\n const response = await fetch('../api/discovery/suggestions/' + id + '/accept', { method: 'POST' });\n if (response.ok) {\n // Reload topology and suggestions\n await loadTopology();\n await loadDiscoverySuggestions();\n updateUI();\n render();\n setStatus('Suggestion accepted', 'success');\n }\n } catch (e) { console.error('Failed to accept discovery suggestion:', e); }\n }\n\n async function rejectDiscoverySuggestion(id) {\n try {\n await fetch('../api/discovery/suggestions/' + id + '/reject', { method: 'POST' });\n await loadDiscoverySuggestions();\n setStatus('Suggestion rejected', 'success');\n } catch (e) { console.error('Failed to reject discovery suggestion:', e); }\n }\n\n // ==================== Live Tracking ====================\n function toggleLiveTracking(enabled) {\n liveTrackingEnabled = enabled;\n if (enabled) {\n loadLiveTracking();\n liveTrackingInterval = setInterval(loadLiveTracking, 2000); // Poll every 2 seconds\n } else {\n if (liveTrackingInterval) {\n clearInterval(liveTrackingInterval);\n liveTrackingInterval = null;\n }\n liveTrackingData = { objects: [], timestamp: 0 };\n selectedJourneyId = null;\n journeyPath = null;\n updateLiveTrackingUI();\n render();\n }\n }\n\n async function loadLiveTracking() {\n try {\n const response = await fetch('../api/live-tracking');\n if (response.ok) {\n liveTrackingData = await response.json();\n updateLiveTrackingUI();\n render();\n }\n } catch (e) { console.error('Failed to load live tracking:', e); }\n }\n\n function updateLiveTrackingUI() {\n const list = document.getElementById('live-tracking-list');\n if (liveTrackingData.objects.length === 0) {\n list.innerHTML = '<div style=\"color: #666; font-size: 12px; text-align: center; padding: 10px;\">No active objects</div>';\n return;\n }\n list.innerHTML = liveTrackingData.objects.map(obj => {\n const isSelected = selectedJourneyId === obj.globalId;\n const ageSeconds = Math.round((Date.now() - obj.lastSeen) / 1000);\n const ageStr = ageSeconds < 60 ? ageSeconds + 's ago' : Math.round(ageSeconds / 60) + 'm ago';\n return '<div class=\"camera-item' + (isSelected ? ' selected' : '') + '\" ' +\n 'onclick=\"selectTrackedObject(\\'' + obj.globalId + '\\')\" ' +\n 'style=\"padding: 8px; cursor: pointer;\">' +\n '<div class=\"camera-name\" style=\"font-size: 12px;\">' +\n (obj.className.charAt(0).toUpperCase() + obj.className.slice(1)) +\n (obj.label ? ' (' + obj.label + ')' : '') + '</div>' +\n '<div class=\"camera-info\">' + obj.lastCameraName + ' • ' + ageStr + '</div>' +\n '</div>';\n }).join('');\n }\n\n async function selectTrackedObject(globalId) {\n if (selectedJourneyId === globalId) {\n // Deselect\n selectedJourneyId = null;\n journeyPath = null;\n } else {\n selectedJourneyId = globalId;\n // Load journey path\n try {\n const response = await fetch('../api/journey-path/' + globalId);\n if (response.ok) {\n journeyPath = await response.json();\n }\n } catch (e) { console.error('Failed to load journey path:', e); }\n }\n updateLiveTrackingUI();\n render();\n }\n\n function openAddLandmarkModal() {\n updateLandmarkSuggestions();\n document.getElementById('add-landmark-modal').classList.add('active');\n }\n\n function updateLandmarkSuggestions() {\n const type = document.getElementById('landmark-type-select').value;\n const template = landmarkTemplates.find(t => t.type === type);\n const container = document.getElementById('landmark-templates');\n if (template) {\n container.innerHTML = template.suggestions.map(s =>\n '<button class=\"btn btn-small\" onclick=\"setLandmarkName(\\'' + s + '\\')\" style=\"margin: 2px;\">' + s + '</button>'\n ).join('');\n } else {\n container.innerHTML = '<span style=\"color: #666; font-size: 12px;\">No templates for this type</span>';\n }\n }\n\n function setLandmarkName(name) {\n document.getElementById('landmark-name-input').value = name;\n }\n\n function addLandmark() {\n const name = document.getElementById('landmark-name-input').value;\n if (!name) { alert('Please enter a landmark name'); return; }\n const type = document.getElementById('landmark-type-select').value;\n const description = document.getElementById('landmark-desc-input').value;\n const isEntry = document.getElementById('landmark-entry-checkbox').checked;\n const isExit = document.getElementById('landmark-exit-checkbox').checked;\n const pos = topology._pendingLandmarkPos || { x: canvas.width / 2 + Math.random() * 100 - 50, y: canvas.height / 2 + Math.random() * 100 - 50 };\n delete topology._pendingLandmarkPos;\n const landmark = {\n id: 'landmark_' + Date.now(),\n name,\n type,\n position: pos,\n description: description || undefined,\n isEntryPoint: isEntry,\n isExitPoint: isExit,\n visibleFromCameras: [],\n };\n if (!topology.landmarks) topology.landmarks = [];\n topology.landmarks.push(landmark);\n closeModal('add-landmark-modal');\n document.getElementById('landmark-name-input').value = '';\n document.getElementById('landmark-desc-input').value = '';\n document.getElementById('landmark-entry-checkbox').checked = false;\n document.getElementById('landmark-exit-checkbox').checked = false;\n updateUI();\n render();\n }\n\n function selectLandmark(id) {\n selectedItem = { type: 'landmark', id };\n const landmark = topology.landmarks.find(l => l.id === id);\n showLandmarkProperties(landmark);\n updateUI();\n render();\n }\n\n function showLandmarkProperties(landmark) {\n const panel = document.getElementById('properties-panel');\n const cameraOptions = topology.cameras.map(c =>\n '<label class=\"checkbox-group\" style=\"margin-bottom: 5px;\"><input type=\"checkbox\" ' +\n ((landmark.visibleFromCameras || []).includes(c.deviceId) ? 'checked' : '') +\n ' onchange=\"toggleLandmarkCamera(\\'' + landmark.id + '\\', \\'' + c.deviceId + '\\', this.checked)\">' +\n c.name + '</label>'\n ).join('');\n panel.innerHTML = '<h3>Landmark Properties</h3>' +\n '<div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + landmark.name + '\" onchange=\"updateLandmarkName(\\'' + landmark.id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Type</label><select onchange=\"updateLandmarkType(\\'' + landmark.id + '\\', this.value)\">' +\n '<option value=\"structure\"' + (landmark.type === 'structure' ? ' selected' : '') + '>Structure</option>' +\n '<option value=\"feature\"' + (landmark.type === 'feature' ? ' selected' : '') + '>Feature</option>' +\n '<option value=\"boundary\"' + (landmark.type === 'boundary' ? ' selected' : '') + '>Boundary</option>' +\n '<option value=\"access\"' + (landmark.type === 'access' ? ' selected' : '') + '>Access</option>' +\n '<option value=\"vehicle\"' + (landmark.type === 'vehicle' ? ' selected' : '') + '>Vehicle</option>' +\n '<option value=\"neighbor\"' + (landmark.type === 'neighbor' ? ' selected' : '') + '>Neighbor</option>' +\n '<option value=\"zone\"' + (landmark.type === 'zone' ? ' selected' : '') + '>Zone</option>' +\n '<option value=\"street\"' + (landmark.type === 'street' ? ' selected' : '') + '>Street</option>' +\n '</select></div>' +\n '<div class=\"form-group\"><label>Description</label><input type=\"text\" value=\"' + (landmark.description || '') + '\" onchange=\"updateLandmarkDesc(\\'' + landmark.id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (landmark.isEntryPoint ? 'checked' : '') + ' onchange=\"updateLandmarkEntry(\\'' + landmark.id + '\\', this.checked)\">Entry Point</label></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (landmark.isExitPoint ? 'checked' : '') + ' onchange=\"updateLandmarkExit(\\'' + landmark.id + '\\', this.checked)\">Exit Point</label></div>' +\n '<div class=\"form-group\"><label>Visible from Cameras</label>' + (cameraOptions || '<span style=\"color:#666;font-size:12px;\">Add cameras first</span>') + '</div>' +\n '<div class=\"form-group\"><button class=\"btn\" style=\"width: 100%; background: #f44336;\" onclick=\"deleteLandmark(\\'' + landmark.id + '\\')\">Delete Landmark</button></div>';\n }\n\n function updateLandmarkName(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.name = value; updateUI(); }\n function updateLandmarkType(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.type = value; render(); }\n function updateLandmarkDesc(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.description = value || undefined; }\n function updateLandmarkEntry(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.isEntryPoint = value; }\n function updateLandmarkExit(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.isExitPoint = value; }\n function toggleLandmarkCamera(landmarkId, cameraId, visible) {\n const l = topology.landmarks.find(x => x.id === landmarkId);\n if (!l) return;\n if (!l.visibleFromCameras) l.visibleFromCameras = [];\n if (visible && !l.visibleFromCameras.includes(cameraId)) {\n l.visibleFromCameras.push(cameraId);\n } else if (!visible) {\n l.visibleFromCameras = l.visibleFromCameras.filter(id => id !== cameraId);\n }\n // Also update camera's visibleLandmarks\n const camera = topology.cameras.find(c => c.deviceId === cameraId);\n if (camera) {\n if (!camera.context) camera.context = {};\n if (!camera.context.visibleLandmarks) camera.context.visibleLandmarks = [];\n if (visible && !camera.context.visibleLandmarks.includes(landmarkId)) {\n camera.context.visibleLandmarks.push(landmarkId);\n } else if (!visible) {\n camera.context.visibleLandmarks = camera.context.visibleLandmarks.filter(id => id !== landmarkId);\n }\n }\n }\n function deleteLandmark(id) {\n if (!confirm('Delete this landmark?')) return;\n topology.landmarks = topology.landmarks.filter(l => l.id !== id);\n selectedItem = null;\n document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select an item to edit.</p>';\n updateUI();\n render();\n }\n\n async function saveTopology() {\n try {\n setStatus('Saving...', 'warning');\n const response = await fetch('../api/topology', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(topology)\n });\n if (response.ok) { setStatus('Saved successfully', 'success'); }\n else { setStatus('Failed to save', 'error'); }\n } catch (e) { console.error('Failed to save topology:', e); setStatus('Failed to save', 'error'); }\n }\n\n function resizeCanvas() {\n const container = canvas.parentElement;\n canvas.width = container.clientWidth;\n canvas.height = container.clientHeight;\n }\n\n function render() {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n // Draw grid for blank canvas\n if (blankCanvasMode && !floorPlanImage) {\n document.getElementById('canvas-placeholder').style.display = 'none';\n ctx.fillStyle = '#1a1a2e';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.strokeStyle = '#2a2a4e';\n ctx.lineWidth = 1;\n const gridSize = 40;\n for (let x = 0; x < canvas.width; x += gridSize) {\n ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke();\n }\n for (let y = 0; y < canvas.height; y += gridSize) {\n ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke();\n }\n } else if (floorPlanImage) {\n document.getElementById('canvas-placeholder').style.display = 'none';\n const scale = Math.min(canvas.width / floorPlanImage.width, canvas.height / floorPlanImage.height) * 0.9;\n const x = (canvas.width - floorPlanImage.width * scale) / 2;\n const y = (canvas.height - floorPlanImage.height * scale) / 2;\n ctx.drawImage(floorPlanImage, x, y, floorPlanImage.width * scale, floorPlanImage.height * scale);\n } else {\n document.getElementById('canvas-placeholder').style.display = 'block';\n }\n\n // Draw saved drawings (walls and rooms)\n if (topology.drawings) {\n for (const drawing of topology.drawings) {\n if (drawing.type === 'wall') {\n ctx.beginPath();\n ctx.moveTo(drawing.x1, drawing.y1);\n ctx.lineTo(drawing.x2, drawing.y2);\n ctx.strokeStyle = '#888';\n ctx.lineWidth = 4;\n ctx.stroke();\n } else if (drawing.type === 'room') {\n ctx.strokeStyle = '#666';\n ctx.lineWidth = 2;\n ctx.strokeRect(drawing.x, drawing.y, drawing.width, drawing.height);\n ctx.fillStyle = 'rgba(100, 100, 150, 0.1)';\n ctx.fillRect(drawing.x, drawing.y, drawing.width, drawing.height);\n if (drawing.label) {\n ctx.fillStyle = '#888';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'center';\n ctx.fillText(drawing.label, drawing.x + drawing.width/2, drawing.y + drawing.height/2);\n }\n }\n }\n }\n\n // Draw current drawing in progress\n if (currentDrawing) {\n if (currentDrawing.type === 'wall') {\n ctx.beginPath();\n ctx.moveTo(currentDrawing.x1, currentDrawing.y1);\n ctx.lineTo(currentDrawing.x2, currentDrawing.y2);\n ctx.strokeStyle = '#e94560';\n ctx.lineWidth = 4;\n ctx.stroke();\n } else if (currentDrawing.type === 'room') {\n ctx.strokeStyle = '#e94560';\n ctx.lineWidth = 2;\n ctx.strokeRect(currentDrawing.x, currentDrawing.y, currentDrawing.width, currentDrawing.height);\n }\n }\n\n // Draw saved zones\n if (topology.drawnZones) {\n for (const zone of topology.drawnZones) {\n drawZone(zone);\n }\n }\n\n // Draw zone currently being drawn\n if (zoneDrawingMode && currentZonePoints.length > 0) {\n const color = pendingZoneConfig ? (ZONE_COLORS[pendingZoneConfig.type] || ZONE_COLORS.custom) : 'rgba(233, 69, 96, 0.3)';\n const strokeColor = pendingZoneConfig ? (ZONE_STROKE_COLORS[pendingZoneConfig.type] || ZONE_STROKE_COLORS.custom) : '#e94560';\n\n ctx.beginPath();\n ctx.moveTo(currentZonePoints[0].x, currentZonePoints[0].y);\n for (let i = 1; i < currentZonePoints.length; i++) {\n ctx.lineTo(currentZonePoints[i].x, currentZonePoints[i].y);\n }\n // Close the polygon if we have 3+ points\n if (currentZonePoints.length >= 3) {\n ctx.closePath();\n ctx.fillStyle = color;\n ctx.fill();\n }\n ctx.strokeStyle = strokeColor;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Draw points\n for (const pt of currentZonePoints) {\n ctx.beginPath();\n ctx.arc(pt.x, pt.y, 5, 0, Math.PI * 2);\n ctx.fillStyle = strokeColor;\n ctx.fill();\n }\n\n // Draw instruction text\n ctx.fillStyle = '#fff';\n ctx.font = 'bold 12px sans-serif';\n ctx.textAlign = 'left';\n ctx.fillText('Click to add points. Double-click or press Enter to finish. Esc to cancel.', 10, canvas.height - 10);\n }\n\n // Draw landmarks first (below cameras and connections)\n for (const landmark of (topology.landmarks || [])) {\n if (landmark.position) { drawLandmark(landmark); }\n }\n for (const conn of topology.connections) {\n const fromCam = topology.cameras.find(c => c.deviceId === conn.fromCameraId);\n const toCam = topology.cameras.find(c => c.deviceId === conn.toCameraId);\n if (fromCam?.floorPlanPosition && toCam?.floorPlanPosition) {\n drawConnection(fromCam.floorPlanPosition, toCam.floorPlanPosition, conn);\n }\n }\n for (const camera of topology.cameras) {\n if (camera.floorPlanPosition) { drawCamera(camera); }\n }\n\n // Draw journey path if selected\n if (journeyPath && journeyPath.segments.length > 0) {\n drawJourneyPath();\n }\n\n // Draw live tracking objects\n if (liveTrackingEnabled && liveTrackingData.objects.length > 0) {\n drawLiveTrackingObjects();\n }\n }\n\n function drawJourneyPath() {\n if (!journeyPath) return;\n\n ctx.strokeStyle = '#ff6b6b';\n ctx.lineWidth = 3;\n ctx.setLineDash([8, 4]);\n\n // Draw path segments\n for (const segment of journeyPath.segments) {\n if (segment.fromCamera.position && segment.toCamera.position) {\n ctx.beginPath();\n ctx.moveTo(segment.fromCamera.position.x, segment.fromCamera.position.y);\n ctx.lineTo(segment.toCamera.position.x, segment.toCamera.position.y);\n ctx.stroke();\n\n // Draw timestamp indicator\n const midX = (segment.fromCamera.position.x + segment.toCamera.position.x) / 2;\n const midY = (segment.fromCamera.position.y + segment.toCamera.position.y) / 2;\n ctx.fillStyle = 'rgba(255, 107, 107, 0.9)';\n ctx.beginPath();\n ctx.arc(midX, midY, 4, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n\n ctx.setLineDash([]);\n\n // Draw current location indicator\n if (journeyPath.currentLocation?.position) {\n const pos = journeyPath.currentLocation.position;\n // Pulsing dot effect\n const pulse = (Date.now() % 1000) / 1000;\n const radius = 10 + pulse * 5;\n const alpha = 1 - pulse * 0.5;\n\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\n ctx.fillStyle = 'rgba(255, 107, 107, ' + alpha + ')';\n ctx.fill();\n\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, 6, 0, Math.PI * 2);\n ctx.fillStyle = '#ff6b6b';\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n }\n\n function drawLiveTrackingObjects() {\n const objectColors = {\n person: '#4caf50',\n car: '#2196f3',\n animal: '#ff9800',\n default: '#9c27b0'\n };\n\n for (const obj of liveTrackingData.objects) {\n if (!obj.cameraPosition) continue;\n\n // Skip if this is the selected journey object (drawn separately with path)\n if (obj.globalId === selectedJourneyId) continue;\n\n const pos = obj.cameraPosition;\n const color = objectColors[obj.className] || objectColors.default;\n const ageSeconds = (Date.now() - obj.lastSeen) / 1000;\n\n // Fade old objects\n const alpha = Math.max(0.3, 1 - ageSeconds / 60);\n\n // Draw object indicator\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, 12, 0, Math.PI * 2);\n ctx.fillStyle = color.replace(')', ', ' + alpha + ')').replace('rgb', 'rgba');\n ctx.fill();\n ctx.strokeStyle = 'rgba(255, 255, 255, ' + alpha + ')';\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Draw class icon\n ctx.fillStyle = 'rgba(255, 255, 255, ' + alpha + ')';\n ctx.font = 'bold 10px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n const icon = obj.className === 'person' ? 'P' : obj.className === 'car' ? 'C' : obj.className === 'animal' ? 'A' : '?';\n ctx.fillText(icon, pos.x, pos.y);\n\n // Draw label below\n if (obj.label) {\n ctx.font = '9px sans-serif';\n ctx.fillText(obj.label.slice(0, 10), pos.x, pos.y + 20);\n }\n }\n }\n\n function drawZone(zone) {\n if (!zone.polygon || zone.polygon.length < 3) return;\n\n const isSelected = selectedItem?.type === 'zone' && selectedItem?.id === zone.id;\n const fillColor = zone.color || ZONE_COLORS[zone.type] || ZONE_COLORS.custom;\n const strokeColor = ZONE_STROKE_COLORS[zone.type] || ZONE_STROKE_COLORS.custom;\n\n // Draw filled polygon\n ctx.beginPath();\n ctx.moveTo(zone.polygon[0].x, zone.polygon[0].y);\n for (let i = 1; i < zone.polygon.length; i++) {\n ctx.lineTo(zone.polygon[i].x, zone.polygon[i].y);\n }\n ctx.closePath();\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.strokeStyle = isSelected ? '#e94560' : strokeColor;\n ctx.lineWidth = isSelected ? 3 : 2;\n ctx.stroke();\n\n // Draw zone label at centroid\n const centroid = getPolygonCentroid(zone.polygon);\n ctx.fillStyle = isSelected ? '#e94560' : '#fff';\n ctx.font = 'bold 12px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(zone.name, centroid.x, centroid.y);\n ctx.font = '10px sans-serif';\n ctx.fillStyle = '#ccc';\n ctx.fillText(zone.type, centroid.x, centroid.y + 14);\n }\n\n function getPolygonCentroid(polygon) {\n let x = 0, y = 0;\n for (const pt of polygon) {\n x += pt.x;\n y += pt.y;\n }\n return { x: x / polygon.length, y: y / polygon.length };\n }\n\n function drawLandmark(landmark) {\n const pos = landmark.position;\n const isSelected = selectedItem?.type === 'landmark' && selectedItem?.id === landmark.id;\n // Color by type\n const colors = {\n structure: '#8b5cf6', // purple\n feature: '#10b981', // green\n boundary: '#f59e0b', // amber\n access: '#3b82f6', // blue\n vehicle: '#6366f1', // indigo\n neighbor: '#ec4899', // pink\n zone: '#14b8a6', // teal\n street: '#6b7280', // gray\n };\n const color = colors[landmark.type] || '#888';\n // Draw landmark marker\n ctx.beginPath();\n ctx.moveTo(pos.x, pos.y - 15);\n ctx.lineTo(pos.x + 12, pos.y + 8);\n ctx.lineTo(pos.x - 12, pos.y + 8);\n ctx.closePath();\n ctx.fillStyle = isSelected ? '#e94560' : color;\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n // Entry/exit indicators\n if (landmark.isEntryPoint || landmark.isExitPoint) {\n ctx.beginPath();\n ctx.arc(pos.x, pos.y - 20, 5, 0, Math.PI * 2);\n ctx.fillStyle = landmark.isEntryPoint ? '#4caf50' : '#ff9800';\n ctx.fill();\n }\n // Label\n ctx.fillStyle = '#fff';\n ctx.font = '11px sans-serif';\n ctx.textAlign = 'center';\n ctx.fillText(landmark.name, pos.x, pos.y + 25);\n }\n\n function drawCamera(camera) {\n const pos = camera.floorPlanPosition;\n const isSelected = selectedItem?.type === 'camera' && selectedItem?.id === camera.deviceId;\n\n // Get FOV settings or defaults\n const fov = camera.fov || { mode: 'simple', angle: 90, direction: 0, range: 80 };\n const direction = (fov.mode === 'simple' || !fov.mode) ? (fov.direction || 0) : 0;\n const fovAngle = (fov.mode === 'simple' || !fov.mode) ? (fov.angle || 90) : 90;\n const range = (fov.mode === 'simple' || !fov.mode) ? (fov.range || 80) : 80;\n\n // Convert direction to radians (0 = up/north, 90 = right/east)\n const dirRad = (direction - 90) * Math.PI / 180;\n const halfFov = (fovAngle / 2) * Math.PI / 180;\n\n // Draw FOV cone\n ctx.beginPath();\n ctx.moveTo(pos.x, pos.y);\n ctx.arc(pos.x, pos.y, range, dirRad - halfFov, dirRad + halfFov);\n ctx.closePath();\n ctx.fillStyle = isSelected ? 'rgba(233, 69, 96, 0.15)' : 'rgba(76, 175, 80, 0.15)';\n ctx.fill();\n ctx.strokeStyle = isSelected ? 'rgba(233, 69, 96, 0.5)' : 'rgba(76, 175, 80, 0.5)';\n ctx.lineWidth = 1;\n ctx.stroke();\n\n // Draw camera circle\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, 20, 0, Math.PI * 2);\n ctx.fillStyle = isSelected ? '#e94560' : '#0f3460';\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Draw camera icon/text\n ctx.fillStyle = '#fff';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText('CAM', pos.x, pos.y);\n ctx.fillText(camera.name, pos.x, pos.y + 35);\n\n // Draw direction handle (when selected) for rotation\n if (isSelected) {\n const handleLength = 45;\n const handleX = pos.x + Math.cos(dirRad) * handleLength;\n const handleY = pos.y + Math.sin(dirRad) * handleLength;\n\n // Handle line\n ctx.beginPath();\n ctx.moveTo(pos.x + Math.cos(dirRad) * 20, pos.y + Math.sin(dirRad) * 20);\n ctx.lineTo(handleX, handleY);\n ctx.strokeStyle = '#ff6b6b';\n ctx.lineWidth = 3;\n ctx.stroke();\n\n // Handle grip (circle at end)\n ctx.beginPath();\n ctx.arc(handleX, handleY, 8, 0, Math.PI * 2);\n ctx.fillStyle = '#ff6b6b';\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Store handle position for hit detection\n camera._handlePos = { x: handleX, y: handleY };\n }\n }\n\n function drawConnection(from, to, conn) {\n const isSelected = selectedItem?.type === 'connection' && selectedItem?.id === conn.id;\n ctx.beginPath();\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(to.x, to.y);\n ctx.strokeStyle = isSelected ? '#e94560' : '#4caf50';\n ctx.lineWidth = isSelected ? 4 : 2;\n ctx.stroke();\n if (!conn.bidirectional) {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n ctx.beginPath();\n ctx.moveTo(midX, midY);\n ctx.lineTo(midX - 10 * Math.cos(angle - 0.5), midY - 10 * Math.sin(angle - 0.5));\n ctx.lineTo(midX - 10 * Math.cos(angle + 0.5), midY - 10 * Math.sin(angle + 0.5));\n ctx.closePath();\n ctx.fillStyle = isSelected ? '#e94560' : '#4caf50';\n ctx.fill();\n }\n }\n\n function uploadFloorPlan() { document.getElementById('upload-modal').classList.add('active'); }\n\n // Compress and resize image to avoid 413 errors (Scrypted has ~50KB limit)\n function compressImage(img, maxSize = 800, quality = 0.5) {\n return new Promise((resolve) => {\n const canvas = document.createElement('canvas');\n let width = img.width;\n let height = img.height;\n\n // Always resize to fit within maxSize\n if (width > maxSize || height > maxSize) {\n if (width > height) {\n height = Math.round(height * maxSize / width);\n width = maxSize;\n } else {\n width = Math.round(width * maxSize / height);\n height = maxSize;\n }\n }\n\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n ctx.drawImage(img, 0, 0, width, height);\n\n // Convert to JPEG with aggressive compression\n let compressed = canvas.toDataURL('image/jpeg', quality);\n console.log('Compressed image from', img.width, 'x', img.height, 'to', width, 'x', height, 'size:', Math.round(compressed.length / 1024), 'KB');\n\n // If still too large, compress more\n let q = quality;\n while (compressed.length > 50000 && q > 0.1) {\n q -= 0.1;\n compressed = canvas.toDataURL('image/jpeg', q);\n console.log('Re-compressed at quality', q.toFixed(1), 'size:', Math.round(compressed.length / 1024), 'KB');\n }\n\n resolve(compressed);\n });\n }\n\n async function handleFloorPlanUpload(event) {\n const file = event.target.files[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = async (e) => {\n const originalData = e.target.result;\n\n // Load image to get dimensions\n const img = new Image();\n img.onload = async () => {\n // Compress image to reduce size\n const imageData = await compressImage(img);\n await loadFloorPlanImage(imageData);\n\n // Store floor plan separately via API\n try {\n setStatus('Uploading floor plan...', 'warning');\n const response = await fetch('../api/floor-plan', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ imageData })\n });\n if (response.ok) {\n setStatus('Floor plan saved', 'success');\n } else {\n setStatus('Failed to save floor plan: ' + response.status, 'error');\n console.error('Floor plan upload failed:', response.status, response.statusText);\n }\n } catch (err) {\n console.error('Failed to save floor plan:', err);\n setStatus('Failed to save floor plan', 'error');\n }\n\n // Store reference in topology (without the large imageData)\n topology.floorPlan = { type: 'uploaded', width: floorPlanImage.width, height: floorPlanImage.height };\n closeModal('upload-modal');\n render();\n };\n img.src = originalData;\n };\n reader.readAsDataURL(file);\n }\n\n function loadFloorPlanImage(imageData) {\n return new Promise((resolve) => {\n floorPlanImage = new Image();\n floorPlanImage.onload = resolve;\n floorPlanImage.src = imageData;\n });\n }\n\n function openAddCameraModal() { document.getElementById('add-camera-modal').classList.add('active'); }\n\n function addCamera() {\n const deviceId = document.getElementById('camera-device-select').value;\n if (!deviceId) {\n alert('Please select a camera');\n return;\n }\n const selectedCam = availableCameras.find(c => c.id === deviceId);\n const customName = document.getElementById('camera-name-input').value;\n const name = customName || (selectedCam ? selectedCam.name : 'New Camera');\n const isEntry = document.getElementById('camera-entry-checkbox').checked;\n const isExit = document.getElementById('camera-exit-checkbox').checked;\n // Use pending position from click, or default to center\n const pos = topology._pendingCameraPos || { x: canvas.width / 2 + Math.random() * 100 - 50, y: canvas.height / 2 + Math.random() * 100 - 50 };\n delete topology._pendingCameraPos;\n const camera = {\n deviceId: deviceId,\n nativeId: 'cam-' + Date.now(),\n name,\n isEntryPoint: isEntry,\n isExitPoint: isExit,\n trackClasses: ['person', 'car', 'animal'],\n floorPlanPosition: pos\n };\n topology.cameras.push(camera);\n closeModal('add-camera-modal');\n // Clear form\n document.getElementById('camera-name-input').value = '';\n document.getElementById('camera-entry-checkbox').checked = false;\n document.getElementById('camera-exit-checkbox').checked = false;\n updateCameraSelects();\n updateUI();\n render();\n }\n\n function openAddConnectionModal() {\n if (topology.cameras.length < 2) { alert('Add at least 2 cameras before creating connections'); return; }\n updateCameraSelects();\n document.getElementById('add-connection-modal').classList.add('active');\n }\n\n function updateCameraSelects() {\n // Update camera device select (for adding new cameras)\n const cameraDeviceSelect = document.getElementById('camera-device-select');\n if (availableCameras.length > 0) {\n const existingIds = topology.cameras.map(c => c.deviceId);\n const available = availableCameras.filter(c => !existingIds.includes(c.id));\n if (available.length > 0) {\n cameraDeviceSelect.innerHTML = '<option value=\"\">Select a camera...</option>' +\n available.map(c => '<option value=\"' + c.id + '\">' + c.name + '</option>').join('');\n } else {\n cameraDeviceSelect.innerHTML = '<option value=\"\">All cameras already added</option>';\n }\n } else {\n cameraDeviceSelect.innerHTML = '<option value=\"\">No cameras with object detection found</option>';\n }\n\n // Update connection selects (for existing topology cameras)\n const options = topology.cameras.map(c => '<option value=\"' + c.deviceId + '\">' + c.name + '</option>').join('');\n document.getElementById('connection-from-select').innerHTML = options;\n document.getElementById('connection-to-select').innerHTML = options;\n }\n\n function addConnection() {\n const name = document.getElementById('connection-name-input').value;\n const fromId = document.getElementById('connection-from-select').value;\n const toId = document.getElementById('connection-to-select').value;\n const minTransit = parseInt(document.getElementById('transit-min').value) * 1000;\n const typicalTransit = parseInt(document.getElementById('transit-typical').value) * 1000;\n const maxTransit = parseInt(document.getElementById('transit-max').value) * 1000;\n const bidirectional = document.getElementById('connection-bidirectional').checked;\n if (fromId === toId) { alert('Please select different cameras'); return; }\n const connection = {\n id: 'conn-' + Date.now(),\n fromCameraId: fromId,\n toCameraId: toId,\n name: name || fromId + ' to ' + toId,\n exitZone: [],\n entryZone: [],\n transitTime: { min: minTransit, typical: typicalTransit, max: maxTransit },\n bidirectional\n };\n topology.connections.push(connection);\n closeModal('add-connection-modal');\n updateUI();\n render();\n }\n\n function updateUI() {\n const cameraList = document.getElementById('camera-list');\n if (topology.cameras.length === 0) {\n cameraList.innerHTML = '<div class=\"camera-item\" style=\"color: #666; text-align: center; cursor: default;\">No cameras configured</div>';\n } else {\n cameraList.innerHTML = topology.cameras.map(c => '<div class=\"camera-item ' + (selectedItem?.type === 'camera' && selectedItem?.id === c.deviceId ? 'selected' : '') + '\" onclick=\"selectCamera(\\'' + c.deviceId + '\\')\"><div class=\"camera-name\">CAM ' + c.name + '</div><div class=\"camera-info\">' + (c.isEntryPoint ? 'Entry ' : '') + (c.isExitPoint ? 'Exit' : '') + '</div></div>').join('');\n }\n const connectionList = document.getElementById('connection-list');\n if (topology.connections.length === 0) {\n connectionList.innerHTML = '<div class=\"connection-item\" style=\"color: #666; text-align: center; cursor: default;\">No connections configured</div>';\n } else {\n connectionList.innerHTML = topology.connections.map(c => '<div class=\"connection-item ' + (selectedItem?.type === 'connection' && selectedItem?.id === c.id ? 'selected' : '') + '\" onclick=\"selectConnection(\\'' + c.id + '\\')\"><div class=\"camera-name\">' + c.name + '</div><div class=\"camera-info\">' + (c.transitTime.typical / 1000) + 's typical ' + (c.bidirectional ? '<->' : '->') + '</div></div>').join('');\n }\n // Landmark list\n const landmarkList = document.getElementById('landmark-list');\n const landmarks = topology.landmarks || [];\n if (landmarks.length === 0) {\n landmarkList.innerHTML = '<div class=\"landmark-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No landmarks configured</div>';\n } else {\n landmarkList.innerHTML = landmarks.map(l => '<div class=\"camera-item ' + (selectedItem?.type === 'landmark' && selectedItem?.id === l.id ? 'selected' : '') + '\" onclick=\"selectLandmark(\\'' + l.id + '\\')\"><div class=\"camera-name\">' + l.name + '</div><div class=\"camera-info\">' + l.type + (l.isEntryPoint ? ' | Entry' : '') + (l.isExitPoint ? ' | Exit' : '') + '</div></div>').join('');\n }\n // Zone list\n const zoneList = document.getElementById('zone-list');\n const zones = topology.drawnZones || [];\n if (zones.length === 0) {\n zoneList.innerHTML = '<div class=\"zone-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No zones drawn</div>';\n } else {\n zoneList.innerHTML = zones.map(z => {\n const color = ZONE_STROKE_COLORS[z.type] || ZONE_STROKE_COLORS.custom;\n return '<div class=\"camera-item ' + (selectedItem?.type === 'zone' && selectedItem?.id === z.id ? 'selected' : '') + '\" onclick=\"selectZone(\\'' + z.id + '\\')\" style=\"border-left: 3px solid ' + color + ';\"><div class=\"camera-name\">' + z.name + '</div><div class=\"camera-info\">' + z.type + ' | ' + z.polygon.length + ' points</div></div>';\n }).join('');\n }\n document.getElementById('camera-count').textContent = topology.cameras.length;\n document.getElementById('connection-count').textContent = topology.connections.length;\n document.getElementById('landmark-count').textContent = landmarks.length;\n }\n\n function selectCamera(deviceId) {\n selectedItem = { type: 'camera', id: deviceId };\n const camera = topology.cameras.find(c => c.deviceId === deviceId);\n showCameraProperties(camera);\n updateUI();\n render();\n }\n\n function selectConnection(connId) {\n selectedItem = { type: 'connection', id: connId };\n const connection = topology.connections.find(c => c.id === connId);\n showConnectionProperties(connection);\n updateUI();\n render();\n }\n\n function showCameraProperties(camera) {\n const panel = document.getElementById('properties-panel');\n const fov = camera.fov || { mode: 'simple', angle: 90, direction: 0, range: 80 };\n // Convert stored pixel range to feet for display\n const rangeInFeet = Math.round(pixelsToFeet(fov.range || 80));\n panel.innerHTML = '<h3>Camera Properties</h3>' +\n '<div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + camera.name + '\" onchange=\"updateCameraName(\\'' + camera.deviceId + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (camera.isEntryPoint ? 'checked' : '') + ' onchange=\"updateCameraEntry(\\'' + camera.deviceId + '\\', this.checked)\">Entry Point</label></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (camera.isExitPoint ? 'checked' : '') + ' onchange=\"updateCameraExit(\\'' + camera.deviceId + '\\', this.checked)\">Exit Point</label></div>' +\n '<h4 style=\"margin-top: 15px; margin-bottom: 10px; color: #888;\">Field of View</h4>' +\n '<div class=\"form-group\"><label>Direction (0=up, 90=right)</label><input type=\"number\" value=\"' + Math.round(fov.direction || 0) + '\" min=\"0\" max=\"359\" onchange=\"updateCameraFov(\\'' + camera.deviceId + '\\', \\'direction\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>FOV Angle (degrees)</label><input type=\"number\" value=\"' + (fov.angle || 90) + '\" min=\"30\" max=\"180\" onchange=\"updateCameraFov(\\'' + camera.deviceId + '\\', \\'angle\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Range (feet)</label><input type=\"number\" value=\"' + rangeInFeet + '\" min=\"5\" max=\"200\" onchange=\"updateCameraFovRange(\\'' + camera.deviceId + '\\', this.value)\"></div>' +\n '<div style=\"font-size: 11px; color: #666; margin-top: -10px; margin-bottom: 15px;\">~' + (fov.range || 80) + ' pixels at current scale</div>' +\n '<div class=\"form-group\"><button class=\"btn\" style=\"width: 100%; background: #f44336;\" onclick=\"deleteCamera(\\'' + camera.deviceId + '\\')\">Delete Camera</button></div>';\n }\n\n function showConnectionProperties(connection) {\n const panel = document.getElementById('properties-panel');\n panel.innerHTML = '<h3>Connection Properties</h3><div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + connection.name + '\" onchange=\"updateConnectionName(\\'' + connection.id + '\\', this.value)\"></div><div class=\"form-group\"><label>Transit Time (seconds)</label><div class=\"transit-time-inputs\"><input type=\"number\" value=\"' + (connection.transitTime.min / 1000) + '\" onchange=\"updateTransitTime(\\'' + connection.id + '\\', \\'min\\', this.value)\"><input type=\"number\" value=\"' + (connection.transitTime.typical / 1000) + '\" onchange=\"updateTransitTime(\\'' + connection.id + '\\', \\'typical\\', this.value)\"><input type=\"number\" value=\"' + (connection.transitTime.max / 1000) + '\" onchange=\"updateTransitTime(\\'' + connection.id + '\\', \\'max\\', this.value)\"></div><div class=\"transit-time-labels\"><span>Min</span><span>Typical</span><span>Max</span></div></div><div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (connection.bidirectional ? 'checked' : '') + ' onchange=\"updateConnectionBidi(\\'' + connection.id + '\\', this.checked)\">Bidirectional</label></div><div class=\"form-group\"><button class=\"btn\" style=\"width: 100%; background: #f44336;\" onclick=\"deleteConnection(\\'' + connection.id + '\\')\">Delete Connection</button></div>';\n }\n\n function updateCameraName(id, value) { const camera = topology.cameras.find(c => c.deviceId === id); if (camera) camera.name = value; updateUI(); }\n function updateCameraEntry(id, value) { const camera = topology.cameras.find(c => c.deviceId === id); if (camera) camera.isEntryPoint = value; }\n function updateCameraExit(id, value) { const camera = topology.cameras.find(c => c.deviceId === id); if (camera) camera.isExitPoint = value; }\n function updateCameraFov(id, field, value) {\n const camera = topology.cameras.find(c => c.deviceId === id);\n if (!camera) return;\n if (!camera.fov) camera.fov = { mode: 'simple', angle: 90, direction: 0, range: 80 };\n camera.fov[field] = parseFloat(value);\n render();\n }\n function updateCameraFovRange(id, feetValue) {\n // Convert feet to pixels and store\n const camera = topology.cameras.find(c => c.deviceId === id);\n if (!camera) return;\n if (!camera.fov) camera.fov = { mode: 'simple', angle: 90, direction: 0, range: 80 };\n camera.fov.range = feetToPixels(parseFloat(feetValue));\n render();\n // Update the pixel display\n showCameraProperties(camera);\n }\n function updateScale(value) {\n floorPlanScale = parseFloat(value) || 5;\n // Store in topology for persistence\n topology.floorPlanScale = floorPlanScale;\n render();\n setStatus('Scale updated: ' + floorPlanScale + ' pixels per foot', 'success');\n }\n function openScaleHelper() {\n alert('How to determine your floor plan scale:\\n\\n' +\n '1. Measure a known distance on your floor plan in pixels\\n' +\n ' (e.g., measure a room that you know is 20 feet wide)\\n\\n' +\n '2. Divide the pixel width by the real width in feet\\n' +\n ' Example: 200 pixels / 20 feet = 10 pixels per foot\\n\\n' +\n '3. Enter that value in the scale field\\n\\n' +\n 'Common scales:\\n' +\n '- Small floor plan (fits on screen): 3-5 px/ft\\n' +\n '- Medium floor plan: 5-10 px/ft\\n' +\n '- Large/detailed floor plan: 10-20 px/ft\\n\\n' +\n 'Tip: Most outdoor cameras see 30-50 feet, indoor 15-30 feet');\n }\n function updateConnectionName(id, value) { const conn = topology.connections.find(c => c.id === id); if (conn) conn.name = value; updateUI(); }\n function updateTransitTime(id, field, value) { const conn = topology.connections.find(c => c.id === id); if (conn) conn.transitTime[field] = parseInt(value) * 1000; }\n function updateConnectionBidi(id, value) { const conn = topology.connections.find(c => c.id === id); if (conn) conn.bidirectional = value; render(); }\n function deleteCamera(id) { if (!confirm('Delete this camera?')) return; topology.cameras = topology.cameras.filter(c => c.deviceId !== id); topology.connections = topology.connections.filter(c => c.fromCameraId !== id && c.toCameraId !== id); selectedItem = null; document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select a camera or connection.</p>'; updateCameraSelects(); updateUI(); render(); }\n function deleteConnection(id) { if (!confirm('Delete this connection?')) return; topology.connections = topology.connections.filter(c => c.id !== id); selectedItem = null; document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select a camera or connection.</p>'; updateUI(); render(); }\n function setTool(tool) {\n // If switching away from zone tool while drawing, cancel\n if (currentTool === 'zone' && tool !== 'zone' && zoneDrawingMode) {\n cancelZoneDrawing();\n }\n currentTool = tool;\n setStatus('Tool: ' + tool, 'success');\n document.querySelectorAll('.toolbar .btn').forEach(b => b.style.background = '');\n const btn = document.getElementById('tool-' + tool);\n if (btn) btn.style.background = tool === 'zone' ? '#2e7d32' : '#e94560';\n\n // If zone tool selected, open the zone config modal\n if (tool === 'zone') {\n openZoneModal();\n }\n }\n\n // ==================== Zone Drawing Functions ====================\n\n function openZoneModal() {\n document.getElementById('zone-name-input').value = '';\n document.getElementById('zone-type-select').value = 'yard';\n document.getElementById('zone-desc-input').value = '';\n document.getElementById('add-zone-modal').classList.add('active');\n }\n\n function startZoneDrawing() {\n const name = document.getElementById('zone-name-input').value.trim();\n const type = document.getElementById('zone-type-select').value;\n const description = document.getElementById('zone-desc-input').value.trim();\n\n if (!name) {\n alert('Please enter a zone name');\n return;\n }\n\n pendingZoneConfig = { name, type, description };\n zoneDrawingMode = true;\n currentZonePoints = [];\n closeModal('add-zone-modal');\n setStatus('Zone drawing mode - click to add points, double-click to finish', 'warning');\n render();\n }\n\n function cancelZoneDrawing() {\n zoneDrawingMode = false;\n currentZonePoints = [];\n pendingZoneConfig = null;\n closeModal('add-zone-modal');\n setTool('select');\n setStatus('Zone drawing cancelled', 'success');\n render();\n }\n\n function finishZoneDrawing() {\n if (currentZonePoints.length < 3) {\n alert('A zone needs at least 3 points');\n return;\n }\n\n if (!pendingZoneConfig) {\n cancelZoneDrawing();\n return;\n }\n\n // Create the zone\n const zone = {\n id: 'zone_' + Date.now(),\n name: pendingZoneConfig.name,\n type: pendingZoneConfig.type,\n description: pendingZoneConfig.description || undefined,\n polygon: currentZonePoints.map(pt => ({ x: pt.x, y: pt.y })),\n };\n\n if (!topology.drawnZones) topology.drawnZones = [];\n topology.drawnZones.push(zone);\n\n // Reset state\n zoneDrawingMode = false;\n currentZonePoints = [];\n pendingZoneConfig = null;\n\n setTool('select');\n updateUI();\n render();\n setStatus('Zone \"' + zone.name + '\" created with ' + zone.polygon.length + ' points', 'success');\n }\n\n function selectZone(id) {\n selectedItem = { type: 'zone', id };\n showZoneProperties(id);\n render();\n }\n\n function showZoneProperties(id) {\n const zone = (topology.drawnZones || []).find(z => z.id === id);\n if (!zone) return;\n\n const panel = document.getElementById('properties-panel');\n panel.innerHTML = '<h3>Zone Properties</h3>' +\n '<div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + zone.name + '\" onchange=\"updateZoneName(\\'' + id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Type</label><select onchange=\"updateZoneType(\\'' + id + '\\', this.value)\">' +\n ['yard','driveway','street','patio','walkway','parking','garden','pool','garage','entrance','custom'].map(t =>\n '<option value=\"' + t + '\"' + (zone.type === t ? ' selected' : '') + '>' + t.charAt(0).toUpperCase() + t.slice(1) + '</option>'\n ).join('') + '</select></div>' +\n '<div class=\"form-group\"><label>Description</label><input type=\"text\" value=\"' + (zone.description || '') + '\" onchange=\"updateZoneDesc(\\'' + id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Points: ' + zone.polygon.length + '</label></div>' +\n '<button class=\"btn btn-primary\" onclick=\"deleteZone(\\'' + id + '\\')\" style=\"background: #dc2626; width: 100%;\">Delete Zone</button>';\n }\n\n function updateZoneName(id, value) { const z = (topology.drawnZones || []).find(z => z.id === id); if (z) { z.name = value; updateUI(); render(); } }\n function updateZoneType(id, value) { const z = (topology.drawnZones || []).find(z => z.id === id); if (z) { z.type = value; updateUI(); render(); } }\n function updateZoneDesc(id, value) { const z = (topology.drawnZones || []).find(z => z.id === id); if (z) { z.description = value || undefined; } }\n function deleteZone(id) {\n if (!confirm('Delete this zone?')) return;\n topology.drawnZones = (topology.drawnZones || []).filter(z => z.id !== id);\n selectedItem = null;\n document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select an item to edit.</p>';\n updateUI();\n render();\n setStatus('Zone deleted', 'success');\n }\n\n function useBlankCanvas() {\n blankCanvasMode = true;\n floorPlanImage = null;\n topology.floorPlan = { type: 'blank', width: canvas.width, height: canvas.height };\n render();\n setStatus('Blank canvas ready - use Draw Wall or Draw Room tools', 'success');\n }\n\n function clearDrawings() {\n if (!confirm('Clear all drawings (walls and rooms)?')) return;\n topology.drawings = [];\n render();\n setStatus('Drawings cleared', 'success');\n }\n\n function clearAllTopology() {\n if (!confirm('DELETE ALL TOPOLOGY DATA?\\n\\nThis will remove:\\n- All cameras\\n- All connections\\n- All landmarks\\n- All zones\\n- All drawings\\n\\nThis cannot be undone.')) return;\n\n topology.cameras = [];\n topology.connections = [];\n topology.landmarks = [];\n topology.globalZones = [];\n topology.drawnZones = [];\n topology.drawings = [];\n topology.relationships = [];\n\n selectedItem = null;\n document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select an item to edit.</p>';\n updateCameraSelects();\n updateUI();\n render();\n setStatus('All topology data cleared', 'warning');\n }\n\n function closeModal(id) { document.getElementById(id).classList.remove('active'); }\n function setStatus(text, type) { document.getElementById('status-text').textContent = text; const dot = document.getElementById('status-dot'); dot.className = 'status-dot'; if (type === 'warning') dot.classList.add('warning'); if (type === 'error') dot.classList.add('error'); }\n\n let dragging = null;\n let rotatingCamera = null;\n\n canvas.addEventListener('mousedown', (e) => {\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n // Handle zone drawing mode separately\n if (zoneDrawingMode) {\n currentZonePoints.push({ x, y });\n render();\n setStatus('Point ' + currentZonePoints.length + ' added. ' + (currentZonePoints.length < 3 ? 'Need at least 3 points.' : 'Double-click or Enter to finish.'), 'warning');\n return;\n }\n\n if (currentTool === 'select') {\n // Check for rotation handle on selected camera first\n if (selectedItem?.type === 'camera') {\n const camera = topology.cameras.find(c => c.deviceId === selectedItem.id);\n if (camera?._handlePos) {\n const dist = Math.hypot(x - camera._handlePos.x, y - camera._handlePos.y);\n if (dist < 15) {\n rotatingCamera = camera;\n setStatus('Drag to rotate camera direction', 'warning');\n return;\n }\n }\n }\n\n // Check cameras\n for (const camera of topology.cameras) {\n if (camera.floorPlanPosition) {\n const dist = Math.hypot(x - camera.floorPlanPosition.x, y - camera.floorPlanPosition.y);\n if (dist < 25) { selectCamera(camera.deviceId); dragging = { type: 'camera', item: camera }; return; }\n }\n }\n // Check landmarks\n for (const landmark of (topology.landmarks || [])) {\n if (landmark.position) {\n const dist = Math.hypot(x - landmark.position.x, y - landmark.position.y);\n if (dist < 20) { selectLandmark(landmark.id); dragging = { type: 'landmark', item: landmark }; return; }\n }\n }\n // Check zones (click inside polygon)\n for (const zone of (topology.drawnZones || [])) {\n if (zone.polygon && isPointInPolygon({ x, y }, zone.polygon)) {\n selectZone(zone.id);\n return;\n }\n }\n } else if (currentTool === 'wall') {\n isDrawing = true;\n drawStart = { x, y };\n currentDrawing = { type: 'wall', x1: x, y1: y, x2: x, y2: y };\n } else if (currentTool === 'room') {\n isDrawing = true;\n drawStart = { x, y };\n currentDrawing = { type: 'room', x: x, y: y, width: 0, height: 0 };\n } else if (currentTool === 'camera') {\n openAddCameraModal();\n topology._pendingCameraPos = { x, y };\n } else if (currentTool === 'landmark') {\n openAddLandmarkModal();\n topology._pendingLandmarkPos = { x, y };\n }\n });\n\n // Double-click to finish zone drawing\n canvas.addEventListener('dblclick', (e) => {\n if (zoneDrawingMode && currentZonePoints.length >= 3) {\n finishZoneDrawing();\n }\n });\n\n // Point-in-polygon test (ray casting algorithm)\n function isPointInPolygon(point, polygon) {\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x, yi = polygon[i].y;\n const xj = polygon[j].x, yj = polygon[j].y;\n if (((yi > point.y) !== (yj > point.y)) &&\n (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi)) {\n inside = !inside;\n }\n }\n return inside;\n }\n\n canvas.addEventListener('mousemove', (e) => {\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n // Handle camera rotation\n if (rotatingCamera) {\n const pos = rotatingCamera.floorPlanPosition;\n const angle = Math.atan2(y - pos.y, x - pos.x);\n // Convert to our direction system (0 = up/north, 90 = right/east)\n const direction = (angle * 180 / Math.PI) + 90;\n if (!rotatingCamera.fov) {\n rotatingCamera.fov = { mode: 'simple', angle: 90, direction: 0, range: 80 };\n }\n rotatingCamera.fov.direction = ((direction % 360) + 360) % 360; // Normalize 0-360\n render();\n return;\n }\n\n if (dragging) {\n if (dragging.type === 'camera') {\n dragging.item.floorPlanPosition.x = x;\n dragging.item.floorPlanPosition.y = y;\n } else if (dragging.type === 'landmark') {\n dragging.item.position.x = x;\n dragging.item.position.y = y;\n }\n render();\n } else if (isDrawing && currentDrawing) {\n if (currentDrawing.type === 'wall') {\n currentDrawing.x2 = x;\n currentDrawing.y2 = y;\n } else if (currentDrawing.type === 'room') {\n currentDrawing.width = x - drawStart.x;\n currentDrawing.height = y - drawStart.y;\n }\n render();\n }\n });\n\n canvas.addEventListener('mouseup', (e) => {\n // Clear camera rotation\n if (rotatingCamera) {\n setStatus('Camera direction updated', 'success');\n rotatingCamera = null;\n return;\n }\n\n if (isDrawing && currentDrawing) {\n if (!topology.drawings) topology.drawings = [];\n // Normalize room coordinates if drawn backwards\n if (currentDrawing.type === 'room') {\n if (currentDrawing.width < 0) {\n currentDrawing.x += currentDrawing.width;\n currentDrawing.width = Math.abs(currentDrawing.width);\n }\n if (currentDrawing.height < 0) {\n currentDrawing.y += currentDrawing.height;\n currentDrawing.height = Math.abs(currentDrawing.height);\n }\n // Only add if room is big enough\n if (currentDrawing.width > 20 && currentDrawing.height > 20) {\n const label = prompt('Room name (optional):');\n if (label) currentDrawing.label = label;\n topology.drawings.push(currentDrawing);\n }\n } else if (currentDrawing.type === 'wall') {\n // Only add if wall is long enough\n const len = Math.hypot(currentDrawing.x2 - currentDrawing.x1, currentDrawing.y2 - currentDrawing.y1);\n if (len > 20) {\n topology.drawings.push(currentDrawing);\n }\n }\n isDrawing = false;\n currentDrawing = null;\n render();\n }\n dragging = null;\n });\n\n window.addEventListener('resize', () => { resizeCanvas(); render(); });\n\n // Keyboard handler for zone drawing\n document.addEventListener('keydown', (e) => {\n if (zoneDrawingMode) {\n if (e.key === 'Enter' && currentZonePoints.length >= 3) {\n finishZoneDrawing();\n } else if (e.key === 'Escape') {\n cancelZoneDrawing();\n } else if (e.key === 'Backspace' && currentZonePoints.length > 0) {\n currentZonePoints.pop();\n render();\n setStatus('Last point removed. ' + currentZonePoints.length + ' points remaining.', 'warning');\n }\n }\n });\n init();\n <\/script>\n</body>\n</html>"},3885(e,t,n){"use strict";e.exports=n(9844)()},3891(e){function t(e){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}t.keys=()=>[],t.resolve=t,t.id=3891,e.exports=t},3936(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=n(4756),o=i(n(9278)),s=i(n(5753)),a=i(n(6968)),c=(0,s.default)("mqttjs:tls");t.default=(e,t)=>{t.port=t.port||8883,t.host=t.hostname||t.host||"localhost",0===o.default.isIP(t.host)&&(t.servername=t.host),t.rejectUnauthorized=!1!==t.rejectUnauthorized,delete t.path,c("port %d host %s rejectUnauthorized %b",t.port,t.host,t.rejectUnauthorized);const n=function(e){const{host:t,port:n,socksProxy:i,...o}=e;if(void 0!==i){const s=(0,a.default)(t,n,i,{timeout:e.socksTimeout});return(0,r.connect)({...o,socket:s})}return(0,r.connect)(e)}(t);function i(i){t.rejectUnauthorized&&e.emit("error",i),n.end()}return n.on("secureConnect",()=>{t.rejectUnauthorized&&!n.authorized?n.emit("error",new Error("TLS not authorized")):n.removeListener("error",i)}),n.on("error",i),n}},4134(e){"use strict";class t extends Error{constructor(e){if(!Array.isArray(e))throw new TypeError("Expected input to be an Array, got "+typeof e);let t="";for(let n=0;n<e.length;n++)t+=` ${e[n].stack}\n`;super(t),this.name="AggregateError",this.errors=e}}e.exports={AggregateError:t,ArrayIsArray:e=>Array.isArray(e),ArrayPrototypeIncludes:(e,t)=>e.includes(t),ArrayPrototypeIndexOf:(e,t)=>e.indexOf(t),ArrayPrototypeJoin:(e,t)=>e.join(t),ArrayPrototypeMap:(e,t)=>e.map(t),ArrayPrototypePop:(e,t)=>e.pop(t),ArrayPrototypePush:(e,t)=>e.push(t),ArrayPrototypeSlice:(e,t,n)=>e.slice(t,n),Error,FunctionPrototypeCall:(e,t,...n)=>e.call(t,...n),FunctionPrototypeSymbolHasInstance:(e,t)=>Function.prototype[Symbol.hasInstance].call(e,t),MathFloor:Math.floor,Number,NumberIsInteger:Number.isInteger,NumberIsNaN:Number.isNaN,NumberMAX_SAFE_INTEGER:Number.MAX_SAFE_INTEGER,NumberMIN_SAFE_INTEGER:Number.MIN_SAFE_INTEGER,NumberParseInt:Number.parseInt,ObjectDefineProperties:(e,t)=>Object.defineProperties(e,t),ObjectDefineProperty:(e,t,n)=>Object.defineProperty(e,t,n),ObjectGetOwnPropertyDescriptor:(e,t)=>Object.getOwnPropertyDescriptor(e,t),ObjectKeys:e=>Object.keys(e),ObjectSetPrototypeOf:(e,t)=>Object.setPrototypeOf(e,t),Promise,PromisePrototypeCatch:(e,t)=>e.catch(t),PromisePrototypeThen:(e,t,n)=>e.then(t,n),PromiseReject:e=>Promise.reject(e),PromiseResolve:e=>Promise.resolve(e),ReflectApply:Reflect.apply,RegExpPrototypeTest:(e,t)=>e.test(t),SafeSet:Set,String,StringPrototypeSlice:(e,t,n)=>e.slice(t,n),StringPrototypeToLowerCase:e=>e.toLowerCase(),StringPrototypeToUpperCase:e=>e.toUpperCase(),StringPrototypeTrim:e=>e.trim(),Symbol,SymbolFor:Symbol.for,SymbolAsyncIterator:Symbol.asyncIterator,SymbolHasInstance:Symbol.hasInstance,SymbolIterator:Symbol.iterator,SymbolDispose:Symbol.dispose||Symbol("Symbol.dispose"),SymbolAsyncDispose:Symbol.asyncDispose||Symbol("Symbol.asyncDispose"),TypedArrayPrototypeSet:(e,t,n)=>e.set(t,n),Boolean,Uint8Array}},4147(e,t,n){"use strict";const{SymbolDispose:i}=n(4134),{AbortError:r,codes:o}=n(6371),{isNodeStream:s,isWebStream:a,kControllerErrorFunction:c}=n(6115),l=n(6238),{ERR_INVALID_ARG_TYPE:d}=o;let u;e.exports.addAbortSignal=function(t,n){if(((e,t)=>{if("object"!=typeof e||!("aborted"in e))throw new d(t,"AbortSignal",e)})(t,"signal"),!s(n)&&!a(n))throw new d("stream",["ReadableStream","WritableStream","Stream"],n);return e.exports.addAbortSignalNoValidate(t,n)},e.exports.addAbortSignalNoValidate=function(e,t){if("object"!=typeof e||!("aborted"in e))return t;const o=s(t)?()=>{t.destroy(new r(void 0,{cause:e.reason}))}:()=>{t[c](new r(void 0,{cause:e.reason}))};if(e.aborted)o();else{u=u||n(7760).addAbortListener;const r=u(e,o);l(t,r[i])}return t}},4152(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.TypedEventEmitter=void 0;const r=i(n(4434)),o=n(4723);class s{}t.TypedEventEmitter=s,(0,o.applyMixin)(s,r.default)},4192(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ScryptedMimeTypes=t.ScryptedInterface=t.MediaPlayerState=t.SecuritySystemObstruction=t.SecuritySystemMode=t.AirQuality=t.AirPurifierMode=t.AirPurifierStatus=t.ChargeState=t.LockState=t.PanTiltZoomMovement=t.ThermostatMode=t.TemperatureUnit=t.FanMode=t.HumidityMode=t.ScryptedDeviceType=t.ScryptedInterfaceDescriptors=t.ScryptedInterfaceMethod=t.ScryptedInterfaceProperty=t.DeviceBase=t.TYPES_VERSION=void 0,t.TYPES_VERSION="0.5.51";var n,i,r,o,s,a,c,l,d,u,p,h,f,g,m,y,b,v;t.DeviceBase=class{},function(e){e.id="id",e.info="info",e.interfaces="interfaces",e.mixins="mixins",e.name="name",e.nativeId="nativeId",e.pluginId="pluginId",e.providedInterfaces="providedInterfaces",e.providedName="providedName",e.providedRoom="providedRoom",e.providedType="providedType",e.providerId="providerId",e.room="room",e.type="type",e.scryptedRuntimeArguments="scryptedRuntimeArguments",e.on="on",e.brightness="brightness",e.colorTemperature="colorTemperature",e.rgb="rgb",e.hsv="hsv",e.buttons="buttons",e.sensors="sensors",e.running="running",e.paused="paused",e.docked="docked",e.temperatureSetting="temperatureSetting",e.temperature="temperature",e.temperatureUnit="temperatureUnit",e.humidity="humidity",e.resolution="resolution",e.audioVolumes="audioVolumes",e.recordingActive="recordingActive",e.ptzCapabilities="ptzCapabilities",e.lockState="lockState",e.entryOpen="entryOpen",e.batteryLevel="batteryLevel",e.chargeState="chargeState",e.online="online",e.fromMimeType="fromMimeType",e.toMimeType="toMimeType",e.converters="converters",e.binaryState="binaryState",e.tampered="tampered",e.sleeping="sleeping",e.powerDetected="powerDetected",e.audioDetected="audioDetected",e.motionDetected="motionDetected",e.ambientLight="ambientLight",e.occupied="occupied",e.flooded="flooded",e.ultraviolet="ultraviolet",e.luminance="luminance",e.position="position",e.securitySystemState="securitySystemState",e.pm10Density="pm10Density",e.pm25Density="pm25Density",e.vocDensity="vocDensity",e.noxDensity="noxDensity",e.co2ppm="co2ppm",e.airQuality="airQuality",e.airPurifierState="airPurifierState",e.filterChangeIndication="filterChangeIndication",e.filterLifeLevel="filterLifeLevel",e.humiditySetting="humiditySetting",e.fan="fan",e.applicationInfo="applicationInfo",e.chatCompletionCapabilities="chatCompletionCapabilities",e.systemDevice="systemDevice"}(n||(t.ScryptedInterfaceProperty=n={})),function(e){e.listen="listen",e.probe="probe",e.setMixins="setMixins",e.setName="setName",e.setRoom="setRoom",e.setType="setType",e.getPluginJson="getPluginJson",e.turnOff="turnOff",e.turnOn="turnOn",e.setBrightness="setBrightness",e.getTemperatureMaxK="getTemperatureMaxK",e.getTemperatureMinK="getTemperatureMinK",e.setColorTemperature="setColorTemperature",e.setRgb="setRgb",e.setHsv="setHsv",e.pressButton="pressButton",e.sendNotification="sendNotification",e.start="start",e.stop="stop",e.pause="pause",e.resume="resume",e.dock="dock",e.setTemperature="setTemperature",e.setTemperatureUnit="setTemperatureUnit",e.getPictureOptions="getPictureOptions",e.takePicture="takePicture",e.getAudioStream="getAudioStream",e.setAudioVolumes="setAudioVolumes",e.startDisplay="startDisplay",e.stopDisplay="stopDisplay",e.getVideoStream="getVideoStream",e.getVideoStreamOptions="getVideoStreamOptions",e.getPrivacyMasks="getPrivacyMasks",e.setPrivacyMasks="setPrivacyMasks",e.getVideoTextOverlays="getVideoTextOverlays",e.setVideoTextOverlay="setVideoTextOverlay",e.getRecordingStream="getRecordingStream",e.getRecordingStreamCurrentTime="getRecordingStreamCurrentTime",e.getRecordingStreamOptions="getRecordingStreamOptions",e.getRecordingStreamThumbnail="getRecordingStreamThumbnail",e.deleteRecordingStream="deleteRecordingStream",e.setRecordingActive="setRecordingActive",e.ptzCommand="ptzCommand",e.getRecordedEvents="getRecordedEvents",e.getVideoClip="getVideoClip",e.getVideoClips="getVideoClips",e.getVideoClipThumbnail="getVideoClipThumbnail",e.removeVideoClips="removeVideoClips",e.setVideoStreamOptions="setVideoStreamOptions",e.startIntercom="startIntercom",e.stopIntercom="stopIntercom",e.lock="lock",e.unlock="unlock",e.addPassword="addPassword",e.getPasswords="getPasswords",e.removePassword="removePassword",e.activate="activate",e.deactivate="deactivate",e.isReversible="isReversible",e.closeEntry="closeEntry",e.openEntry="openEntry",e.getDevice="getDevice",e.releaseDevice="releaseDevice",e.adoptDevice="adoptDevice",e.discoverDevices="discoverDevices",e.createDevice="createDevice",e.getCreateDeviceSettings="getCreateDeviceSettings",e.reboot="reboot",e.getRefreshFrequency="getRefreshFrequency",e.refresh="refresh",e.getMediaStatus="getMediaStatus",e.load="load",e.seek="seek",e.skipNext="skipNext",e.skipPrevious="skipPrevious",e.convert="convert",e.convertMedia="convertMedia",e.getSettings="getSettings",e.putSetting="putSetting",e.armSecuritySystem="armSecuritySystem",e.disarmSecuritySystem="disarmSecuritySystem",e.setAirPurifierState="setAirPurifierState",e.getReadmeMarkdown="getReadmeMarkdown",e.getOauthUrl="getOauthUrl",e.onOauthCallback="onOauthCallback",e.canMixin="canMixin",e.getMixin="getMixin",e.releaseMixin="releaseMixin",e.onRequest="onRequest",e.onConnection="onConnection",e.onPush="onPush",e.run="run",e.eval="eval",e.loadScripts="loadScripts",e.saveScript="saveScript",e.forkInterface="forkInterface",e.getDetectionInput="getDetectionInput",e.getObjectTypes="getObjectTypes",e.detectObjects="detectObjects",e.generateObjectDetections="generateObjectDetections",e.getDetectionModel="getDetectionModel",e.setHumidity="setHumidity",e.setFan="setFan",e.startRTCSignalingSession="startRTCSignalingSession",e.createRTCSignalingSession="createRTCSignalingSession",e.getScryptedUserAccessControl="getScryptedUserAccessControl",e.generateVideoFrames="generateVideoFrames",e.connectStream="connectStream",e.getTTYSettings="getTTYSettings",e.getChatCompletion="getChatCompletion",e.streamChatCompletion="streamChatCompletion",e.getTextEmbedding="getTextEmbedding",e.getImageEmbedding="getImageEmbedding",e.callLLMTool="callLLMTool",e.getLLMTools="getLLMTools"}(i||(t.ScryptedInterfaceMethod=i={})),t.ScryptedInterfaceDescriptors={ScryptedDevice:{name:"ScryptedDevice",methods:["listen","probe","setMixins","setName","setRoom","setType"],properties:["id","info","interfaces","mixins","name","nativeId","pluginId","providedInterfaces","providedName","providedRoom","providedType","providerId","room","type"]},ScryptedPlugin:{name:"ScryptedPlugin",methods:["getPluginJson"],properties:[]},ScryptedPluginRuntime:{name:"ScryptedPluginRuntime",methods:[],properties:["scryptedRuntimeArguments"]},OnOff:{name:"OnOff",methods:["turnOff","turnOn"],properties:["on"]},Brightness:{name:"Brightness",methods:["setBrightness"],properties:["brightness"]},ColorSettingTemperature:{name:"ColorSettingTemperature",methods:["getTemperatureMaxK","getTemperatureMinK","setColorTemperature"],properties:["colorTemperature"]},ColorSettingRgb:{name:"ColorSettingRgb",methods:["setRgb"],properties:["rgb"]},ColorSettingHsv:{name:"ColorSettingHsv",methods:["setHsv"],properties:["hsv"]},Buttons:{name:"Buttons",methods:[],properties:["buttons"]},PressButtons:{name:"PressButtons",methods:["pressButton"],properties:[]},Sensors:{name:"Sensors",methods:[],properties:["sensors"]},Notifier:{name:"Notifier",methods:["sendNotification"],properties:[]},StartStop:{name:"StartStop",methods:["start","stop"],properties:["running"]},Pause:{name:"Pause",methods:["pause","resume"],properties:["paused"]},Dock:{name:"Dock",methods:["dock"],properties:["docked"]},TemperatureSetting:{name:"TemperatureSetting",methods:["setTemperature"],properties:["temperatureSetting"]},Thermometer:{name:"Thermometer",methods:["setTemperatureUnit"],properties:["temperature","temperatureUnit"]},HumiditySensor:{name:"HumiditySensor",methods:[],properties:["humidity"]},Camera:{name:"Camera",methods:["getPictureOptions","takePicture"],properties:[]},Resolution:{name:"Resolution",methods:[],properties:["resolution"]},Microphone:{name:"Microphone",methods:["getAudioStream"],properties:[]},AudioVolumeControl:{name:"AudioVolumeControl",methods:["setAudioVolumes"],properties:["audioVolumes"]},Display:{name:"Display",methods:["startDisplay","stopDisplay"],properties:[]},VideoCamera:{name:"VideoCamera",methods:["getVideoStream","getVideoStreamOptions"],properties:[]},VideoCameraMask:{name:"VideoCameraMask",methods:["getPrivacyMasks","setPrivacyMasks"],properties:[]},VideoTextOverlays:{name:"VideoTextOverlays",methods:["getVideoTextOverlays","setVideoTextOverlay"],properties:[]},VideoRecorder:{name:"VideoRecorder",methods:["getRecordingStream","getRecordingStreamCurrentTime","getRecordingStreamOptions","getRecordingStreamThumbnail"],properties:["recordingActive"]},VideoRecorderManagement:{name:"VideoRecorderManagement",methods:["deleteRecordingStream","setRecordingActive"],properties:[]},PanTiltZoom:{name:"PanTiltZoom",methods:["ptzCommand"],properties:["ptzCapabilities"]},EventRecorder:{name:"EventRecorder",methods:["getRecordedEvents"],properties:[]},VideoClips:{name:"VideoClips",methods:["getVideoClip","getVideoClips","getVideoClipThumbnail","removeVideoClips"],properties:[]},VideoCameraConfiguration:{name:"VideoCameraConfiguration",methods:["setVideoStreamOptions"],properties:[]},Intercom:{name:"Intercom",methods:["startIntercom","stopIntercom"],properties:[]},Lock:{name:"Lock",methods:["lock","unlock"],properties:["lockState"]},PasswordStore:{name:"PasswordStore",methods:["addPassword","getPasswords","removePassword"],properties:[]},Scene:{name:"Scene",methods:["activate","deactivate","isReversible"],properties:[]},Entry:{name:"Entry",methods:["closeEntry","openEntry"],properties:[]},EntrySensor:{name:"EntrySensor",methods:[],properties:["entryOpen"]},DeviceProvider:{name:"DeviceProvider",methods:["getDevice","releaseDevice"],properties:[]},DeviceDiscovery:{name:"DeviceDiscovery",methods:["adoptDevice","discoverDevices"],properties:[]},DeviceCreator:{name:"DeviceCreator",methods:["createDevice","getCreateDeviceSettings"],properties:[]},Battery:{name:"Battery",methods:[],properties:["batteryLevel"]},Charger:{name:"Charger",methods:[],properties:["chargeState"]},Reboot:{name:"Reboot",methods:["reboot"],properties:[]},Refresh:{name:"Refresh",methods:["getRefreshFrequency","refresh"],properties:[]},MediaPlayer:{name:"MediaPlayer",methods:["getMediaStatus","load","seek","skipNext","skipPrevious"],properties:[]},Online:{name:"Online",methods:[],properties:["online"]},BufferConverter:{name:"BufferConverter",methods:["convert"],properties:["fromMimeType","toMimeType"]},MediaConverter:{name:"MediaConverter",methods:["convertMedia"],properties:["converters"]},Settings:{name:"Settings",methods:["getSettings","putSetting"],properties:[]},BinarySensor:{name:"BinarySensor",methods:[],properties:["binaryState"]},TamperSensor:{name:"TamperSensor",methods:[],properties:["tampered"]},Sleep:{name:"Sleep",methods:[],properties:["sleeping"]},PowerSensor:{name:"PowerSensor",methods:[],properties:["powerDetected"]},AudioSensor:{name:"AudioSensor",methods:[],properties:["audioDetected"]},MotionSensor:{name:"MotionSensor",methods:[],properties:["motionDetected"]},AmbientLightSensor:{name:"AmbientLightSensor",methods:[],properties:["ambientLight"]},OccupancySensor:{name:"OccupancySensor",methods:[],properties:["occupied"]},FloodSensor:{name:"FloodSensor",methods:[],properties:["flooded"]},UltravioletSensor:{name:"UltravioletSensor",methods:[],properties:["ultraviolet"]},LuminanceSensor:{name:"LuminanceSensor",methods:[],properties:["luminance"]},PositionSensor:{name:"PositionSensor",methods:[],properties:["position"]},SecuritySystem:{name:"SecuritySystem",methods:["armSecuritySystem","disarmSecuritySystem"],properties:["securitySystemState"]},PM10Sensor:{name:"PM10Sensor",methods:[],properties:["pm10Density"]},PM25Sensor:{name:"PM25Sensor",methods:[],properties:["pm25Density"]},VOCSensor:{name:"VOCSensor",methods:[],properties:["vocDensity"]},NOXSensor:{name:"NOXSensor",methods:[],properties:["noxDensity"]},CO2Sensor:{name:"CO2Sensor",methods:[],properties:["co2ppm"]},AirQualitySensor:{name:"AirQualitySensor",methods:[],properties:["airQuality"]},AirPurifier:{name:"AirPurifier",methods:["setAirPurifierState"],properties:["airPurifierState"]},FilterMaintenance:{name:"FilterMaintenance",methods:[],properties:["filterChangeIndication","filterLifeLevel"]},Readme:{name:"Readme",methods:["getReadmeMarkdown"],properties:[]},OauthClient:{name:"OauthClient",methods:["getOauthUrl","onOauthCallback"],properties:[]},MixinProvider:{name:"MixinProvider",methods:["canMixin","getMixin","releaseMixin"],properties:[]},HttpRequestHandler:{name:"HttpRequestHandler",methods:["onRequest"],properties:[]},EngineIOHandler:{name:"EngineIOHandler",methods:["onConnection"],properties:[]},PushHandler:{name:"PushHandler",methods:["onPush"],properties:[]},Program:{name:"Program",methods:["run"],properties:[]},Scriptable:{name:"Scriptable",methods:["eval","loadScripts","saveScript"],properties:[]},ClusterForkInterface:{name:"ClusterForkInterface",methods:["forkInterface"],properties:[]},ObjectDetector:{name:"ObjectDetector",methods:["getDetectionInput","getObjectTypes"],properties:[]},ObjectDetection:{name:"ObjectDetection",methods:["detectObjects","generateObjectDetections","getDetectionModel"],properties:[]},ObjectDetectionPreview:{name:"ObjectDetectionPreview",methods:[],properties:[]},ObjectDetectionGenerator:{name:"ObjectDetectionGenerator",methods:[],properties:[]},HumiditySetting:{name:"HumiditySetting",methods:["setHumidity"],properties:["humiditySetting"]},Fan:{name:"Fan",methods:["setFan"],properties:["fan"]},RTCSignalingChannel:{name:"RTCSignalingChannel",methods:["startRTCSignalingSession"],properties:[]},RTCSignalingClient:{name:"RTCSignalingClient",methods:["createRTCSignalingSession"],properties:[]},LauncherApplication:{name:"LauncherApplication",methods:[],properties:["applicationInfo"]},ScryptedUser:{name:"ScryptedUser",methods:["getScryptedUserAccessControl"],properties:[]},VideoFrameGenerator:{name:"VideoFrameGenerator",methods:["generateVideoFrames"],properties:[]},StreamService:{name:"StreamService",methods:["connectStream"],properties:[]},TTY:{name:"TTY",methods:[],properties:[]},TTYSettings:{name:"TTYSettings",methods:["getTTYSettings"],properties:[]},ChatCompletion:{name:"ChatCompletion",methods:["getChatCompletion","streamChatCompletion"],properties:["chatCompletionCapabilities"]},TextEmbedding:{name:"TextEmbedding",methods:["getTextEmbedding"],properties:[]},ImageEmbedding:{name:"ImageEmbedding",methods:["getImageEmbedding"],properties:[]},LLMTools:{name:"LLMTools",methods:["callLLMTool","getLLMTools"],properties:[]},ScryptedSystemDevice:{name:"ScryptedSystemDevice",methods:[],properties:["systemDevice"]},ScryptedDeviceCreator:{name:"ScryptedDeviceCreator",methods:[],properties:[]},ScryptedSettings:{name:"ScryptedSettings",methods:[],properties:[]}},function(e){e.Builtin="Builtin",e.Internal="Internal",e.Camera="Camera",e.Fan="Fan",e.Light="Light",e.Switch="Switch",e.Outlet="Outlet",e.Sensor="Sensor",e.Scene="Scene",e.Program="Program",e.Automation="Automation",e.Vacuum="Vacuum",e.Notifier="Notifier",e.Thermostat="Thermostat",e.Lock="Lock",e.PasswordControl="PasswordControl",e.Display="Display",e.SmartDisplay="SmartDisplay",e.Speaker="Speaker",e.SmartSpeaker="SmartSpeaker",e.RemoteDesktop="RemoteDesktop",e.Event="Event",e.Entry="Entry",e.Garage="Garage",e.DeviceProvider="DeviceProvider",e.DataSource="DataSource",e.API="API",e.Buttons="Buttons",e.Doorbell="Doorbell",e.Irrigation="Irrigation",e.Valve="Valve",e.Person="Person",e.SecuritySystem="SecuritySystem",e.WindowCovering="WindowCovering",e.Siren="Siren",e.AirPurifier="AirPurifier",e.Internet="Internet",e.Network="Network",e.Bridge="Bridge",e.LLM="LLM",e.Unknown="Unknown"}(r||(t.ScryptedDeviceType=r={})),function(e){e.Humidify="Humidify",e.Dehumidify="Dehumidify",e.Auto="Auto",e.Off="Off"}(o||(t.HumidityMode=o={})),function(e){e.Auto="Auto",e.Manual="Manual"}(s||(t.FanMode=s={})),function(e){e.C="C",e.F="F"}(a||(t.TemperatureUnit=a={})),function(e){e.Off="Off",e.Cool="Cool",e.Heat="Heat",e.HeatCool="HeatCool",e.Auto="Auto",e.FanOnly="FanOnly",e.Purifier="Purifier",e.Eco="Eco",e.Dry="Dry",e.On="On"}(c||(t.ThermostatMode=c={})),function(e){e.Absolute="Absolute",e.Relative="Relative",e.Continuous="Continuous",e.Preset="Preset",e.Home="Home"}(l||(t.PanTiltZoomMovement=l={})),function(e){e.Locked="Locked",e.Unlocked="Unlocked",e.Jammed="Jammed"}(d||(t.LockState=d={})),function(e){e.Trickle="trickle",e.Charging="charging",e.NotCharging="not-charging"}(u||(t.ChargeState=u={})),function(e){e.Inactive="Inactive",e.Idle="Idle",e.Active="Active",e.ActiveNightMode="ActiveNightMode"}(p||(t.AirPurifierStatus=p={})),function(e){e.Manual="Manual",e.Automatic="Automatic"}(h||(t.AirPurifierMode=h={})),function(e){e.Unknown="Unknown",e.Excellent="Excellent",e.Good="Good",e.Fair="Fair",e.Inferior="Inferior",e.Poor="Poor"}(f||(t.AirQuality=f={})),function(e){e.Disarmed="Disarmed",e.HomeArmed="HomeArmed",e.AwayArmed="AwayArmed",e.NightArmed="NightArmed"}(g||(t.SecuritySystemMode=g={})),function(e){e.Sensor="Sensor",e.Occupied="Occupied",e.Time="Time",e.Error="Error"}(m||(t.SecuritySystemObstruction=m={})),function(e){e.Idle="Idle",e.Playing="Playing",e.Paused="Paused",e.Buffering="Buffering"}(y||(t.MediaPlayerState=y={})),function(e){e.ScryptedDevice="ScryptedDevice",e.ScryptedPlugin="ScryptedPlugin",e.ScryptedPluginRuntime="ScryptedPluginRuntime",e.OnOff="OnOff",e.Brightness="Brightness",e.ColorSettingTemperature="ColorSettingTemperature",e.ColorSettingRgb="ColorSettingRgb",e.ColorSettingHsv="ColorSettingHsv",e.Buttons="Buttons",e.PressButtons="PressButtons",e.Sensors="Sensors",e.Notifier="Notifier",e.StartStop="StartStop",e.Pause="Pause",e.Dock="Dock",e.TemperatureSetting="TemperatureSetting",e.Thermometer="Thermometer",e.HumiditySensor="HumiditySensor",e.Camera="Camera",e.Resolution="Resolution",e.Microphone="Microphone",e.AudioVolumeControl="AudioVolumeControl",e.Display="Display",e.VideoCamera="VideoCamera",e.VideoCameraMask="VideoCameraMask",e.VideoTextOverlays="VideoTextOverlays",e.VideoRecorder="VideoRecorder",e.VideoRecorderManagement="VideoRecorderManagement",e.PanTiltZoom="PanTiltZoom",e.EventRecorder="EventRecorder",e.VideoClips="VideoClips",e.VideoCameraConfiguration="VideoCameraConfiguration",e.Intercom="Intercom",e.Lock="Lock",e.PasswordStore="PasswordStore",e.Scene="Scene",e.Entry="Entry",e.EntrySensor="EntrySensor",e.DeviceProvider="DeviceProvider",e.DeviceDiscovery="DeviceDiscovery",e.DeviceCreator="DeviceCreator",e.Battery="Battery",e.Charger="Charger",e.Reboot="Reboot",e.Refresh="Refresh",e.MediaPlayer="MediaPlayer",e.Online="Online",e.BufferConverter="BufferConverter",e.MediaConverter="MediaConverter",e.Settings="Settings",e.BinarySensor="BinarySensor",e.TamperSensor="TamperSensor",e.Sleep="Sleep",e.PowerSensor="PowerSensor",e.AudioSensor="AudioSensor",e.MotionSensor="MotionSensor",e.AmbientLightSensor="AmbientLightSensor",e.OccupancySensor="OccupancySensor",e.FloodSensor="FloodSensor",e.UltravioletSensor="UltravioletSensor",e.LuminanceSensor="LuminanceSensor",e.PositionSensor="PositionSensor",e.SecuritySystem="SecuritySystem",e.PM10Sensor="PM10Sensor",e.PM25Sensor="PM25Sensor",e.VOCSensor="VOCSensor",e.NOXSensor="NOXSensor",e.CO2Sensor="CO2Sensor",e.AirQualitySensor="AirQualitySensor",e.AirPurifier="AirPurifier",e.FilterMaintenance="FilterMaintenance",e.Readme="Readme",e.OauthClient="OauthClient",e.MixinProvider="MixinProvider",e.HttpRequestHandler="HttpRequestHandler",e.EngineIOHandler="EngineIOHandler",e.PushHandler="PushHandler",e.Program="Program",e.Scriptable="Scriptable",e.ClusterForkInterface="ClusterForkInterface",e.ObjectDetector="ObjectDetector",e.ObjectDetection="ObjectDetection",e.ObjectDetectionPreview="ObjectDetectionPreview",e.ObjectDetectionGenerator="ObjectDetectionGenerator",e.HumiditySetting="HumiditySetting",e.Fan="Fan",e.RTCSignalingChannel="RTCSignalingChannel",e.RTCSignalingClient="RTCSignalingClient",e.LauncherApplication="LauncherApplication",e.ScryptedUser="ScryptedUser",e.VideoFrameGenerator="VideoFrameGenerator",e.StreamService="StreamService",e.TTY="TTY",e.TTYSettings="TTYSettings",e.ChatCompletion="ChatCompletion",e.TextEmbedding="TextEmbedding",e.ImageEmbedding="ImageEmbedding",e.LLMTools="LLMTools",e.ScryptedSystemDevice="ScryptedSystemDevice",e.ScryptedDeviceCreator="ScryptedDeviceCreator",e.ScryptedSettings="ScryptedSettings"}(b||(t.ScryptedInterface=b={})),function(e){e.Url="text/x-uri",e.InsecureLocalUrl="text/x-insecure-local-uri",e.LocalUrl="text/x-local-uri",e.ServerId="text/x-server-id",e.PushEndpoint="text/x-push-endpoint",e.SchemePrefix="x-scrypted/x-scrypted-scheme-",e.MediaStreamUrl="text/x-media-url",e.MediaObject="x-scrypted/x-scrypted-media-object",e.RequestMediaObject="x-scrypted/x-scrypted-request-media-object",e.RequestMediaStream="x-scrypted/x-scrypted-request-stream",e.MediaStreamFeedback="x-scrypted/x-media-stream-feedback",e.FFmpegInput="x-scrypted/x-ffmpeg-input",e.FFmpegTranscodeStream="x-scrypted/x-ffmpeg-transcode-stream",e.RTCSignalingChannel="x-scrypted/x-scrypted-rtc-signaling-channel",e.RTCSignalingSession="x-scrypted/x-scrypted-rtc-signaling-session",e.RTCConnectionManagement="x-scrypted/x-scrypted-rtc-connection-management",e.Image="x-scrypted/x-scrypted-image"}(v||(t.ScryptedMimeTypes=v={}))},4259(e,t,n){"use strict";const{ArrayIsArray:i,ObjectSetPrototypeOf:r}=n(4134),{EventEmitter:o}=n(4434);function s(e){o.call(this,e)}function a(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?i(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}r(s.prototype,o.prototype),r(s,o),s.prototype.pipe=function(e,t){const n=this;function i(t){e.writable&&!1===e.write(t)&&n.pause&&n.pause()}function r(){n.readable&&n.resume&&n.resume()}n.on("data",i),e.on("drain",r),e._isStdio||t&&!1===t.end||(n.on("end",c),n.on("close",l));let s=!1;function c(){s||(s=!0,e.end())}function l(){s||(s=!0,"function"==typeof e.destroy&&e.destroy())}function d(e){u(),0===o.listenerCount(this,"error")&&this.emit("error",e)}function u(){n.removeListener("data",i),e.removeListener("drain",r),n.removeListener("end",c),n.removeListener("close",l),n.removeListener("error",d),e.removeListener("error",d),n.removeListener("end",u),n.removeListener("close",u),e.removeListener("close",u)}return a(n,"error",d),a(e,"error",d),n.on("end",u),n.on("close",u),e.on("close",u),e.emit("pipe",n),e},e.exports={Stream:s,prependListener:a}},4264(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=(e,t,n)=>{e.log("handling pubrel packet");const i="undefined"!=typeof n?n:e.noop,{messageId:r}=t,o={cmd:"pubcomp",messageId:r};e.incomingStore.get(t,(t,n)=>{t?e._sendPacket(o,i):(e.emit("message",n.topic,n.payload,n),e.handleMessage(n,t=>{if(t)return i(t);e.incomingStore.del(n,e.noop),e._sendPacket(o,i)}))})}},4386(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.AlertManager=void 0;const a=s(n(7562)),c=n(4997),{systemManager:l,mediaManager:d}=a.default;t.AlertManager=class{rules=[];recentAlerts=[];cooldowns=new Map;console;storage;maxAlerts=100;constructor(e,t){this.console=e,this.storage=t,this.loadRules()}async checkAndAlert(e,t,n){const i=this.rules.find(t=>t.type===e&&t.enabled);if(!i)return null;if(i.objectClasses&&i.objectClasses.length>0&&!i.objectClasses.includes(t.className))return null;if(i.cameraIds&&i.cameraIds.length>0&&n.cameraId&&!i.cameraIds.includes(n.cameraId))return null;const r=`${i.id}:${t.globalId}`,o=this.cooldowns.get(r)||0;if(i.cooldown>0&&Date.now()-o<i.cooldown)return null;if(!this.evaluateConditions(i.conditions,t))return null;const s={...n,objectClass:t.className,objectLabel:t.label},a=(0,c.createAlert)(e,t.globalId,s,i.severity,i.id);return this.recentAlerts.unshift(a),this.recentAlerts.length>this.maxAlerts&&this.recentAlerts.pop(),this.cooldowns.set(r,Date.now()),await this.sendNotifications(a,i),this.console.log(`Alert generated: [${a.severity}] ${a.message}`),a}async sendNotifications(e,t){const n=t.notifiers.length>0?t.notifiers:this.getDefaultNotifiers();let i;const r=e.details.toCameraId||e.details.cameraId;if(r)try{const e=l.getDeviceById(r);e&&e.interfaces?.includes(a.ScryptedInterface.Camera)&&(i=await e.takePicture())}catch(e){this.console.warn(`Failed to get thumbnail from camera ${r}:`,e)}for(const t of n)try{const n=l.getDeviceById(t);if(!n){this.console.warn(`Notifier not found: ${t}`);continue}await n.sendNotification(this.getNotificationTitle(e),{body:e.message,data:{type:e.type,severity:e.severity,trackedObjectId:e.trackedObjectId,timestamp:e.timestamp}},i),this.console.log(`Notification sent to ${t}${i?" with thumbnail":""}`)}catch(e){this.console.error(`Failed to send notification to ${t}:`,e)}}getNotificationTitle(e){const t="critical"===e.severity?"🚨 ":"warning"===e.severity?"⚠️ ":"",n=e.details.objectClass?e.details.objectClass.charAt(0).toUpperCase()+e.details.objectClass.slice(1):"Object";switch(e.type){case"property_entry":return`${t}${n} Arrived`;case"property_exit":return`${t}${n} Left`;case"movement":return`${t}${n} → ${e.details.toCameraName||"area"}`;case"unusual_path":return`${t}Unusual Route`;case"dwell_time":return`${t}${n} Lingering`;case"restricted_zone":return`${t}Restricted Zone!`;case"lost_tracking":return`${t}${n} Lost`;case"reappearance":return`${t}${n} Reappeared`;default:return`${t}Spatial Alert`}}getDefaultNotifiers(){try{const e=this.storage.getItem("defaultNotifiers");if(e)try{const t=JSON.parse(e);if(Array.isArray(t))return t}catch{return e.includes(",")?e.split(",").map(e=>e.trim()).filter(Boolean):[e]}const t=this.storage.getItem("defaultNotifier");return t?[t]:[]}catch{return[]}}evaluateConditions(e,t){for(const n of e){const e=this.getFieldValue(n.field,t);switch(n.operator){case"equals":if(e!==n.value)return!1;break;case"not_equals":if(e===n.value)return!1;break;case"contains":if(!String(e).includes(String(n.value)))return!1;break;case"greater_than":if(Number(e)<=Number(n.value))return!1;break;case"less_than":if(Number(e)>=Number(n.value))return!1}}return!0}getFieldValue(e,t){const n=e.split(".");let i=t;for(const e of n){if(null==i)return;i=i[e]}return i}getRecentAlerts(e=50){return this.recentAlerts.slice(0,e)}acknowledgeAlert(e){const t=this.recentAlerts.find(t=>t.id===e);return!!t&&(t.acknowledged=!0,!0)}getAlertsForObject(e){return this.recentAlerts.filter(t=>t.trackedObjectId===e)}setRules(e){this.rules=e,this.saveRules()}getRules(){return this.rules}upsertRule(e){const t=this.rules.findIndex(t=>t.id===e.id);t>=0?this.rules[t]=e:this.rules.push(e),this.saveRules()}deleteRule(e){const t=this.rules.findIndex(t=>t.id===e);return t>=0&&(this.rules.splice(t,1),this.saveRules(),!0)}setRuleEnabled(e,t){const n=this.rules.find(t=>t.id===e);return!!n&&(n.enabled=t,this.saveRules(),!0)}loadRules(){try{const e=this.storage.getItem("alertRules");this.rules=e?JSON.parse(e):(0,c.createDefaultRules)()}catch(e){this.console.error("Failed to load alert rules:",e),this.rules=(0,c.createDefaultRules)()}}saveRules(){try{this.storage.setItem("alertRules",JSON.stringify(this.rules))}catch(e){this.console.error("Failed to save alert rules:",e)}}clearCooldowns(){this.cooldowns.clear()}clearHistory(){this.recentAlerts=[]}}},4422(e){e.exports=global.process},4434(e){"use strict";e.exports=require("events")},4478(e,t,n){"use strict";const i=n(2203);if(i&&"disable"===process.env.READABLE_STREAM){const t=i.promises;e.exports._uint8ArrayToBuffer=i._uint8ArrayToBuffer,e.exports._isUint8Array=i._isUint8Array,e.exports.isDisturbed=i.isDisturbed,e.exports.isErrored=i.isErrored,e.exports.isReadable=i.isReadable,e.exports.Readable=i.Readable,e.exports.Writable=i.Writable,e.exports.Duplex=i.Duplex,e.exports.Transform=i.Transform,e.exports.PassThrough=i.PassThrough,e.exports.addAbortSignal=i.addAbortSignal,e.exports.finished=i.finished,e.exports.destroy=i.destroy,e.exports.pipeline=i.pipeline,e.exports.compose=i.compose,Object.defineProperty(i,"promises",{configurable:!0,enumerable:!0,get:()=>t}),e.exports.Stream=i.Stream}else{const t=n(5506),i=n(3095),r=t.Readable.destroy;e.exports=t.Readable,e.exports._uint8ArrayToBuffer=t._uint8ArrayToBuffer,e.exports._isUint8Array=t._isUint8Array,e.exports.isDisturbed=t.isDisturbed,e.exports.isErrored=t.isErrored,e.exports.isReadable=t.isReadable,e.exports.Readable=t.Readable,e.exports.Writable=t.Writable,e.exports.Duplex=t.Duplex,e.exports.Transform=t.Transform,e.exports.PassThrough=t.PassThrough,e.exports.addAbortSignal=t.addAbortSignal,e.exports.finished=t.finished,e.exports.destroy=t.destroy,e.exports.destroy=r,e.exports.pipeline=t.pipeline,e.exports.compose=t.compose,Object.defineProperty(t,"promises",{configurable:!0,enumerable:!0,get:()=>i}),e.exports.Stream=t.Stream}e.exports.default=e.exports},4723(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.MQTTJS_VERSION=t.nextTick=t.ErrorWithSubackPacket=t.ErrorWithReasonCode=void 0,t.applyMixin=function(e,t,n=!1){const i=[t];for(;;){const e=i[0],t=Object.getPrototypeOf(e);if(!t?.prototype)break;i.unshift(t)}for(const t of i)for(const i of Object.getOwnPropertyNames(t.prototype))(n||"constructor"!==i)&&Object.defineProperty(e.prototype,i,Object.getOwnPropertyDescriptor(t.prototype,i)??Object.create(null))};class i extends Error{code;constructor(e,t){super(e),this.code=t,Object.setPrototypeOf(this,i.prototype),Object.getPrototypeOf(this).name="ErrorWithReasonCode"}}t.ErrorWithReasonCode=i;class r extends Error{packet;constructor(e,t){super(e),this.packet=t,Object.setPrototypeOf(this,r.prototype),Object.getPrototypeOf(this).name="ErrorWithSubackPacket"}}t.ErrorWithSubackPacket=r,t.nextTick="function"==typeof process?.nextTick?process.nextTick:e=>{setTimeout(e,0)},t.MQTTJS_VERSION=n(2860).version},4756(e){"use strict";e.exports=require("tls")},4759(e){"use strict";const t=Symbol("kDone"),n=Symbol("kRun");e.exports=class{constructor(e){this[t]=()=>{this.pending--,this[n]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[n]()}[n](){if(this.pending!==this.concurrency&&this.jobs.length){const e=this.jobs.shift();this.pending++,e(this[t])}}}},4829(e,t,n){"use strict";const i=n(4478).Duplex,r=n(2017),o=n(7813);function s(e){if(!(this instanceof s))return new s(e);if("function"==typeof e){this._callback=e;const t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)}),e=null}o._init.call(this,e),i.call(this)}r(s,i),Object.assign(s.prototype,o.prototype),s.prototype._new=function(e){return new s(e)},s.prototype._write=function(e,t,n){this._appendBuffer(e),"function"==typeof n&&n()},s.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)},s.prototype.end=function(e){i.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},s.prototype._destroy=function(e,t){this._bufs.length=0,this.length=0,t(e)},s.prototype._isBufferList=function(e){return e instanceof s||e instanceof o||s.isBufferList(e)},s.isBufferList=o.isBufferList,e.exports=s,e.exports.BufferListStream=s,e.exports.BufferList=o},4959(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=[0,16,128,131,135,144,145,151,153];t.default=(e,t,i)=>{e.log("handlePublish: packet %o",t),i="undefined"!=typeof i?i:e.noop;let r=t.topic.toString();const o=t.payload,{qos:s}=t,{messageId:a}=t,{options:c}=e;if(5===e.options.protocolVersion){let n;if(t.properties&&(n=t.properties.topicAlias),"undefined"!=typeof n)if(0===r.length){if(!(n>0&&n<=65535))return e.log("handlePublish :: topic alias out of range. alias: %d",n),void e.emit("error",new Error("Received Topic Alias is out of range"));{const t=e.topicAliasRecv.getTopicByAlias(n);if(!t)return e.log("handlePublish :: unregistered topic alias. alias: %d",n),void e.emit("error",new Error("Received unregistered Topic Alias"));r=t,e.log("handlePublish :: topic complemented by alias. topic: %s - alias: %d",r,n)}}else{if(!e.topicAliasRecv.put(r,n))return e.log("handlePublish :: topic alias out of range. alias: %d",n),void e.emit("error",new Error("Received Topic Alias is out of range"));e.log("handlePublish :: registered topic: %s - alias: %d",r,n)}}switch(e.log("handlePublish: qos %d",s),s){case 2:c.customHandleAcks(r,o,t,(r,o)=>("number"==typeof r&&(o=r,r=null),r?e.emit("error",r):-1===n.indexOf(o)?e.emit("error",new Error("Wrong reason code for pubrec")):void(o?e._sendPacket({cmd:"pubrec",messageId:a,reasonCode:o},i):e.incomingStore.put(t,()=>{e._sendPacket({cmd:"pubrec",messageId:a},i)}))));break;case 1:c.customHandleAcks(r,o,t,(s,c)=>("number"==typeof s&&(c=s,s=null),s?e.emit("error",s):-1===n.indexOf(c)?e.emit("error",new Error("Wrong reason code for puback")):(c||e.emit("message",r,o,t),void e.handleMessage(t,t=>{if(t)return i&&i(t);e._sendPacket({cmd:"puback",messageId:a,reasonCode:c},i)}))));break;case 0:e.emit("message",r,o,t),e.handleMessage(t,i);break;default:e.log("handlePublish: unknown QoS. Doing nothing.")}}},4966(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.LRUCache=void 0;const n="object"==typeof performance&&performance&&"function"==typeof performance.now?performance:Date,i=new Set,r="object"==typeof process&&process?process:{},o=(e,t,n,i)=>{"function"==typeof r.emitWarning?r.emitWarning(e,t,n,i):console.error(`[${n}] ${t}: ${e}`)};let s=globalThis.AbortController,a=globalThis.AbortSignal;if("undefined"==typeof s){a=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(e,t){this._onabort.push(t)}},s=class{constructor(){t()}signal=new a;abort(e){if(!this.signal.aborted){this.signal.reason=e,this.signal.aborted=!0;for(const t of this.signal._onabort)t(e);this.signal.onabort?.(e)}}};let e="1"!==r.env?.LRU_CACHE_IGNORE_AC_WARNING;const t=()=>{e&&(e=!1,o("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}Symbol("type");const c=e=>e&&e===Math.floor(e)&&e>0&&isFinite(e),l=e=>c(e)?e<=Math.pow(2,8)?Uint8Array:e<=Math.pow(2,16)?Uint16Array:e<=Math.pow(2,32)?Uint32Array:e<=Number.MAX_SAFE_INTEGER?d:null:null;class d extends Array{constructor(e){super(e),this.fill(0)}}class u{heap;length;static#e=!1;static create(e){const t=l(e);if(!t)return[];u.#e=!0;const n=new u(e,t);return u.#e=!1,n}constructor(e,t){if(!u.#e)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}}class p{#t;#n;#i;#r;#o;#s;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#a;#c;#l;#d;#u;#p;#h;#f;#g;#m;#y;#b;#v;#S;#_;#w;#k;static unsafeExposeInternals(e){return{starts:e.#v,ttls:e.#S,sizes:e.#b,keyMap:e.#l,keyList:e.#d,valList:e.#u,next:e.#p,prev:e.#h,get head(){return e.#f},get tail(){return e.#g},free:e.#m,isBackgroundFetch:t=>e.#I(t),backgroundFetch:(t,n,i,r)=>e.#x(t,n,i,r),moveToTail:t=>e.#C(t),indexes:t=>e.#E(t),rindexes:t=>e.#T(t),isStale:t=>e.#O(t)}}get max(){return this.#t}get maxSize(){return this.#n}get calculatedSize(){return this.#c}get size(){return this.#a}get fetchMethod(){return this.#o}get memoMethod(){return this.#s}get dispose(){return this.#i}get disposeAfter(){return this.#r}constructor(e){const{max:t=0,ttl:n,ttlResolution:r=1,ttlAutopurge:s,updateAgeOnGet:a,updateAgeOnHas:d,allowStale:h,dispose:f,disposeAfter:g,noDisposeOnSet:m,noUpdateTTL:y,maxSize:b=0,maxEntrySize:v=0,sizeCalculation:S,fetchMethod:_,memoMethod:w,noDeleteOnFetchRejection:k,noDeleteOnStaleGet:I,allowStaleOnFetchRejection:x,allowStaleOnFetchAbort:C,ignoreFetchAbort:E}=e;if(0!==t&&!c(t))throw new TypeError("max option must be a nonnegative integer");const T=t?l(t):Array;if(!T)throw new Error("invalid max value: "+t);if(this.#t=t,this.#n=b,this.maxEntrySize=v||this.#n,this.sizeCalculation=S,this.sizeCalculation){if(!this.#n&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if("function"!=typeof this.sizeCalculation)throw new TypeError("sizeCalculation set to non-function")}if(void 0!==w&&"function"!=typeof w)throw new TypeError("memoMethod must be a function if defined");if(this.#s=w,void 0!==_&&"function"!=typeof _)throw new TypeError("fetchMethod must be a function if specified");if(this.#o=_,this.#w=!!_,this.#l=new Map,this.#d=new Array(t).fill(void 0),this.#u=new Array(t).fill(void 0),this.#p=new T(t),this.#h=new T(t),this.#f=0,this.#g=0,this.#m=u.create(t),this.#a=0,this.#c=0,"function"==typeof f&&(this.#i=f),"function"==typeof g?(this.#r=g,this.#y=[]):(this.#r=void 0,this.#y=void 0),this.#_=!!this.#i,this.#k=!!this.#r,this.noDisposeOnSet=!!m,this.noUpdateTTL=!!y,this.noDeleteOnFetchRejection=!!k,this.allowStaleOnFetchRejection=!!x,this.allowStaleOnFetchAbort=!!C,this.ignoreFetchAbort=!!E,0!==this.maxEntrySize){if(0!==this.#n&&!c(this.#n))throw new TypeError("maxSize must be a positive integer if specified");if(!c(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#P()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!I,this.updateAgeOnGet=!!a,this.updateAgeOnHas=!!d,this.ttlResolution=c(r)||0===r?r:1,this.ttlAutopurge=!!s,this.ttl=n||0,this.ttl){if(!c(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#A()}if(0===this.#t&&0===this.ttl&&0===this.#n)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#t&&!this.#n){const e="LRU_CACHE_UNBOUNDED";if((e=>!i.has(e))(e)){i.add(e);o("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",e,p)}}}getRemainingTTL(e){return this.#l.has(e)?1/0:0}#A(){const e=new d(this.#t),t=new d(this.#t);this.#S=e,this.#v=t,this.#R=(i,r,o=n.now())=>{if(t[i]=0!==r?o:0,e[i]=r,0!==r&&this.ttlAutopurge){const e=setTimeout(()=>{this.#O(i)&&this.#M(this.#d[i],"expire")},r+1);e.unref&&e.unref()}},this.#L=i=>{t[i]=0!==e[i]?n.now():0},this.#N=(n,o)=>{if(e[o]){const s=e[o],a=t[o];if(!s||!a)return;n.ttl=s,n.start=a,n.now=i||r();const c=n.now-a;n.remainingTTL=s-c}};let i=0;const r=()=>{const e=n.now();if(this.ttlResolution>0){i=e;const t=setTimeout(()=>i=0,this.ttlResolution);t.unref&&t.unref()}return e};this.getRemainingTTL=n=>{const o=this.#l.get(n);if(void 0===o)return 0;const s=e[o],a=t[o];if(!s||!a)return 1/0;return s-((i||r())-a)},this.#O=n=>{const o=t[n],s=e[n];return!!s&&!!o&&(i||r())-o>s}}#L=()=>{};#N=()=>{};#R=()=>{};#O=()=>!1;#P(){const e=new d(this.#t);this.#c=0,this.#b=e,this.#D=t=>{this.#c-=e[t],e[t]=0},this.#B=(e,t,n,i)=>{if(this.#I(t))return 0;if(!c(n)){if(!i)throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");if("function"!=typeof i)throw new TypeError("sizeCalculation must be a function");if(n=i(t,e),!c(n))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}return n},this.#j=(t,n,i)=>{if(e[t]=n,this.#n){const n=this.#n-e[t];for(;this.#c>n;)this.#$(!0)}this.#c+=e[t],i&&(i.entrySize=n,i.totalCalculatedSize=this.#c)}}#D=e=>{};#j=(e,t,n)=>{};#B=(e,t,n,i)=>{if(n||i)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#E({allowStale:e=this.allowStale}={}){if(this.#a)for(let t=this.#g;this.#F(t)&&(!e&&this.#O(t)||(yield t),t!==this.#f);)t=this.#h[t]}*#T({allowStale:e=this.allowStale}={}){if(this.#a)for(let t=this.#f;this.#F(t)&&(!e&&this.#O(t)||(yield t),t!==this.#g);)t=this.#p[t]}#F(e){return void 0!==e&&this.#l.get(this.#d[e])===e}*entries(){for(const e of this.#E())void 0===this.#u[e]||void 0===this.#d[e]||this.#I(this.#u[e])||(yield[this.#d[e],this.#u[e]])}*rentries(){for(const e of this.#T())void 0===this.#u[e]||void 0===this.#d[e]||this.#I(this.#u[e])||(yield[this.#d[e],this.#u[e]])}*keys(){for(const e of this.#E()){const t=this.#d[e];void 0===t||this.#I(this.#u[e])||(yield t)}}*rkeys(){for(const e of this.#T()){const t=this.#d[e];void 0===t||this.#I(this.#u[e])||(yield t)}}*values(){for(const e of this.#E()){void 0===this.#u[e]||this.#I(this.#u[e])||(yield this.#u[e])}}*rvalues(){for(const e of this.#T()){void 0===this.#u[e]||this.#I(this.#u[e])||(yield this.#u[e])}}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(const n of this.#E()){const i=this.#u[n],r=this.#I(i)?i.__staleWhileFetching:i;if(void 0!==r&&e(r,this.#d[n],this))return this.get(this.#d[n],t)}}forEach(e,t=this){for(const n of this.#E()){const i=this.#u[n],r=this.#I(i)?i.__staleWhileFetching:i;void 0!==r&&e.call(t,r,this.#d[n],this)}}rforEach(e,t=this){for(const n of this.#T()){const i=this.#u[n],r=this.#I(i)?i.__staleWhileFetching:i;void 0!==r&&e.call(t,r,this.#d[n],this)}}purgeStale(){let e=!1;for(const t of this.#T({allowStale:!0}))this.#O(t)&&(this.#M(this.#d[t],"expire"),e=!0);return e}info(e){const t=this.#l.get(e);if(void 0===t)return;const i=this.#u[t],r=this.#I(i)?i.__staleWhileFetching:i;if(void 0===r)return;const o={value:r};if(this.#S&&this.#v){const e=this.#S[t],i=this.#v[t];if(e&&i){const t=e-(n.now()-i);o.ttl=t,o.start=Date.now()}}return this.#b&&(o.size=this.#b[t]),o}dump(){const e=[];for(const t of this.#E({allowStale:!0})){const i=this.#d[t],r=this.#u[t],o=this.#I(r)?r.__staleWhileFetching:r;if(void 0===o||void 0===i)continue;const s={value:o};if(this.#S&&this.#v){s.ttl=this.#S[t];const e=n.now()-this.#v[t];s.start=Math.floor(Date.now()-e)}this.#b&&(s.size=this.#b[t]),e.unshift([i,s])}return e}load(e){this.clear();for(const[t,i]of e){if(i.start){const e=Date.now()-i.start;i.start=n.now()-e}this.set(t,i.value,i)}}set(e,t,n={}){if(void 0===t)return this.delete(e),this;const{ttl:i=this.ttl,start:r,noDisposeOnSet:o=this.noDisposeOnSet,sizeCalculation:s=this.sizeCalculation,status:a}=n;let{noUpdateTTL:c=this.noUpdateTTL}=n;const l=this.#B(e,t,n.size||0,s);if(this.maxEntrySize&&l>this.maxEntrySize)return a&&(a.set="miss",a.maxEntrySizeExceeded=!0),this.#M(e,"set"),this;let d=0===this.#a?void 0:this.#l.get(e);if(void 0===d)d=0===this.#a?this.#g:0!==this.#m.length?this.#m.pop():this.#a===this.#t?this.#$(!1):this.#a,this.#d[d]=e,this.#u[d]=t,this.#l.set(e,d),this.#p[this.#g]=d,this.#h[d]=this.#g,this.#g=d,this.#a++,this.#j(d,l,a),a&&(a.set="add"),c=!1;else{this.#C(d);const n=this.#u[d];if(t!==n){if(this.#w&&this.#I(n)){n.__abortController.abort(new Error("replaced"));const{__staleWhileFetching:t}=n;void 0===t||o||(this.#_&&this.#i?.(t,e,"set"),this.#k&&this.#y?.push([t,e,"set"]))}else o||(this.#_&&this.#i?.(n,e,"set"),this.#k&&this.#y?.push([n,e,"set"]));if(this.#D(d),this.#j(d,l,a),this.#u[d]=t,a){a.set="replace";const e=n&&this.#I(n)?n.__staleWhileFetching:n;void 0!==e&&(a.oldValue=e)}}else a&&(a.set="update")}if(0===i||this.#S||this.#A(),this.#S&&(c||this.#R(d,i,r),a&&this.#N(a,d)),!o&&this.#k&&this.#y){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}return this}pop(){try{for(;this.#a;){const e=this.#u[this.#f];if(this.#$(!0),this.#I(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(void 0!==e)return e}}finally{if(this.#k&&this.#y){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}}}#$(e){const t=this.#f,n=this.#d[t],i=this.#u[t];return this.#w&&this.#I(i)?i.__abortController.abort(new Error("evicted")):(this.#_||this.#k)&&(this.#_&&this.#i?.(i,n,"evict"),this.#k&&this.#y?.push([i,n,"evict"])),this.#D(t),e&&(this.#d[t]=void 0,this.#u[t]=void 0,this.#m.push(t)),1===this.#a?(this.#f=this.#g=0,this.#m.length=0):this.#f=this.#p[t],this.#l.delete(n),this.#a--,t}has(e,t={}){const{updateAgeOnHas:n=this.updateAgeOnHas,status:i}=t,r=this.#l.get(e);if(void 0!==r){const e=this.#u[r];if(this.#I(e)&&void 0===e.__staleWhileFetching)return!1;if(!this.#O(r))return n&&this.#L(r),i&&(i.has="hit",this.#N(i,r)),!0;i&&(i.has="stale",this.#N(i,r))}else i&&(i.has="miss");return!1}peek(e,t={}){const{allowStale:n=this.allowStale}=t,i=this.#l.get(e);if(void 0===i||!n&&this.#O(i))return;const r=this.#u[i];return this.#I(r)?r.__staleWhileFetching:r}#x(e,t,n,i){const r=void 0===t?void 0:this.#u[t];if(this.#I(r))return r;const o=new s,{signal:a}=n;a?.addEventListener("abort",()=>o.abort(a.reason),{signal:o.signal});const c={signal:o.signal,options:n,context:i},l=(i,r=!1)=>{const{aborted:s}=o.signal,a=n.ignoreFetchAbort&&void 0!==i;if(n.status&&(s&&!r?(n.status.fetchAborted=!0,n.status.fetchError=o.signal.reason,a&&(n.status.fetchAbortIgnored=!0)):n.status.fetchResolved=!0),s&&!a&&!r)return d(o.signal.reason);const l=u;return this.#u[t]===u&&(void 0===i?l.__staleWhileFetching?this.#u[t]=l.__staleWhileFetching:this.#M(e,"fetch"):(n.status&&(n.status.fetchUpdated=!0),this.set(e,i,c.options))),i},d=i=>{const{aborted:r}=o.signal,s=r&&n.allowStaleOnFetchAbort,a=s||n.allowStaleOnFetchRejection,c=a||n.noDeleteOnFetchRejection,l=u;if(this.#u[t]===u){!c||void 0===l.__staleWhileFetching?this.#M(e,"fetch"):s||(this.#u[t]=l.__staleWhileFetching)}if(a)return n.status&&void 0!==l.__staleWhileFetching&&(n.status.returnedStale=!0),l.__staleWhileFetching;if(l.__returned===l)throw i};n.status&&(n.status.fetchDispatched=!0);const u=new Promise((t,i)=>{const s=this.#o?.(e,r,c);s&&s instanceof Promise&&s.then(e=>t(void 0===e?void 0:e),i),o.signal.addEventListener("abort",()=>{n.ignoreFetchAbort&&!n.allowStaleOnFetchAbort||(t(void 0),n.allowStaleOnFetchAbort&&(t=e=>l(e,!0)))})}).then(l,e=>(n.status&&(n.status.fetchRejected=!0,n.status.fetchError=e),d(e))),p=Object.assign(u,{__abortController:o,__staleWhileFetching:r,__returned:void 0});return void 0===t?(this.set(e,p,{...c.options,status:void 0}),t=this.#l.get(e)):this.#u[t]=p,p}#I(e){if(!this.#w)return!1;const t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof s}async fetch(e,t={}){const{allowStale:n=this.allowStale,updateAgeOnGet:i=this.updateAgeOnGet,noDeleteOnStaleGet:r=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:s=this.noDisposeOnSet,size:a=0,sizeCalculation:c=this.sizeCalculation,noUpdateTTL:l=this.noUpdateTTL,noDeleteOnFetchRejection:d=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:u=this.allowStaleOnFetchRejection,ignoreFetchAbort:p=this.ignoreFetchAbort,allowStaleOnFetchAbort:h=this.allowStaleOnFetchAbort,context:f,forceRefresh:g=!1,status:m,signal:y}=t;if(!this.#w)return m&&(m.fetch="get"),this.get(e,{allowStale:n,updateAgeOnGet:i,noDeleteOnStaleGet:r,status:m});const b={allowStale:n,updateAgeOnGet:i,noDeleteOnStaleGet:r,ttl:o,noDisposeOnSet:s,size:a,sizeCalculation:c,noUpdateTTL:l,noDeleteOnFetchRejection:d,allowStaleOnFetchRejection:u,allowStaleOnFetchAbort:h,ignoreFetchAbort:p,status:m,signal:y};let v=this.#l.get(e);if(void 0===v){m&&(m.fetch="miss");const t=this.#x(e,v,b,f);return t.__returned=t}{const t=this.#u[v];if(this.#I(t)){const e=n&&void 0!==t.__staleWhileFetching;return m&&(m.fetch="inflight",e&&(m.returnedStale=!0)),e?t.__staleWhileFetching:t.__returned=t}const r=this.#O(v);if(!g&&!r)return m&&(m.fetch="hit"),this.#C(v),i&&this.#L(v),m&&this.#N(m,v),t;const o=this.#x(e,v,b,f),s=void 0!==o.__staleWhileFetching&&n;return m&&(m.fetch=r?"stale":"refresh",s&&r&&(m.returnedStale=!0)),s?o.__staleWhileFetching:o.__returned=o}}async forceFetch(e,t={}){const n=await this.fetch(e,t);if(void 0===n)throw new Error("fetch() returned undefined");return n}memo(e,t={}){const n=this.#s;if(!n)throw new Error("no memoMethod provided to constructor");const{context:i,forceRefresh:r,...o}=t,s=this.get(e,o);if(!r&&void 0!==s)return s;const a=n(e,s,{options:o,context:i});return this.set(e,a,o),a}get(e,t={}){const{allowStale:n=this.allowStale,updateAgeOnGet:i=this.updateAgeOnGet,noDeleteOnStaleGet:r=this.noDeleteOnStaleGet,status:o}=t,s=this.#l.get(e);if(void 0!==s){const t=this.#u[s],a=this.#I(t);return o&&this.#N(o,s),this.#O(s)?(o&&(o.get="stale"),a?(o&&n&&void 0!==t.__staleWhileFetching&&(o.returnedStale=!0),n?t.__staleWhileFetching:void 0):(r||this.#M(e,"expire"),o&&n&&(o.returnedStale=!0),n?t:void 0)):(o&&(o.get="hit"),a?t.__staleWhileFetching:(this.#C(s),i&&this.#L(s),t))}o&&(o.get="miss")}#U(e,t){this.#h[t]=e,this.#p[e]=t}#C(e){e!==this.#g&&(e===this.#f?this.#f=this.#p[e]:this.#U(this.#h[e],this.#p[e]),this.#U(this.#g,e),this.#g=e)}delete(e){return this.#M(e,"delete")}#M(e,t){let n=!1;if(0!==this.#a){const i=this.#l.get(e);if(void 0!==i)if(n=!0,1===this.#a)this.#z(t);else{this.#D(i);const n=this.#u[i];if(this.#I(n)?n.__abortController.abort(new Error("deleted")):(this.#_||this.#k)&&(this.#_&&this.#i?.(n,e,t),this.#k&&this.#y?.push([n,e,t])),this.#l.delete(e),this.#d[i]=void 0,this.#u[i]=void 0,i===this.#g)this.#g=this.#h[i];else if(i===this.#f)this.#f=this.#p[i];else{const e=this.#h[i];this.#p[e]=this.#p[i];const t=this.#p[i];this.#h[t]=this.#h[i]}this.#a--,this.#m.push(i)}}if(this.#k&&this.#y?.length){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}return n}clear(){return this.#z("delete")}#z(e){for(const t of this.#T({allowStale:!0})){const n=this.#u[t];if(this.#I(n))n.__abortController.abort(new Error("deleted"));else{const i=this.#d[t];this.#_&&this.#i?.(n,i,e),this.#k&&this.#y?.push([n,i,e])}}if(this.#l.clear(),this.#u.fill(void 0),this.#d.fill(void 0),this.#S&&this.#v&&(this.#S.fill(0),this.#v.fill(0)),this.#b&&this.#b.fill(0),this.#f=0,this.#g=0,this.#m.length=0,this.#c=0,this.#a=0,this.#k&&this.#y){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}}}t.LRUCache=p},4988(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=new WeakMap,i=new WeakMap;function r(e){const t=n.get(e);return console.assert(null!=t,"'this' is expected an Event object, but got",e),t}function o(e){null==e.passiveListener?e.event.cancelable&&(e.canceled=!0,"function"==typeof e.event.preventDefault&&e.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",e.passiveListener)}function s(e,t){n.set(this,{eventTarget:e,event:t,eventPhase:2,currentTarget:e,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:t.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});const i=Object.keys(t);for(let e=0;e<i.length;++e){const t=i[e];t in this||Object.defineProperty(this,t,a(t))}}function a(e){return{get(){return r(this).event[e]},set(t){r(this).event[e]=t},configurable:!0,enumerable:!0}}function c(e){return{value(){const t=r(this).event;return t[e].apply(t,arguments)},configurable:!0,enumerable:!0}}function l(e){if(null==e||e===Object.prototype)return s;let t=i.get(e);return null==t&&(t=function(e,t){const n=Object.keys(t);if(0===n.length)return e;function i(t,n){e.call(this,t,n)}i.prototype=Object.create(e.prototype,{constructor:{value:i,configurable:!0,writable:!0}});for(let r=0;r<n.length;++r){const o=n[r];if(!(o in e.prototype)){const e="function"==typeof Object.getOwnPropertyDescriptor(t,o).value;Object.defineProperty(i.prototype,o,e?c(o):a(o))}}return i}(l(Object.getPrototypeOf(e)),e),i.set(e,t)),t}function d(e){return r(e).immediateStopped}function u(e,t){r(e).passiveListener=t}s.prototype={get type(){return r(this).event.type},get target(){return r(this).eventTarget},get currentTarget(){return r(this).currentTarget},composedPath(){const e=r(this).currentTarget;return null==e?[]:[e]},get NONE(){return 0},get CAPTURING_PHASE(){return 1},get AT_TARGET(){return 2},get BUBBLING_PHASE(){return 3},get eventPhase(){return r(this).eventPhase},stopPropagation(){const e=r(this);e.stopped=!0,"function"==typeof e.event.stopPropagation&&e.event.stopPropagation()},stopImmediatePropagation(){const e=r(this);e.stopped=!0,e.immediateStopped=!0,"function"==typeof e.event.stopImmediatePropagation&&e.event.stopImmediatePropagation()},get bubbles(){return Boolean(r(this).event.bubbles)},get cancelable(){return Boolean(r(this).event.cancelable)},preventDefault(){o(r(this))},get defaultPrevented(){return r(this).canceled},get composed(){return Boolean(r(this).event.composed)},get timeStamp(){return r(this).timeStamp},get srcElement(){return r(this).eventTarget},get cancelBubble(){return r(this).stopped},set cancelBubble(e){if(!e)return;const t=r(this);t.stopped=!0,"boolean"==typeof t.event.cancelBubble&&(t.event.cancelBubble=!0)},get returnValue(){return!r(this).canceled},set returnValue(e){e||o(r(this))},initEvent(){}},Object.defineProperty(s.prototype,"constructor",{value:s,configurable:!0,writable:!0}),"undefined"!=typeof window&&"undefined"!=typeof window.Event&&(Object.setPrototypeOf(s.prototype,window.Event.prototype),i.set(window.Event.prototype,s));const p=new WeakMap;function h(e){return null!==e&&"object"==typeof e}function f(e){const t=p.get(e);if(null==t)throw new TypeError("'this' is expected an EventTarget object, but got another value.");return t}function g(e,t){Object.defineProperty(e,`on${t}`,function(e){return{get(){let t=f(this).get(e);for(;null!=t;){if(3===t.listenerType)return t.listener;t=t.next}return null},set(t){"function"==typeof t||h(t)||(t=null);const n=f(this);let i=null,r=n.get(e);for(;null!=r;)3===r.listenerType?null!==i?i.next=r.next:null!==r.next?n.set(e,r.next):n.delete(e):i=r,r=r.next;if(null!==t){const r={listener:t,listenerType:3,passive:!1,once:!1,next:null};null===i?n.set(e,r):i.next=r}},configurable:!0,enumerable:!0}}(t))}function m(e){function t(){y.call(this)}t.prototype=Object.create(y.prototype,{constructor:{value:t,configurable:!0,writable:!0}});for(let n=0;n<e.length;++n)g(t.prototype,e[n]);return t}function y(){if(!(this instanceof y)){if(1===arguments.length&&Array.isArray(arguments[0]))return m(arguments[0]);if(arguments.length>0){const e=new Array(arguments.length);for(let t=0;t<arguments.length;++t)e[t]=arguments[t];return m(e)}throw new TypeError("Cannot call a class as a function")}p.set(this,new Map)}y.prototype={addEventListener(e,t,n){if(null==t)return;if("function"!=typeof t&&!h(t))throw new TypeError("'listener' should be a function or an object.");const i=f(this),r=h(n),o=(r?Boolean(n.capture):Boolean(n))?1:2,s={listener:t,listenerType:o,passive:r&&Boolean(n.passive),once:r&&Boolean(n.once),next:null};let a=i.get(e);if(void 0===a)return void i.set(e,s);let c=null;for(;null!=a;){if(a.listener===t&&a.listenerType===o)return;c=a,a=a.next}c.next=s},removeEventListener(e,t,n){if(null==t)return;const i=f(this),r=(h(n)?Boolean(n.capture):Boolean(n))?1:2;let o=null,s=i.get(e);for(;null!=s;){if(s.listener===t&&s.listenerType===r)return void(null!==o?o.next=s.next:null!==s.next?i.set(e,s.next):i.delete(e));o=s,s=s.next}},dispatchEvent(e){if(null==e||"string"!=typeof e.type)throw new TypeError('"event.type" should be a string.');const t=f(this),n=e.type;let i=t.get(n);if(null==i)return!0;const o=function(e,t){return new(l(Object.getPrototypeOf(t)))(e,t)}(this,e);let s=null;for(;null!=i;){if(i.once?null!==s?s.next=i.next:null!==i.next?t.set(n,i.next):t.delete(n):s=i,u(o,i.passive?i.listener:null),"function"==typeof i.listener)try{i.listener.call(this,o)}catch(e){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(e)}else 3!==i.listenerType&&"function"==typeof i.listener.handleEvent&&i.listener.handleEvent(o);if(d(o))break;i=i.next}return u(o,null),function(e,t){r(e).eventPhase=t}(o,0),function(e,t){r(e).currentTarget=t}(o,null),!o.defaultPrevented}},Object.defineProperty(y.prototype,"constructor",{value:y,configurable:!0,writable:!0}),"undefined"!=typeof window&&"undefined"!=typeof window.EventTarget&&Object.setPrototypeOf(y.prototype,window.EventTarget.prototype),t.defineEventAttribute=g,t.EventTarget=y,t.default=y,e.exports=y,e.exports.EventTarget=e.exports.default=y,e.exports.defineEventAttribute=g},4997(e,t){"use strict";function n(e,t){const n=e=>e?e.charAt(0).toUpperCase()+e.slice(1):"Object",i=t.objectLabel?`${n(t.objectClass||"")} (${t.objectLabel})`:n(t.objectClass||"");switch(e){case"property_entry":return t.objectLabel&&t.objectLabel!==t.objectClass?t.objectLabel:t.involvedLandmarks&&t.involvedLandmarks.length>0?`${i} entered property near ${t.involvedLandmarks[0]}`:`${i} entered property at ${t.cameraName||"entrance"}`;case"property_exit":return t.objectLabel&&t.objectLabel!==t.objectClass?t.objectLabel:t.involvedLandmarks&&t.involvedLandmarks.length>0?`${i} left property via ${t.involvedLandmarks[0]}`:`${i} left property`;case"movement":if(t.objectLabel&&t.objectLabel!==t.objectClass){if(t.fromCameraId&&t.fromCameraId!==t.toCameraId&&t.transitTime){const e=Math.round(t.transitTime/1e3),n=e>0?` (${e}s)`:"",i=t.pathDescription?` via ${t.pathDescription}`:"";return`${t.objectLabel}${i}${n}`}return t.objectLabel}if(t.fromCameraId&&t.fromCameraId!==t.toCameraId){const e=t.transitTime?Math.round(t.transitTime/1e3):0,n=e>0?` (${e}s transit)`:"";let r=`${i} moving from ${t.fromCameraName||"unknown"} towards ${t.toCameraName||"unknown"}`;return t.involvedLandmarks&&t.involvedLandmarks.length>0&&(r+=` near ${t.involvedLandmarks.join(", ")}`),`${r}${n}`}return t.involvedLandmarks&&t.involvedLandmarks.length>0?`${i} detected near ${t.involvedLandmarks[0]}`:`${i} detected at ${t.cameraName||"camera"}`;case"unusual_path":return`${i} took unusual path: ${t.actualPath||"unknown"}`;case"dwell_time":return`${i} has been present for ${Math.round((t.dwellTime||0)/6e4)} minutes in ${t.zoneName||t.cameraName||"area"}`;case"restricted_zone":return`${i} entered restricted zone: ${t.zoneName}`;case"lost_tracking":return`Lost tracking of ${i} near ${t.cameraName||"unknown location"}`;case"reappearance":return`${i} reappeared on ${t.cameraName}`;case"zone_entry":return`${i} entered ${t.zoneName}`;case"zone_exit":return`${i} exited ${t.zoneName}`;default:return`Tracking event: ${e}`}}Object.defineProperty(t,"__esModule",{value:!0}),t.createDefaultRules=function(){return[{id:"property-entry",name:"Property Entry",enabled:!0,type:"property_entry",conditions:[],severity:"info",notifiers:[],cooldown:6e4},{id:"property-exit",name:"Property Exit",enabled:!0,type:"property_exit",conditions:[],severity:"info",notifiers:[],cooldown:6e4},{id:"movement",name:"Movement Between Cameras",enabled:!0,type:"movement",conditions:[],severity:"info",notifiers:[],cooldown:1e4},{id:"unusual-path",name:"Unusual Path Detected",enabled:!0,type:"unusual_path",conditions:[],severity:"warning",notifiers:[],cooldown:6e5},{id:"dwell-time",name:"Extended Dwell Time",enabled:!0,type:"dwell_time",conditions:[{field:"totalDwellTime",operator:"greater_than",value:3e5}],severity:"warning",notifiers:[],cooldown:6e5},{id:"restricted-zone",name:"Restricted Zone Entry",enabled:!0,type:"restricted_zone",conditions:[],severity:"critical",notifiers:[],cooldown:0},{id:"lost-tracking",name:"Lost Object Tracking",enabled:!1,type:"lost_tracking",conditions:[],severity:"info",notifiers:[],cooldown:3e5}]},t.generateAlertMessage=n,t.createAlert=function(e,t,i,r="info",o){return{id:`${Date.now()}-${Math.random().toString(36).slice(2,9)}`,type:e,severity:r,timestamp:Date.now(),trackedObjectId:t,message:n(e,i),details:i,acknowledged:!1,ruleId:o}}},5228(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(4723),r=n(1021);t.default=(e,t)=>{const{options:n}=e,o=n.protocolVersion,s=5===o?t.reasonCode:t.returnCode;if(5!==o){const t=new i.ErrorWithReasonCode(`Protocol error: Auth packets are only supported in MQTT 5. Your version:${o}`,s);return void e.emit("error",t)}e.handleAuth(t,(t,n)=>{if(t)e.emit("error",t);else if(24===s)e.reconnecting=!1,e._sendPacket(n);else{const t=new i.ErrorWithReasonCode(`Connection refused: ${r.ReasonCodes[s]}`,s);e.emit("error",t)}})}},5291(e,t,n){"use strict";const{MathFloor:i,NumberIsInteger:r}=n(4134),{validateInteger:o}=n(277),{ERR_INVALID_ARG_VALUE:s}=n(6371).codes;let a=16384,c=16;function l(e){return e?c:a}e.exports={getHighWaterMark:function(e,t,n,o){const a=function(e,t,n){return null!=e.highWaterMark?e.highWaterMark:t?e[n]:null}(t,o,n);if(null!=a){if(!r(a)||a<0){throw new s(o?`options.${n}`:"options.highWaterMark",a)}return i(a)}return l(e.objectMode)},getDefaultHighWaterMark:l,setDefaultHighWaterMark:function(e,t){o(t,"value",0),e?c=t:a=t}}},5389(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TrackingState=void 0;const i=n(441);t.TrackingState=class{objects=new Map;objectsByCamera=new Map;changeCallbacks=[];storage;console;constructor(e,t){this.storage=e,this.console=t,this.loadPersistedState()}createObject(e,t,n){const r=(0,i.createTrackedObject)(e,t,n);return this.upsertObject(r),r}upsertObject(e){const t=this.objects.get(e.globalId);if(t)for(const n of t.activeOnCameras)this.objectsByCamera.get(n)?.delete(e.globalId);for(const t of e.activeOnCameras)this.objectsByCamera.has(t)||this.objectsByCamera.set(t,new Set),this.objectsByCamera.get(t).add(e.globalId);this.objects.set(e.globalId,e),this.notifyChange(),this.persistState()}addSighting(e,t){const n=this.objects.get(e);return!!n&&((0,i.addSighting)(n,t),this.objectsByCamera.has(t.cameraId)||this.objectsByCamera.set(t.cameraId,new Set),this.objectsByCamera.get(t.cameraId).add(e),this.notifyChange(),this.persistState(),!0)}addJourney(e,t){const n=this.objects.get(e);return!!n&&((0,i.addJourneySegment)(n,t),this.objectsByCamera.get(t.fromCameraId)?.delete(e),this.objectsByCamera.has(t.toCameraId)||this.objectsByCamera.set(t.toCameraId,new Set),this.objectsByCamera.get(t.toCameraId).add(e),this.notifyChange(),this.persistState(),!0)}getObject(e){return this.objects.get(e)}getActiveObjects(){return Array.from(this.objects.values()).filter(e=>"active"===e.state||"pending"===e.state)}getObjectsOnCamera(e){const t=this.objectsByCamera.get(e)||new Set;return Array.from(t).map(e=>this.objects.get(e)).filter(e=>!!e&&"active"===e.state)}getAllObjects(){return Array.from(this.objects.values())}getActiveCount(){return this.getActiveObjects().length}getJourney(e){return this.objects.get(e)?.journey}markExited(e,t,n){const i=this.objects.get(e);if(i){i.state="exited",i.hasExited=!0,i.exitCamera=t,i.exitCameraName=n,i.activeOnCameras=[];for(const[t,n]of this.objectsByCamera.entries())n.delete(e);this.notifyChange(),this.persistState()}}markLost(e){const t=this.objects.get(e);if(t){t.state="lost",t.activeOnCameras=[];for(const[t,n]of this.objectsByCamera.entries())n.delete(e);this.notifyChange(),this.persistState()}}markPending(e){const t=this.objects.get(e);t&&"active"===t.state&&(t.state="pending",this.notifyChange())}reactivate(e){const t=this.objects.get(e);t&&"pending"===t.state&&(t.state="active",this.notifyChange())}onStateChange(e){this.changeCallbacks.push(e)}offStateChange(e){const t=this.changeCallbacks.indexOf(e);-1!==t&&this.changeCallbacks.splice(t,1)}notifyChange(){const e=this.getAllObjects();for(const t of this.changeCallbacks)try{t(e)}catch(e){this.console.error("State change callback error:",e)}}persistState(){try{const e=Date.now(),t=Array.from(this.objects.values()).filter(t=>"active"===t.state||"pending"===t.state||e-t.lastSeen<36e5);this.storage.setItem("tracked-objects",JSON.stringify(t))}catch(e){this.console.error("Failed to persist tracking state:",e)}}loadPersistedState(){try{const e=this.storage.getItem("tracked-objects");if(e){const t=JSON.parse(e),n=Date.now();for(const e of t){"active"===e.state&&n-e.lastSeen>3e5&&(e.state="lost",e.activeOnCameras=[]),this.objects.set(e.globalId,e);for(const t of e.activeOnCameras)this.objectsByCamera.has(t)||this.objectsByCamera.set(t,new Set),this.objectsByCamera.get(t).add(e.globalId)}this.console.log(`Loaded ${t.length} persisted tracked objects`)}}catch(e){this.console.error("Failed to load persisted tracking state:",e)}}cleanup(e=864e5){const t=Date.now();let n=0;for(const[i,r]of this.objects.entries())t-r.lastSeen>e&&"active"!==r.state&&(this.objects.delete(i),n++);n>0&&(this.console.log(`Cleaned up ${n} old tracked objects`),this.persistState())}generateId(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}}},5399(e,t,n){const i=e.exports,{Buffer:r}=n(181);i.types={0:"reserved",1:"connect",2:"connack",3:"publish",4:"puback",5:"pubrec",6:"pubrel",7:"pubcomp",8:"subscribe",9:"suback",10:"unsubscribe",11:"unsuback",12:"pingreq",13:"pingresp",14:"disconnect",15:"auth"},i.requiredHeaderFlags={1:0,2:0,4:0,5:0,6:2,7:0,8:2,9:0,10:2,11:0,12:0,13:0,14:0,15:0},i.requiredHeaderFlagsErrors={};for(const e in i.requiredHeaderFlags){const t=i.requiredHeaderFlags[e];i.requiredHeaderFlagsErrors[e]="Invalid header flag bits, must be 0x"+t.toString(16)+" for "+i.types[e]+" packet"}i.codes={};for(const e in i.types){const t=i.types[e];i.codes[t]=e}i.CMD_SHIFT=4,i.CMD_MASK=240,i.DUP_MASK=8,i.QOS_MASK=3,i.QOS_SHIFT=1,i.RETAIN_MASK=1,i.VARBYTEINT_MASK=127,i.VARBYTEINT_FIN_MASK=128,i.VARBYTEINT_MAX=268435455,i.SESSIONPRESENT_MASK=1,i.SESSIONPRESENT_HEADER=r.from([i.SESSIONPRESENT_MASK]),i.CONNACK_HEADER=r.from([i.codes.connack<<i.CMD_SHIFT]),i.USERNAME_MASK=128,i.PASSWORD_MASK=64,i.WILL_RETAIN_MASK=32,i.WILL_QOS_MASK=24,i.WILL_QOS_SHIFT=3,i.WILL_FLAG_MASK=4,i.CLEAN_SESSION_MASK=2,i.CONNECT_HEADER=r.from([i.codes.connect<<i.CMD_SHIFT]),i.properties={sessionExpiryInterval:17,willDelayInterval:24,receiveMaximum:33,maximumPacketSize:39,topicAliasMaximum:34,requestResponseInformation:25,requestProblemInformation:23,userProperties:38,authenticationMethod:21,authenticationData:22,payloadFormatIndicator:1,messageExpiryInterval:2,contentType:3,responseTopic:8,correlationData:9,maximumQoS:36,retainAvailable:37,assignedClientIdentifier:18,reasonString:31,wildcardSubscriptionAvailable:40,subscriptionIdentifiersAvailable:41,sharedSubscriptionAvailable:42,serverKeepAlive:19,responseInformation:26,serverReference:28,topicAlias:35,subscriptionIdentifier:11},i.propertiesCodes={};for(const e in i.properties){const t=i.properties[e];i.propertiesCodes[t]=e}function o(e){return[0,1,2].map(t=>[0,1].map(n=>[0,1].map(o=>{const s=r.alloc(1);return s.writeUInt8(i.codes[e]<<i.CMD_SHIFT|(n?i.DUP_MASK:0)|t<<i.QOS_SHIFT|o,0,!0),s})))}i.propertiesTypes={sessionExpiryInterval:"int32",willDelayInterval:"int32",receiveMaximum:"int16",maximumPacketSize:"int32",topicAliasMaximum:"int16",requestResponseInformation:"byte",requestProblemInformation:"byte",userProperties:"pair",authenticationMethod:"string",authenticationData:"binary",payloadFormatIndicator:"byte",messageExpiryInterval:"int32",contentType:"string",responseTopic:"string",correlationData:"binary",maximumQoS:"int8",retainAvailable:"byte",assignedClientIdentifier:"string",reasonString:"string",wildcardSubscriptionAvailable:"byte",subscriptionIdentifiersAvailable:"byte",sharedSubscriptionAvailable:"byte",serverKeepAlive:"int16",responseInformation:"string",serverReference:"string",topicAlias:"int16",subscriptionIdentifier:"var"},i.PUBLISH_HEADER=o("publish"),i.SUBSCRIBE_HEADER=o("subscribe"),i.SUBSCRIBE_OPTIONS_QOS_MASK=3,i.SUBSCRIBE_OPTIONS_NL_MASK=1,i.SUBSCRIBE_OPTIONS_NL_SHIFT=2,i.SUBSCRIBE_OPTIONS_RAP_MASK=1,i.SUBSCRIBE_OPTIONS_RAP_SHIFT=3,i.SUBSCRIBE_OPTIONS_RH_MASK=3,i.SUBSCRIBE_OPTIONS_RH_SHIFT=4,i.SUBSCRIBE_OPTIONS_RH=[0,16,32],i.SUBSCRIBE_OPTIONS_NL=4,i.SUBSCRIBE_OPTIONS_RAP=8,i.SUBSCRIBE_OPTIONS_QOS=[0,1,2],i.UNSUBSCRIBE_HEADER=o("unsubscribe"),i.ACKS={unsuback:o("unsuback"),puback:o("puback"),pubcomp:o("pubcomp"),pubrel:o("pubrel"),pubrec:o("pubrec")},i.SUBACK_HEADER=r.from([i.codes.suback<<i.CMD_SHIFT]),i.VERSION3=r.from([3]),i.VERSION4=r.from([4]),i.VERSION5=r.from([5]),i.VERSION131=r.from([131]),i.VERSION132=r.from([132]),i.QOS=[0,1,2].map(e=>r.from([e])),i.EMPTY={pingreq:r.from([i.codes.pingreq<<4,0]),pingresp:r.from([i.codes.pingresp<<4,0]),disconnect:r.from([i.codes.disconnect<<4,0])},i.MQTT5_PUBACK_PUBREC_CODES={0:"Success",16:"No matching subscribers",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",144:"Topic Name invalid",145:"Packet identifier in use",151:"Quota exceeded",153:"Payload format invalid"},i.MQTT5_PUBREL_PUBCOMP_CODES={0:"Success",146:"Packet Identifier not found"},i.MQTT5_SUBACK_CODES={0:"Granted QoS 0",1:"Granted QoS 1",2:"Granted QoS 2",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",143:"Topic Filter invalid",145:"Packet Identifier in use",151:"Quota exceeded",158:"Shared Subscriptions not supported",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"},i.MQTT5_UNSUBACK_CODES={0:"Success",17:"No subscription existed",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",143:"Topic Filter invalid",145:"Packet Identifier in use"},i.MQTT5_DISCONNECT_CODES={0:"Normal disconnection",4:"Disconnect with Will Message",128:"Unspecified error",129:"Malformed Packet",130:"Protocol Error",131:"Implementation specific error",135:"Not authorized",137:"Server busy",139:"Server shutting down",141:"Keep Alive timeout",142:"Session taken over",143:"Topic Filter invalid",144:"Topic Name invalid",147:"Receive Maximum exceeded",148:"Topic Alias invalid",149:"Packet too large",150:"Message rate too high",151:"Quota exceeded",152:"Administrative action",153:"Payload format invalid",154:"Retain not supported",155:"QoS not supported",156:"Use another server",157:"Server moved",158:"Shared Subscriptions not supported",159:"Connection rate exceeded",160:"Maximum connect time",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"},i.MQTT5_AUTH_CODES={0:"Success",24:"Continue authentication",25:"Re-authenticate"}},5438(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SOCKS5_NO_ACCEPTABLE_AUTH=t.SOCKS5_CUSTOM_AUTH_END=t.SOCKS5_CUSTOM_AUTH_START=t.SOCKS_INCOMING_PACKET_SIZES=t.SocksClientState=t.Socks5Response=t.Socks5HostType=t.Socks5Auth=t.Socks4Response=t.SocksCommand=t.ERRORS=t.DEFAULT_TIMEOUT=void 0;t.DEFAULT_TIMEOUT=3e4;t.ERRORS={InvalidSocksCommand:"An invalid SOCKS command was provided. Valid options are connect, bind, and associate.",InvalidSocksCommandForOperation:"An invalid SOCKS command was provided. Only a subset of commands are supported for this operation.",InvalidSocksCommandChain:"An invalid SOCKS command was provided. Chaining currently only supports the connect command.",InvalidSocksClientOptionsDestination:"An invalid destination host was provided.",InvalidSocksClientOptionsExistingSocket:"An invalid existing socket was provided. This should be an instance of stream.Duplex.",InvalidSocksClientOptionsProxy:"Invalid SOCKS proxy details were provided.",InvalidSocksClientOptionsTimeout:"An invalid timeout value was provided. Please enter a value above 0 (in ms).",InvalidSocksClientOptionsProxiesLength:"At least two socks proxies must be provided for chaining.",InvalidSocksClientOptionsCustomAuthRange:"Custom auth must be a value between 0x80 and 0xFE.",InvalidSocksClientOptionsCustomAuthOptions:"When a custom_auth_method is provided, custom_auth_request_handler, custom_auth_response_size, and custom_auth_response_handler must also be provided and valid.",NegotiationError:"Negotiation error",SocketClosed:"Socket closed",ProxyConnectionTimedOut:"Proxy connection timed out",InternalError:"SocksClient internal error (this should not happen)",InvalidSocks4HandshakeResponse:"Received invalid Socks4 handshake response",Socks4ProxyRejectedConnection:"Socks4 Proxy rejected connection",InvalidSocks4IncomingConnectionResponse:"Socks4 invalid incoming connection response",Socks4ProxyRejectedIncomingBoundConnection:"Socks4 Proxy rejected incoming bound connection",InvalidSocks5InitialHandshakeResponse:"Received invalid Socks5 initial handshake response",InvalidSocks5IntiailHandshakeSocksVersion:"Received invalid Socks5 initial handshake (invalid socks version)",InvalidSocks5InitialHandshakeNoAcceptedAuthType:"Received invalid Socks5 initial handshake (no accepted authentication type)",InvalidSocks5InitialHandshakeUnknownAuthType:"Received invalid Socks5 initial handshake (unknown authentication type)",Socks5AuthenticationFailed:"Socks5 Authentication failed",InvalidSocks5FinalHandshake:"Received invalid Socks5 final handshake response",InvalidSocks5FinalHandshakeRejected:"Socks5 proxy rejected connection",InvalidSocks5IncomingConnectionResponse:"Received invalid Socks5 incoming connection response",Socks5ProxyRejectedIncomingBoundConnection:"Socks5 Proxy rejected incoming bound connection"};var n,i,r;t.SOCKS_INCOMING_PACKET_SIZES={Socks5InitialHandshakeResponse:2,Socks5UserPassAuthenticationResponse:2,Socks5ResponseHeader:5,Socks5ResponseIPv4:10,Socks5ResponseIPv6:22,Socks5ResponseHostname:e=>e+7,Socks4Response:8},function(e){e[e.connect=1]="connect",e[e.bind=2]="bind",e[e.associate=3]="associate"}(n||(t.SocksCommand=n={})),function(e){e[e.Granted=90]="Granted",e[e.Failed=91]="Failed",e[e.Rejected=92]="Rejected",e[e.RejectedIdent=93]="RejectedIdent"}(i||(t.Socks4Response=i={})),function(e){e[e.NoAuth=0]="NoAuth",e[e.GSSApi=1]="GSSApi",e[e.UserPass=2]="UserPass"}(r||(t.Socks5Auth=r={}));t.SOCKS5_CUSTOM_AUTH_START=128;t.SOCKS5_CUSTOM_AUTH_END=254;var o,s,a;t.SOCKS5_NO_ACCEPTABLE_AUTH=255,function(e){e[e.Granted=0]="Granted",e[e.Failure=1]="Failure",e[e.NotAllowed=2]="NotAllowed",e[e.NetworkUnreachable=3]="NetworkUnreachable",e[e.HostUnreachable=4]="HostUnreachable",e[e.ConnectionRefused=5]="ConnectionRefused",e[e.TTLExpired=6]="TTLExpired",e[e.CommandNotSupported=7]="CommandNotSupported",e[e.AddressNotSupported=8]="AddressNotSupported"}(o||(t.Socks5Response=o={})),function(e){e[e.IPv4=1]="IPv4",e[e.Hostname=3]="Hostname",e[e.IPv6=4]="IPv6"}(s||(t.Socks5HostType=s={})),function(e){e[e.Created=0]="Created",e[e.Connecting=1]="Connecting",e[e.Connected=2]="Connected",e[e.SentInitialHandshake=3]="SentInitialHandshake",e[e.ReceivedInitialHandshakeResponse=4]="ReceivedInitialHandshakeResponse",e[e.SentAuthentication=5]="SentAuthentication",e[e.ReceivedAuthenticationResponse=6]="ReceivedAuthenticationResponse",e[e.SentFinalHandshake=7]="SentFinalHandshake",e[e.ReceivedFinalResponse=8]="ReceivedFinalResponse",e[e.BoundWaitingForConnection=9]="BoundWaitingForConnection",e[e.Established=10]="Established",e[e.Disconnected=11]="Disconnected",e[e.Error=99]="Error"}(a||(t.SocksClientState=a={}))},5471(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.GlobalTrackerSensor=void 0;const i=n(7562),r=n(441);class o extends i.ScryptedDeviceBase{trackingState;plugin;constructor(e,t,n){super(t),this.plugin=e,this.trackingState=n,n.onStateChange(()=>this.updateOccupancy()),this.updateOccupancy()}updateOccupancy(){const e=this.trackingState.getActiveCount();this.occupied=e>0}async getSettings(){const e=this.trackingState.getActiveObjects(),t=this.trackingState.getAllObjects(),n=[];if(n.push({key:"activeCount",title:"Currently Active",type:"string",readonly:!0,value:`${e.length} object${1!==e.length?"s":""}`,group:"Status"}),n.push({key:"totalTracked",title:"Total Tracked (24h)",type:"string",readonly:!0,value:`${t.length} object${1!==t.length?"s":""}`,group:"Status"}),e.length>0){n.push({key:"activeObjectsHeader",title:"Active Objects",type:"html",value:'<h4 style="margin: 0;">Currently Tracked</h4>',group:"Active Objects"});for(const t of e.slice(0,10)){const e=(0,r.calculateDwellTime)(t),i=Math.round(e/6e4);n.push({key:`active-${t.globalId}`,title:`${t.className}${t.label?` (${t.label})`:""}`,type:"string",readonly:!0,value:`Cameras: ${t.activeOnCameras.join(", ")} | Time: ${i}m`,group:"Active Objects"})}e.length>10&&n.push({key:"moreActive",title:"More",type:"string",readonly:!0,value:`...and ${e.length-10} more`,group:"Active Objects"})}const i=t.filter(e=>"exited"===e.state).sort((e,t)=>t.lastSeen-e.lastSeen).slice(0,5);if(i.length>0){n.push({key:"recentExitsHeader",title:"Recent Exits",type:"html",value:'<h4 style="margin: 0;">Recently Exited</h4>',group:"Recent Activity"});for(const e of i){const t=new Date(e.lastSeen).toLocaleTimeString(),i=(0,r.getJourneySummary)(e);n.push({key:`exit-${e.globalId}`,title:`${e.className} at ${t}`,type:"string",readonly:!0,value:i||"No journey recorded",group:"Recent Activity"})}}return n}async putSetting(e,t){}async getReadmeMarkdown(){const e=this.trackingState.getActiveObjects(),t=this.trackingState.getAllObjects(),n=e.filter(e=>"person"===e.className).length,i=e.filter(e=>["car","vehicle","truck"].includes(e.className)).length,r=e.filter(e=>"animal"===e.className).length;let o="";return n>0&&(o+=`- People: ${n}\n`),i>0&&(o+=`- Vehicles: ${i}\n`),r>0&&(o+=`- Animals: ${r}\n`),`\n# Global Object Tracker\n\nThis sensor tracks the presence of objects across all connected cameras in your property.\n\n## Current Status\n\n**Occupied**: ${this.occupied?"Yes":"No"}\n\n**Active Objects**: ${e.length}\n${o||"- None currently"}\n\n**Total Tracked (24h)**: ${t.length}\n\n## How It Works\n\nThe Global Tracker combines detection events from all configured cameras to maintain a unified view of objects on your property. When an object moves from one camera's view to another, the system correlates these sightings to track the object's journey.\n\n## States\n\n- **Active**: Object is currently visible on camera\n- **Pending**: Object left camera view, waiting for correlation\n- **Exited**: Object left the property\n- **Lost**: Object disappeared without exiting (timeout)\n\n## Integration\n\nThis sensor can be used in automations:\n- Trigger actions when property becomes occupied/unoccupied\n- Create presence-based automations\n- Monitor overall property activity\n`}}t.GlobalTrackerSensor=o},5506(e,t,n){"use strict";const{Buffer:i}=n(181),{ObjectDefineProperty:r,ObjectKeys:o,ReflectApply:s}=n(4134),{promisify:{custom:a}}=n(7760),{streamReturningOperators:c,promiseReturningOperators:l}=n(823),{codes:{ERR_ILLEGAL_CONSTRUCTOR:d}}=n(6371),u=n(7830),{setDefaultHighWaterMark:p,getDefaultHighWaterMark:h}=n(5291),{pipeline:f}=n(7758),{destroyer:g}=n(5896),m=n(6238),y=n(3095),b=n(6115),v=e.exports=n(4259).Stream;v.isDestroyed=b.isDestroyed,v.isDisturbed=b.isDisturbed,v.isErrored=b.isErrored,v.isReadable=b.isReadable,v.isWritable=b.isWritable,v.Readable=n(7576);for(const _ of o(c)){const w=c[_];function k(...e){if(new.target)throw d();return v.Readable.from(s(w,this,e))}r(k,"name",{__proto__:null,value:w.name}),r(k,"length",{__proto__:null,value:w.length}),r(v.Readable.prototype,_,{__proto__:null,value:k,enumerable:!1,configurable:!0,writable:!0})}for(const I of o(l)){const x=l[I];function C(...e){if(new.target)throw d();return s(x,this,e)}r(C,"name",{__proto__:null,value:x.name}),r(C,"length",{__proto__:null,value:x.length}),r(v.Readable.prototype,I,{__proto__:null,value:C,enumerable:!1,configurable:!0,writable:!0})}v.Writable=n(8584),v.Duplex=n(3370),v.Transform=n(7382),v.PassThrough=n(6524),v.pipeline=f;const{addAbortSignal:S}=n(4147);v.addAbortSignal=S,v.finished=m,v.destroy=g,v.compose=u,v.setDefaultHighWaterMark=p,v.getDefaultHighWaterMark=h,r(v,"promises",{__proto__:null,configurable:!0,enumerable:!0,get:()=>y}),r(f,a,{__proto__:null,enumerable:!0,get:()=>y.pipeline}),r(m,a,{__proto__:null,enumerable:!0,get:()=>y.finished}),v.Stream=v,v._isUint8Array=function(e){return e instanceof Uint8Array},v._uint8ArrayToBuffer=function(e){return i.from(e.buffer,e.byteOffset,e.byteLength)}},5670(e,t,n){"use strict";const i=n(181),r=n(4478),o=n(2635);let s,a,c;t.A=(e,t)=>{if(t.hostname=t.hostname||t.host,!t.hostname)throw new Error("Could not determine host. Specify host manually.");const n="MQIsdp"===t.protocolId&&3===t.protocolVersion?"mqttv3.1":"mqtt";!function(e){e.hostname||(e.hostname="localhost"),e.path||(e.path="/"),e.wsOptions||(e.wsOptions={})}(t);const l=function(e,t){const n="wxs"===e.protocol?"wss":"ws";let i=`${n}://${e.hostname}${e.path}`;return e.port&&80!==e.port&&443!==e.port&&(i=`${n}://${e.hostname}:${e.port}${e.path}`),"function"==typeof e.transformWsUrl&&(i=e.transformWsUrl(i,e,t)),i}(t,e);s=wx.connectSocket({url:l,protocols:[n]}),a=function(){const e=new r.Transform;return e._write=(e,t,n)=>{s.send({data:e.buffer,success(){n()},fail(e){n(new Error(e))}})},e._flush=e=>{s.close({success(){e()}})},e}(),c=new o.BufferedDuplex(t,a,s),c._destroy=(e,t)=>{s.close({success(){t&&t(e)}})};const d=c.destroy;return c.destroy=(e,t)=>(c.destroy=d,setTimeout(()=>{s.close({fail(){c._destroy(e,t)}})},0),c),s.onOpen(()=>{c.socketReady()}),s.onMessage(e=>{let{data:t}=e;t=t instanceof ArrayBuffer?i.Buffer.from(t):i.Buffer.from(t,"utf8"),a.push(t)}),s.onClose(()=>{c.emit("close"),c.end(),c.destroy()}),s.onError(e=>{const t=new Error(e.errMsg);c.destroy(t)}),c}},5692(e){"use strict";e.exports=require("https")},5753(e,t,n){"undefined"==typeof process||"renderer"===process.type||!0===process.browser||process.__nwjs?e.exports=n(7833):e.exports=n(6033)},5861(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||i(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),r(n(7631),t)},5880(e,t,n){"use strict";const{isUtf8:i}=n(181),{hasBlob:r}=n(2614);function o(e){const t=e.length;let n=0;for(;n<t;)if(128&e[n])if(192==(224&e[n])){if(n+1===t||128!=(192&e[n+1])||192==(254&e[n]))return!1;n+=2}else if(224==(240&e[n])){if(n+2>=t||128!=(192&e[n+1])||128!=(192&e[n+2])||224===e[n]&&128==(224&e[n+1])||237===e[n]&&160==(224&e[n+1]))return!1;n+=3}else{if(240!=(248&e[n]))return!1;if(n+3>=t||128!=(192&e[n+1])||128!=(192&e[n+2])||128!=(192&e[n+3])||240===e[n]&&128==(240&e[n+1])||244===e[n]&&e[n+1]>143||e[n]>244)return!1;n+=4}else n++;return!0}if(e.exports={isBlob:function(e){return r&&"object"==typeof e&&"function"==typeof e.arrayBuffer&&"string"==typeof e.type&&"function"==typeof e.stream&&("Blob"===e[Symbol.toStringTag]||"File"===e[Symbol.toStringTag])},isValidStatusCode:function(e){return e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e||e>=3e3&&e<=4999},isValidUTF8:o,tokenChars:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0]},i)e.exports.isValidUTF8=function(e){return e.length<24?o(e):i(e)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{const t=n(Object(function(){var e=new Error("Cannot find module 'utf-8-validate'");throw e.code="MODULE_NOT_FOUND",e}()));e.exports.isValidUTF8=function(e){return e.length<32?o(e):t(e)}}catch(e){}},5884(e){"use strict";e.exports=(e,t=process.argv)=>{const n=e.startsWith("-")?"":1===e.length?"-":"--",i=t.indexOf(n+e),r=t.indexOf("--");return-1!==i&&(-1===r||i<r)}},5896(e,t,n){"use strict";const i=n(4422),{aggregateTwoErrors:r,codes:{ERR_MULTIPLE_CALLBACK:o},AbortError:s}=n(6371),{Symbol:a}=n(4134),{kIsDestroyed:c,isDestroyed:l,isFinished:d,isServerRequest:u}=n(6115),p=a("kDestroy"),h=a("kConstruct");function f(e,t,n){e&&(e.stack,t&&!t.errored&&(t.errored=e),n&&!n.errored&&(n.errored=e))}function g(e,t,n){let r=!1;function o(t){if(r)return;r=!0;const o=e._readableState,s=e._writableState;f(t,s,o),s&&(s.closed=!0),o&&(o.closed=!0),"function"==typeof n&&n(t),t?i.nextTick(m,e,t):i.nextTick(y,e)}try{e._destroy(t||null,o)}catch(t){o(t)}}function m(e,t){b(e,t),y(e)}function y(e){const t=e._readableState,n=e._writableState;n&&(n.closeEmitted=!0),t&&(t.closeEmitted=!0),(null!=n&&n.emitClose||null!=t&&t.emitClose)&&e.emit("close")}function b(e,t){const n=e._readableState,i=e._writableState;null!=i&&i.errorEmitted||null!=n&&n.errorEmitted||(i&&(i.errorEmitted=!0),n&&(n.errorEmitted=!0),e.emit("error",t))}function v(e,t,n){const r=e._readableState,o=e._writableState;if(null!=o&&o.destroyed||null!=r&&r.destroyed)return this;null!=r&&r.autoDestroy||null!=o&&o.autoDestroy?e.destroy(t):t&&(t.stack,o&&!o.errored&&(o.errored=t),r&&!r.errored&&(r.errored=t),n?i.nextTick(b,e,t):b(e,t))}function S(e){let t=!1;function n(n){if(t)return void v(e,null!=n?n:new o);t=!0;const r=e._readableState,s=e._writableState,a=s||r;r&&(r.constructed=!0),s&&(s.constructed=!0),a.destroyed?e.emit(p,n):n?v(e,n,!0):i.nextTick(_,e)}try{e._construct(e=>{i.nextTick(n,e)})}catch(e){i.nextTick(n,e)}}function _(e){e.emit(h)}function w(e){return(null==e?void 0:e.setHeader)&&"function"==typeof e.abort}function k(e){e.emit("close")}function I(e,t){e.emit("error",t),i.nextTick(k,e)}e.exports={construct:function(e,t){if("function"!=typeof e._construct)return;const n=e._readableState,r=e._writableState;n&&(n.constructed=!1),r&&(r.constructed=!1),e.once(h,t),e.listenerCount(h)>1||i.nextTick(S,e)},destroyer:function(e,t){e&&!l(e)&&(t||d(e)||(t=new s),u(e)?(e.socket=null,e.destroy(t)):w(e)?e.abort():w(e.req)?e.req.abort():"function"==typeof e.destroy?e.destroy(t):"function"==typeof e.close?e.close():t?i.nextTick(I,e,t):i.nextTick(k,e),e.destroyed||(e[c]=!0))},destroy:function(e,t){const n=this._readableState,i=this._writableState,o=i||n;return null!=i&&i.destroyed||null!=n&&n.destroyed?("function"==typeof t&&t(),this):(f(e,i,n),i&&(i.destroyed=!0),n&&(n.destroyed=!0),o.constructed?g(this,e,t):this.once(p,function(n){g(this,r(n,e),t)}),this)},undestroy:function(){const e=this._readableState,t=this._writableState;e&&(e.constructed=!0,e.closed=!1,e.closeEmitted=!1,e.destroyed=!1,e.errored=null,e.errorEmitted=!1,e.reading=!1,e.ended=!1===e.readable,e.endEmitted=!1===e.readable),t&&(t.constructed=!0,t.destroyed=!1,t.closed=!1,t.closeEmitted=!1,t.errored=null,t.errorEmitted=!1,t.finalCalled=!1,t.prefinished=!1,t.ended=!1===t.writable,t.ending=!1===t.writable,t.finished=!1===t.writable)},errorOrDestroy:v}},5926(e,t,n){"use strict";const{tokenChars:i}=n(5880);function r(e,t,n){void 0===e[t]?e[t]=[n]:e[t].push(n)}e.exports={format:function(e){return Object.keys(e).map(t=>{let n=e[t];return Array.isArray(n)||(n=[n]),n.map(e=>[t].concat(Object.keys(e).map(t=>{let n=e[t];return Array.isArray(n)||(n=[n]),n.map(e=>!0===e?t:`${t}=${e}`).join("; ")})).join("; ")).join(", ")}).join(", ")},parse:function(e){const t=Object.create(null);let n,o,s=Object.create(null),a=!1,c=!1,l=!1,d=-1,u=-1,p=-1,h=0;for(;h<e.length;h++)if(u=e.charCodeAt(h),void 0===n)if(-1===p&&1===i[u])-1===d&&(d=h);else if(0===h||32!==u&&9!==u){if(59!==u&&44!==u)throw new SyntaxError(`Unexpected character at index ${h}`);{if(-1===d)throw new SyntaxError(`Unexpected character at index ${h}`);-1===p&&(p=h);const i=e.slice(d,p);44===u?(r(t,i,s),s=Object.create(null)):n=i,d=p=-1}}else-1===p&&-1!==d&&(p=h);else if(void 0===o)if(-1===p&&1===i[u])-1===d&&(d=h);else if(32===u||9===u)-1===p&&-1!==d&&(p=h);else if(59===u||44===u){if(-1===d)throw new SyntaxError(`Unexpected character at index ${h}`);-1===p&&(p=h),r(s,e.slice(d,p),!0),44===u&&(r(t,n,s),s=Object.create(null),n=void 0),d=p=-1}else{if(61!==u||-1===d||-1!==p)throw new SyntaxError(`Unexpected character at index ${h}`);o=e.slice(d,h),d=p=-1}else if(c){if(1!==i[u])throw new SyntaxError(`Unexpected character at index ${h}`);-1===d?d=h:a||(a=!0),c=!1}else if(l)if(1===i[u])-1===d&&(d=h);else if(34===u&&-1!==d)l=!1,p=h;else{if(92!==u)throw new SyntaxError(`Unexpected character at index ${h}`);c=!0}else if(34===u&&61===e.charCodeAt(h-1))l=!0;else if(-1===p&&1===i[u])-1===d&&(d=h);else if(-1===d||32!==u&&9!==u){if(59!==u&&44!==u)throw new SyntaxError(`Unexpected character at index ${h}`);{if(-1===d)throw new SyntaxError(`Unexpected character at index ${h}`);-1===p&&(p=h);let i=e.slice(d,p);a&&(i=i.replace(/\\/g,""),a=!1),r(s,o,i),44===u&&(r(t,n,s),s=Object.create(null),n=void 0),o=void 0,d=p=-1}}else-1===p&&(p=h);if(-1===d||l||32===u||9===u)throw new SyntaxError("Unexpected end of input");-1===p&&(p=h);const f=e.slice(d,p);return void 0===n?r(t,f,s):(void 0===o?r(s,f,!0):r(s,o,a?f.replace(/\\/g,""):f),r(t,n,s)),t}}},6033(e,t,n){const i=n(2018),r=n(9023);t.init=function(e){e.inspectOpts={};const n=Object.keys(t.inspectOpts);for(let i=0;i<n.length;i++)e.inspectOpts[n[i]]=t.inspectOpts[n[i]]},t.log=function(...e){return process.stderr.write(r.formatWithOptions(t.inspectOpts,...e)+"\n")},t.formatArgs=function(n){const{namespace:i,useColors:r}=this;if(r){const t=this.color,r="[3"+(t<8?t:"8;5;"+t),o=` ${r};1m${i} [0m`;n[0]=o+n[0].split("\n").join("\n"+o),n.push(r+"m+"+e.exports.humanize(this.diff)+"[0m")}else n[0]=function(){if(t.inspectOpts.hideDate)return"";return(new Date).toISOString()+" "}()+i+" "+n[0]},t.save=function(e){e?process.env.DEBUG=e:delete process.env.DEBUG},t.load=function(){return process.env.DEBUG},t.useColors=function(){return"colors"in t.inspectOpts?Boolean(t.inspectOpts.colors):i.isatty(process.stderr.fd)},t.destroy=r.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."),t.colors=[6,2,3,4,5,1];try{const e=n(7687);e&&(e.stderr||e).level>=2&&(t.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch(e){}t.inspectOpts=Object.keys(process.env).filter(e=>/^debug_/i.test(e)).reduce((e,t)=>{const n=t.substring(6).toLowerCase().replace(/_([a-z])/g,(e,t)=>t.toUpperCase());let i=process.env[t];return i=!!/^(yes|on|true|enabled)$/i.test(i)||!/^(no|off|false|disabled)$/i.test(i)&&("null"===i?null:Number(i)),e[n]=i,e},{}),e.exports=n(736)(t);const{formatters:o}=e.exports;o.o=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts).split("\n").map(e=>e.trim()).join(" ")},o.O=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts)}},6115(e,t,n){"use strict";const{SymbolAsyncIterator:i,SymbolIterator:r,SymbolFor:o}=n(4134),s=o("nodejs.stream.destroyed"),a=o("nodejs.stream.errored"),c=o("nodejs.stream.readable"),l=o("nodejs.stream.writable"),d=o("nodejs.stream.disturbed"),u=o("nodejs.webstream.isClosedPromise"),p=o("nodejs.webstream.controllerErrorFunction");function h(e,t=!1){var n;return!(!e||"function"!=typeof e.pipe||"function"!=typeof e.on||t&&("function"!=typeof e.pause||"function"!=typeof e.resume)||e._writableState&&!1===(null===(n=e._readableState)||void 0===n?void 0:n.readable)||e._writableState&&!e._readableState)}function f(e){var t;return!(!e||"function"!=typeof e.write||"function"!=typeof e.on||e._readableState&&!1===(null===(t=e._writableState)||void 0===t?void 0:t.writable))}function g(e){return e&&(e._readableState||e._writableState||"function"==typeof e.write&&"function"==typeof e.on||"function"==typeof e.pipe&&"function"==typeof e.on)}function m(e){return!(!e||g(e)||"function"!=typeof e.pipeThrough||"function"!=typeof e.getReader||"function"!=typeof e.cancel)}function y(e){return!(!e||g(e)||"function"!=typeof e.getWriter||"function"!=typeof e.abort)}function b(e){return!(!e||g(e)||"object"!=typeof e.readable||"object"!=typeof e.writable)}function v(e){if(!g(e))return null;const t=e._writableState,n=e._readableState,i=t||n;return!!(e.destroyed||e[s]||null!=i&&i.destroyed)}function S(e){if(!f(e))return null;if(!0===e.writableEnded)return!0;const t=e._writableState;return(null==t||!t.errored)&&("boolean"!=typeof(null==t?void 0:t.ended)?null:t.ended)}function _(e,t){if(!h(e))return null;const n=e._readableState;return(null==n||!n.errored)&&("boolean"!=typeof(null==n?void 0:n.endEmitted)?null:!!(n.endEmitted||!1===t&&!0===n.ended&&0===n.length))}function w(e){return e&&null!=e[c]?e[c]:"boolean"!=typeof(null==e?void 0:e.readable)?null:!v(e)&&(h(e)&&e.readable&&!_(e))}function k(e){return e&&null!=e[l]?e[l]:"boolean"!=typeof(null==e?void 0:e.writable)?null:!v(e)&&(f(e)&&e.writable&&!S(e))}function I(e){return"boolean"==typeof e._closed&&"boolean"==typeof e._defaultKeepAlive&&"boolean"==typeof e._removedConnection&&"boolean"==typeof e._removedContLen}function x(e){return"boolean"==typeof e._sent100&&I(e)}e.exports={isDestroyed:v,kIsDestroyed:s,isDisturbed:function(e){var t;return!(!e||!(null!==(t=e[d])&&void 0!==t?t:e.readableDidRead||e.readableAborted))},kIsDisturbed:d,isErrored:function(e){var t,n,i,r,o,s,c,l,d,u;return!(!e||!(null!==(t=null!==(n=null!==(i=null!==(r=null!==(o=null!==(s=e[a])&&void 0!==s?s:e.readableErrored)&&void 0!==o?o:e.writableErrored)&&void 0!==r?r:null===(c=e._readableState)||void 0===c?void 0:c.errorEmitted)&&void 0!==i?i:null===(l=e._writableState)||void 0===l?void 0:l.errorEmitted)&&void 0!==n?n:null===(d=e._readableState)||void 0===d?void 0:d.errored)&&void 0!==t?t:null===(u=e._writableState)||void 0===u?void 0:u.errored))},kIsErrored:a,isReadable:w,kIsReadable:c,kIsClosedPromise:u,kControllerErrorFunction:p,kIsWritable:l,isClosed:function(e){if(!g(e))return null;if("boolean"==typeof e.closed)return e.closed;const t=e._writableState,n=e._readableState;return"boolean"==typeof(null==t?void 0:t.closed)||"boolean"==typeof(null==n?void 0:n.closed)?(null==t?void 0:t.closed)||(null==n?void 0:n.closed):"boolean"==typeof e._closed&&I(e)?e._closed:null},isDuplexNodeStream:function(e){return!(!e||"function"!=typeof e.pipe||!e._readableState||"function"!=typeof e.on||"function"!=typeof e.write)},isFinished:function(e,t){return g(e)?!!v(e)||(!1===(null==t?void 0:t.readable)||!w(e))&&(!1===(null==t?void 0:t.writable)||!k(e)):null},isIterable:function(e,t){return null!=e&&(!0===t?"function"==typeof e[i]:!1===t?"function"==typeof e[r]:"function"==typeof e[i]||"function"==typeof e[r])},isReadableNodeStream:h,isReadableStream:m,isReadableEnded:function(e){if(!h(e))return null;if(!0===e.readableEnded)return!0;const t=e._readableState;return!(!t||t.errored)&&("boolean"!=typeof(null==t?void 0:t.ended)?null:t.ended)},isReadableFinished:_,isReadableErrored:function(e){var t,n;return g(e)?e.readableErrored?e.readableErrored:null!==(t=null===(n=e._readableState)||void 0===n?void 0:n.errored)&&void 0!==t?t:null:null},isNodeStream:g,isWebStream:function(e){return m(e)||y(e)||b(e)},isWritable:k,isWritableNodeStream:f,isWritableStream:y,isWritableEnded:S,isWritableFinished:function(e,t){if(!f(e))return null;if(!0===e.writableFinished)return!0;const n=e._writableState;return(null==n||!n.errored)&&("boolean"!=typeof(null==n?void 0:n.finished)?null:!!(n.finished||!1===t&&!0===n.ended&&0===n.length))},isWritableErrored:function(e){var t,n;return g(e)?e.writableErrored?e.writableErrored:null!==(t=null===(n=e._writableState)||void 0===n?void 0:n.errored)&&void 0!==t?t:null:null},isServerRequest:function(e){var t;return"boolean"==typeof e._consuming&&"boolean"==typeof e._dumped&&void 0===(null===(t=e.req)||void 0===t?void 0:t.upgradeOrConnect)},isServerResponse:x,willEmitClose:function(e){if(!g(e))return null;const t=e._writableState,n=e._readableState,i=t||n;return!i&&x(e)||!!(i&&i.autoDestroy&&i.emitClose&&!1===i.closed)},isTransformStream:b}},6117(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.StorageSettings=void 0;const a=s(n(7562)),{systemManager:c}=a.default;t.StorageSettings=class{constructor(e,t){this.device=e,this.settings=t,this.values={},this.hasValue={};for(const e of Object.keys(t)){const n=t[e],i=()=>this.getItem(e);let r;r="clippath"!==n.type?i:()=>{try{return JSON.parse(i())}catch(e){}},Object.defineProperty(this.values,e,{get:r,set:t=>this.putSetting(e,t),enumerable:!0}),Object.defineProperty(this.hasValue,e,{get:()=>null!=this.device.storage.getItem(e),enumerable:!0})}}get keys(){const e={};for(const t of Object.keys(this.settings))e[t]=t;return e}async getSettings(){const e=await(this.options?.onGet?.()),t=[];for(const[n,i]of Object.entries(this.settings)){let r=Object.assign({},i);e?.[n]&&(r=Object.assign(r,e[n])),r.onGet&&(r=Object.assign(r,await r.onGet())),r.hide||await(this.options?.hide?.[n]?.())||(r.key=n,r.value=this.getItemInternal(n,r,!0),"function"==typeof r.deviceFilter&&(r.deviceFilter=r.deviceFilter.toString()),t.push(r),delete r.onPut,delete r.onGet,delete r.mapPut,delete r.mapGet)}return t}async putSetting(e,t){const n=this.settings[e];let i;return n&&(i=this.getItemInternal(e,n)),this.putSettingInternal(n,i,e,t)}putSettingInternal(e,t,n,i){e?.noStore||(e?.mapPut&&(i=e.mapPut(t,i)),null==i?this.device.storage.removeItem(n):"object"==typeof i?this.device.storage.setItem(n,JSON.stringify(i)):this.device.storage.setItem(n,i?.toString())),e?.onPut?.(t,i),e?.hide||this.device.onDeviceEvent(a.ScryptedInterface.Settings,void 0)}getItemInternal(e,t,n){if(!t)return this.device.storage.getItem(e);const i=function(e,t,n,i){if(null==e)return n();const r=t.multiple?"array":t.type;if("boolean"===r)return"true"===e||"false"!==e&&(n()||!1);if("number"===r){const t=parseFloat(e);return isNaN(t)?n()||0:t}if("integer"===r){const t=parseInt(e);return isNaN(t)?n()||0:t}if("array"===r){if(!e)return n()||[];try{return JSON.parse(e)}catch(e){return n()||[]}}if("device"===r)return i?e:c.getDeviceById(e)||c.getDeviceById(n());if(e&&t.json)try{return JSON.parse(e)}catch(e){return n()}return e||n()}(this.device.storage.getItem(e),t,()=>null!=t.persistedDefaultValue?(this.putSettingInternal(t,void 0,e,t.persistedDefaultValue),t.persistedDefaultValue):t.defaultValue,n);return t.mapGet?t.mapGet(i):i}getItem(e){return this.getItemInternal(e,this.settings[e])}}},6172(e,t,n){const{Buffer:i}=n(181),r={},o=i.isBuffer(i.from([1,2]).subarray(0,1));function s(e){const t=i.allocUnsafe(2);return t.writeUInt8(e>>8,0),t.writeUInt8(255&e,1),t}e.exports={cache:r,generateCache:function(){for(let e=0;e<65536;e++)r[e]=s(e)},generateNumber:s,genBufVariableByteInt:function(e){let t=0,n=0;const r=i.allocUnsafe(4);do{t=e%128|0,(e=e/128|0)>0&&(t|=128),r.writeUInt8(t,n++)}while(e>0&&n<4);return e>0&&(n=0),o?r.subarray(0,n):r.slice(0,n)},generate4ByteBuffer:function(e){const t=i.allocUnsafe(4);return t.writeUInt32BE(e,0),t}}},6238(e,t,n){"use strict";const i=n(4422),{AbortError:r,codes:o}=n(6371),{ERR_INVALID_ARG_TYPE:s,ERR_STREAM_PREMATURE_CLOSE:a}=o,{kEmptyObject:c,once:l}=n(7760),{validateAbortSignal:d,validateFunction:u,validateObject:p,validateBoolean:h}=n(277),{Promise:f,PromisePrototypeThen:g,SymbolDispose:m}=n(4134),{isClosed:y,isReadable:b,isReadableNodeStream:v,isReadableStream:S,isReadableFinished:_,isReadableErrored:w,isWritable:k,isWritableNodeStream:I,isWritableStream:x,isWritableFinished:C,isWritableErrored:E,isNodeStream:T,willEmitClose:O,kIsClosedPromise:P}=n(6115);let A;const R=()=>{};function M(e,t,o){var h,f;if(2===arguments.length?(o=t,t=c):null==t?t=c:p(t,"options"),u(o,"callback"),d(t.signal,"options.signal"),o=l(o),S(e)||x(e))return function(e,t,o){let s=!1,a=R;if(t.signal)if(a=()=>{s=!0,o.call(e,new r(void 0,{cause:t.signal.reason}))},t.signal.aborted)i.nextTick(a);else{A=A||n(7760).addAbortListener;const i=A(t.signal,a),r=o;o=l((...t)=>{i[m](),r.apply(e,t)})}const c=(...t)=>{s||i.nextTick(()=>o.apply(e,t))};return g(e[P].promise,c,c),R}(e,t,o);if(!T(e))throw new s("stream",["ReadableStream","WritableStream","Stream"],e);const M=null!==(h=t.readable)&&void 0!==h?h:v(e),L=null!==(f=t.writable)&&void 0!==f?f:I(e),N=e._writableState,D=e._readableState,B=()=>{e.writable||F()};let j=O(e)&&v(e)===M&&I(e)===L,$=C(e,!1);const F=()=>{$=!0,e.destroyed&&(j=!1),(!j||e.readable&&!M)&&(M&&!U||o.call(e))};let U=_(e,!1);const z=()=>{U=!0,e.destroyed&&(j=!1),(!j||e.writable&&!L)&&(L&&!$||o.call(e))},V=t=>{o.call(e,t)};let W=y(e);const H=()=>{W=!0;const t=E(e)||w(e);return t&&"boolean"!=typeof t?o.call(e,t):M&&!U&&v(e,!0)&&!_(e,!1)?o.call(e,new a):!L||$||C(e,!1)?void o.call(e):o.call(e,new a)},q=()=>{W=!0;const t=E(e)||w(e);if(t&&"boolean"!=typeof t)return o.call(e,t);o.call(e)},G=()=>{e.req.on("finish",F)};!function(e){return e.setHeader&&"function"==typeof e.abort}(e)?L&&!N&&(e.on("end",B),e.on("close",B)):(e.on("complete",F),j||e.on("abort",H),e.req?G():e.on("request",G)),j||"boolean"!=typeof e.aborted||e.on("aborted",H),e.on("end",z),e.on("finish",F),!1!==t.error&&e.on("error",V),e.on("close",H),W?i.nextTick(H):null!=N&&N.errorEmitted||null!=D&&D.errorEmitted?j||i.nextTick(q):(M||j&&!b(e)||!$&&!1!==k(e))&&(L||j&&!k(e)||!U&&!1!==b(e))?D&&e.req&&e.aborted&&i.nextTick(q):i.nextTick(q);const K=()=>{o=R,e.removeListener("aborted",H),e.removeListener("complete",F),e.removeListener("abort",H),e.removeListener("request",G),e.req&&e.req.removeListener("finish",F),e.removeListener("end",B),e.removeListener("close",B),e.removeListener("finish",F),e.removeListener("end",z),e.removeListener("error",V),e.removeListener("close",H)};if(t.signal&&!W){const s=()=>{const n=o;K(),n.call(e,new r(void 0,{cause:t.signal.reason}))};if(t.signal.aborted)i.nextTick(s);else{A=A||n(7760).addAbortListener;const i=A(t.signal,s),r=o;o=l((...t)=>{i[m](),r.apply(e,t)})}}return K}e.exports=M,e.exports.finished=function(e,t){var n;let i=!1;return null===t&&(t=c),null!==(n=t)&&void 0!==n&&n.cleanup&&(h(t.cleanup,"cleanup"),i=t.cleanup),new f((n,r)=>{const o=M(e,t,e=>{i&&o(),e?r(e):n()})})}},6286(e,t,n){"use strict";const{Writable:i}=n(2203),r=n(2971),{BINARY_TYPES:o,EMPTY_BUFFER:s,kStatusCode:a,kWebSocket:c}=n(2614),{concat:l,toArrayBuffer:d,unmask:u}=n(3338),{isValidStatusCode:p,isValidUTF8:h}=n(5880),f=Buffer[Symbol.species];e.exports=class extends i{constructor(e={}){super(),this._allowSynchronousEvents=void 0===e.allowSynchronousEvents||e.allowSynchronousEvents,this._binaryType=e.binaryType||o[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxPayload=0|e.maxPayload,this._skipUTF8Validation=!!e.skipUTF8Validation,this[c]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=0}_write(e,t,n){if(8===this._opcode&&0==this._state)return n();this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(n)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){const t=this._buffers[0];return this._buffers[0]=new f(t.buffer,t.byteOffset+e,t.length-e),new f(t.buffer,t.byteOffset,e)}const t=Buffer.allocUnsafe(e);do{const n=this._buffers[0],i=t.length-e;e>=n.length?t.set(this._buffers.shift(),i):(t.set(new Uint8Array(n.buffer,n.byteOffset,e),i),this._buffers[0]=new f(n.buffer,n.byteOffset+e,n.length-e)),e-=n.length}while(e>0);return t}startLoop(e){this._loop=!0;do{switch(this._state){case 0:this.getInfo(e);break;case 1:this.getPayloadLength16(e);break;case 2:this.getPayloadLength64(e);break;case 3:this.getMask();break;case 4:this.getData(e);break;case 5:case 6:return void(this._loop=!1)}}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2)return void(this._loop=!1);const t=this.consume(2);if(48&t[0]){return void e(this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3"))}const n=!(64&~t[0]);if(n&&!this._extensions[r.extensionName]){return void e(this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1"))}if(this._fin=!(128&~t[0]),this._opcode=15&t[0],this._payloadLength=127&t[1],0===this._opcode){if(n){return void e(this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1"))}if(!this._fragmented){return void e(this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE"))}this._opcode=this._fragmented}else if(1===this._opcode||2===this._opcode){if(this._fragmented){return void e(this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE"))}this._compressed=n}else{if(!(this._opcode>7&&this._opcode<11)){return void e(this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE"))}if(!this._fin){return void e(this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN"))}if(n){return void e(this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1"))}if(this._payloadLength>125||8===this._opcode&&1===this._payloadLength){return void e(this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"))}}if(this._fin||this._fragmented||(this._fragmented=this._opcode),this._masked=!(128&~t[1]),this._isServer){if(!this._masked){return void e(this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK"))}}else if(this._masked){return void e(this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK"))}126===this._payloadLength?this._state=1:127===this._payloadLength?this._state=2:this.haveLength(e)}getPayloadLength16(e){this._bufferedBytes<2?this._loop=!1:(this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e))}getPayloadLength64(e){if(this._bufferedBytes<8)return void(this._loop=!1);const t=this.consume(8),n=t.readUInt32BE(0);if(n>Math.pow(2,21)-1){return void e(this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"))}this._payloadLength=n*Math.pow(2,32)+t.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){return void e(this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"))}this._masked?this._state=3:this._state=4}getMask(){this._bufferedBytes<4?this._loop=!1:(this._mask=this.consume(4),this._state=4)}getData(e){let t=s;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength)return void(this._loop=!1);t=this.consume(this._payloadLength),this._masked&&0!==(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])&&u(t,this._mask)}if(this._opcode>7)this.controlMessage(t,e);else{if(this._compressed)return this._state=5,void this.decompress(t,e);t.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(t)),this.dataMessage(e)}}decompress(e,t){this._extensions[r.extensionName].decompress(e,this._fin,(e,n)=>{if(e)return t(e);if(n.length){if(this._messageLength+=n.length,this._messageLength>this._maxPayload&&this._maxPayload>0){const e=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");return void t(e)}this._fragments.push(n)}this.dataMessage(t),0===this._state&&this.startLoop(t)})}dataMessage(e){if(!this._fin)return void(this._state=0);const t=this._messageLength,n=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],2===this._opcode){let i;i="nodebuffer"===this._binaryType?l(n,t):"arraybuffer"===this._binaryType?d(l(n,t)):"blob"===this._binaryType?new Blob(n):n,this._allowSynchronousEvents?(this.emit("message",i,!0),this._state=0):(this._state=6,setImmediate(()=>{this.emit("message",i,!0),this._state=0,this.startLoop(e)}))}else{const i=l(n,t);if(!this._skipUTF8Validation&&!h(i)){const t=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");return void e(t)}5===this._state||this._allowSynchronousEvents?(this.emit("message",i,!1),this._state=0):(this._state=6,setImmediate(()=>{this.emit("message",i,!1),this._state=0,this.startLoop(e)}))}}controlMessage(e,t){if(8!==this._opcode)this._allowSynchronousEvents?(this.emit(9===this._opcode?"ping":"pong",e),this._state=0):(this._state=6,setImmediate(()=>{this.emit(9===this._opcode?"ping":"pong",e),this._state=0,this.startLoop(t)}));else{if(0===e.length)this._loop=!1,this.emit("conclude",1005,s),this.end();else{const n=e.readUInt16BE(0);if(!p(n)){const e=this.createError(RangeError,`invalid status code ${n}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");return void t(e)}const i=new f(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!h(i)){const e=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");return void t(e)}this._loop=!1,this.emit("conclude",n,i),this.end()}this._state=0}}createError(e,t,n,i,r){this._loop=!1,this._errored=!0;const o=new e(n?`Invalid WebSocket frame: ${t}`:t);return Error.captureStackTrace(o,this.createError),o.code=r,o[a]=i,o}}},6329(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Address6=void 0;const s=o(n(837)),a=o(n(9576)),c=o(n(8914)),l=o(n(465)),d=n(2839),u=n(321),p=n(2437),h=n(837);function f(e){if(!e)throw new Error("Assertion failed.")}function g(e){return e=(e=e.replace(/^(0{1,})([1-9]+)$/,'<span class="parse-error">$1</span>$2')).replace(/^(0{1,})(0)$/,'<span class="parse-error">$1</span>$2')}function m(e){return parseInt(e,16).toString(16).padStart(4,"0")}function y(e){return 255&e}class b{constructor(e,t){this.addressMinusSuffix="",this.parsedSubnet="",this.subnet="/128",this.subnetMask=128,this.v4=!1,this.zone="",this.isInSubnet=s.isInSubnet,this.isCorrect=s.isCorrect(c.BITS),this.groups=void 0===t?c.GROUPS:t,this.address=e;const n=c.RE_SUBNET_STRING.exec(e);if(n){if(this.parsedSubnet=n[0].replace("/",""),this.subnetMask=parseInt(this.parsedSubnet,10),this.subnet=`/${this.subnetMask}`,Number.isNaN(this.subnetMask)||this.subnetMask<0||this.subnetMask>c.BITS)throw new p.AddressError("Invalid subnet mask.");e=e.replace(c.RE_SUBNET_STRING,"")}else if(/\//.test(e))throw new p.AddressError("Invalid subnet mask.");const i=c.RE_ZONE_STRING.exec(e);i&&(this.zone=i[0],e=e.replace(c.RE_ZONE_STRING,"")),this.addressMinusSuffix=e,this.parsedAddress=this.parse(this.addressMinusSuffix)}static isValid(e){try{return new b(e),!0}catch(e){return!1}}static fromBigInt(e){const t=e.toString(16).padStart(32,"0"),n=[];let i;for(i=0;i<c.GROUPS;i++)n.push(t.slice(4*i,4*(i+1)));return new b(n.join(":"))}static fromURL(e){let t,n,i=null;if(-1!==e.indexOf("[")&&-1!==e.indexOf("]:")){if(n=c.RE_URL_WITH_PORT.exec(e),null===n)return{error:"failed to parse address with port",address:null,port:null};t=n[1],i=n[2]}else if(-1!==e.indexOf("/")){if(e=e.replace(/^[a-z0-9]+:\/\//,""),n=c.RE_URL.exec(e),null===n)return{error:"failed to parse address from URL",address:null,port:null};t=n[1]}else t=e;return i?(i=parseInt(i,10),(i<0||i>65536)&&(i=null)):i=null,{address:new b(t),port:i}}static fromAddress4(e){const t=new d.Address4(e),n=c.BITS-(a.BITS-t.subnetMask);return new b(`::ffff:${t.correctForm()}/${n}`)}static fromArpa(e){let t=e.replace(/(\.ip6\.arpa)?\.$/,"");if(63!==t.length)throw new p.AddressError("Invalid 'ip6.arpa' form.");const n=t.split(".").reverse();for(let e=7;e>0;e--){const t=4*e;n.splice(t,0,":")}return t=n.join(""),new b(t)}microsoftTranscription(){return`${this.correctForm().replace(/:/g,"-")}.ipv6-literal.net`}mask(e=this.subnetMask){return this.getBitsBase2(0,e)}possibleSubnets(e=128){const t=c.BITS-this.subnetMask-Math.abs(e-c.BITS);return t<0?"0":function(e){const t=/(\d+)(\d{3})/;for(;t.test(e);)e=e.replace(t,"$1,$2");return e}((BigInt("2")**BigInt(t)).toString(10))}_startAddress(){return BigInt(`0b${this.mask()+"0".repeat(c.BITS-this.subnetMask)}`)}startAddress(){return b.fromBigInt(this._startAddress())}startAddressExclusive(){const e=BigInt("1");return b.fromBigInt(this._startAddress()+e)}_endAddress(){return BigInt(`0b${this.mask()+"1".repeat(c.BITS-this.subnetMask)}`)}endAddress(){return b.fromBigInt(this._endAddress())}endAddressExclusive(){const e=BigInt("1");return b.fromBigInt(this._endAddress()-e)}getScope(){let e=c.SCOPES[parseInt(this.getBits(12,16).toString(10),10)];return"Global unicast"===this.getType()&&"Link local"!==e&&(e="Global"),e||"Unknown"}getType(){for(const e of Object.keys(c.TYPES))if(this.isInSubnet(new b(e)))return c.TYPES[e];return"Global unicast"}getBits(e,t){return BigInt(`0b${this.getBitsBase2(e,t)}`)}getBitsBase2(e,t){return this.binaryZeroPad().slice(e,t)}getBitsBase16(e,t){const n=t-e;if(n%4!=0)throw new Error("Length of bits to retrieve must be divisible by four");return this.getBits(e,t).toString(16).padStart(n/4,"0")}getBitsPastSubnet(){return this.getBitsBase2(this.subnetMask,c.BITS)}reverseForm(e){e||(e={});const t=Math.floor(this.subnetMask/4),n=this.canonicalForm().replace(/:/g,"").split("").slice(0,t).reverse().join(".");return t>0?e.omitSuffix?n:`${n}.ip6.arpa.`:e.omitSuffix?"":"ip6.arpa."}correctForm(){let e,t=[],n=0;const i=[];for(e=0;e<this.parsedAddress.length;e++){const t=parseInt(this.parsedAddress[e],16);0===t&&n++,0!==t&&n>0&&(n>1&&i.push([e-n,e-1]),n=0)}n>1&&i.push([this.parsedAddress.length-n,this.parsedAddress.length-1]);const r=i.map(e=>e[1]-e[0]+1);if(i.length>0){const e=r.indexOf(Math.max(...r));t=function(e,t){const n=[],i=[];let r;for(r=0;r<e.length;r++)r<t[0]?n.push(e[r]):r>t[1]&&i.push(e[r]);return n.concat(["compact"]).concat(i)}(this.parsedAddress,i[e])}else t=this.parsedAddress;for(e=0;e<t.length;e++)"compact"!==t[e]&&(t[e]=parseInt(t[e],16).toString(16));let o=t.join(":");return o=o.replace(/^compact$/,"::"),o=o.replace(/(^compact)|(compact$)/,":"),o=o.replace(/compact/,""),o}binaryZeroPad(){return this.bigInt().toString(2).padStart(c.BITS,"0")}parse4in6(e){const t=e.split(":"),n=t.slice(-1)[0].match(a.RE_ADDRESS);if(n){this.parsedAddress4=n[0],this.address4=new d.Address4(this.parsedAddress4);for(let t=0;t<this.address4.groups;t++)if(/^0[0-9]+/.test(this.address4.parsedAddress[t]))throw new p.AddressError("IPv4 addresses can't have leading zeroes.",e.replace(a.RE_ADDRESS,this.address4.parsedAddress.map(g).join(".")));this.v4=!0,t[t.length-1]=this.address4.toGroup6(),e=t.join(":")}return e}parse(e){const t=(e=this.parse4in6(e)).match(c.RE_BAD_CHARACTERS);if(t)throw new p.AddressError(`Bad character${t.length>1?"s":""} detected in address: ${t.join("")}`,e.replace(c.RE_BAD_CHARACTERS,'<span class="parse-error">$1</span>'));const n=e.match(c.RE_BAD_ADDRESS);if(n)throw new p.AddressError(`Address failed regex: ${n.join("")}`,e.replace(c.RE_BAD_ADDRESS,'<span class="parse-error">$1</span>'));let i=[];const r=e.split("::");if(2===r.length){let e=r[0].split(":"),t=r[1].split(":");1===e.length&&""===e[0]&&(e=[]),1===t.length&&""===t[0]&&(t=[]);const n=this.groups-(e.length+t.length);if(!n)throw new p.AddressError("Error parsing groups");this.elidedGroups=n,this.elisionBegin=e.length,this.elisionEnd=e.length+this.elidedGroups,i=i.concat(e);for(let e=0;e<n;e++)i.push("0");i=i.concat(t)}else{if(1!==r.length)throw new p.AddressError("Too many :: groups found");i=e.split(":"),this.elidedGroups=0}if(i=i.map(e=>parseInt(e,16).toString(16)),i.length!==this.groups)throw new p.AddressError("Incorrect number of groups found");return i}canonicalForm(){return this.parsedAddress.map(m).join(":")}decimal(){return this.parsedAddress.map(e=>parseInt(e,16).toString(10).padStart(5,"0")).join(":")}bigInt(){return BigInt(`0x${this.parsedAddress.map(m).join("")}`)}to4(){const e=this.binaryZeroPad().split("");return d.Address4.fromHex(BigInt(`0b${e.slice(96,128).join("")}`).toString(16))}to4in6(){const e=this.to4(),t=new b(this.parsedAddress.slice(0,6).join(":"),6).correctForm();let n="";return/:$/.test(t)||(n=":"),t+n+e.address}inspectTeredo(){const e=this.getBitsBase16(0,32),t=(this.getBits(80,96)^BigInt("0xffff")).toString(),n=d.Address4.fromHex(this.getBitsBase16(32,64)),i=this.getBits(96,128),r=d.Address4.fromHex((i^BigInt("0xffffffff")).toString(16)),o=this.getBitsBase2(64,80),s=(0,h.testBit)(o,15),a=(0,h.testBit)(o,14),c=(0,h.testBit)(o,8),l=(0,h.testBit)(o,9),u=BigInt(`0b${o.slice(2,6)+o.slice(8,16)}`).toString(10);return{prefix:`${e.slice(0,4)}:${e.slice(4,8)}`,server4:n.address,client4:r.address,flags:o,coneNat:s,microsoft:{reserved:a,universalLocal:l,groupIndividual:c,nonce:u},udpPort:t}}inspect6to4(){const e=this.getBitsBase16(0,16),t=d.Address4.fromHex(this.getBitsBase16(16,48));return{prefix:e.slice(0,4),gateway:t.address}}to6to4(){if(!this.is4())return null;const e=["2002",this.getBitsBase16(96,112),this.getBitsBase16(112,128),"","/16"].join(":");return new b(e)}toByteArray(){const e=this.bigInt().toString(16),t=`${"0".repeat(e.length%2)}${e}`,n=[];for(let e=0,i=t.length;e<i;e+=2)n.push(parseInt(t.substring(e,e+2),16));return n}toUnsignedByteArray(){return this.toByteArray().map(y)}static fromByteArray(e){return this.fromUnsignedByteArray(e.map(y))}static fromUnsignedByteArray(e){const t=BigInt("256");let n=BigInt("0"),i=BigInt("1");for(let r=e.length-1;r>=0;r--)n+=i*BigInt(e[r].toString(10)),i*=t;return b.fromBigInt(n)}isCanonical(){return this.addressMinusSuffix===this.canonicalForm()}isLinkLocal(){return"1111111010000000000000000000000000000000000000000000000000000000"===this.getBitsBase2(0,64)}isMulticast(){return"Multicast"===this.getType()}is4(){return this.v4}isTeredo(){return this.isInSubnet(new b("2001::/32"))}is6to4(){return this.isInSubnet(new b("2002::/16"))}isLoopback(){return"Loopback"===this.getType()}href(e){return e=void 0===e?"":`:${e}`,`http://[${this.correctForm()}]${e}/`}link(e){e||(e={}),void 0===e.className&&(e.className=""),void 0===e.prefix&&(e.prefix="/#address="),void 0===e.v4&&(e.v4=!1);let t=this.correctForm;e.v4&&(t=this.to4in6);const n=t.call(this);return e.className?`<a href="${e.prefix}${n}" class="${e.className}">${n}</a>`:`<a href="${e.prefix}${n}">${n}</a>`}group(){if(0===this.elidedGroups)return l.simpleGroup(this.address).join(":");f("number"==typeof this.elidedGroups),f("number"==typeof this.elisionBegin);const e=[],[t,n]=this.address.split("::");t.length?e.push(...l.simpleGroup(t)):e.push("");const i=["hover-group"];for(let e=this.elisionBegin;e<this.elisionBegin+this.elidedGroups;e++)i.push(`group-${e}`);return e.push(`<span class="${i.join(" ")}"></span>`),n.length?e.push(...l.simpleGroup(n,this.elisionEnd)):e.push(""),this.is4()&&(f(this.address4 instanceof d.Address4),e.pop(),e.push(this.address4.groupForV6())),e.join(":")}regularExpressionString(e=!1){let t=[];const n=new b(this.correctForm());if(0===n.elidedGroups)t.push((0,u.simpleRegularExpression)(n.parsedAddress));else if(n.elidedGroups===c.GROUPS)t.push((0,u.possibleElisions)(c.GROUPS));else{const e=n.address.split("::");e[0].length&&t.push((0,u.simpleRegularExpression)(e[0].split(":"))),f("number"==typeof n.elidedGroups),t.push((0,u.possibleElisions)(n.elidedGroups,0!==e[0].length,0!==e[1].length)),e[1].length&&t.push((0,u.simpleRegularExpression)(e[1].split(":"))),t=[t.join(":")]}return e||(t=["(?=^|",u.ADDRESS_BOUNDARY,"|[^\\w\\:])(",...t,")(?=[^\\w\\:]|",u.ADDRESS_BOUNDARY,"|$)"]),t.join("")}regularExpression(e=!1){return new RegExp(this.regularExpressionString(e),"i")}}t.Address6=b},6371(e,t,n){"use strict";const{format:i,inspect:r}=n(9231),{AggregateError:o}=n(4134),s=globalThis.AggregateError||o,a=Symbol("kIsNodeError"),c=["string","function","number","object","Function","Object","boolean","bigint","symbol"],l=/^([A-Z][a-z0-9]*)+$/,d={};function u(e,t){if(!e)throw new d.ERR_INTERNAL_ASSERTION(t)}function p(e){let t="",n=e.length;const i="-"===e[0]?1:0;for(;n>=i+4;n-=3)t=`_${e.slice(n-3,n)}${t}`;return`${e.slice(0,n)}${t}`}function h(e,t,n){n||(n=Error);class r extends n{constructor(...n){super(function(e,t,n){if("function"==typeof t)return u(t.length<=n.length,`Code: ${e}; The provided arguments length (${n.length}) does not match the required ones (${t.length}).`),t(...n);const r=(t.match(/%[dfijoOs]/g)||[]).length;return u(r===n.length,`Code: ${e}; The provided arguments length (${n.length}) does not match the required ones (${r}).`),0===n.length?t:i(t,...n)}(e,t,n))}toString(){return`${this.name} [${e}]: ${this.message}`}}Object.defineProperties(r.prototype,{name:{value:n.name,writable:!0,enumerable:!1,configurable:!0},toString:{value(){return`${this.name} [${e}]: ${this.message}`},writable:!0,enumerable:!1,configurable:!0}}),r.prototype.code=e,r.prototype[a]=!0,d[e]=r}function f(e){const t="__node_internal_"+e.name;return Object.defineProperty(e,"name",{value:t}),e}class g extends Error{constructor(e="The operation was aborted",t=void 0){if(void 0!==t&&"object"!=typeof t)throw new d.ERR_INVALID_ARG_TYPE("options","Object",t);super(e,t),this.code="ABORT_ERR",this.name="AbortError"}}h("ERR_ASSERTION","%s",Error),h("ERR_INVALID_ARG_TYPE",(e,t,n)=>{u("string"==typeof e,"'name' must be a string"),Array.isArray(t)||(t=[t]);let i="The ";e.endsWith(" argument")?i+=`${e} `:i+=`"${e}" ${e.includes(".")?"property":"argument"} `,i+="must be ";const o=[],s=[],a=[];for(const e of t)u("string"==typeof e,"All expected entries have to be of type string"),c.includes(e)?o.push(e.toLowerCase()):l.test(e)?s.push(e):(u("object"!==e,'The value "object" should be written as "Object"'),a.push(e));if(s.length>0){const e=o.indexOf("object");-1!==e&&(o.splice(o,e,1),s.push("Object"))}if(o.length>0){switch(o.length){case 1:i+=`of type ${o[0]}`;break;case 2:i+=`one of type ${o[0]} or ${o[1]}`;break;default:{const e=o.pop();i+=`one of type ${o.join(", ")}, or ${e}`}}(s.length>0||a.length>0)&&(i+=" or ")}if(s.length>0){switch(s.length){case 1:i+=`an instance of ${s[0]}`;break;case 2:i+=`an instance of ${s[0]} or ${s[1]}`;break;default:{const e=s.pop();i+=`an instance of ${s.join(", ")}, or ${e}`}}a.length>0&&(i+=" or ")}switch(a.length){case 0:break;case 1:a[0].toLowerCase()!==a[0]&&(i+="an "),i+=`${a[0]}`;break;case 2:i+=`one of ${a[0]} or ${a[1]}`;break;default:{const e=a.pop();i+=`one of ${a.join(", ")}, or ${e}`}}if(null==n)i+=`. Received ${n}`;else if("function"==typeof n&&n.name)i+=`. Received function ${n.name}`;else if("object"==typeof n){var d;if(null!==(d=n.constructor)&&void 0!==d&&d.name)i+=`. Received an instance of ${n.constructor.name}`;else{i+=`. Received ${r(n,{depth:-1})}`}}else{let e=r(n,{colors:!1});e.length>25&&(e=`${e.slice(0,25)}...`),i+=`. Received type ${typeof n} (${e})`}return i},TypeError),h("ERR_INVALID_ARG_VALUE",(e,t,n="is invalid")=>{let i=r(t);i.length>128&&(i=i.slice(0,128)+"...");return`The ${e.includes(".")?"property":"argument"} '${e}' ${n}. Received ${i}`},TypeError),h("ERR_INVALID_RETURN_VALUE",(e,t,n)=>{var i;return`Expected ${e} to be returned from the "${t}" function but got ${null!=n&&null!==(i=n.constructor)&&void 0!==i&&i.name?`instance of ${n.constructor.name}`:"type "+typeof n}.`},TypeError),h("ERR_MISSING_ARGS",(...e)=>{let t;u(e.length>0,"At least one arg needs to be specified");const n=e.length;switch(e=(Array.isArray(e)?e:[e]).map(e=>`"${e}"`).join(" or "),n){case 1:t+=`The ${e[0]} argument`;break;case 2:t+=`The ${e[0]} and ${e[1]} arguments`;break;default:{const n=e.pop();t+=`The ${e.join(", ")}, and ${n} arguments`}}return`${t} must be specified`},TypeError),h("ERR_OUT_OF_RANGE",(e,t,n)=>{let i;if(u(t,'Missing "range" argument'),Number.isInteger(n)&&Math.abs(n)>2**32)i=p(String(n));else if("bigint"==typeof n){i=String(n);const e=BigInt(2)**BigInt(32);(n>e||n<-e)&&(i=p(i)),i+="n"}else i=r(n);return`The value of "${e}" is out of range. It must be ${t}. Received ${i}`},RangeError),h("ERR_MULTIPLE_CALLBACK","Callback called multiple times",Error),h("ERR_METHOD_NOT_IMPLEMENTED","The %s method is not implemented",Error),h("ERR_STREAM_ALREADY_FINISHED","Cannot call %s after a stream was finished",Error),h("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable",Error),h("ERR_STREAM_DESTROYED","Cannot call %s after a stream was destroyed",Error),h("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),h("ERR_STREAM_PREMATURE_CLOSE","Premature close",Error),h("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF",Error),h("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event",Error),h("ERR_STREAM_WRITE_AFTER_END","write after end",Error),h("ERR_UNKNOWN_ENCODING","Unknown encoding: %s",TypeError),e.exports={AbortError:g,aggregateTwoErrors:f(function(e,t){if(e&&t&&e!==t){if(Array.isArray(t.errors))return t.errors.push(e),t;const n=new s([t,e],t.message);return n.code=t.code,n}return e||t}),hideStackFrames:f,codes:d}},6524(e,t,n){"use strict";const{ObjectSetPrototypeOf:i}=n(4134);e.exports=o;const r=n(7382);function o(e){if(!(this instanceof o))return new o(e);r.call(this,e)}i(o.prototype,r.prototype),i(o,r),o.prototype._transform=function(e,t,n){n(null,e)}},6532(e,t,n){"use strict";const i=n(4422),{PromisePrototypeThen:r,SymbolAsyncIterator:o,SymbolIterator:s}=n(4134),{Buffer:a}=n(181),{ERR_INVALID_ARG_TYPE:c,ERR_STREAM_NULL_VALUES:l}=n(6371).codes;e.exports=function(e,t,n){let d,u;if("string"==typeof t||t instanceof a)return new e({objectMode:!0,...n,read(){this.push(t),this.push(null)}});if(t&&t[o])u=!0,d=t[o]();else{if(!t||!t[s])throw new c("iterable",["Iterable"],t);u=!1,d=t[s]()}const p=new e({objectMode:!0,highWaterMark:1,...n});let h=!1;return p._read=function(){h||(h=!0,async function(){for(;;){try{const{value:e,done:t}=u?await d.next():d.next();if(t)p.push(null);else{const t=e&&"function"==typeof e.then?await e:e;if(null===t)throw h=!1,new l;if(p.push(t))continue;h=!1}}catch(e){p.destroy(e)}break}}())},p._destroy=function(e,t){r(async function(e){const t=null!=e,n="function"==typeof d.throw;if(t&&n){const{value:t,done:n}=await d.throw(e);if(await t,n)return}if("function"==typeof d.return){const{value:e}=await d.return();await e}}(e),()=>i.nextTick(t,e),n=>i.nextTick(t,n||e))},p}},6584(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=n(4988);class r extends i.EventTarget{constructor(){throw super(),new TypeError("AbortSignal cannot be constructed directly")}get aborted(){const e=o.get(this);if("boolean"!=typeof e)throw new TypeError("Expected 'this' to be an 'AbortSignal' object, but got "+(null===this?"null":typeof this));return e}}i.defineEventAttribute(r.prototype,"abort");const o=new WeakMap;Object.defineProperties(r.prototype,{aborted:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag&&Object.defineProperty(r.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortSignal"});class s{constructor(){a.set(this,function(){const e=Object.create(r.prototype);return i.EventTarget.call(e),o.set(e,!1),e}())}get signal(){return c(this)}abort(){var e;e=c(this),!1===o.get(e)&&(o.set(e,!0),e.dispatchEvent({type:"abort"}))}}const a=new WeakMap;function c(e){const t=a.get(e);if(null==t)throw new TypeError("Expected 'this' to be an 'AbortController' object, but got "+(null===e?"null":typeof e));return t}Object.defineProperties(s.prototype,{signal:{enumerable:!0},abort:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag&&Object.defineProperty(s.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortController"}),t.AbortController=s,t.AbortSignal=r,t.default=s,e.exports=s,e.exports.AbortController=e.exports.default=s,e.exports.AbortSignal=r},6585(e){var t=1e3,n=60*t,i=60*n,r=24*i,o=7*r,s=365.25*r;function a(e,t,n,i){var r=t>=1.5*n;return Math.round(e/n)+" "+i+(r?"s":"")}e.exports=function(e,c){c=c||{};var l=typeof e;if("string"===l&&e.length>0)return function(e){if((e=String(e)).length>100)return;var a=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!a)return;var c=parseFloat(a[1]);switch((a[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return c*s;case"weeks":case"week":case"w":return c*o;case"days":case"day":case"d":return c*r;case"hours":case"hour":case"hrs":case"hr":case"h":return c*i;case"minutes":case"minute":case"mins":case"min":case"m":return c*n;case"seconds":case"second":case"secs":case"sec":case"s":return c*t;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return c;default:return}}(e);if("number"===l&&isFinite(e))return c.long?function(e){var o=Math.abs(e);if(o>=r)return a(e,o,r,"day");if(o>=i)return a(e,o,i,"hour");if(o>=n)return a(e,o,n,"minute");if(o>=t)return a(e,o,t,"second");return e+" ms"}(e):function(e){var o=Math.abs(e);if(o>=r)return Math.round(e/r)+"d";if(o>=i)return Math.round(e/i)+"h";if(o>=n)return Math.round(e/n)+"m";if(o>=t)return Math.round(e/t)+"s";return e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},6687(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.SpatialReasoningEngine=void 0,t.mediaObjectToBase64=c,t.buildImageContent=l,t.isVisionFormatError=d;const r=i(n(7562)),o=n(1554),{systemManager:s,mediaManager:a}=r.default;async function c(e){try{const t=e?.mimeType||"image/jpeg";let n;console.log(`[Image] Converting MediaObject, mimeType=${t}`);try{n=await a.convertMediaObjectToBuffer(e,t)}catch(t){console.warn("[Image] Direct conversion failed, trying with explicit JPEG:",t);try{const t=e;if("function"!=typeof t.getData)return console.warn("[Image] No getData method available"),null;{const e=await t.getData();if(!(e&&Buffer.isBuffer(e)&&e.length>1e3))return console.warn("[Image] getData returned invalid data"),null;console.log(`[Image] Got raw data: ${e.length} bytes`),n=e}}catch(e){return console.warn("[Image] Alternate data fetch failed:",e),null}}const i=Buffer.isBuffer(n),r=i?n.length:0;if(console.log(`[Image] Buffer: isBuffer=${i}, length=${r}`),!i||0===r)return console.warn("[Image] Did not receive a valid Buffer"),null;if(r<1e3)return console.warn(`[Image] Buffer too small: ${r} bytes`),null;const o=n.toString("base64");return console.log(`[Image] Converted to base64: ${o.length} chars`),{base64:o,mediaType:"image/jpeg"}}catch(e){return console.warn("[Image] Failed to convert MediaObject to base64:",e),null}}function l(e,t="unknown"){return{type:"image_url",image_url:{url:`data:${e.mediaType};base64,${e.base64}`}}}function d(e){const t=String(e);return t.includes("content.str")||t.includes("should be a valid string")||t.includes("Invalid content type")||t.includes("does not support vision")||t.includes("invalid base64")||t.includes("Invalid base64")||t.includes(".image.source")||t.includes(".image_url")||t.includes("image_url")&&t.includes("not supported")||t.includes("400")&&t.includes("content")}t.SpatialReasoningEngine=class{config;console;topology=null;llmDevice=null;contextChunks=[];topologyContextCache=null;contextCacheTime=0;landmarkSuggestions=new Map;constructor(e,t){this.config=e,this.console=t}updateTopology(e){this.topology=e,this.rebuildContextChunks(),this.topologyContextCache=null,this.contextCacheTime=0}rebuildContextChunks(){if(this.topology){this.contextChunks=[],this.topology.property&&this.contextChunks.push({id:"property",type:"property",content:this.buildPropertyContext(),metadata:{...this.topology.property}});for(const e of this.topology.cameras)this.contextChunks.push({id:`camera_${e.deviceId}`,type:"camera",content:this.buildCameraContext(e),metadata:{deviceId:e.deviceId,name:e.name,isEntryPoint:e.isEntryPoint,isExitPoint:e.isExitPoint}});for(const e of this.topology.landmarks||[])this.contextChunks.push({id:`landmark_${e.id}`,type:"landmark",content:this.buildLandmarkContext(e),metadata:{id:e.id,name:e.name,type:e.type,isEntryPoint:e.isEntryPoint,isExitPoint:e.isExitPoint}});for(const e of this.topology.connections)this.contextChunks.push({id:`connection_${e.id}`,type:"connection",content:this.buildConnectionContext(e),metadata:{id:e.id,fromCameraId:e.fromCameraId,toCameraId:e.toCameraId}});this.console.log(`Built ${this.contextChunks.length} context chunks for spatial reasoning`)}}buildPropertyContext(){if(!this.topology?.property)return"";const e=this.topology.property,t=[];return e.propertyType&&t.push(`Property type: ${e.propertyType}`),e.description&&t.push(e.description),e.frontFacing&&t.push(`Front faces ${e.frontFacing}`),e.features?.length&&t.push(`Features: ${e.features.join(", ")}`),t.join(". ")}buildCameraContext(e){const t=[`Camera: ${e.name}`];if(e.context?.mountLocation&&t.push(`Mounted at: ${e.context.mountLocation}`),e.context?.coverageDescription&&t.push(`Coverage: ${e.context.coverageDescription}`),e.context?.mountHeight&&t.push(`Height: ${e.context.mountHeight} feet`),e.isEntryPoint&&t.push("Watches property entry point"),e.isExitPoint&&t.push("Watches property exit point"),this.topology&&e.context?.visibleLandmarks?.length){const n=e.context.visibleLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);n.length&&t.push(`Can see: ${n.join(", ")}`)}return t.join(". ")}buildLandmarkContext(e){const t=[`${e.name} (${e.type})`];if(e.description&&t.push(e.description),e.isEntryPoint&&t.push("Property entry point"),e.isExitPoint&&t.push("Property exit point"),this.topology&&e.adjacentTo?.length){const n=e.adjacentTo.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);n.length&&t.push(`Adjacent to: ${n.join(", ")}`)}return t.join(". ")}buildConnectionContext(e){if(!this.topology)return"";const t=(0,o.findCamera)(this.topology,e.fromCameraId),n=(0,o.findCamera)(this.topology,e.toCameraId);if(!t||!n)return"";const i=[`Path from ${t.name} to ${n.name}`];e.name&&i.push(`Called: ${e.name}`);const r=Math.round(e.transitTime.typical/1e3);if(i.push(`Typical transit: ${r} seconds`),e.bidirectional&&i.push("Bidirectional path"),e.pathLandmarks?.length){const t=e.pathLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);t.length&&i.push(`Passes: ${t.join(" → ")}`)}return i.join(". ")}getTopologyContext(){const e=Date.now();return this.topologyContextCache&&e-this.contextCacheTime<this.config.contextCacheTtl?this.topologyContextCache:this.topology?(this.topologyContextCache=(0,o.generateTopologyDescription)(this.topology),this.contextCacheTime=e,this.topologyContextCache):""}retrieveRelevantContext(e,t){const n=[],i=this.contextChunks.find(e=>"property"===e.type);i&&n.push(i);const r=this.contextChunks.find(t=>t.id===`camera_${e}`),s=this.contextChunks.find(e=>e.id===`camera_${t}`);r&&n.push(r),s&&n.push(s);const a=this.contextChunks.find(n=>"connection"===n.type&&(n.metadata.fromCameraId===e&&n.metadata.toCameraId===t||n.metadata.fromCameraId===t&&n.metadata.toCameraId===e));if(a&&n.push(a),this.topology){const i=(0,o.getLandmarksVisibleFromCamera)(this.topology,e),r=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),s=new Set([...i.map(e=>e.id),...r.map(e=>e.id)]);for(const e of s){const t=this.contextChunks.find(t=>t.id===`landmark_${e}`);t&&n.push(t)}}return n}llmSearched=!1;llmProvider=null;llmProviderType="unknown";async findLlmDevice(){if(this.llmDevice)return this.llmDevice;if(this.llmSearched)return null;this.llmSearched=!0;try{for(const e of Object.keys(s.getSystemState())){const t=s.getDeviceById(e);if(t&&t.interfaces?.includes("ChatCompletion")){const e=t.name?.toLowerCase()||"",n=t.pluginId?.toLowerCase()||"";let i="Unknown",r="unknown";return e.includes("openai")||e.includes("gpt")?(i="OpenAI",r="openai"):e.includes("anthropic")||e.includes("claude")?(i="Anthropic",r="anthropic"):e.includes("ollama")?(i="Ollama",r="openai"):e.includes("gemini")||e.includes("google")?(i="Google",r="openai"):e.includes("llama")?(i="llama.cpp",r="openai"):(n.includes("@scrypted/llm")||n.includes("llm"))&&(i="Scrypted LLM",r="unknown"),this.llmDevice=t,this.llmProvider=`${i} (${t.name})`,this.llmProviderType=r,this.console.log(`[LLM] Connected to ${i}: ${t.name}`),this.console.log(`[LLM] Plugin: ${n||"N/A"}`),this.console.log(`[LLM] Image format: ${r}`),this.console.log(`[LLM] Interfaces: ${t.interfaces?.join(", ")}`),this.llmDevice}}this.console.warn("[LLM] No ChatCompletion device found. Install @scrypted/llm for enhanced descriptions."),this.console.warn("[LLM] Falling back to rule-based descriptions using topology data.")}catch(e){this.console.error("[LLM] Error searching for LLM device:",e)}return null}getLlmProvider(){return this.llmProvider}getLlmProviderType(){return this.llmProviderType}isLlmAvailable(){return null!==this.llmDevice}async generateEntryDescription(e,t,n){if(!this.topology)return{description:`${this.capitalizeFirst(e.className)} entered property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const i=(0,o.findCamera)(this.topology,t);if(!i)return{description:`${this.capitalizeFirst(e.className)} entered property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const r=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),s=this.capitalizeFirst(e.className),a=this.describeLocation(i,r,"to"),c=r.find(e=>"street"===e.type),l=r.find(e=>"neighbor"===e.type);let d="";c?d=` from ${c.name}`:l&&(d=` from ${l.name}`);const u=`${s} arrived at ${a}${d}`;if(this.console.log(`[Entry] enableLlm=${this.config.enableLlm}, hasMediaObject=${!!n}`),this.config.enableLlm&&n){this.console.log("[Entry] Attempting LLM description for entry event");const t=await this.getLlmEntryExitDescription(e,i,r,"entry",n);if(t)return this.console.log(`[Entry] LLM returned: ${t.substring(0,50)}...`),{description:t,involvedLandmarks:r,confidence:.9,usedLlm:!0};this.console.warn("[Entry] LLM returned null, falling back to basic")}else this.console.log(`[Entry] Skipping LLM (enableLlm=${this.config.enableLlm}, mediaObject=${!!n})`);return{description:u,involvedLandmarks:r,confidence:.8,usedLlm:!1}}async generateExitDescription(e,t,n){if(!this.topology)return{description:`${this.capitalizeFirst(e.className)} left property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const i=(0,o.findCamera)(this.topology,t);if(!i)return{description:`${this.capitalizeFirst(e.className)} left property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const r=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),s=this.capitalizeFirst(e.className),a=this.describeLocation(i,r,"from"),c=r.find(e=>e.isExitPoint),l=r.find(e=>"street"===e.type);let d="";l?d=` towards ${l.name}`:c&&(d=` via ${c.name}`);const u=Math.round((e.lastSeen-e.firstSeen)/1e3);let p="";u>60?p=` after ${Math.round(u/60)}m on property`:u>10&&(p=` after ${u}s`);let h="";if(e.journey.length>0&&this.topology){const t=[];if(e.entryCamera){const n=(0,o.getLandmarksVisibleFromCamera)(this.topology,e.entryCamera),i=n.find(e=>e.isEntryPoint||"access"===e.type)||n[0];i&&t.push(i.name)}for(const n of e.journey){const e=(0,o.getLandmarksVisibleFromCamera)(this.topology,n.toCameraId).find(e=>!t.includes(e.name)&&("access"===e.type||"zone"===e.type||"structure"===e.type));e&&!t.includes(e.name)&&t.push(e.name)}t.length>1&&(h=` — visited ${t.join(" → ")}`)}const f=`${s} left ${a}${d}${p}${h}`;if(this.console.log(`[Exit] enableLlm=${this.config.enableLlm}, hasMediaObject=${!!n}`),this.config.enableLlm&&n){this.console.log("[Exit] Attempting LLM description for exit event");const t=await this.getLlmEntryExitDescription(e,i,r,"exit",n,h);if(t)return this.console.log(`[Exit] LLM returned: ${t.substring(0,50)}...`),{description:t,involvedLandmarks:r,confidence:.9,usedLlm:!0};this.console.warn("[Exit] LLM returned null, falling back to basic")}else this.console.log(`[Exit] Skipping LLM (enableLlm=${this.config.enableLlm}, mediaObject=${!!n})`);return{description:f,involvedLandmarks:r,confidence:.8,usedLlm:!1}}async generateMovementDescription(e,t,n,i,r){if(!this.topology)return{description:`${e.className} moving between cameras`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const s=(0,o.findCamera)(this.topology,t),a=(0,o.findCamera)(this.topology,n);if(!s||!a)return{description:`${e.className} moving between cameras`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const c=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),l=(0,o.getLandmarksVisibleFromCamera)(this.topology,n),d=[...new Set([...c,...l])];let u=this.buildBasicDescription(e,s,a,i,c,l);if(this.config.enableLlm&&r){const t=await this.getLlmEnhancedDescription(e,s,a,i,c,l,r);if(t)return{description:t,involvedLandmarks:d,pathDescription:this.buildPathDescription(s,a),confidence:.9,usedLlm:!0}}return{description:u,involvedLandmarks:d,pathDescription:this.buildPathDescription(s,a),confidence:.7,usedLlm:!1}}buildBasicDescription(e,t,n,i,r,s){const a=this.capitalizeFirst(e.className),c=Math.round(i/1e3),l=this.topology?(0,o.findConnection)(this.topology,t.deviceId,n.deviceId):null;let d=this.describeLocation(t,r,"from"),u=this.describeLocation(n,s,"to"),p="";if(l?.name)p=` via ${l.name}`;else if(l?.pathLandmarks?.length&&this.topology){const e=l.pathLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);e.length>0&&(p=` past ${e.join(" and ")}`)}let h="";if(e.journey.length>0){const t=Math.round((Date.now()-e.firstSeen)/1e3);t>60&&(h=` (${Math.round(t/60)}m on property)`)}return`${a} ${this.getMovementVerb(e.className,c)} ${d} heading ${u}${p}${h}`}describeLocation(e,t,n){const i=t.find(e=>"from"===n&&e.isExitPoint||"to"===n&&e.isEntryPoint);if(i)return`the ${i.name}`;const r=t.find(e=>"access"===e.type);if(r)return`the ${r.name}`;const o=t.find(e=>"zone"===e.type);if(o)return`the ${o.name}`;if(t.length>0)return`near ${t[0].name}`;if(e.context?.coverageDescription){return`the ${e.context.coverageDescription.split(".")[0].toLowerCase()}`}return"property"}getMovementVerb(e,t){return"car"===e||"vehicle"===e||"truck"===e?t<10?"driving from":"moved from":t<5?"walking from":t<30?"moved from":"traveled from"}buildPathDescription(e,t){if(!this.topology)return;const n=(0,o.findConnection)(this.topology,e.deviceId,t.deviceId);if(n){if(n.pathLandmarks?.length){const e=n.pathLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);if(e.length)return`Via ${e.join(" → ")}`}return n.name||void 0}}async getLlmEnhancedDescription(e,t,n,i,r,o,s){const a=await this.findLlmDevice();if(!a||!a.getChatCompletion)return null;try{const d=await c(s),u=this.retrieveRelevantContext(t.deviceId,n.deviceId).map(e=>e.content).join("\n\n"),p=this.buildLlmPrompt(e,t,n,i,r,o,u);let h;h=d?[{type:"text",text:p},l(d,this.llmProviderType)]:p;const f=await a.getChatCompletion({messages:[{role:"user",content:h}],max_tokens:150,temperature:.7}),g=f?.choices?.[0]?.message?.content;return g&&"string"==typeof g?g.trim():null}catch(e){return this.console.warn("LLM description generation failed:",e),null}}async getLlmEntryExitDescription(e,t,n,i,r,o){this.console.log(`[LLM] getLlmEntryExitDescription called for ${i} event`);const s=await this.findLlmDevice();if(!s)return this.console.warn(`[LLM] No LLM device found for ${i} description`),null;if(!s.getChatCompletion)return this.console.warn("[LLM] LLM device has no getChatCompletion method"),null;this.console.log(`[LLM] Using LLM device: ${this.llmProvider}`);try{const a=await c(r);this.console.log(`[LLM] Image converted: ${a?"success":"failed"}, type: ${a?.mediaType}`);const u=n.map(e=>e.name).join(", ")||"none identified",p=Math.round((e.lastSeen-e.firstSeen)/1e3),h="entry"===i?`You are a security camera system. Analyze this image and describe who/what just arrived.\n\nCONTEXT:\n- Camera: ${t.name}\n- Object type: ${e.className}\n- Nearby landmarks: ${u}\n\nINSTRUCTIONS:\nLook at the image and generate a single, natural sentence describing:\n1. Physical description (if person: gender, clothing, items carried; if vehicle: color, type, make)\n2. What they appear to be doing (arriving, approaching, etc.)\n3. Relevant landmark context (driveway, front door, mailbox, etc.)\n\nExamples of good descriptions:\n- "Man in gray hoodie approaching the front door"\n- "Woman in scrubs arriving with shopping bags"\n- "White delivery van pulling into the driveway"\n- "UPS driver carrying package towards the porch"\n- "Teenager on bicycle coming up the driveway"\n\nGenerate ONLY the description, nothing else:`:`You are a security camera system. Analyze this image and describe who/what is leaving.\n\nCONTEXT:\n- Camera: ${t.name}\n- Object type: ${e.className}\n- Time on property: ${p>60?Math.round(p/60)+" minutes":p+" seconds"}\n- Nearby landmarks: ${u}\n${o?`- Journey: ${o}`:""}\n\nINSTRUCTIONS:\nLook at the image and generate a single, natural sentence describing:\n1. Physical description (if person: gender, clothing, items carried; if vehicle: color, type)\n2. What they did (if determinable from context)\n3. Direction they're leaving towards\n\nExamples of good descriptions:\n- "Man in black hoodie leaving after checking the mailbox"\n- "Woman in business attire heading to car in driveway"\n- "Red sedan backing out of the driveway"\n- "Delivery driver returning to FedEx truck after leaving package"\n- "Landscaper with leaf blower heading to work truck"\n\nGenerate ONLY the description, nothing else:`;let f,g=!1;if(a)try{this.console.log(`[LLM] Attempting multimodal ${i} call with image...`);const e=[{type:"text",text:h},l(a,this.llmProviderType)];f=await s.getChatCompletion({messages:[{role:"user",content:e}],max_tokens:100,temperature:.7}),g=!0}catch(e){d(e)?this.console.warn(`[LLM] Vision format not supported, falling back to text-only: ${e.message||e}`):this.console.warn(`[LLM] Multimodal call failed, trying text-only: ${e.message||e}`)}f||(this.console.log(`[LLM] Calling text-only getChatCompletion for ${i}...`),f=await s.getChatCompletion({messages:[{role:"user",content:h}],max_tokens:100,temperature:.7}));const m=f?.choices?.[0]?.message?.content;return m&&"string"==typeof m?(this.console.log(`[LLM] Got ${i} description (vision=${g}): ${m.trim().substring(0,50)}...`),m.trim()):(this.console.warn(`[LLM] No content in response for ${i}`),null)}catch(e){return this.console.warn(`[LLM] ${i} description generation failed:`,e),null}}buildLlmPrompt(e,t,n,i,r,o,s){const a=Math.round(i/1e3);return`You are a security camera system describing movement on a property.\n\nPROPERTY CONTEXT:\n${s}\n\nCURRENT EVENT:\n- Object type: ${e.className}\n- Moving from: ${t.name}${r.length?` (near ${r.map(e=>e.name).join(", ")})`:""}\n- Moving to: ${n.name}${o.length?` (near ${o.map(e=>e.name).join(", ")})`:""}\n- Transit time: ${a} seconds\n\nINSTRUCTIONS:\nGenerate a single, concise sentence describing this movement. Include:\n1. Description of the ${e.className} (if person: gender, clothing; if vehicle: color, type)\n2. Where they came from (using landmark names if available)\n3. Where they're heading (using landmark names if available)\n\nExamples of good descriptions:\n- "Man in blue jacket walking from the driveway towards the front door"\n- "Black SUV pulling into the driveway from the street"\n- "Woman with dog walking from the backyard towards the side gate"\n- "Delivery person approaching the front porch from the mailbox"\n\nGenerate ONLY the description, nothing else:`}async suggestLandmark(e,t,n,i){if(!this.config.enableLandmarkLearning)return null;const r=await this.findLlmDevice();if(!r||!r.getChatCompletion)return null;try{const o=await c(t),s=`Analyze this security camera image. A ${n} was detected.\n\nLooking at the surroundings and environment, identify any notable landmarks or features visible that could help describe this location. Consider:\n- Structures (house, garage, shed, porch)\n- Features (mailbox, tree, pool, garden)\n- Access points (driveway, walkway, gate, door)\n- Boundaries (fence, wall, hedge)\n\nIf you can identify a clear landmark feature, respond with ONLY a JSON object:\n{"name": "Landmark Name", "type": "structure|feature|boundary|access|vehicle|neighbor|zone|street", "description": "Brief description"}\n\nIf no clear landmark is identifiable, respond with: {"name": null}`;let a;a=o?[{type:"text",text:s},l(o,this.llmProviderType)]:s;const d=await r.getChatCompletion({messages:[{role:"user",content:a}],max_tokens:100,temperature:.3}),u=d?.choices?.[0]?.message?.content;if(u&&"string"==typeof u)try{const t=JSON.parse(u.trim());if(t.name&&t.type){const n=`suggest_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,r={id:n,landmark:{id:`landmark_${Date.now()}`,name:t.name,type:t.type,position:i,description:t.description,aiSuggested:!0,aiConfidence:.7,visibleFromCameras:[e]},detectedByCameras:[e],timestamp:Date.now(),detectionCount:1,status:"pending"},o=this.findSimilarSuggestion(t.name,i);if(o){const t=this.landmarkSuggestions.get(o);return t.detectionCount++,t.landmark.aiConfidence=Math.min(.95,t.landmark.aiConfidence+.05),t.detectedByCameras.includes(e)||t.detectedByCameras.push(e),t}return this.landmarkSuggestions.set(n,r),r}}catch(e){}return null}catch(e){return this.console.warn("Landmark suggestion failed:",e),null}}findSimilarSuggestion(e,t){const n=e.toLowerCase();for(const[e,i]of this.landmarkSuggestions){if("pending"!==i.status)continue;const r=i.landmark.name.toLowerCase(),o=Math.sqrt(Math.pow(i.landmark.position.x-t.x,2)+Math.pow(i.landmark.position.y-t.y,2));if((r.includes(n)||n.includes(r))&&o<100)return e}return null}getPendingSuggestions(){return Array.from(this.landmarkSuggestions.values()).filter(e=>"pending"===e.status&&e.landmark.aiConfidence>=this.config.landmarkConfidenceThreshold).sort((e,t)=>t.detectionCount-e.detectionCount)}acceptSuggestion(e){const t=this.landmarkSuggestions.get(e);if(!t)return null;t.status="accepted";const n={...t.landmark};return n.aiSuggested=!1,this.landmarkSuggestions.delete(e),n}rejectSuggestion(e){const t=this.landmarkSuggestions.get(e);return!!t&&(t.status="rejected",this.landmarkSuggestions.delete(e),!0)}capitalizeFirst(e){return e?e.charAt(0).toUpperCase()+e.slice(1):"Object"}getLandmarkTemplates(){return o.LANDMARK_TEMPLATES}}},6698(e){"function"==typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}},6706(e,t,n){const i=n(4422),r=n(181),{isReadable:o,isWritable:s,isIterable:a,isNodeStream:c,isReadableNodeStream:l,isWritableNodeStream:d,isDuplexNodeStream:u,isReadableStream:p,isWritableStream:h}=n(6115),f=n(6238),{AbortError:g,codes:{ERR_INVALID_ARG_TYPE:m,ERR_INVALID_RETURN_VALUE:y}}=n(6371),{destroyer:b}=n(5896),v=n(3370),S=n(7576),_=n(8584),{createDeferredPromise:w}=n(7760),k=n(6532),I=globalThis.Blob||r.Blob,x="undefined"!=typeof I?function(e){return e instanceof I}:function(e){return!1},C=globalThis.AbortController||n(6584).AbortController,{FunctionPrototypeCall:E}=n(4134);class T extends v{constructor(e){super(e),!1===(null==e?void 0:e.readable)&&(this._readableState.readable=!1,this._readableState.ended=!0,this._readableState.endEmitted=!0),!1===(null==e?void 0:e.writable)&&(this._writableState.writable=!1,this._writableState.ending=!0,this._writableState.ended=!0,this._writableState.finished=!0)}}function O(e){const t=e.readable&&"function"!=typeof e.readable.read?S.wrap(e.readable):e.readable,n=e.writable;let i,r,a,c,l,d=!!o(t),u=!!s(n);function p(e){const t=c;c=null,t?t(e):e&&l.destroy(e)}return l=new T({readableObjectMode:!(null==t||!t.readableObjectMode),writableObjectMode:!(null==n||!n.writableObjectMode),readable:d,writable:u}),u&&(f(n,e=>{u=!1,e&&b(t,e),p(e)}),l._write=function(e,t,r){n.write(e,t)?r():i=r},l._final=function(e){n.end(),r=e},n.on("drain",function(){if(i){const e=i;i=null,e()}}),n.on("finish",function(){if(r){const e=r;r=null,e()}})),d&&(f(t,e=>{d=!1,e&&b(t,e),p(e)}),t.on("readable",function(){if(a){const e=a;a=null,e()}}),t.on("end",function(){l.push(null)}),l._read=function(){for(;;){const e=t.read();if(null===e)return void(a=l._read);if(!l.push(e))return}}),l._destroy=function(e,o){e||null===c||(e=new g),a=null,i=null,r=null,null===c?o(e):(c=o,b(n,e),b(t,e))},l}e.exports=function e(t,n){if(u(t))return t;if(l(t))return O({readable:t});if(d(t))return O({writable:t});if(c(t))return O({writable:!1,readable:!1});if(p(t))return O({readable:S.fromWeb(t)});if(h(t))return O({writable:_.fromWeb(t)});if("function"==typeof t){const{value:e,write:r,final:o,destroy:s}=function(e){let{promise:t,resolve:n}=w();const r=new C,o=r.signal,s=e(async function*(){for(;;){const e=t;t=null;const{chunk:r,done:s,cb:a}=await e;if(i.nextTick(a),s)return;if(o.aborted)throw new g(void 0,{cause:o.reason});({promise:t,resolve:n}=w()),yield r}}(),{signal:o});return{value:s,write(e,t,i){const r=n;n=null,r({chunk:e,done:!1,cb:i})},final(e){const t=n;n=null,t({done:!0,cb:e})},destroy(e,t){r.abort(),t(e)}}}(t);if(a(e))return k(T,e,{objectMode:!0,write:r,final:o,destroy:s});const c=null==e?void 0:e.then;if("function"==typeof c){let t;const n=E(c,e,e=>{if(null!=e)throw new y("nully","body",e)},e=>{b(t,e)});return t=new T({objectMode:!0,readable:!1,write:r,final(e){o(async()=>{try{await n,i.nextTick(e,null)}catch(t){i.nextTick(e,t)}})},destroy:s})}throw new y("Iterable, AsyncIterable or AsyncFunction",n,e)}if(x(t))return e(t.arrayBuffer());if(a(t))return k(T,t,{objectMode:!0,writable:!1});if(p(null==t?void 0:t.readable)&&h(null==t?void 0:t.writable))return T.fromWeb(t);if("object"==typeof(null==t?void 0:t.writable)||"object"==typeof(null==t?void 0:t.readable)){return O({readable:null!=t&&t.readable?l(null==t?void 0:t.readable)?null==t?void 0:t.readable:e(t.readable):void 0,writable:null!=t&&t.writable?d(null==t?void 0:t.writable)?null==t?void 0:t.writable:e(t.writable):void 0})}const r=null==t?void 0:t.then;if("function"==typeof r){let e;return E(r,t,t=>{null!=t&&e.push(t),e.push(null)},t=>{b(e,t)}),e=new T({objectMode:!0,writable:!1,read(){}})}throw new m(n,["Blob","ReadableStream","WritableStream","Stream","Iterable","AsyncIterable","Function","{ readable, writable } pair","Promise"],t)}},6751(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ObjectCorrelator=void 0;const i=n(1554),r=n(441);t.ObjectCorrelator=class{topology;config;constructor(e,t){this.topology=e,this.config=t}async findBestMatch(e,t){const n=[];for(const i of t){const t=await this.evaluateCandidate(i,e);t.confidence>=this.config.correlationThreshold&&n.push(t)}if(0===n.length){const n=t.filter(t=>t.className===e.detection.className);if(1===n.length){const t=await this.evaluateCandidate(n[0],e);if(t.confidence>=.3&&t.factors.timing>0)return t}return null}return n.sort((e,t)=>t.confidence-e.confidence),n[0]}async evaluateCandidate(e,t){const n={timing:this.evaluateTimingFactor(e,t),visual:await this.evaluateVisualFactor(e,t),spatial:this.evaluateSpatialFactor(e,t),class:this.evaluateClassFactor(e,t)};if(0===n.class)return{trackedObject:e,newSighting:t,confidence:0,factors:n};if(0===n.timing)return{trackedObject:e,newSighting:t,confidence:0,factors:n};return{trackedObject:e,newSighting:t,confidence:.3*n.timing+.35*n.visual+.25*n.spatial+.1*n.class,factors:n}}evaluateTimingFactor(e,t){const n=(0,r.getLastSighting)(e);if(!n)return 0;if(n.cameraId===t.cameraId)return 1;const o=t.timestamp-n.timestamp,s=(0,i.findConnection)(this.topology,n.cameraId,t.cameraId);if(!s){return o>0&&o<3e5?o<6e4?.9:o<12e4?.7:Math.max(.4,.7-(o-12e4)/18e4*.3):.3}const{min:a,typical:c,max:l}=s.transitTime;if(o<.5*a||o>2*l)return 0;if(o<a||o>l)return o<a?o/a*.3:l/o*.3;const d=Math.abs(o-c),u=(l-a)/2;return 0===u?1:Math.max(.5,1-d/u*.5)}async evaluateVisualFactor(e,t){if(!this.config.useVisualMatching)return.5;if(!e.visualDescriptor||!t.embedding)return.5;try{return(this.cosineSimilarity(e.visualDescriptor,t.embedding)+1)/2}catch(e){return.5}}evaluateSpatialFactor(e,t){const n=(0,r.getLastSighting)(e);if(!n)return.5;if(n.cameraId===t.cameraId)return 1;const o=(0,i.findConnection)(this.topology,n.cameraId,t.cameraId);if(!o)return.5;let s=0;if(n.position&&o.exitZone.length>0){this.isPointNearZone(n.position,o.exitZone,.2)&&(s+=.5)}else s+=.25;if(t.position&&o.entryZone.length>0){this.isPointNearZone(t.position,o.entryZone,.2)&&(s+=.5)}else s+=.25;return s}evaluateClassFactor(e,t){if(e.className===t.detection.className)return 1;return({car:["vehicle","truck","suv"],vehicle:["car","truck","suv"],truck:["vehicle","car"],person:["human"],human:["person"]}[e.className]||[]).includes(t.detection.className)?.8:0}cosineSimilarity(e,t){try{const n=this.decodeEmbedding(e),i=this.decodeEmbedding(t);if(n.length!==i.length||0===n.length)return 0;let r=0,o=0,s=0;for(let e=0;e<n.length;e++)r+=n[e]*i[e],o+=n[e]*n[e],s+=i[e]*i[e];return o=Math.sqrt(o),s=Math.sqrt(s),0===o||0===s?0:r/(o*s)}catch(e){return 0}}decodeEmbedding(e){try{const t=Buffer.from(e,"base64"),n=[];for(let e=0;e<t.length;e+=4)n.push(t.readFloatLE(e));return n}catch(e){return[]}}isPointNearZone(e,t,n){if(t.length<3)return!1;const i=100*e.x,r=100*e.y;let o=!1;for(let e=0,n=t.length-1;e<t.length;n=e++){const s=t[e][0],a=t[e][1],c=t[n][0],l=t[n][1];a>r!=l>r&&i<(c-s)*(r-a)/(l-a)+s&&(o=!o)}if(o)return!0;for(const e of t){const t=Math.abs(i-e[0])/100,o=Math.abs(r-e[1])/100;if(t<n&&o<n)return!0}return!1}}},6887(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isReactNativeBrowser=t.isWebWorker=void 0;const n=()=>Boolean("object"==typeof self&&self?.constructor?.name?.includes("WorkerGlobalScope")&&"undefined"==typeof Deno),i=()=>"undefined"!=typeof navigator&&"ReactNative"===navigator.product,r=(()=>{if("undefined"!=typeof window){if("undefined"!=typeof navigator&&navigator.userAgent?.toLowerCase().indexOf(" electron/")>-1&&process?.versions){return!Object.prototype.hasOwnProperty.call(process.versions,"electron")}return"undefined"!=typeof window.document}return!1})()||n()||i();t.isWebWorker=n(),t.isReactNativeBrowser=i(),t.default=r},6912(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=i(n(4959)),o=i(n(5228)),s=i(n(495)),a=i(n(1021)),c=i(n(4264));t.default=(e,t,n)=>{const{options:i}=e;if(5===i.protocolVersion&&i.properties&&i.properties.maximumPacketSize&&i.properties.maximumPacketSize<t.length)return e.emit("error",new Error(`exceeding packets size ${t.cmd}`)),e.end({reasonCode:149,properties:{reasonString:"Maximum packet size was exceeded"}}),e;switch(e.log("_handlePacket :: emitting packetreceive"),e.emit("packetreceive",t),t.cmd){case"publish":(0,r.default)(e,t,n);break;case"puback":case"pubrec":case"pubcomp":case"suback":case"unsuback":e.reschedulePing(),(0,a.default)(e,t),n();break;case"pubrel":e.reschedulePing(),(0,c.default)(e,t,n);break;case"connack":(0,s.default)(e,t),n();break;case"auth":e.reschedulePing(),(0,o.default)(e,t),n();break;case"pingresp":e.log("_handlePacket :: received pingresp"),e.reschedulePing(!0),n();break;case"disconnect":e.emit("disconnect",t),n();break;default:e.log("_handlePacket :: unknown command"),n()}}},6928(e){"use strict";e.exports=require("path")},6968(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,n,i){f("SOCKS connection to %s:%d via %s",e,t,n);const r=new g;return async function(e,t,n,i,r={}){const o=r.lookup??(0,p.promisify)(u.lookup),[s,a]=function(e){const t=new URL(e);if(t.pathname||t.hash||t.search)throw m(new Error("bad SOCKS URL"));const[n,i]=function(e){switch(e){case"socks5h:":return[5,!0];case"socks4a:":return[4,!0];case"socks5:":return[5,!1];case"socks4:":return[4,!1];default:return[void 0,!1]}}(t.protocol);if(!n)throw m(new Error("bad SOCKS URL: invalid protocol"));const r=parseInt(t.port,10);if(Number.isNaN(r))throw m(new Error("bad SOCKS URL: invalid port"));const o={host:t.hostname,port:r,type:n};return[o,i]}(n);a||(f("resolving %s locally",e),e=(await o(e,{family:4===s.type?4:0})).address);f("establishing SOCKS%d connection to %s:%d via %s:%d",s.type,e,t,s.host,s.port);const c=new d.SocksClient({command:"connect",destination:{host:e,port:t},proxy:{...s},timeout:r.timeout});c.connect(),c.on("established",({socket:e})=>i._start(e)),c.on("error",e=>{f("SOCKS failed: %s",e),i.destroy(m(e))})}(e,t,n,r,i).catch(e=>{f("SOCKS failed: %s",e),r.destroy(e)}),r};const c=a(n(5753)),l=n(2203),d=n(5861),u=s(n(2250)),p=n(9023),h=a(n(2613)),f=(0,c.default)("mqttjs:socks");class g extends l.Duplex{_flowing=!1;_socket;constructor(){super({autoDestroy:!1}),this.cork()}_start(e){f("proxy stream started"),(0,h.default)(!this._socket),this.destroyed?e.destroy(this.errored):(this._socket=e,this._flowing||e.pause(),e.on("data",this._onData),e.on("end",this._onEnd),e.on("error",this._onError),e.on("close",this._onClose),e.emit("connect"),this.uncork())}_write(e,t,n){(0,h.default)(this._socket),this._socket.write(e,n)}_read(e){this._flowing=!0,this._socket?.resume?.()}_destroy(e,t){this._socket?.destroy?.(e),t(e)}_onData=e=>{(0,h.default)(this._socket),this._flowing=this.push(e),this._flowing||this._socket.pause()};_onEnd=()=>{f("proxy stream received EOF"),this.push(null)};_onClose=()=>{f("proxy stream closed"),this.destroy()};_onError=e=>{f("proxy stream died with error %s",e),this.destroy(e)}}function m(e){try{return void 0===e.code&&(e.code="SOCKS"),e}catch{return e}}},6982(e){"use strict";e.exports=require("crypto")},7016(e){"use strict";e.exports=require("url")},7130(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ipToBuffer=t.int32ToIpv4=t.ipv4ToInt32=t.validateSocksClientChainOptions=t.validateSocksClientOptions=void 0;const i=n(3763),r=n(5438),o=n(2203),s=n(9424),a=n(9278);function c(e,t){if(void 0!==e.custom_auth_method){if(e.custom_auth_method<r.SOCKS5_CUSTOM_AUTH_START||e.custom_auth_method>r.SOCKS5_CUSTOM_AUTH_END)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthRange,t);if(void 0===e.custom_auth_request_handler||"function"!=typeof e.custom_auth_request_handler)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthOptions,t);if(void 0===e.custom_auth_response_size)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthOptions,t);if(void 0===e.custom_auth_response_handler||"function"!=typeof e.custom_auth_response_handler)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthOptions,t)}}function l(e){return e&&"string"==typeof e.host&&Buffer.byteLength(e.host)<256&&"number"==typeof e.port&&e.port>=0&&e.port<=65535}function d(e){return e&&("string"==typeof e.host||"string"==typeof e.ipaddress)&&"number"==typeof e.port&&e.port>=0&&e.port<=65535&&(4===e.type||5===e.type)}function u(e){return"number"==typeof e&&e>0}t.validateSocksClientOptions=function(e,t=["connect","bind","associate"]){if(!r.SocksCommand[e.command])throw new i.SocksClientError(r.ERRORS.InvalidSocksCommand,e);if(-1===t.indexOf(e.command))throw new i.SocksClientError(r.ERRORS.InvalidSocksCommandForOperation,e);if(!l(e.destination))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsDestination,e);if(!d(e.proxy))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsProxy,e);if(c(e.proxy,e),e.timeout&&!u(e.timeout))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsTimeout,e);if(e.existing_socket&&!(e.existing_socket instanceof o.Duplex))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsExistingSocket,e)},t.validateSocksClientChainOptions=function(e){if("connect"!==e.command)throw new i.SocksClientError(r.ERRORS.InvalidSocksCommandChain,e);if(!l(e.destination))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsDestination,e);if(!(e.proxies&&Array.isArray(e.proxies)&&e.proxies.length>=2))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsProxiesLength,e);if(e.proxies.forEach(t=>{if(!d(t))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsProxy,e);c(t,e)}),e.timeout&&!u(e.timeout))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsTimeout,e)},t.ipv4ToInt32=function(e){return new s.Address4(e).toArray().reduce((e,t)=>(e<<8)+t,0)>>>0},t.int32ToIpv4=function(e){return[e>>>24&255,e>>>16&255,e>>>8&255,255&e].join(".")},t.ipToBuffer=function(e){if(a.isIPv4(e)){const t=new s.Address4(e);return Buffer.from(t.toArray())}if(a.isIPv6(e)){const t=new s.Address6(e);return Buffer.from(t.canonicalForm().split(":").map(e=>e.padStart(4,"0")).join(""),"hex")}throw new Error("Invalid IP address format")}},7136(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.TrackingEngine=void 0;const a=s(n(7562)),c=n(1554),l=n(441),d=n(397),u=n(6751),p=n(6687),{systemManager:h}=a.default;t.TrackingEngine=class{topology;state;alertManager;config;console;correlator;spatialReasoning;listeners=new Map;pendingTimers=new Map;lostCheckInterval=null;objectLastAlertTime=new Map;onTopologyChange;lastLlmCallTime=0;llmDebounceTimer=null;observedTransits=new Map;connectionSuggestions=new Map;MIN_OBSERVATIONS_FOR_SUGGESTION=3;trainingSession=null;trainingConfig=d.DEFAULT_TRAINING_CONFIG;onTrainingStatusUpdate;constructor(e,t,n,i,r){this.topology=e,this.state=t,this.alertManager=n,this.config=i,this.console=r,this.correlator=new u.ObjectCorrelator(e,i);const o={enableLlm:i.useLlmDescriptions,enableLandmarkLearning:i.enableLandmarkLearning??!0,landmarkConfidenceThreshold:i.landmarkConfidenceThreshold??.7,contextCacheTtl:6e4};this.spatialReasoning=new p.SpatialReasoningEngine(o,r),this.spatialReasoning.updateTopology(e)}setTopologyChangeCallback(e){this.onTopologyChange=e}async startTracking(){this.console.log("Starting tracking engine..."),await this.stopTracking();for(const e of this.topology.cameras)try{const t=h.getDeviceById(e.deviceId);if(!t){this.console.warn(`Camera not found: ${e.deviceId} (${e.name})`);continue}if(!t.interfaces?.includes(a.ScryptedInterface.ObjectDetector)){this.console.warn(`Camera ${e.name} does not support object detection`);continue}const n=t.listen(a.ScryptedInterface.ObjectDetector,(t,n,i)=>{this.handleDetection(e.deviceId,e.name,i)});this.listeners.set(e.deviceId,n),this.console.log(`Listening to camera: ${e.name}`)}catch(t){this.console.error(`Failed to subscribe to camera ${e.name}:`,t)}this.lostCheckInterval=setInterval(()=>{this.checkForLostObjects()},3e4),this.console.log(`Tracking engine started with ${this.listeners.size} cameras`)}async stopTracking(){for(const[e,t]of this.listeners.entries())try{t.removeListener()}catch(t){this.console.error(`Failed to remove listener for ${e}:`,t)}this.listeners.clear();for(const e of this.pendingTimers.values())clearTimeout(e);this.pendingTimers.clear(),this.lostCheckInterval&&(clearInterval(this.lostCheckInterval),this.lostCheckInterval=null),this.console.log("Tracking engine stopped")}async handleDetection(e,t,n){if(!n.detections||0===n.detections.length)return;const i=(0,c.findCamera)(this.topology,e);if(!i)return;const r=n.timestamp||Date.now();for(const o of n.detections){if(o.score<.5)continue;if(this.isTrainingActive()&&"person"===o.className&&this.recordTrainerDetection(e,o,o.score),i.trackClasses.length>0&&!i.trackClasses.includes(o.className))continue;const s={detection:o,cameraId:e,cameraName:t,timestamp:r,confidence:o.score,embedding:o.embedding,detectionId:n.detectionId,position:o.boundingBox?{x:(o.boundingBox[0]+o.boundingBox[2]/2)/100,y:(o.boundingBox[1]+o.boundingBox[3]/2)/100}:void 0};await this.processSighting(s,i.isEntryPoint,i.isExitPoint)}}passesLoiteringThreshold(e){return e.lastSeen-e.firstSeen>=this.config.loiteringThreshold}isInAlertCooldown(e){const t=this.objectLastAlertTime.get(e);return!!t&&Date.now()-t<this.config.objectAlertCooldown}recordAlertTime(e){this.objectLastAlertTime.set(e,Date.now())}isLlmCallAllowed(){const e=this.config.llmDebounceInterval||0;if(e<=0)return!0;return Date.now()-this.lastLlmCallTime>=e}recordLlmCall(){this.lastLlmCallTime=Date.now()}async getSpatialDescription(e,t,n,i,r){const o=this.config.llmFallbackEnabled??!0,s=this.config.llmFallbackTimeout??3e3;try{if(!this.isLlmCallAllowed())return this.console.log("LLM rate-limited, using basic notification"),null;let c,l;if(this.config.useLlmDescriptions){const e=h.getDeviceById(r);e?.interfaces?.includes(a.ScryptedInterface.Camera)&&(c=await e.takePicture())}if(this.recordLlmCall(),o&&c){const r=new Promise((e,t)=>{setTimeout(()=>t(new Error("LLM timeout")),s)}),o=this.spatialReasoning.generateMovementDescription(e,t,n,i,c);try{l=await Promise.race([o,r])}catch(e){return this.console.log("LLM timed out, using basic notification"),null}}else l=await this.spatialReasoning.generateMovementDescription(e,t,n,i,c);return this.config.enableLandmarkLearning&&c&&this.tryLearnLandmark(r,c,e.className),l}catch(e){return this.console.warn("Spatial reasoning failed:",e),null}}async tryLearnLandmark(e,t,n){try{const i={x:50,y:50},r=await this.spatialReasoning.suggestLandmark(e,t,n,i);r&&this.console.log(`AI suggested landmark: ${r.landmark.name} (${r.landmark.type}, confidence: ${r.landmark.aiConfidence?.toFixed(2)})`)}catch(e){}}async processSighting(e,t,n){const i=await this.correlateDetection(e);if(i){const t=i.trackedObject,r=(0,l.getLastSighting)(t);if(r&&r.cameraId!==e.cameraId){const n=e.timestamp-r.timestamp;if(this.state.addJourney(t.globalId,{fromCameraId:r.cameraId,fromCameraName:r.cameraName,toCameraId:e.cameraId,toCameraName:e.cameraName,exitTime:r.timestamp,entryTime:e.timestamp,transitDuration:n,correlationConfidence:i.confidence}),this.recordObservedTransit(r.cameraId,e.cameraId,n),this.console.log(`Object ${t.globalId.slice(0,8)} transited: ${r.cameraName} → ${e.cameraName} (confidence: ${(100*i.confidence).toFixed(0)}%)`),this.passesLoiteringThreshold(t)&&!this.isInAlertCooldown(t.globalId)){const i=await this.getSpatialDescription(t,r.cameraId,e.cameraId,n,e.cameraId);await this.alertManager.checkAndAlert("movement",t,{fromCameraId:r.cameraId,fromCameraName:r.cameraName,toCameraId:e.cameraId,toCameraName:e.cameraName,transitTime:n,objectClass:e.detection.className,objectLabel:i?.description||e.detection.label,detectionId:e.detectionId,pathDescription:i?.pathDescription,involvedLandmarks:i?.involvedLandmarks?.map(e=>e.name),usedLlm:i?.usedLlm}),this.recordAlertTime(t.globalId)}}this.state.addSighting(t.globalId,e);const o=this.pendingTimers.get(t.globalId);o&&(clearTimeout(o),this.pendingTimers.delete(t.globalId)),this.state.reactivate(t.globalId),n&&this.isLeavingFrame(e)&&this.handlePotentialExit(t,e)}else{const n=this.state.generateId();this.state.createObject(n,e,t);this.console.log(`New ${e.detection.className} detected on ${e.cameraName} (ID: ${n.slice(0,8)})`),this.scheduleLoiteringAlert(n,e,t)}}scheduleLoiteringAlert(e,t,n){setTimeout(async()=>{const i=this.state.getObject(e);if(!i||"active"!==i.state)return;if(this.isInAlertCooldown(e))return;let r;if(this.console.log(`[Entry Alert] useLlmDescriptions=${this.config.useLlmDescriptions}`),this.config.useLlmDescriptions)try{const e=h.getDeviceById(t.cameraId);this.console.log(`[Entry Alert] Camera ${t.cameraId} has Camera interface: ${e?.interfaces?.includes(a.ScryptedInterface.Camera)}`),e?.interfaces?.includes(a.ScryptedInterface.Camera)&&(r=await e.takePicture(),this.console.log(`[Entry Alert] Got snapshot: ${!!r}`))}catch(e){this.console.warn("[Entry Alert] Failed to get snapshot:",e)}this.console.log(`[Entry Alert] Calling generateEntryDescription with mediaObject=${!!r}`);const o=await this.spatialReasoning.generateEntryDescription(i,t.cameraId,r);this.console.log(`[Entry Alert] Got description: "${o.description.substring(0,60)}...", usedLlm=${o.usedLlm}`),n?await this.alertManager.checkAndAlert("property_entry",i,{cameraId:t.cameraId,cameraName:t.cameraName,objectClass:t.detection.className,objectLabel:o.description,detectionId:t.detectionId,involvedLandmarks:o.involvedLandmarks?.map(e=>e.name),usedLlm:o.usedLlm}):await this.alertManager.checkAndAlert("movement",i,{cameraId:t.cameraId,cameraName:t.cameraName,toCameraId:t.cameraId,toCameraName:t.cameraName,objectClass:t.detection.className,objectLabel:o.description,detectionId:t.detectionId,involvedLandmarks:o.involvedLandmarks?.map(e=>e.name),usedLlm:o.usedLlm}),this.recordAlertTime(e)},this.config.loiteringThreshold)}async correlateDetection(e){const t=this.state.getActiveObjects();if(0===t.length)return null;for(const n of t){const t=(0,l.getLastSighting)(n);if(t&&t.cameraId===e.cameraId&&t.detection.id===e.detection.id)return{trackedObject:n,newSighting:e,confidence:1,factors:{timing:1,visual:1,spatial:1,class:1}}}return await this.correlator.findBestMatch(e,t)}isLeavingFrame(e){if(!e.position)return!1;const t=.1;return e.position.x<t||e.position.x>.9||e.position.y<t||e.position.y>.9}handlePotentialExit(e,t){this.state.markPending(e.globalId);const n=setTimeout(async()=>{const n=this.state.getObject(e.globalId);if(n&&"pending"===n.state){let i;if(this.state.markExited(e.globalId,t.cameraId,t.cameraName),this.console.log(`[Exit Alert] useLlmDescriptions=${this.config.useLlmDescriptions}`),this.config.useLlmDescriptions)try{const e=h.getDeviceById(t.cameraId);this.console.log(`[Exit Alert] Camera ${t.cameraId} has Camera interface: ${e?.interfaces?.includes(a.ScryptedInterface.Camera)}`),e?.interfaces?.includes(a.ScryptedInterface.Camera)&&(i=await e.takePicture(),this.console.log(`[Exit Alert] Got snapshot: ${!!i}`))}catch(e){this.console.warn("[Exit Alert] Failed to get snapshot:",e)}this.console.log(`[Exit Alert] Calling generateExitDescription with mediaObject=${!!i}`);const r=await this.spatialReasoning.generateExitDescription(n,t.cameraId,i);this.console.log(`[Exit Alert] Object ${e.globalId.slice(0,8)} exited: "${r.description.substring(0,60)}...", usedLlm=${r.usedLlm}`),await this.alertManager.checkAndAlert("property_exit",n,{cameraId:t.cameraId,cameraName:t.cameraName,objectClass:n.className,objectLabel:r.description,involvedLandmarks:r.involvedLandmarks?.map(e=>e.name),usedLlm:r.usedLlm})}this.pendingTimers.delete(e.globalId)},this.config.correlationWindow);this.pendingTimers.set(e.globalId,n)}checkForLostObjects(){const e=Date.now(),t=this.state.getActiveObjects();for(const n of t){const t=e-n.lastSeen;t>this.config.lostTimeout&&(this.state.markLost(n.globalId),this.console.log(`Object ${n.globalId.slice(0,8)} marked as lost (not seen for ${Math.round(t/1e3)}s)`),this.alertManager.checkAndAlert("lost_tracking",n,{objectClass:n.className,objectLabel:n.label}))}}updateTopology(e){this.topology=e,this.correlator=new u.ObjectCorrelator(e,this.config),this.spatialReasoning.updateTopology(e)}getPendingLandmarkSuggestions(){return this.spatialReasoning.getPendingSuggestions()}acceptLandmarkSuggestion(e){const t=this.spatialReasoning.acceptSuggestion(e);return t&&this.topology&&(this.topology.landmarks||(this.topology.landmarks=[]),this.topology.landmarks.push(t),this.onTopologyChange&&this.onTopologyChange(this.topology)),t}rejectLandmarkSuggestion(e){return this.spatialReasoning.rejectSuggestion(e)}getLandmarkTemplates(){return this.spatialReasoning.getLandmarkTemplates()}getSpatialReasoningEngine(){return this.spatialReasoning}getTopology(){return this.topology}getTrackedObjects(){return this.state.getAllObjects()}getTrackedObject(e){return this.state.getObject(e)}recordObservedTransit(e,t,n){if(!this.config.enableTransitTimeLearning)return;const i=`${e}->${t}`,r={fromCameraId:e,toCameraId:t,transitTime:n,timestamp:Date.now()};this.observedTransits.has(i)||this.observedTransits.set(i,[]);const o=this.observedTransits.get(i);o.push(r),o.length>100&&o.shift();const s=(0,c.findConnection)(this.topology,e,t);s?this.maybeUpdateConnectionTransitTime(s,o):this.config.enableConnectionSuggestions&&this.maybeCreateConnectionSuggestion(e,t,o)}maybeUpdateConnectionTransitTime(e,t){if(t.length<5)return;const n=t.map(e=>e.transitTime).sort((e,t)=>e-t),i=n[Math.floor(.1*n.length)],r=n[Math.floor(.5*n.length)],o=n[Math.floor(.9*n.length)],s=e.transitTime.typical;Math.abs(r-s)/s>.2&&t.length>=10&&(this.console.log(`Updating transit time for ${e.name}: ${Math.round(s/1e3)}s → ${Math.round(r/1e3)}s (based on ${t.length} observations)`),e.transitTime={min:i,typical:r,max:o},this.onTopologyChange&&this.onTopologyChange(this.topology))}maybeCreateConnectionSuggestion(e,t,n){if(n.length<this.MIN_OBSERVATIONS_FOR_SUGGESTION)return;const i=(0,c.findCamera)(this.topology,e),r=(0,c.findCamera)(this.topology,t);if(!i||!r)return;const o=`${e}->${t}`,s=n.map(e=>e.transitTime).sort((e,t)=>e-t),a=s[Math.floor(.1*s.length)]||s[0],l=s[Math.floor(.5*s.length)]||s[0],d=s[Math.floor(.9*s.length)]||s[s.length-1],u=s.reduce((e,t)=>e+t,0)/s.length,p=s.reduce((e,t)=>e+Math.pow(t-u,2),0)/s.length,h=Math.sqrt(p)/u,f=.6*Math.min(n.length/10,1)+.4*Math.max(0,1-h),g={id:`suggest_${o}`,fromCameraId:e,fromCameraName:i.name,toCameraId:t,toCameraName:r.name,observedTransits:n.slice(-10),suggestedTransitTime:{min:a,typical:l,max:d},confidence:f,timestamp:Date.now()};this.connectionSuggestions.set(o,g),n.length===this.MIN_OBSERVATIONS_FOR_SUGGESTION&&this.console.log(`New connection suggested: ${i.name} → ${r.name} (typical: ${Math.round(l/1e3)}s, confidence: ${Math.round(100*f)}%)`)}getConnectionSuggestions(){return Array.from(this.connectionSuggestions.values()).filter(e=>e.confidence>=.5).sort((e,t)=>t.confidence-e.confidence)}acceptConnectionSuggestion(e){const t=e.replace("suggest_",""),n=this.connectionSuggestions.get(t);if(!n)return null;const i=(0,c.findCamera)(this.topology,n.fromCameraId),r=(0,c.findCamera)(this.topology,n.toCameraId);if(!i||!r)return null;const o={id:`conn-${Date.now()}`,fromCameraId:n.fromCameraId,toCameraId:n.toCameraId,name:`${i.name} to ${r.name}`,exitZone:[],entryZone:[],transitTime:n.suggestedTransitTime,bidirectional:!0};return this.topology.connections.push(o),this.connectionSuggestions.delete(t),this.onTopologyChange&&this.onTopologyChange(this.topology),this.console.log(`Connection accepted: ${o.name}`),o}rejectConnectionSuggestion(e){const t=e.replace("suggest_","");return!!this.connectionSuggestions.has(t)&&(this.connectionSuggestions.delete(t),this.observedTransits.delete(t),!0)}getLiveTrackingState(){return{objects:this.state.getActiveObjects().map(e=>{const t=(0,l.getLastSighting)(e),n=t?(0,c.findCamera)(this.topology,t.cameraId):null;return{globalId:e.globalId,className:e.className,label:e.label,lastCameraId:t?.cameraId||"",lastCameraName:t?.cameraName||"",lastSeen:e.lastSeen,state:e.state,cameraPosition:n?.floorPlanPosition}}),timestamp:Date.now()}}getJourneyPath(e){const t=this.state.getObject(e);if(!t)return null;const n=t.journey.map(e=>{const t=(0,c.findCamera)(this.topology,e.fromCameraId),n=(0,c.findCamera)(this.topology,e.toCameraId);return{fromCamera:{id:e.fromCameraId,name:e.fromCameraName,position:t?.floorPlanPosition},toCamera:{id:e.toCameraId,name:e.toCameraName,position:n?.floorPlanPosition},transitTime:e.transitDuration,timestamp:e.entryTime}}),i=(0,l.getLastSighting)(t);let r;if(i){const e=(0,c.findCamera)(this.topology,i.cameraId);r={cameraId:i.cameraId,cameraName:i.cameraName,position:e?.floorPlanPosition}}return{segments:n,currentLocation:r}}setTrainingStatusCallback(e){this.onTrainingStatusUpdate=e}getTrainingSession(){return this.trainingSession}isTrainingActive(){return null!==this.trainingSession&&"active"===this.trainingSession.state}startTrainingSession(e,t){return this.trainingSession&&"active"===this.trainingSession.state&&this.endTrainingSession(),t&&(this.trainingConfig={...d.DEFAULT_TRAINING_CONFIG,...t}),this.trainingSession=(0,d.createTrainingSession)(e),this.trainingSession.state="active",this.console.log(`Training session started: ${this.trainingSession.id}`),this.emitTrainingStatus(),this.trainingSession}pauseTrainingSession(){return!(!this.trainingSession||"active"!==this.trainingSession.state)&&(this.trainingSession.state="paused",this.trainingSession.updatedAt=Date.now(),this.console.log("Training session paused"),this.emitTrainingStatus(),!0)}resumeTrainingSession(){return!(!this.trainingSession||"paused"!==this.trainingSession.state)&&(this.trainingSession.state="active",this.trainingSession.updatedAt=Date.now(),this.console.log("Training session resumed"),this.emitTrainingStatus(),!0)}endTrainingSession(){if(!this.trainingSession)return null;this.trainingSession.state="completed",this.trainingSession.completedAt=Date.now(),this.trainingSession.updatedAt=Date.now(),this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.console.log(`Training session completed: ${this.trainingSession.stats.camerasVisited} cameras, ${this.trainingSession.stats.transitsRecorded} transits, ${this.trainingSession.stats.landmarksMarked} landmarks`);const e=this.trainingSession;return this.emitTrainingStatus(),e}recordTrainerDetection(e,t,n){if(!this.trainingSession||"active"!==this.trainingSession.state)return;if("person"!==t.className)return;if(n<this.trainingConfig.minDetectionConfidence)return;const i=(0,c.findCamera)(this.topology,e),r=i?.name||e,o=Date.now();if(this.trainingSession.currentCameraId===e){const i=this.trainingSession.visits.find(t=>t.cameraId===e&&null===t.departedAt);i&&(i.detectionConfidence=Math.max(i.detectionConfidence,n),t.boundingBox&&(i.boundingBox=t.boundingBox))}else{if(this.trainingSession.currentCameraId&&this.trainingSession.transitStartTime){const t=o-this.trainingSession.transitStartTime,n=this.trainingSession.previousCameraId||this.trainingSession.currentCameraId,i=(0,c.findCamera)(this.topology,n),s=this.trainingSession.visits.find(e=>e.cameraId===n&&null===e.departedAt);s&&(s.departedAt=this.trainingSession.transitStartTime);const a=this.checkTrainingOverlap(n,e,o),l={id:`transit-${o}`,fromCameraId:n,toCameraId:e,startTime:this.trainingSession.transitStartTime,endTime:o,transitSeconds:Math.round(t/1e3),hasOverlap:a};this.trainingSession.transits.push(l),this.console.log(`Training transit: ${i?.name||n} → ${r} (${l.transitSeconds}s${a?", overlap detected":""})`),a&&this.trainingConfig.autoDetectOverlaps&&this.recordTrainingOverlap(n,e)}const s={cameraId:e,cameraName:r,arrivedAt:o,departedAt:null,trainerEmbedding:t.embedding,detectionConfidence:n,boundingBox:t.boundingBox,floorPlanPosition:i?.floorPlanPosition};this.trainingSession.visits.push(s),this.trainingSession.previousCameraId=this.trainingSession.currentCameraId,this.trainingSession.currentCameraId=e,this.trainingSession.transitStartTime=o,!this.trainingSession.trainerEmbedding&&t.embedding&&(this.trainingSession.trainerEmbedding=t.embedding)}this.trainingSession.updatedAt=o,this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.emitTrainingStatus()}checkTrainingOverlap(e,t,n){const i=this.trainingSession?.visits.find(t=>t.cameraId===e&&(null===t.departedAt||t.departedAt>n-5e3)),r=this.trainingSession?.visits.find(e=>e.cameraId===t&&e.arrivedAt<=n&&e.arrivedAt>=n-5e3);return!(!i||!r)}recordTrainingOverlap(e,t){if(!this.trainingSession)return;if(this.trainingSession.overlaps.find(n=>n.camera1Id===e&&n.camera2Id===t||n.camera1Id===t&&n.camera2Id===e))return;const n=(0,c.findCamera)(this.topology,e),i=(0,c.findCamera)(this.topology,t);let r={x:50,y:50};n?.floorPlanPosition&&i?.floorPlanPosition&&(r={x:(n.floorPlanPosition.x+i.floorPlanPosition.x)/2,y:(n.floorPlanPosition.y+i.floorPlanPosition.y)/2});const o={id:`overlap-${Date.now()}`,camera1Id:e,camera2Id:t,position:r,radius:30,markedAt:Date.now()};this.trainingSession.overlaps.push(o),this.console.log(`Camera overlap detected: ${n?.name} ↔ ${i?.name}`)}markTrainingLandmark(e){if(!this.trainingSession)return null;const t={...e,id:`landmark-${Date.now()}`,markedAt:Date.now()};return this.trainingSession.landmarks.push(t),this.trainingSession.updatedAt=Date.now(),this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.console.log(`Landmark marked: ${t.name} (${t.type})`),this.emitTrainingStatus(),t}markTrainingStructure(e){if(!this.trainingSession)return null;const t={...e,id:`structure-${Date.now()}`,markedAt:Date.now()};return this.trainingSession.structures.push(t),this.trainingSession.updatedAt=Date.now(),this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.console.log(`Structure marked: ${t.name} (${t.type})`),this.emitTrainingStatus(),t}confirmCameraPosition(e,t){if(!this.trainingSession)return!1;const n=this.trainingSession.visits.find(t=>t.cameraId===e);n&&(n.floorPlanPosition=t);const i=(0,c.findCamera)(this.topology,e);return i&&(i.floorPlanPosition=t,this.onTopologyChange&&this.onTopologyChange(this.topology)),this.trainingSession.updatedAt=Date.now(),this.emitTrainingStatus(),!0}getTrainingStatus(){if(!this.trainingSession)return null;const e=this.trainingSession.currentCameraId?(0,c.findCamera)(this.topology,this.trainingSession.currentCameraId):null,t=this.trainingSession.previousCameraId?(0,c.findCamera)(this.topology,this.trainingSession.previousCameraId):null,n=[],i=new Set(this.trainingSession.visits.map(e=>e.cameraId)),r=this.topology.cameras.filter(e=>!i.has(e.deviceId));if(r.length>0){const t=(e?(0,c.findConnectionsFrom)(this.topology,e.deviceId):[]).map(e=>e.toCameraId).filter(e=>!i.has(e));if(t.length>0){const e=(0,c.findCamera)(this.topology,t[0]);e&&n.push(`Walk to ${e.name}`)}else n.push(`${r.length} cameras not yet visited`)}this.trainingSession.visits.length>=2&&0===this.trainingSession.landmarks.length&&n.push("Consider marking some landmarks"),i.size>=this.topology.cameras.length&&n.push("All cameras visited! You can end training.");return{sessionId:this.trainingSession.id,state:this.trainingSession.state,currentCamera:e?{id:e.deviceId,name:e.name,detectedAt:this.trainingSession.visits.find(t=>t.cameraId===e.deviceId&&!t.departedAt)?.arrivedAt||Date.now(),confidence:this.trainingSession.visits.find(t=>t.cameraId===e.deviceId&&!t.departedAt)?.detectionConfidence||0}:void 0,activeTransit:this.trainingSession.transitStartTime&&t?{fromCameraId:t.deviceId,fromCameraName:t.name,startTime:this.trainingSession.transitStartTime,elapsedSeconds:Math.round((Date.now()-this.trainingSession.transitStartTime)/1e3)}:void 0,stats:this.trainingSession.stats,suggestions:n}}emitTrainingStatus(){if(this.onTrainingStatusUpdate){const e=this.getTrainingStatus();e&&this.onTrainingStatusUpdate(e)}}applyTrainingToTopology(){const e={camerasAdded:0,connectionsCreated:0,connectionsUpdated:0,landmarksAdded:0,zonesCreated:0,warnings:[],success:!1};if(!this.trainingSession)return e.warnings.push("No training session to apply"),e;try{for(const t of this.trainingSession.visits){const n=(0,c.findCamera)(this.topology,t.cameraId);n&&t.floorPlanPosition&&(n.floorPlanPosition||(n.floorPlanPosition=t.floorPlanPosition,e.camerasAdded++))}for(const t of this.trainingSession.transits){const n=(0,c.findConnection)(this.topology,t.fromCameraId,t.toCameraId);if(n){const i=1e3*t.transitSeconds;n.transitTime={min:Math.min(n.transitTime.min,.7*i),typical:i,max:Math.max(n.transitTime.max,1.3*i)},e.connectionsUpdated++}else{const n=(0,c.findCamera)(this.topology,t.fromCameraId),i=(0,c.findCamera)(this.topology,t.toCameraId);if(n&&i){const r=1e3*t.transitSeconds,o={id:`conn-training-${Date.now()}-${e.connectionsCreated}`,fromCameraId:t.fromCameraId,toCameraId:t.toCameraId,name:`${n.name} to ${i.name}`,exitZone:[],entryZone:[],transitTime:{min:.7*r,typical:r,max:1.3*r},bidirectional:!0};this.topology.connections.push(o),e.connectionsCreated++}}}for(const t of this.trainingSession.landmarks){const n={mailbox:"feature",garage:"structure",shed:"structure",tree:"feature",gate:"access",door:"access",driveway:"access",pathway:"access",garden:"feature",pool:"feature",deck:"structure",patio:"structure",other:"feature"},i={id:t.id,name:t.name,type:n[t.type]||"feature",position:t.position,visibleFromCameras:t.visibleFromCameras.length>0?t.visibleFromCameras:void 0,description:t.description};this.topology.landmarks||(this.topology.landmarks=[]),this.topology.landmarks.push(i),e.landmarksAdded++}for(const t of this.trainingSession.overlaps){const n=(0,c.findCamera)(this.topology,t.camera1Id),i=(0,c.findCamera)(this.topology,t.camera2Id);if(n&&i){const r=`${n.name}/${i.name} Overlap`,o=this.topology.globalZones?.find(e=>e.name===r);if(!o){this.topology.globalZones||(this.topology.globalZones=[]);const n=[{cameraId:t.camera1Id,zone:[]},{cameraId:t.camera2Id,zone:[]}];this.topology.globalZones.push({id:`zone-overlap-${t.id}`,name:r,type:"dwell",cameraZones:n}),e.zonesCreated++}}}this.onTopologyChange&&this.onTopologyChange(this.topology),e.success=!0,this.console.log(`Training applied: ${e.connectionsCreated} connections created, ${e.connectionsUpdated} updated, ${e.landmarksAdded} landmarks added`)}catch(t){e.warnings.push(`Error applying training: ${t}`)}return e}clearTrainingSession(){this.trainingSession=null,this.emitTrainingStatus()}}},7279(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MqttPublisher=void 0;const r=i(n(9372));t.MqttPublisher=class{client=null;config;console;connected=!1;reconnectTimer=null;constructor(e,t){this.config=e,this.console=t}async connect(){if(this.client)return;const e={clientId:`scrypted-spatial-awareness-${Date.now()}`,clean:!0,connectTimeout:1e4,reconnectPeriod:5e3};this.config.username&&(e.username=this.config.username,e.password=this.config.password);try{this.client=r.default.connect(this.config.broker,e),this.client.on("connect",()=>{this.connected=!0,this.console.log(`MQTT connected to ${this.config.broker}`),this.publishDiscovery()}),this.client.on("error",e=>{this.console.error("MQTT error:",e)}),this.client.on("close",()=>{this.connected=!1,this.console.log("MQTT connection closed")}),this.client.on("offline",()=>{this.connected=!1,this.console.log("MQTT offline")})}catch(e){this.console.error("Failed to connect to MQTT:",e)}}disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.client&&(this.client.end(),this.client=null,this.connected=!1)}publishDiscovery(){if(!this.client||!this.connected)return;const e=this.config.baseTopic,t={name:"Property Occupancy",unique_id:"spatial_awareness_occupancy",state_topic:`${e}/occupancy/state`,device_class:"occupancy",payload_on:"ON",payload_off:"OFF",device:{identifiers:["spatial_awareness"],name:"Spatial Awareness",model:"Cross-Camera Tracker",manufacturer:"Scrypted"}};this.client.publish("homeassistant/binary_sensor/spatial_awareness_occupancy/config",JSON.stringify(t),{retain:!0});const n={name:"Active Tracked Objects",unique_id:"spatial_awareness_count",state_topic:`${e}/count/state`,icon:"mdi:account-multiple",device:{identifiers:["spatial_awareness"]}};this.client.publish("homeassistant/sensor/spatial_awareness_count/config",JSON.stringify(n),{retain:!0});const i={name:"People on Property",unique_id:"spatial_awareness_person_count",state_topic:`${e}/person_count/state`,icon:"mdi:account-group",device:{identifiers:["spatial_awareness"]}};this.client.publish("homeassistant/sensor/spatial_awareness_person_count/config",JSON.stringify(i),{retain:!0});const r={name:"Vehicles on Property",unique_id:"spatial_awareness_vehicle_count",state_topic:`${e}/vehicle_count/state`,icon:"mdi:car",device:{identifiers:["spatial_awareness"]}};this.client.publish("homeassistant/sensor/spatial_awareness_vehicle_count/config",JSON.stringify(r),{retain:!0}),this.console.log("MQTT discovery published")}publishState(e){if(!this.client||!this.connected)return;const t=this.config.baseTopic,n=e.filter(e=>"active"===e.state||"pending"===e.state),i=n.length>0;this.client.publish(`${t}/occupancy/state`,i?"ON":"OFF",{retain:!0}),this.client.publish(`${t}/count/state`,String(n.length),{retain:!0});const r=n.filter(e=>"person"===e.className).length;this.client.publish(`${t}/person_count/state`,String(r),{retain:!0});const o=n.filter(e=>["car","vehicle","truck"].includes(e.className)).length;this.client.publish(`${t}/vehicle_count/state`,String(o),{retain:!0});const s={timestamp:Date.now(),occupied:i,activeCount:n.length,personCount:r,vehicleCount:o,objects:n.map(e=>({id:e.globalId,class:e.className,label:e.label,cameras:e.activeOnCameras,firstSeen:e.firstSeen,lastSeen:e.lastSeen,state:e.state}))};this.client.publish(`${t}/state`,JSON.stringify(s),{retain:!0})}publishAlert(e){if(!this.client||!this.connected)return;const t=this.config.baseTopic,n={id:e.id,type:e.type,severity:e.severity,message:e.message,timestamp:e.timestamp,objectId:e.trackedObjectId,details:e.details};this.client.publish(`${t}/alerts`,JSON.stringify(n)),this.client.publish(`${t}/alerts/${e.type}`,JSON.stringify(n))}publishEntry(e,t){if(!this.client||!this.connected)return;const n=this.config.baseTopic,i={event:"entry",timestamp:Date.now(),object:{id:e.globalId,class:e.className,label:e.label},camera:t};this.client.publish(`${n}/events/entry`,JSON.stringify(i))}publishExit(e,t){if(!this.client||!this.connected)return;const n=this.config.baseTopic,i={event:"exit",timestamp:Date.now(),object:{id:e.globalId,class:e.className,label:e.label,dwellTime:e.lastSeen-e.firstSeen},camera:t};this.client.publish(`${n}/events/exit`,JSON.stringify(i))}publishTransition(e,t,n){if(!this.client||!this.connected)return;const i=this.config.baseTopic,r={event:"transition",timestamp:Date.now(),object:{id:e.globalId,class:e.className,label:e.label},from:t,to:n};this.client.publish(`${i}/events/transition`,JSON.stringify(r))}isConnected(){return this.connected}}},7382(e,t,n){"use strict";const{ObjectSetPrototypeOf:i,Symbol:r}=n(4134);e.exports=l;const{ERR_METHOD_NOT_IMPLEMENTED:o}=n(6371).codes,s=n(3370),{getHighWaterMark:a}=n(5291);i(l.prototype,s.prototype),i(l,s);const c=r("kCallback");function l(e){if(!(this instanceof l))return new l(e);const t=e?a(this,e,"readableHighWaterMark",!0):null;0===t&&(e={...e,highWaterMark:null,readableHighWaterMark:t,writableHighWaterMark:e.writableHighWaterMark||0}),s.call(this,e),this._readableState.sync=!1,this[c]=null,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",u)}function d(e){"function"!=typeof this._flush||this.destroyed?(this.push(null),e&&e()):this._flush((t,n)=>{t?e?e(t):this.destroy(t):(null!=n&&this.push(n),this.push(null),e&&e())})}function u(){this._final!==d&&d.call(this)}l.prototype._final=d,l.prototype._transform=function(e,t,n){throw new o("_transform()")},l.prototype._write=function(e,t,n){const i=this._readableState,r=this._writableState,o=i.length;this._transform(e,t,(e,t)=>{e?n(e):(null!=t&&this.push(t),r.ended||o===i.length||i.length<i.highWaterMark?n():this[c]=n)})},l.prototype._read=function(){if(this[c]){const e=this[c];this[c]=null,e()}}},7562(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||i(t,e,n)},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.sdk=t.MixinDeviceBase=t.ScryptedDeviceBase=void 0,r(n(4192),t);const s=o(n(9896)),a=n(4192);n(3339);class c extends a.DeviceBase{constructor(e){super(),this.nativeId=e}get storage(){return this._storage||(this._storage=t.sdk.deviceManager.getDeviceStorage(this.nativeId)),this._storage}get log(){return this._log||(this._log=t.sdk.deviceManager.getDeviceLogger(this.nativeId)),this._log}get console(){return this._console||(this._console=t.sdk.deviceManager.getDeviceConsole(this.nativeId)),this._console}async createMediaObject(e,n){return t.sdk.mediaManager.createMediaObject(e,n,{sourceId:this.id})}getMediaObjectConsole(e){return"string"!=typeof e.sourceId?this.console:t.sdk.deviceManager.getMixinConsole(e.sourceId,this.nativeId)}_lazyLoadDeviceState(){this._deviceState||(this.nativeId?this._deviceState=t.sdk.deviceManager.getDeviceState(this.nativeId):this._deviceState=t.sdk.deviceManager.getDeviceState())}onDeviceEvent(e,n){return t.sdk.deviceManager.onDeviceEvent(this.nativeId,e,n)}}t.ScryptedDeviceBase=c;class l extends a.DeviceBase{constructor(e){super(),this._listeners=new Set,this.mixinDevice=e.mixinDevice,this.mixinDeviceInterfaces=e.mixinDeviceInterfaces,this.mixinStorageSuffix=e.mixinStorageSuffix,this._deviceState=e.mixinDeviceState,this.nativeId=t.sdk.systemManager.getDeviceById(this.id).nativeId,this.mixinProviderNativeId=e.mixinProviderNativeId,this._deviceState.__rpcproxy_traps_all_properties&&"string"==typeof this._deviceState.id&&(this._deviceState=t.sdk.deviceManager.createDeviceState(this._deviceState.id,this._deviceState.setState))}get storage(){if(!this._storage){const e=this.mixinStorageSuffix,n=this.id+(e?":"+e:"");this._storage=t.sdk.deviceManager.getMixinStorage(n,this.mixinProviderNativeId)}return this._storage}get console(){return this._console||(t.sdk.deviceManager.getMixinConsole?this._console=t.sdk.deviceManager.getMixinConsole(this.id,this.mixinProviderNativeId):this._console=t.sdk.deviceManager.getDeviceConsole(this.mixinProviderNativeId)),this._console}async createMediaObject(e,n){return t.sdk.mediaManager.createMediaObject(e,n,{sourceId:this.id})}getMediaObjectConsole(e){return"string"!=typeof e.sourceId?this.console:t.sdk.deviceManager.getMixinConsole(e.sourceId,this.mixinProviderNativeId)}onDeviceEvent(e,n){return t.sdk.deviceManager.onMixinEvent(this.id,this,e,n)}_lazyLoadDeviceState(){}manageListener(e){this._listeners.add(e)}release(){for(const e of this._listeners)e.removeListener()}}t.MixinDeviceBase=l,function(){function e(e){return function(){return this._lazyLoadDeviceState(),this._deviceState?.[e]}}function t(e){return function(t){this._lazyLoadDeviceState(),this._deviceState?this._deviceState[e]=t:console.warn("device state is unavailable. the device must be discovered with deviceManager.onDeviceDiscovered or deviceManager.onDevicesChanged before the state can be set.")}}for(const n of Object.values(a.ScryptedInterfaceProperty))n!==a.ScryptedInterfaceProperty.nativeId&&(Object.defineProperty(c.prototype,n,{set:t(n),get:e(n)}),Object.defineProperty(l.prototype,n,{set:t(n),get:e(n)}))}(),t.sdk={};try{let e=!1;try{process.env.SCRYPTED_SDK_ES_MODULE||process.env.SCRYPTED_SDK_MODULE;const i=process.env.SCRYPTED_SDK_CJS_MODULE||process.env.SCRYPTED_SDK_MODULE;if(i)if("undefined"!=typeof require){const n=require(process.env.SCRYPTED_SDK_MODULE);Object.assign(t.sdk,n.getScryptedStatic()),e=!0}else{const r=n(3891)(i);Object.assign(t.sdk,r.getScryptedStatic()),e=!0}}catch(e){throw console.warn("failed to load sdk module",e),e}if(!e){let e;try{e=pluginRuntimeAPI}catch(e){}Object.assign(t.sdk,{log:deviceManager.getDeviceLogger(void 0),deviceManager,endpointManager,mediaManager,systemManager,pluginHostAPI,...e})}try{let e={...a.ScryptedInterfaceDescriptors};try{const t=JSON.parse(s.default.readFileSync("../sdk.json").toString()).interfaceDescriptors;t&&(e={...e,...t})}catch(e){console.warn("failed to load custom interface descriptors",e)}t.sdk.systemManager.setScryptedInterfaceDescriptors?.(a.TYPES_VERSION,e)?.catch(()=>{})}catch(e){}}catch(e){console.error("sdk initialization error, import @scrypted/types or use @scrypted/client instead",e)}t.default=t.sdk},7575(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(1725);class r{constructor(e){if(this.length=0,this._encoding="utf8",this._writeOffset=0,this._readOffset=0,r.isSmartBufferOptions(e))if(e.encoding&&(i.checkEncoding(e.encoding),this._encoding=e.encoding),e.size){if(!(i.isFiniteInteger(e.size)&&e.size>0))throw new Error(i.ERRORS.INVALID_SMARTBUFFER_SIZE);this._buff=Buffer.allocUnsafe(e.size)}else if(e.buff){if(!Buffer.isBuffer(e.buff))throw new Error(i.ERRORS.INVALID_SMARTBUFFER_BUFFER);this._buff=e.buff,this.length=e.buff.length}else this._buff=Buffer.allocUnsafe(4096);else{if("undefined"!=typeof e)throw new Error(i.ERRORS.INVALID_SMARTBUFFER_OBJECT);this._buff=Buffer.allocUnsafe(4096)}}static fromSize(e,t){return new this({size:e,encoding:t})}static fromBuffer(e,t){return new this({buff:e,encoding:t})}static fromOptions(e){return new this(e)}static isSmartBufferOptions(e){const t=e;return t&&(void 0!==t.encoding||void 0!==t.size||void 0!==t.buff)}readInt8(e){return this._readNumberValue(Buffer.prototype.readInt8,1,e)}readInt16BE(e){return this._readNumberValue(Buffer.prototype.readInt16BE,2,e)}readInt16LE(e){return this._readNumberValue(Buffer.prototype.readInt16LE,2,e)}readInt32BE(e){return this._readNumberValue(Buffer.prototype.readInt32BE,4,e)}readInt32LE(e){return this._readNumberValue(Buffer.prototype.readInt32LE,4,e)}readBigInt64BE(e){return i.bigIntAndBufferInt64Check("readBigInt64BE"),this._readNumberValue(Buffer.prototype.readBigInt64BE,8,e)}readBigInt64LE(e){return i.bigIntAndBufferInt64Check("readBigInt64LE"),this._readNumberValue(Buffer.prototype.readBigInt64LE,8,e)}writeInt8(e,t){return this._writeNumberValue(Buffer.prototype.writeInt8,1,e,t),this}insertInt8(e,t){return this._insertNumberValue(Buffer.prototype.writeInt8,1,e,t)}writeInt16BE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt16BE,2,e,t)}insertInt16BE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt16BE,2,e,t)}writeInt16LE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt16LE,2,e,t)}insertInt16LE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt16LE,2,e,t)}writeInt32BE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt32BE,4,e,t)}insertInt32BE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt32BE,4,e,t)}writeInt32LE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt32LE,4,e,t)}insertInt32LE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt32LE,4,e,t)}writeBigInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64BE"),this._writeNumberValue(Buffer.prototype.writeBigInt64BE,8,e,t)}insertBigInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64BE"),this._insertNumberValue(Buffer.prototype.writeBigInt64BE,8,e,t)}writeBigInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64LE"),this._writeNumberValue(Buffer.prototype.writeBigInt64LE,8,e,t)}insertBigInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64LE"),this._insertNumberValue(Buffer.prototype.writeBigInt64LE,8,e,t)}readUInt8(e){return this._readNumberValue(Buffer.prototype.readUInt8,1,e)}readUInt16BE(e){return this._readNumberValue(Buffer.prototype.readUInt16BE,2,e)}readUInt16LE(e){return this._readNumberValue(Buffer.prototype.readUInt16LE,2,e)}readUInt32BE(e){return this._readNumberValue(Buffer.prototype.readUInt32BE,4,e)}readUInt32LE(e){return this._readNumberValue(Buffer.prototype.readUInt32LE,4,e)}readBigUInt64BE(e){return i.bigIntAndBufferInt64Check("readBigUInt64BE"),this._readNumberValue(Buffer.prototype.readBigUInt64BE,8,e)}readBigUInt64LE(e){return i.bigIntAndBufferInt64Check("readBigUInt64LE"),this._readNumberValue(Buffer.prototype.readBigUInt64LE,8,e)}writeUInt8(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt8,1,e,t)}insertUInt8(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt8,1,e,t)}writeUInt16BE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt16BE,2,e,t)}insertUInt16BE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt16BE,2,e,t)}writeUInt16LE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt16LE,2,e,t)}insertUInt16LE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt16LE,2,e,t)}writeUInt32BE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt32BE,4,e,t)}insertUInt32BE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt32BE,4,e,t)}writeUInt32LE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt32LE,4,e,t)}insertUInt32LE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt32LE,4,e,t)}writeBigUInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64BE"),this._writeNumberValue(Buffer.prototype.writeBigUInt64BE,8,e,t)}insertBigUInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64BE"),this._insertNumberValue(Buffer.prototype.writeBigUInt64BE,8,e,t)}writeBigUInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64LE"),this._writeNumberValue(Buffer.prototype.writeBigUInt64LE,8,e,t)}insertBigUInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64LE"),this._insertNumberValue(Buffer.prototype.writeBigUInt64LE,8,e,t)}readFloatBE(e){return this._readNumberValue(Buffer.prototype.readFloatBE,4,e)}readFloatLE(e){return this._readNumberValue(Buffer.prototype.readFloatLE,4,e)}writeFloatBE(e,t){return this._writeNumberValue(Buffer.prototype.writeFloatBE,4,e,t)}insertFloatBE(e,t){return this._insertNumberValue(Buffer.prototype.writeFloatBE,4,e,t)}writeFloatLE(e,t){return this._writeNumberValue(Buffer.prototype.writeFloatLE,4,e,t)}insertFloatLE(e,t){return this._insertNumberValue(Buffer.prototype.writeFloatLE,4,e,t)}readDoubleBE(e){return this._readNumberValue(Buffer.prototype.readDoubleBE,8,e)}readDoubleLE(e){return this._readNumberValue(Buffer.prototype.readDoubleLE,8,e)}writeDoubleBE(e,t){return this._writeNumberValue(Buffer.prototype.writeDoubleBE,8,e,t)}insertDoubleBE(e,t){return this._insertNumberValue(Buffer.prototype.writeDoubleBE,8,e,t)}writeDoubleLE(e,t){return this._writeNumberValue(Buffer.prototype.writeDoubleLE,8,e,t)}insertDoubleLE(e,t){return this._insertNumberValue(Buffer.prototype.writeDoubleLE,8,e,t)}readString(e,t){let n;"number"==typeof e?(i.checkLengthValue(e),n=Math.min(e,this.length-this._readOffset)):(t=e,n=this.length-this._readOffset),"undefined"!=typeof t&&i.checkEncoding(t);const r=this._buff.slice(this._readOffset,this._readOffset+n).toString(t||this._encoding);return this._readOffset+=n,r}insertString(e,t,n){return i.checkOffsetValue(t),this._handleString(e,!0,t,n)}writeString(e,t,n){return this._handleString(e,!1,t,n)}readStringNT(e){"undefined"!=typeof e&&i.checkEncoding(e);let t=this.length;for(let e=this._readOffset;e<this.length;e++)if(0===this._buff[e]){t=e;break}const n=this._buff.slice(this._readOffset,t);return this._readOffset=t+1,n.toString(e||this._encoding)}insertStringNT(e,t,n){return i.checkOffsetValue(t),this.insertString(e,t,n),this.insertUInt8(0,t+e.length),this}writeStringNT(e,t,n){return this.writeString(e,t,n),this.writeUInt8(0,"number"==typeof t?t+e.length:this.writeOffset),this}readBuffer(e){"undefined"!=typeof e&&i.checkLengthValue(e);const t="number"==typeof e?e:this.length,n=Math.min(this.length,this._readOffset+t),r=this._buff.slice(this._readOffset,n);return this._readOffset=n,r}insertBuffer(e,t){return i.checkOffsetValue(t),this._handleBuffer(e,!0,t)}writeBuffer(e,t){return this._handleBuffer(e,!1,t)}readBufferNT(){let e=this.length;for(let t=this._readOffset;t<this.length;t++)if(0===this._buff[t]){e=t;break}const t=this._buff.slice(this._readOffset,e);return this._readOffset=e+1,t}insertBufferNT(e,t){return i.checkOffsetValue(t),this.insertBuffer(e,t),this.insertUInt8(0,t+e.length),this}writeBufferNT(e,t){return"undefined"!=typeof t&&i.checkOffsetValue(t),this.writeBuffer(e,t),this.writeUInt8(0,"number"==typeof t?t+e.length:this._writeOffset),this}clear(){return this._writeOffset=0,this._readOffset=0,this.length=0,this}remaining(){return this.length-this._readOffset}get readOffset(){return this._readOffset}set readOffset(e){i.checkOffsetValue(e),i.checkTargetOffset(e,this),this._readOffset=e}get writeOffset(){return this._writeOffset}set writeOffset(e){i.checkOffsetValue(e),i.checkTargetOffset(e,this),this._writeOffset=e}get encoding(){return this._encoding}set encoding(e){i.checkEncoding(e),this._encoding=e}get internalBuffer(){return this._buff}toBuffer(){return this._buff.slice(0,this.length)}toString(e){const t="string"==typeof e?e:this._encoding;return i.checkEncoding(t),this._buff.toString(t,0,this.length)}destroy(){return this.clear(),this}_handleString(e,t,n,r){let o=this._writeOffset,s=this._encoding;"number"==typeof n?o=n:"string"==typeof n&&(i.checkEncoding(n),s=n),"string"==typeof r&&(i.checkEncoding(r),s=r);const a=Buffer.byteLength(e,s);return t?this.ensureInsertable(a,o):this._ensureWriteable(a,o),this._buff.write(e,o,a,s),t?this._writeOffset+=a:"number"==typeof n?this._writeOffset=Math.max(this._writeOffset,o+a):this._writeOffset+=a,this}_handleBuffer(e,t,n){const i="number"==typeof n?n:this._writeOffset;return t?this.ensureInsertable(e.length,i):this._ensureWriteable(e.length,i),e.copy(this._buff,i),t?this._writeOffset+=e.length:"number"==typeof n?this._writeOffset=Math.max(this._writeOffset,i+e.length):this._writeOffset+=e.length,this}ensureReadable(e,t){let n=this._readOffset;if("undefined"!=typeof t&&(i.checkOffsetValue(t),n=t),n<0||n+e>this.length)throw new Error(i.ERRORS.INVALID_READ_BEYOND_BOUNDS)}ensureInsertable(e,t){i.checkOffsetValue(t),this._ensureCapacity(this.length+e),t<this.length&&this._buff.copy(this._buff,t+e,t,this._buff.length),t+e>this.length?this.length=t+e:this.length+=e}_ensureWriteable(e,t){const n="number"==typeof t?t:this._writeOffset;this._ensureCapacity(n+e),n+e>this.length&&(this.length=n+e)}_ensureCapacity(e){const t=this._buff.length;if(e>t){let n=this._buff,i=3*t/2+1;i<e&&(i=e),this._buff=Buffer.allocUnsafe(i),n.copy(this._buff,0,0,t)}}_readNumberValue(e,t,n){this.ensureReadable(t,n);const i=e.call(this._buff,"number"==typeof n?n:this._readOffset);return"undefined"==typeof n&&(this._readOffset+=t),i}_insertNumberValue(e,t,n,r){return i.checkOffsetValue(r),this.ensureInsertable(t,r),e.call(this._buff,n,r),this._writeOffset+=t,this}_writeNumberValue(e,t,n,r){if("number"==typeof r){if(r<0)throw new Error(i.ERRORS.INVALID_WRITE_BEYOND_BOUNDS);i.checkOffsetValue(r)}const o="number"==typeof r?r:this._writeOffset;return this._ensureWriteable(t,o),e.call(this._buff,n,o),"number"==typeof r?this._writeOffset=Math.max(this._writeOffset,o+t):this._writeOffset+=t,this}}t.SmartBuffer=r},7576(e,t,n){"use strict";const i=n(4422),{ArrayPrototypeIndexOf:r,NumberIsInteger:o,NumberIsNaN:s,NumberParseInt:a,ObjectDefineProperties:c,ObjectKeys:l,ObjectSetPrototypeOf:d,Promise:u,SafeSet:p,SymbolAsyncDispose:h,SymbolAsyncIterator:f,Symbol:g}=n(4134);e.exports=W,W.ReadableState=V;const{EventEmitter:m}=n(4434),{Stream:y,prependListener:b}=n(4259),{Buffer:v}=n(181),{addAbortSignal:S}=n(4147),_=n(6238);let w=n(7760).debuglog("stream",e=>{w=e});const k=n(345),I=n(5896),{getHighWaterMark:x,getDefaultHighWaterMark:C}=n(5291),{aggregateTwoErrors:E,codes:{ERR_INVALID_ARG_TYPE:T,ERR_METHOD_NOT_IMPLEMENTED:O,ERR_OUT_OF_RANGE:P,ERR_STREAM_PUSH_AFTER_EOF:A,ERR_STREAM_UNSHIFT_AFTER_END_EVENT:R},AbortError:M}=n(6371),{validateObject:L}=n(277),N=g("kPaused"),{StringDecoder:D}=n(3141),B=n(6532);d(W.prototype,y.prototype),d(W,y);const j=()=>{},{errorOrDestroy:$}=I,F=2048,U=4096;function z(e){return{enumerable:!1,get(){return 0!==(this.state&e)},set(t){t?this.state|=e:this.state&=~e}}}function V(e,t,i){"boolean"!=typeof i&&(i=t instanceof n(3370)),this.state=6192,e&&e.objectMode&&(this.state|=1),i&&e&&e.readableObjectMode&&(this.state|=1),this.highWaterMark=e?x(this,e,"readableHighWaterMark",i):C(!1),this.buffer=new k,this.length=0,this.pipes=[],this.flowing=null,this[N]=null,e&&!1===e.emitClose&&(this.state&=-2049),e&&!1===e.autoDestroy&&(this.state&=-4097),this.errored=null,this.defaultEncoding=e&&e.defaultEncoding||"utf8",this.awaitDrainWriters=null,this.decoder=null,this.encoding=null,e&&e.encoding&&(this.decoder=new D(e.encoding),this.encoding=e.encoding)}function W(e){if(!(this instanceof W))return new W(e);const t=this instanceof n(3370);this._readableState=new V(e,this,t),e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.construct&&(this._construct=e.construct),e.signal&&!t&&S(e.signal,this)),y.call(this,e),I.construct(this,()=>{this._readableState.needReadable&&J(this,this._readableState)})}function H(e,t,n,i){w("readableAddChunk",t);const r=e._readableState;let o;if(1&r.state||("string"==typeof t?(n=n||r.defaultEncoding,r.encoding!==n&&(i&&r.encoding?t=v.from(t,n).toString(r.encoding):(t=v.from(t,n),n=""))):t instanceof v?n="":y._isUint8Array(t)?(t=y._uint8ArrayToBuffer(t),n=""):null!=t&&(o=new T("chunk",["string","Buffer","Uint8Array"],t))),o)$(e,o);else if(null===t)r.state&=-9,function(e,t){if(w("onEofChunk"),t.ended)return;if(t.decoder){const e=t.decoder.end();e&&e.length&&(t.buffer.push(e),t.length+=t.objectMode?1:e.length)}t.ended=!0,t.sync?K(e):(t.needReadable=!1,t.emittedReadable=!0,Z(e))}(e,r);else if(1&r.state||t&&t.length>0)if(i)if(4&r.state)$(e,new R);else{if(r.destroyed||r.errored)return!1;q(e,r,t,!0)}else if(r.ended)$(e,new A);else{if(r.destroyed||r.errored)return!1;r.state&=-9,r.decoder&&!n?(t=r.decoder.write(t),r.objectMode||0!==t.length?q(e,r,t,!1):J(e,r)):q(e,r,t,!1)}else i||(r.state&=-9,J(e,r));return!r.ended&&(r.length<r.highWaterMark||0===r.length)}function q(e,t,n,i){t.flowing&&0===t.length&&!t.sync&&e.listenerCount("data")>0?(65536&t.state?t.awaitDrainWriters.clear():t.awaitDrainWriters=null,t.dataEmitted=!0,e.emit("data",n)):(t.length+=t.objectMode?1:n.length,i?t.buffer.unshift(n):t.buffer.push(n),64&t.state&&K(e)),J(e,t)}c(V.prototype,{objectMode:z(1),ended:z(2),endEmitted:z(4),reading:z(8),constructed:z(16),sync:z(32),needReadable:z(64),emittedReadable:z(128),readableListening:z(256),resumeScheduled:z(512),errorEmitted:z(1024),emitClose:z(F),autoDestroy:z(U),destroyed:z(8192),closed:z(16384),closeEmitted:z(32768),multiAwaitDrain:z(65536),readingMore:z(1<<17),dataEmitted:z(1<<18)}),W.prototype.destroy=I.destroy,W.prototype._undestroy=I.undestroy,W.prototype._destroy=function(e,t){t(e)},W.prototype[m.captureRejectionSymbol]=function(e){this.destroy(e)},W.prototype[h]=function(){let e;return this.destroyed||(e=this.readableEnded?null:new M,this.destroy(e)),new u((t,n)=>_(this,i=>i&&i!==e?n(i):t(null)))},W.prototype.push=function(e,t){return H(this,e,t,!1)},W.prototype.unshift=function(e,t){return H(this,e,t,!0)},W.prototype.isPaused=function(){const e=this._readableState;return!0===e[N]||!1===e.flowing},W.prototype.setEncoding=function(e){const t=new D(e);this._readableState.decoder=t,this._readableState.encoding=this._readableState.decoder.encoding;const n=this._readableState.buffer;let i="";for(const e of n)i+=t.write(e);return n.clear(),""!==i&&n.push(i),this._readableState.length=i.length,this};function G(e,t){return e<=0||0===t.length&&t.ended?0:1&t.state?1:s(e)?t.flowing&&t.length?t.buffer.first().length:t.length:e<=t.length?e:t.ended?t.length:0}function K(e){const t=e._readableState;w("emitReadable",t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(w("emitReadable",t.flowing),t.emittedReadable=!0,i.nextTick(Z,e))}function Z(e){const t=e._readableState;w("emitReadable_",t.destroyed,t.length,t.ended),t.destroyed||t.errored||!t.length&&!t.ended||(e.emit("readable"),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,te(e)}function J(e,t){!t.readingMore&&t.constructed&&(t.readingMore=!0,i.nextTick(Q,e,t))}function Q(e,t){for(;!t.reading&&!t.ended&&(t.length<t.highWaterMark||t.flowing&&0===t.length);){const n=t.length;if(w("maybeReadMore read 0"),e.read(0),n===t.length)break}t.readingMore=!1}function Y(e){const t=e._readableState;t.readableListening=e.listenerCount("readable")>0,t.resumeScheduled&&!1===t[N]?t.flowing=!0:e.listenerCount("data")>0?e.resume():t.readableListening||(t.flowing=null)}function X(e){w("readable nexttick read 0"),e.read(0)}function ee(e,t){w("resume",t.reading),t.reading||e.read(0),t.resumeScheduled=!1,e.emit("resume"),te(e),t.flowing&&!t.reading&&e.read(0)}function te(e){const t=e._readableState;for(w("flow",t.flowing);t.flowing&&null!==e.read(););}function ne(e,t){"function"!=typeof e.read&&(e=W.wrap(e,{objectMode:!0}));const n=async function*(e,t){let n,i=j;function r(t){this===e?(i(),i=j):i=t}e.on("readable",r);const o=_(e,{writable:!1},e=>{n=e?E(n,e):null,i(),i=j});try{for(;;){const t=e.destroyed?null:e.read();if(null!==t)yield t;else{if(n)throw n;if(null===n)return;await new u(r)}}}catch(e){throw n=E(n,e),n}finally{!n&&!1===(null==t?void 0:t.destroyOnReturn)||void 0!==n&&!e._readableState.autoDestroy?(e.off("readable",r),o()):I.destroyer(e,null)}}(e,t);return n.stream=e,n}function ie(e,t){if(0===t.length)return null;let n;return t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.first():t.buffer.concat(t.length),t.buffer.clear()):n=t.buffer.consume(e,t.decoder),n}function re(e){const t=e._readableState;w("endReadable",t.endEmitted),t.endEmitted||(t.ended=!0,i.nextTick(oe,t,e))}function oe(e,t){if(w("endReadableNT",e.endEmitted,e.length),!e.errored&&!e.closeEmitted&&!e.endEmitted&&0===e.length)if(e.endEmitted=!0,t.emit("end"),t.writable&&!1===t.allowHalfOpen)i.nextTick(se,t);else if(e.autoDestroy){const e=t._writableState;(!e||e.autoDestroy&&(e.finished||!1===e.writable))&&t.destroy()}}function se(e){e.writable&&!e.writableEnded&&!e.destroyed&&e.end()}let ae;function ce(){return void 0===ae&&(ae={}),ae}W.prototype.read=function(e){w("read",e),void 0===e?e=NaN:o(e)||(e=a(e,10));const t=this._readableState,n=e;if(e>t.highWaterMark&&(t.highWaterMark=function(e){if(e>1073741824)throw new P("size","<= 1GiB",e);return e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,++e}(e)),0!==e&&(t.state&=-129),0===e&&t.needReadable&&((0!==t.highWaterMark?t.length>=t.highWaterMark:t.length>0)||t.ended))return w("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?re(this):K(this),null;if(0===(e=G(e,t))&&t.ended)return 0===t.length&&re(this),null;let i,r=!!(64&t.state);if(w("need readable",r),(0===t.length||t.length-e<t.highWaterMark)&&(r=!0,w("length less than watermark",r)),t.ended||t.reading||t.destroyed||t.errored||!t.constructed)r=!1,w("reading, ended or constructing",r);else if(r){w("do read"),t.state|=40,0===t.length&&(t.state|=64);try{this._read(t.highWaterMark)}catch(e){$(this,e)}t.state&=-33,t.reading||(e=G(n,t))}return i=e>0?ie(e,t):null,null===i?(t.needReadable=t.length<=t.highWaterMark,e=0):(t.length-=e,t.multiAwaitDrain?t.awaitDrainWriters.clear():t.awaitDrainWriters=null),0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&re(this)),null===i||t.errorEmitted||t.closeEmitted||(t.dataEmitted=!0,this.emit("data",i)),i},W.prototype._read=function(e){throw new O("_read()")},W.prototype.pipe=function(e,t){const n=this,r=this._readableState;1===r.pipes.length&&(r.multiAwaitDrain||(r.multiAwaitDrain=!0,r.awaitDrainWriters=new p(r.awaitDrainWriters?[r.awaitDrainWriters]:[]))),r.pipes.push(e),w("pipe count=%d opts=%j",r.pipes.length,t);const o=(!t||!1!==t.end)&&e!==i.stdout&&e!==i.stderr?a:m;function s(t,i){w("onunpipe"),t===n&&i&&!1===i.hasUnpiped&&(i.hasUnpiped=!0,function(){w("cleanup"),e.removeListener("close",f),e.removeListener("finish",g),c&&e.removeListener("drain",c);e.removeListener("error",h),e.removeListener("unpipe",s),n.removeListener("end",a),n.removeListener("end",m),n.removeListener("data",u),l=!0,c&&r.awaitDrainWriters&&(!e._writableState||e._writableState.needDrain)&&c()}())}function a(){w("onend"),e.end()}let c;r.endEmitted?i.nextTick(o):n.once("end",o),e.on("unpipe",s);let l=!1;function d(){l||(1===r.pipes.length&&r.pipes[0]===e?(w("false write response, pause",0),r.awaitDrainWriters=e,r.multiAwaitDrain=!1):r.pipes.length>1&&r.pipes.includes(e)&&(w("false write response, pause",r.awaitDrainWriters.size),r.awaitDrainWriters.add(e)),n.pause()),c||(c=function(e,t){return function(){const n=e._readableState;n.awaitDrainWriters===t?(w("pipeOnDrain",1),n.awaitDrainWriters=null):n.multiAwaitDrain&&(w("pipeOnDrain",n.awaitDrainWriters.size),n.awaitDrainWriters.delete(t)),n.awaitDrainWriters&&0!==n.awaitDrainWriters.size||!e.listenerCount("data")||e.resume()}}(n,e),e.on("drain",c))}function u(t){w("ondata");const n=e.write(t);w("dest.write",n),!1===n&&d()}function h(t){if(w("onerror",t),m(),e.removeListener("error",h),0===e.listenerCount("error")){const n=e._writableState||e._readableState;n&&!n.errorEmitted?$(e,t):e.emit("error",t)}}function f(){e.removeListener("finish",g),m()}function g(){w("onfinish"),e.removeListener("close",f),m()}function m(){w("unpipe"),n.unpipe(e)}return n.on("data",u),b(e,"error",h),e.once("close",f),e.once("finish",g),e.emit("pipe",n),!0===e.writableNeedDrain?d():r.flowing||(w("pipe resume"),n.resume()),e},W.prototype.unpipe=function(e){const t=this._readableState;if(0===t.pipes.length)return this;if(!e){const e=t.pipes;t.pipes=[],this.pause();for(let t=0;t<e.length;t++)e[t].emit("unpipe",this,{hasUnpiped:!1});return this}const n=r(t.pipes,e);return-1===n||(t.pipes.splice(n,1),0===t.pipes.length&&this.pause(),e.emit("unpipe",this,{hasUnpiped:!1})),this},W.prototype.on=function(e,t){const n=y.prototype.on.call(this,e,t),r=this._readableState;return"data"===e?(r.readableListening=this.listenerCount("readable")>0,!1!==r.flowing&&this.resume()):"readable"===e&&(r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.flowing=!1,r.emittedReadable=!1,w("on readable",r.length,r.reading),r.length?K(this):r.reading||i.nextTick(X,this))),n},W.prototype.addListener=W.prototype.on,W.prototype.removeListener=function(e,t){const n=y.prototype.removeListener.call(this,e,t);return"readable"===e&&i.nextTick(Y,this),n},W.prototype.off=W.prototype.removeListener,W.prototype.removeAllListeners=function(e){const t=y.prototype.removeAllListeners.apply(this,arguments);return"readable"!==e&&void 0!==e||i.nextTick(Y,this),t},W.prototype.resume=function(){const e=this._readableState;return e.flowing||(w("resume"),e.flowing=!e.readableListening,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,i.nextTick(ee,e,t))}(this,e)),e[N]=!1,this},W.prototype.pause=function(){return w("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(w("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState[N]=!0,this},W.prototype.wrap=function(e){let t=!1;e.on("data",n=>{!this.push(n)&&e.pause&&(t=!0,e.pause())}),e.on("end",()=>{this.push(null)}),e.on("error",e=>{$(this,e)}),e.on("close",()=>{this.destroy()}),e.on("destroy",()=>{this.destroy()}),this._read=()=>{t&&e.resume&&(t=!1,e.resume())};const n=l(e);for(let t=1;t<n.length;t++){const i=n[t];void 0===this[i]&&"function"==typeof e[i]&&(this[i]=e[i].bind(e))}return this},W.prototype[f]=function(){return ne(this)},W.prototype.iterator=function(e){return void 0!==e&&L(e,"options"),ne(this,e)},c(W.prototype,{readable:{__proto__:null,get(){const e=this._readableState;return!(!e||!1===e.readable||e.destroyed||e.errorEmitted||e.endEmitted)},set(e){this._readableState&&(this._readableState.readable=!!e)}},readableDidRead:{__proto__:null,enumerable:!1,get:function(){return this._readableState.dataEmitted}},readableAborted:{__proto__:null,enumerable:!1,get:function(){return!(!1===this._readableState.readable||!this._readableState.destroyed&&!this._readableState.errored||this._readableState.endEmitted)}},readableHighWaterMark:{__proto__:null,enumerable:!1,get:function(){return this._readableState.highWaterMark}},readableBuffer:{__proto__:null,enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}},readableFlowing:{__proto__:null,enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}},readableLength:{__proto__:null,enumerable:!1,get(){return this._readableState.length}},readableObjectMode:{__proto__:null,enumerable:!1,get(){return!!this._readableState&&this._readableState.objectMode}},readableEncoding:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.encoding:null}},errored:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.errored:null}},closed:{__proto__:null,get(){return!!this._readableState&&this._readableState.closed}},destroyed:{__proto__:null,enumerable:!1,get(){return!!this._readableState&&this._readableState.destroyed},set(e){this._readableState&&(this._readableState.destroyed=e)}},readableEnded:{__proto__:null,enumerable:!1,get(){return!!this._readableState&&this._readableState.endEmitted}}}),c(V.prototype,{pipesCount:{__proto__:null,get(){return this.pipes.length}},paused:{__proto__:null,get(){return!1!==this[N]},set(e){this[N]=!!e}}}),W._fromList=ie,W.from=function(e,t){return B(W,e,t)},W.fromWeb=function(e,t){return ce().newStreamReadableFromReadableStream(e,t)},W.toWeb=function(e,t){return ce().newReadableStreamFromStreamReadable(e,t)},W.wrap=function(e,t){var n,i;return new W({objectMode:null===(n=null!==(i=e.readableObjectMode)&&void 0!==i?i:e.objectMode)||void 0===n||n,...t,destroy(t,n){I.destroyer(e,t),n(t)}}).wrap(e)}},7631(e,t,n){"use strict";var i=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{c(i.next(e))}catch(e){o(e)}}function a(e){try{c(i.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}c((i=i.apply(e,t||[])).next())})};Object.defineProperty(t,"__esModule",{value:!0}),t.SocksClientError=t.SocksClient=void 0;const r=n(4434),o=n(9278),s=n(7575),a=n(5438),c=n(7130),l=n(7736),d=n(3763);Object.defineProperty(t,"SocksClientError",{enumerable:!0,get:function(){return d.SocksClientError}});const u=n(9424);class p extends r.EventEmitter{constructor(e){super(),this.options=Object.assign({},e),(0,c.validateSocksClientOptions)(e),this.setState(a.SocksClientState.Created)}static createConnection(e,t){return new Promise((n,i)=>{try{(0,c.validateSocksClientOptions)(e,["connect"])}catch(e){return"function"==typeof t?(t(e),n(e)):i(e)}const r=new p(e);r.connect(e.existing_socket),r.once("established",e=>{r.removeAllListeners(),"function"==typeof t?(t(null,e),n(e)):n(e)}),r.once("error",e=>{r.removeAllListeners(),"function"==typeof t?(t(e),n(e)):i(e)})})}static createConnectionChain(e,t){return new Promise((n,r)=>i(this,void 0,void 0,function*(){try{(0,c.validateSocksClientChainOptions)(e)}catch(e){return"function"==typeof t?(t(e),n(e)):r(e)}e.randomizeChain&&(0,d.shuffleArray)(e.proxies);try{let i;for(let t=0;t<e.proxies.length;t++){const n=e.proxies[t],r=t===e.proxies.length-1?e.destination:{host:e.proxies[t+1].host||e.proxies[t+1].ipaddress,port:e.proxies[t+1].port},o=yield p.createConnection({command:"connect",proxy:n,destination:r,existing_socket:i});i=i||o.socket}"function"==typeof t?(t(null,{socket:i}),n({socket:i})):n({socket:i})}catch(e){"function"==typeof t?(t(e),n(e)):r(e)}}))}static createUDPFrame(e){const t=new s.SmartBuffer;return t.writeUInt16BE(0),t.writeUInt8(e.frameNumber||0),o.isIPv4(e.remoteHost.host)?(t.writeUInt8(a.Socks5HostType.IPv4),t.writeUInt32BE((0,c.ipv4ToInt32)(e.remoteHost.host))):o.isIPv6(e.remoteHost.host)?(t.writeUInt8(a.Socks5HostType.IPv6),t.writeBuffer((0,c.ipToBuffer)(e.remoteHost.host))):(t.writeUInt8(a.Socks5HostType.Hostname),t.writeUInt8(Buffer.byteLength(e.remoteHost.host)),t.writeString(e.remoteHost.host)),t.writeUInt16BE(e.remoteHost.port),t.writeBuffer(e.data),t.toBuffer()}static parseUDPFrame(e){const t=s.SmartBuffer.fromBuffer(e);t.readOffset=2;const n=t.readUInt8(),i=t.readUInt8();let r;r=i===a.Socks5HostType.IPv4?(0,c.int32ToIpv4)(t.readUInt32BE()):i===a.Socks5HostType.IPv6?u.Address6.fromByteArray(Array.from(t.readBuffer(16))).canonicalForm():t.readString(t.readUInt8());return{frameNumber:n,remoteHost:{host:r,port:t.readUInt16BE()},data:t.readBuffer()}}setState(e){this.state!==a.SocksClientState.Error&&(this.state=e)}connect(e){this.onDataReceived=e=>this.onDataReceivedHandler(e),this.onClose=()=>this.onCloseHandler(),this.onError=e=>this.onErrorHandler(e),this.onConnect=()=>this.onConnectHandler();const t=setTimeout(()=>this.onEstablishedTimeout(),this.options.timeout||a.DEFAULT_TIMEOUT);t.unref&&"function"==typeof t.unref&&t.unref(),this.socket=e||new o.Socket,this.socket.once("close",this.onClose),this.socket.once("error",this.onError),this.socket.once("connect",this.onConnect),this.socket.on("data",this.onDataReceived),this.setState(a.SocksClientState.Connecting),this.receiveBuffer=new l.ReceiveBuffer,e?this.socket.emit("connect"):(this.socket.connect(this.getSocketOptions()),void 0!==this.options.set_tcp_nodelay&&null!==this.options.set_tcp_nodelay&&this.socket.setNoDelay(!!this.options.set_tcp_nodelay)),this.prependOnceListener("established",e=>{setImmediate(()=>{if(this.receiveBuffer.length>0){const t=this.receiveBuffer.get(this.receiveBuffer.length);e.socket.emit("data",t)}e.socket.resume()})})}getSocketOptions(){return Object.assign(Object.assign({},this.options.socket_options),{host:this.options.proxy.host||this.options.proxy.ipaddress,port:this.options.proxy.port})}onEstablishedTimeout(){this.state!==a.SocksClientState.Established&&this.state!==a.SocksClientState.BoundWaitingForConnection&&this.closeSocket(a.ERRORS.ProxyConnectionTimedOut)}onConnectHandler(){this.setState(a.SocksClientState.Connected),4===this.options.proxy.type?this.sendSocks4InitialHandshake():this.sendSocks5InitialHandshake(),this.setState(a.SocksClientState.SentInitialHandshake)}onDataReceivedHandler(e){this.receiveBuffer.append(e),this.processData()}processData(){for(;this.state!==a.SocksClientState.Established&&this.state!==a.SocksClientState.Error&&this.receiveBuffer.length>=this.nextRequiredPacketBufferSize;)if(this.state===a.SocksClientState.SentInitialHandshake)4===this.options.proxy.type?this.handleSocks4FinalHandshakeResponse():this.handleInitialSocks5HandshakeResponse();else if(this.state===a.SocksClientState.SentAuthentication)this.handleInitialSocks5AuthenticationHandshakeResponse();else if(this.state===a.SocksClientState.SentFinalHandshake)this.handleSocks5FinalHandshakeResponse();else{if(this.state!==a.SocksClientState.BoundWaitingForConnection){this.closeSocket(a.ERRORS.InternalError);break}4===this.options.proxy.type?this.handleSocks4IncomingConnectionResponse():this.handleSocks5IncomingConnectionResponse()}}onCloseHandler(){this.closeSocket(a.ERRORS.SocketClosed)}onErrorHandler(e){this.closeSocket(e.message)}removeInternalSocketHandlers(){this.socket.pause(),this.socket.removeListener("data",this.onDataReceived),this.socket.removeListener("close",this.onClose),this.socket.removeListener("error",this.onError),this.socket.removeListener("connect",this.onConnect)}closeSocket(e){this.state!==a.SocksClientState.Error&&(this.setState(a.SocksClientState.Error),this.socket.destroy(),this.removeInternalSocketHandlers(),this.emit("error",new d.SocksClientError(e,this.options)))}sendSocks4InitialHandshake(){const e=this.options.proxy.userId||"",t=new s.SmartBuffer;t.writeUInt8(4),t.writeUInt8(a.SocksCommand[this.options.command]),t.writeUInt16BE(this.options.destination.port),o.isIPv4(this.options.destination.host)?(t.writeBuffer((0,c.ipToBuffer)(this.options.destination.host)),t.writeStringNT(e)):(t.writeUInt8(0),t.writeUInt8(0),t.writeUInt8(0),t.writeUInt8(1),t.writeStringNT(e),t.writeStringNT(this.options.destination.host)),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks4Response,this.socket.write(t.toBuffer())}handleSocks4FinalHandshakeResponse(){const e=this.receiveBuffer.get(8);if(e[1]!==a.Socks4Response.Granted)this.closeSocket(`${a.ERRORS.Socks4ProxyRejectedConnection} - (${a.Socks4Response[e[1]]})`);else if(a.SocksCommand[this.options.command]===a.SocksCommand.bind){const t=s.SmartBuffer.fromBuffer(e);t.readOffset=2;const n={port:t.readUInt16BE(),host:(0,c.int32ToIpv4)(t.readUInt32BE())};"0.0.0.0"===n.host&&(n.host=this.options.proxy.ipaddress),this.setState(a.SocksClientState.BoundWaitingForConnection),this.emit("bound",{remoteHost:n,socket:this.socket})}else this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{socket:this.socket})}handleSocks4IncomingConnectionResponse(){const e=this.receiveBuffer.get(8);if(e[1]!==a.Socks4Response.Granted)this.closeSocket(`${a.ERRORS.Socks4ProxyRejectedIncomingBoundConnection} - (${a.Socks4Response[e[1]]})`);else{const t=s.SmartBuffer.fromBuffer(e);t.readOffset=2;const n={port:t.readUInt16BE(),host:(0,c.int32ToIpv4)(t.readUInt32BE())};this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket})}}sendSocks5InitialHandshake(){const e=new s.SmartBuffer,t=[a.Socks5Auth.NoAuth];(this.options.proxy.userId||this.options.proxy.password)&&t.push(a.Socks5Auth.UserPass),void 0!==this.options.proxy.custom_auth_method&&t.push(this.options.proxy.custom_auth_method),e.writeUInt8(5),e.writeUInt8(t.length);for(const n of t)e.writeUInt8(n);this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5InitialHandshakeResponse,this.socket.write(e.toBuffer()),this.setState(a.SocksClientState.SentInitialHandshake)}handleInitialSocks5HandshakeResponse(){const e=this.receiveBuffer.get(2);5!==e[0]?this.closeSocket(a.ERRORS.InvalidSocks5IntiailHandshakeSocksVersion):e[1]===a.SOCKS5_NO_ACCEPTABLE_AUTH?this.closeSocket(a.ERRORS.InvalidSocks5InitialHandshakeNoAcceptedAuthType):e[1]===a.Socks5Auth.NoAuth?(this.socks5ChosenAuthType=a.Socks5Auth.NoAuth,this.sendSocks5CommandRequest()):e[1]===a.Socks5Auth.UserPass?(this.socks5ChosenAuthType=a.Socks5Auth.UserPass,this.sendSocks5UserPassAuthentication()):e[1]===this.options.proxy.custom_auth_method?(this.socks5ChosenAuthType=this.options.proxy.custom_auth_method,this.sendSocks5CustomAuthentication()):this.closeSocket(a.ERRORS.InvalidSocks5InitialHandshakeUnknownAuthType)}sendSocks5UserPassAuthentication(){const e=this.options.proxy.userId||"",t=this.options.proxy.password||"",n=new s.SmartBuffer;n.writeUInt8(1),n.writeUInt8(Buffer.byteLength(e)),n.writeString(e),n.writeUInt8(Buffer.byteLength(t)),n.writeString(t),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5UserPassAuthenticationResponse,this.socket.write(n.toBuffer()),this.setState(a.SocksClientState.SentAuthentication)}sendSocks5CustomAuthentication(){return i(this,void 0,void 0,function*(){this.nextRequiredPacketBufferSize=this.options.proxy.custom_auth_response_size,this.socket.write(yield this.options.proxy.custom_auth_request_handler()),this.setState(a.SocksClientState.SentAuthentication)})}handleSocks5CustomAuthHandshakeResponse(e){return i(this,void 0,void 0,function*(){return yield this.options.proxy.custom_auth_response_handler(e)})}handleSocks5AuthenticationNoAuthHandshakeResponse(e){return i(this,void 0,void 0,function*(){return 0===e[1]})}handleSocks5AuthenticationUserPassHandshakeResponse(e){return i(this,void 0,void 0,function*(){return 0===e[1]})}handleInitialSocks5AuthenticationHandshakeResponse(){return i(this,void 0,void 0,function*(){this.setState(a.SocksClientState.ReceivedAuthenticationResponse);let e=!1;this.socks5ChosenAuthType===a.Socks5Auth.NoAuth?e=yield this.handleSocks5AuthenticationNoAuthHandshakeResponse(this.receiveBuffer.get(2)):this.socks5ChosenAuthType===a.Socks5Auth.UserPass?e=yield this.handleSocks5AuthenticationUserPassHandshakeResponse(this.receiveBuffer.get(2)):this.socks5ChosenAuthType===this.options.proxy.custom_auth_method&&(e=yield this.handleSocks5CustomAuthHandshakeResponse(this.receiveBuffer.get(this.options.proxy.custom_auth_response_size))),e?this.sendSocks5CommandRequest():this.closeSocket(a.ERRORS.Socks5AuthenticationFailed)})}sendSocks5CommandRequest(){const e=new s.SmartBuffer;e.writeUInt8(5),e.writeUInt8(a.SocksCommand[this.options.command]),e.writeUInt8(0),o.isIPv4(this.options.destination.host)?(e.writeUInt8(a.Socks5HostType.IPv4),e.writeBuffer((0,c.ipToBuffer)(this.options.destination.host))):o.isIPv6(this.options.destination.host)?(e.writeUInt8(a.Socks5HostType.IPv6),e.writeBuffer((0,c.ipToBuffer)(this.options.destination.host))):(e.writeUInt8(a.Socks5HostType.Hostname),e.writeUInt8(this.options.destination.host.length),e.writeString(this.options.destination.host)),e.writeUInt16BE(this.options.destination.port),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHeader,this.socket.write(e.toBuffer()),this.setState(a.SocksClientState.SentFinalHandshake)}handleSocks5FinalHandshakeResponse(){const e=this.receiveBuffer.peek(5);if(5!==e[0]||e[1]!==a.Socks5Response.Granted)this.closeSocket(`${a.ERRORS.InvalidSocks5FinalHandshakeRejected} - ${a.Socks5Response[e[1]]}`);else{const t=e[3];let n,i;if(t===a.Socks5HostType.IPv4){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv4;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:(0,c.int32ToIpv4)(i.readUInt32BE()),port:i.readUInt16BE()},"0.0.0.0"===n.host&&(n.host=this.options.proxy.ipaddress)}else if(t===a.Socks5HostType.Hostname){const t=e[4],r=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHostname(t);if(this.receiveBuffer.length<r)return void(this.nextRequiredPacketBufferSize=r);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(r).slice(5)),n={host:i.readString(t),port:i.readUInt16BE()}}else if(t===a.Socks5HostType.IPv6){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv6;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:u.Address6.fromByteArray(Array.from(i.readBuffer(16))).canonicalForm(),port:i.readUInt16BE()}}this.setState(a.SocksClientState.ReceivedFinalResponse),a.SocksCommand[this.options.command]===a.SocksCommand.connect?(this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket})):a.SocksCommand[this.options.command]===a.SocksCommand.bind?(this.setState(a.SocksClientState.BoundWaitingForConnection),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHeader,this.emit("bound",{remoteHost:n,socket:this.socket})):a.SocksCommand[this.options.command]===a.SocksCommand.associate&&(this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket}))}}handleSocks5IncomingConnectionResponse(){const e=this.receiveBuffer.peek(5);if(5!==e[0]||e[1]!==a.Socks5Response.Granted)this.closeSocket(`${a.ERRORS.Socks5ProxyRejectedIncomingBoundConnection} - ${a.Socks5Response[e[1]]}`);else{const t=e[3];let n,i;if(t===a.Socks5HostType.IPv4){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv4;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:(0,c.int32ToIpv4)(i.readUInt32BE()),port:i.readUInt16BE()},"0.0.0.0"===n.host&&(n.host=this.options.proxy.ipaddress)}else if(t===a.Socks5HostType.Hostname){const t=e[4],r=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHostname(t);if(this.receiveBuffer.length<r)return void(this.nextRequiredPacketBufferSize=r);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(r).slice(5)),n={host:i.readString(t),port:i.readUInt16BE()}}else if(t===a.Socks5HostType.IPv6){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv6;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:u.Address6.fromByteArray(Array.from(i.readBuffer(16))).canonicalForm(),port:i.readUInt16BE()}}this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket})}}get socksClientOptions(){return Object.assign({},this.options)}}t.SocksClient=p},7687(e,t,n){"use strict";const i=n(857),r=n(2018),o=n(5884),{env:s}=process;let a;function c(e){return 0!==e&&{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function l(e,t){if(0===a)return 0;if(o("color=16m")||o("color=full")||o("color=truecolor"))return 3;if(o("color=256"))return 2;if(e&&!t&&void 0===a)return 0;const n=a||0;if("dumb"===s.TERM)return n;if("win32"===process.platform){const e=i.release().split(".");return Number(e[0])>=10&&Number(e[2])>=10586?Number(e[2])>=14931?3:2:1}if("CI"in s)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(e=>e in s)||"codeship"===s.CI_NAME?1:n;if("TEAMCITY_VERSION"in s)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(s.TEAMCITY_VERSION)?1:0;if("truecolor"===s.COLORTERM)return 3;if("TERM_PROGRAM"in s){const e=parseInt((s.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(s.TERM_PROGRAM){case"iTerm.app":return e>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(s.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(s.TERM)||"COLORTERM"in s?1:n}o("no-color")||o("no-colors")||o("color=false")||o("color=never")?a=0:(o("color")||o("colors")||o("color=true")||o("color=always"))&&(a=1),"FORCE_COLOR"in s&&(a="true"===s.FORCE_COLOR?1:"false"===s.FORCE_COLOR?0:0===s.FORCE_COLOR.length?1:Math.min(parseInt(s.FORCE_COLOR,10),3)),e.exports={supportsColor:function(e){return c(l(e,e&&e.isTTY))},stdout:c(l(!0,r.isatty(1))),stderr:c(l(!0,r.isatty(2)))}},7699(e,t,n){"use strict";const i=n(1060);i.createWebSocketStream=n(3719),i.Server=n(1722),i.Receiver=n(6286),i.Sender=n(914),i.WebSocket=i,i.WebSocketServer=i.Server,e.exports=i},7732(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0});const a=n(8600),c=s(n(6887)),l={set:a.setInterval,clear:a.clearInterval},d={set:(e,t)=>setInterval(e,t),clear:e=>clearInterval(e)};t.default=e=>{switch(e){case"native":return d;case"worker":return l;default:return!c.default||c.isWebWorker||c.isReactNativeBrowser?d:l}}},7736(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ReceiveBuffer=void 0;t.ReceiveBuffer=class{constructor(e=4096){this.buffer=Buffer.allocUnsafe(e),this.offset=0,this.originalSize=e}get length(){return this.offset}append(e){if(!Buffer.isBuffer(e))throw new Error("Attempted to append a non-buffer instance to ReceiveBuffer.");if(this.offset+e.length>=this.buffer.length){const t=this.buffer;this.buffer=Buffer.allocUnsafe(Math.max(this.buffer.length+this.originalSize,this.buffer.length+e.length)),t.copy(this.buffer)}return e.copy(this.buffer,this.offset),this.offset+=e.length}peek(e){if(e>this.offset)throw new Error("Attempted to read beyond the bounds of the managed internal data.");return this.buffer.slice(0,e)}get(e){if(e>this.offset)throw new Error("Attempted to read beyond the bounds of the managed internal data.");const t=Buffer.allocUnsafe(e);return this.buffer.slice(0,e).copy(t),this.buffer.copyWithin(0,e,e+this.offset-e),this.offset-=e,t}}},7758(e,t,n){const i=n(4422),{ArrayIsArray:r,Promise:o,SymbolAsyncIterator:s,SymbolDispose:a}=n(4134),c=n(6238),{once:l}=n(7760),d=n(5896),u=n(3370),{aggregateTwoErrors:p,codes:{ERR_INVALID_ARG_TYPE:h,ERR_INVALID_RETURN_VALUE:f,ERR_MISSING_ARGS:g,ERR_STREAM_DESTROYED:m,ERR_STREAM_PREMATURE_CLOSE:y},AbortError:b}=n(6371),{validateFunction:v,validateAbortSignal:S}=n(277),{isIterable:_,isReadable:w,isReadableNodeStream:k,isNodeStream:I,isTransformStream:x,isWebStream:C,isReadableStream:E,isReadableFinished:T}=n(6115),O=globalThis.AbortController||n(6584).AbortController;let P,A,R;function M(e,t,n){let i=!1;e.on("close",()=>{i=!0});return{destroy:t=>{i||(i=!0,d.destroyer(e,t||new m("pipe")))},cleanup:c(e,{readable:t,writable:n},e=>{i=!e})}}function L(e){if(_(e))return e;if(k(e))return async function*(e){A||(A=n(7576));yield*A.prototype[s].call(e)}(e);throw new h("val",["Readable","Iterable","AsyncIterable"],e)}async function N(e,t,n,{end:i}){let r,s=null;const a=e=>{if(e&&(r=e),s){const e=s;s=null,e()}},l=()=>new o((e,t)=>{r?t(r):s=()=>{r?t(r):e()}});t.on("drain",a);const d=c(t,{readable:!1},a);try{t.writableNeedDrain&&await l();for await(const n of e)t.write(n)||await l();i&&(t.end(),await l()),n()}catch(e){n(r!==e?p(r,e):e)}finally{d(),t.off("drain",a)}}async function D(e,t,n,{end:i}){x(t)&&(t=t.writable);const r=t.getWriter();try{for await(const t of e)await r.ready,r.write(t).catch(()=>{});await r.ready,i&&await r.close(),n()}catch(e){try{await r.abort(e),n(e)}catch(e){n(e)}}}function B(e,t,o){if(1===e.length&&r(e[0])&&(e=e[0]),e.length<2)throw new g("streams");const s=new O,c=s.signal,l=null==o?void 0:o.signal,d=[];function p(){F(new b)}let m,y,v;S(l,"options.signal"),R=R||n(7760).addAbortListener,l&&(m=R(l,p));const T=[];let A,B=0;function $(e){F(e,0===--B)}function F(e,n){var r;if(!e||y&&"ERR_STREAM_PREMATURE_CLOSE"!==y.code||(y=e),y||n){for(;T.length;)T.shift()(y);null===(r=m)||void 0===r||r[a](),s.abort(),n&&(y||d.forEach(e=>e()),i.nextTick(t,y,v))}}for(let W=0;W<e.length;W++){const H=e[W],q=W<e.length-1,G=W>0,K=q||!1!==(null==o?void 0:o.end),Z=W===e.length-1;if(I(H)){if(K){const{destroy:J,cleanup:Q}=M(H,q,G);T.push(J),w(H)&&Z&&d.push(Q)}function U(e){e&&"AbortError"!==e.name&&"ERR_STREAM_PREMATURE_CLOSE"!==e.code&&$(e)}H.on("error",U),w(H)&&Z&&d.push(()=>{H.removeListener("error",U)})}if(0===W)if("function"==typeof H){if(A=H({signal:c}),!_(A))throw new f("Iterable, AsyncIterable or Stream","source",A)}else A=_(H)||k(H)||x(H)?H:u.from(H);else if("function"==typeof H){var z;if(x(A))A=L(null===(z=A)||void 0===z?void 0:z.readable);else A=L(A);if(A=H(A,{signal:c}),q){if(!_(A,!0))throw new f("AsyncIterable",`transform[${W-1}]`,A)}else{var V;P||(P=n(6524));const Y=new P({objectMode:!0}),X=null===(V=A)||void 0===V?void 0:V.then;if("function"==typeof X)B++,X.call(A,e=>{v=e,null!=e&&Y.write(e),K&&Y.end(),i.nextTick($)},e=>{Y.destroy(e),i.nextTick($,e)});else if(_(A,!0))B++,N(A,Y,$,{end:K});else{if(!E(A)&&!x(A))throw new f("AsyncIterable or Promise","destination",A);{const ne=A.readable||A;B++,N(ne,Y,$,{end:K})}}A=Y;const{destroy:ee,cleanup:te}=M(A,!1,!0);T.push(ee),Z&&d.push(te)}}else if(I(H)){if(k(A)){B+=2;const ie=j(A,H,$,{end:K});w(H)&&Z&&d.push(ie)}else if(x(A)||E(A)){const re=A.readable||A;B++,N(re,H,$,{end:K})}else{if(!_(A))throw new h("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],A);B++,N(A,H,$,{end:K})}A=H}else if(C(H)){if(k(A))B++,D(L(A),H,$,{end:K});else if(E(A)||_(A))B++,D(A,H,$,{end:K});else{if(!x(A))throw new h("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],A);B++,D(A.readable,H,$,{end:K})}A=H}else A=u.from(H)}return(null!=c&&c.aborted||null!=l&&l.aborted)&&i.nextTick(p),A}function j(e,t,n,{end:r}){let o=!1;if(t.on("close",()=>{o||n(new y)}),e.pipe(t,{end:!1}),r){function s(){o=!0,t.end()}T(e)?i.nextTick(s):e.once("end",s)}else n();return c(e,{readable:!0,writable:!1},t=>{const i=e._readableState;t&&"ERR_STREAM_PREMATURE_CLOSE"===t.code&&i&&i.ended&&!i.errored&&!i.errorEmitted?e.once("end",n).once("error",n):n(t)}),c(t,{readable:!1,writable:!0},n)}e.exports={pipelineImpl:B,pipeline:function(...e){return B(e,l(function(e){return v(e[e.length-1],"streams[stream.length - 1]"),e.pop()}(e)))}}},7760(e,t,n){"use strict";const i=n(181),{format:r,inspect:o}=n(9231),{codes:{ERR_INVALID_ARG_TYPE:s}}=n(6371),{kResistStopPropagation:a,AggregateError:c,SymbolDispose:l}=n(4134),d=globalThis.AbortSignal||n(6584).AbortSignal,u=globalThis.AbortController||n(6584).AbortController,p=Object.getPrototypeOf(async function(){}).constructor,h=globalThis.Blob||i.Blob,f="undefined"!=typeof h?function(e){return e instanceof h}:function(e){return!1},g=(e,t)=>{if(void 0!==e&&(null===e||"object"!=typeof e||!("aborted"in e)))throw new s(t,"AbortSignal",e)};e.exports={AggregateError:c,kEmptyObject:Object.freeze({}),once(e){let t=!1;return function(...n){t||(t=!0,e.apply(this,n))}},createDeferredPromise:function(){let e,t;return{promise:new Promise((n,i)=>{e=n,t=i}),resolve:e,reject:t}},promisify:e=>new Promise((t,n)=>{e((e,...i)=>e?n(e):t(...i))}),debuglog:()=>function(){},format:r,inspect:o,types:{isAsyncFunction:e=>e instanceof p,isArrayBufferView:e=>ArrayBuffer.isView(e)},isBlob:f,deprecate:(e,t)=>e,addAbortListener:n(4434).addAbortListener||function(e,t){if(void 0===e)throw new s("signal","AbortSignal",e);let n;return g(e,"signal"),((e,t)=>{if("function"!=typeof e)throw new s(t,"Function",e)})(t,"listener"),e.aborted?queueMicrotask(()=>t()):(e.addEventListener("abort",t,{__proto__:null,once:!0,[a]:!0}),n=()=>{e.removeEventListener("abort",t)}),{__proto__:null,[l](){var e;null===(e=n)||void 0===e||e()}}},AbortSignalAny:d.any||function(e){if(1===e.length)return e[0];const t=new u,n=()=>t.abort();return e.forEach(e=>{g(e,"signals"),e.addEventListener("abort",n,{once:!0})}),t.signal.addEventListener("abort",()=>{e.forEach(e=>e.removeEventListener("abort",n))},{once:!0}),t.signal}},e.exports.promisify.custom=Symbol.for("nodejs.util.promisify.custom")},7813(e,t,n){"use strict";const{Buffer:i}=n(181),r=Symbol.for("BufferList");function o(e){if(!(this instanceof o))return new o(e);o._init.call(this,e)}o._init=function(e){Object.defineProperty(this,r,{value:!0}),this._bufs=[],this.length=0,e&&this.append(e)},o.prototype._new=function(e){return new o(e)},o.prototype._offset=function(e){if(0===e)return[0,0];let t=0;for(let n=0;n<this._bufs.length;n++){const i=t+this._bufs[n].length;if(e<i||n===this._bufs.length-1)return[n,e-t];t=i}},o.prototype._reverseOffset=function(e){const t=e[0];let n=e[1];for(let e=0;e<t;e++)n+=this._bufs[e].length;return n},o.prototype.getBuffers=function(){return this._bufs},o.prototype.get=function(e){if(e>this.length||e<0)return;const t=this._offset(e);return this._bufs[t[0]][t[1]]},o.prototype.slice=function(e,t){return"number"==typeof e&&e<0&&(e+=this.length),"number"==typeof t&&t<0&&(t+=this.length),this.copy(null,0,e,t)},o.prototype.copy=function(e,t,n,r){if(("number"!=typeof n||n<0)&&(n=0),("number"!=typeof r||r>this.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);const o=!!e,s=this._offset(n),a=r-n;let c=a,l=o&&t||0,d=s[1];if(0===n&&r===this.length){if(!o)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(let t=0;t<this._bufs.length;t++)this._bufs[t].copy(e,l),l+=this._bufs[t].length;return e}if(c<=this._bufs[s[0]].length-d)return o?this._bufs[s[0]].copy(e,t,d,d+c):this._bufs[s[0]].slice(d,d+c);o||(e=i.allocUnsafe(a));for(let t=s[0];t<this._bufs.length;t++){const n=this._bufs[t].length-d;if(!(c>n)){this._bufs[t].copy(e,l,d,d+c),l+=n;break}this._bufs[t].copy(e,l,d),l+=n,c-=n,d&&(d=0)}return e.length>l?e.slice(0,l):e},o.prototype.shallowSlice=function(e,t){if(e=e||0,t="number"!=typeof t?this.length:t,e<0&&(e+=this.length),t<0&&(t+=this.length),e===t)return this._new();const n=this._offset(e),i=this._offset(t),r=this._bufs.slice(n[0],i[0]+1);return 0===i[1]?r.pop():r[r.length-1]=r[r.length-1].slice(0,i[1]),0!==n[1]&&(r[0]=r[0].slice(n[1])),this._new(r)},o.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},o.prototype.consume=function(e){if(e=Math.trunc(e),Number.isNaN(e)||e<=0)return this;for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},o.prototype.duplicate=function(){const e=this._new();for(let t=0;t<this._bufs.length;t++)e.append(this._bufs[t]);return e},o.prototype.append=function(e){return this._attach(e,o.prototype._appendBuffer)},o.prototype.prepend=function(e){return this._attach(e,o.prototype._prependBuffer,!0)},o.prototype._attach=function(e,t,n){if(null==e)return this;if(e.buffer)t.call(this,i.from(e.buffer,e.byteOffset,e.byteLength));else if(Array.isArray(e)){const[i,r]=n?[e.length-1,-1]:[0,1];for(let o=i;o>=0&&o<e.length;o+=r)this._attach(e[o],t,n)}else if(this._isBufferList(e)){const[i,r]=n?[e._bufs.length-1,-1]:[0,1];for(let o=i;o>=0&&o<e._bufs.length;o+=r)this._attach(e._bufs[o],t,n)}else"number"==typeof e&&(e=e.toString()),t.call(this,i.from(e));return this},o.prototype._appendBuffer=function(e){this._bufs.push(e),this.length+=e.length},o.prototype._prependBuffer=function(e){this._bufs.unshift(e),this.length+=e.length},o.prototype.indexOf=function(e,t,n){if(void 0===n&&"string"==typeof t&&(n=t,t=void 0),"function"==typeof e||Array.isArray(e))throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.');if("number"==typeof e?e=i.from([e]):"string"==typeof e?e=i.from(e,n):this._isBufferList(e)?e=e.slice():Array.isArray(e.buffer)?e=i.from(e.buffer,e.byteOffset,e.byteLength):i.isBuffer(e)||(e=i.from(e)),t=Number(t||0),isNaN(t)&&(t=0),t<0&&(t=this.length+t),t<0&&(t=0),0===e.length)return t>this.length?this.length:t;const r=this._offset(t);let o=r[0],s=r[1];for(;o<this._bufs.length;o++){const t=this._bufs[o];for(;s<t.length;){if(t.length-s>=e.length){const n=t.indexOf(e,s);if(-1!==n)return this._reverseOffset([o,n]);s=t.length-e.length+1}else{const t=this._reverseOffset([o,s]);if(this._match(t,e))return t;s++}}s=0}return-1},o.prototype._match=function(e,t){if(this.length-e<t.length)return!1;for(let n=0;n<t.length;n++)if(this.get(e+n)!==t[n])return!1;return!0},function(){const e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readBigInt64BE:8,readBigInt64LE:8,readBigUInt64BE:8,readBigUInt64LE:8,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1,readIntBE:null,readIntLE:null,readUIntBE:null,readUIntLE:null};for(const t in e)(function(t){o.prototype[t]=null===e[t]?function(e,n){return this.slice(e,e+n)[t](0,n)}:function(n=0){return this.slice(n,n+e[t])[t](0)}})(t)}(),o.prototype._isBufferList=function(e){return e instanceof o||o.isBufferList(e)},o.isBufferList=function(e){return null!=e&&e[r]},e.exports=o},7830(e,t,n){"use strict";const{pipeline:i}=n(7758),r=n(3370),{destroyer:o}=n(5896),{isNodeStream:s,isReadable:a,isWritable:c,isWebStream:l,isTransformStream:d,isWritableStream:u,isReadableStream:p}=n(6115),{AbortError:h,codes:{ERR_INVALID_ARG_VALUE:f,ERR_MISSING_ARGS:g}}=n(6371),m=n(6238);e.exports=function(...e){if(0===e.length)throw new g("streams");if(1===e.length)return r.from(e[0]);const t=[...e];if("function"==typeof e[0]&&(e[0]=r.from(e[0])),"function"==typeof e[e.length-1]){const t=e.length-1;e[t]=r.from(e[t])}for(let n=0;n<e.length;++n)if(s(e[n])||l(e[n])){if(n<e.length-1&&!(a(e[n])||p(e[n])||d(e[n])))throw new f(`streams[${n}]`,t[n],"must be readable");if(n>0&&!(c(e[n])||u(e[n])||d(e[n])))throw new f(`streams[${n}]`,t[n],"must be writable")}let n,y,b,v,S;const _=e[0],w=i(e,function(e){const t=v;v=null,t?t(e):e?S.destroy(e):I||k||S.destroy()}),k=!!(c(_)||u(_)||d(_)),I=!!(a(w)||p(w)||d(w));if(S=new r({writableObjectMode:!(null==_||!_.writableObjectMode),readableObjectMode:!(null==w||!w.readableObjectMode),writable:k,readable:I}),k){if(s(_))S._write=function(e,t,i){_.write(e,t)?i():n=i},S._final=function(e){_.end(),y=e},_.on("drain",function(){if(n){const e=n;n=null,e()}});else if(l(_)){const e=(d(_)?_.writable:_).getWriter();S._write=async function(t,n,i){try{await e.ready,e.write(t).catch(()=>{}),i()}catch(e){i(e)}},S._final=async function(t){try{await e.ready,e.close().catch(()=>{}),y=t}catch(e){t(e)}}}const e=d(w)?w.readable:w;m(e,()=>{if(y){const e=y;y=null,e()}})}if(I)if(s(w))w.on("readable",function(){if(b){const e=b;b=null,e()}}),w.on("end",function(){S.push(null)}),S._read=function(){for(;;){const e=w.read();if(null===e)return void(b=S._read);if(!S.push(e))return}};else if(l(w)){const e=(d(w)?w.readable:w).getReader();S._read=async function(){for(;;)try{const{value:t,done:n}=await e.read();if(!S.push(t))return;if(n)return void S.push(null)}catch{return}}}return S._destroy=function(e,t){e||null===v||(e=new h),b=null,n=null,y=null,null===v?t(e):(v=t,s(w)&&o(w,e))},S}},7833(e,t,n){t.formatArgs=function(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+e.exports.humanize(this.diff),!this.useColors)return;const n="color: "+this.color;t.splice(1,0,n,"color: inherit");let i=0,r=0;t[0].replace(/%[a-zA-Z%]/g,e=>{"%%"!==e&&(i++,"%c"===e&&(r=i))}),t.splice(r,0,n)},t.save=function(e){try{e?t.storage.setItem("debug",e):t.storage.removeItem("debug")}catch(e){}},t.load=function(){let e;try{e=t.storage.getItem("debug")||t.storage.getItem("DEBUG")}catch(e){}!e&&"undefined"!=typeof process&&"env"in process&&(e=process.env.DEBUG);return e},t.useColors=function(){if("undefined"!=typeof window&&window.process&&("renderer"===window.process.type||window.process.__nwjs))return!0;if("undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let e;return"undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&(e=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(e[1],10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)},t.storage=function(){try{return localStorage}catch(e){}}(),t.destroy=(()=>{let e=!1;return()=>{e||(e=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),t.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],t.log=console.debug||console.log||(()=>{}),e.exports=n(736)(t);const{formatters:i}=e.exports;i.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}},7927(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.SpatialAwarenessPlugin=void 0;const a=s(n(7562)),c=n(6117),l=s(n(9896)),d=s(n(6928)),u=n(1554),p=n(4997),h=n(5389),f=n(7136),g=n(4386),m=n(5471),y=n(2846),b=n(7279),v=n(3874),S=n(1711),_=n(8462),{deviceManager:w,systemManager:k,mediaManager:I}=a.default,x="tracking-zone:",C="global-tracker";class E extends a.ScryptedDeviceBase{trackingEngine=null;trackingState;alertManager;mqttPublisher=null;discoveryEngine=null;devices=new Map;storageSettings=new c.StorageSettings(this,{topology:{title:"Camera Topology",type:"string",description:"JSON configuration of camera relationships",hide:!0},floorPlanImage:{title:"Floor Plan Image",type:"string",hide:!0},correlationWindow:{title:"Correlation Window (seconds)",type:"number",defaultValue:30,description:"Maximum time to wait for an object to appear on connected camera",group:"Tracking"},correlationThreshold:{title:"Correlation Confidence Threshold",type:"number",defaultValue:.35,description:"Minimum confidence (0-1) for automatic object correlation. Lower values allow more matches.",group:"Tracking"},lostTimeout:{title:"Lost Object Timeout (seconds)",type:"number",defaultValue:300,description:"Time before marking a tracked object as lost",group:"Tracking"},useVisualMatching:{title:"Use Visual Matching",type:"boolean",defaultValue:!0,description:"Use visual embeddings for object correlation (requires compatible detectors)",group:"Tracking"},loiteringThreshold:{title:"Loitering Threshold (seconds)",type:"number",defaultValue:3,description:"Object must be visible for this duration before triggering movement alerts",group:"Tracking"},objectAlertCooldown:{title:"Per-Object Alert Cooldown (seconds)",type:"number",defaultValue:30,description:"Minimum time between alerts for the same tracked object",group:"Tracking"},useLlmDescriptions:{title:"Use LLM for Rich Descriptions",type:"boolean",defaultValue:!0,description:'Use LLM plugin (if installed) to generate descriptive alerts like "Man walking from garage towards front door"',group:"AI & Spatial Reasoning"},llmDebounceInterval:{title:"LLM Rate Limit (seconds)",type:"number",defaultValue:10,description:"Minimum time between LLM calls to prevent API overload (0 = no limit)",group:"AI & Spatial Reasoning"},llmFallbackEnabled:{title:"Fallback to Basic Notifications",type:"boolean",defaultValue:!0,description:"When LLM is rate-limited or slow, fall back to basic notifications immediately",group:"AI & Spatial Reasoning"},llmFallbackTimeout:{title:"LLM Timeout (seconds)",type:"number",defaultValue:3,description:"Maximum time to wait for LLM response before falling back to basic notification",group:"AI & Spatial Reasoning"},enableTransitTimeLearning:{title:"Learn Transit Times",type:"boolean",defaultValue:!0,description:"Automatically adjust connection transit times based on observed movement patterns",group:"AI & Spatial Reasoning"},enableConnectionSuggestions:{title:"Suggest Camera Connections",type:"boolean",defaultValue:!0,description:"Automatically suggest new camera connections based on observed movement patterns",group:"AI & Spatial Reasoning"},enableLandmarkLearning:{title:"Learn Landmarks from AI",type:"boolean",defaultValue:!0,description:"Allow AI to suggest new landmarks based on detected objects and camera context",group:"AI & Spatial Reasoning"},landmarkConfidenceThreshold:{title:"Landmark Suggestion Confidence",type:"number",defaultValue:.7,description:"Minimum AI confidence (0-1) to suggest a landmark",group:"AI & Spatial Reasoning"},discoveryIntervalHours:{title:"Auto-Discovery Interval (hours)",type:"number",defaultValue:0,description:"Automatically scan cameras to discover landmarks and connections. Set to 0 to disable. Uses vision LLM to analyze camera views.",group:"Auto-Topology Discovery"},minLandmarkConfidence:{title:"Min Landmark Confidence",type:"number",defaultValue:.6,description:"Minimum confidence (0-1) for discovered landmarks",group:"Auto-Topology Discovery"},minConnectionConfidence:{title:"Min Connection Confidence",type:"number",defaultValue:.5,description:"Minimum confidence (0-1) for suggested camera connections",group:"Auto-Topology Discovery"},autoAcceptThreshold:{title:"Auto-Accept Threshold",type:"number",defaultValue:.85,description:"Suggestions above this confidence are automatically accepted (0-1)",group:"Auto-Topology Discovery"},enableMqtt:{title:"Enable MQTT",type:"boolean",defaultValue:!1,group:"MQTT Integration"},mqttBroker:{title:"MQTT Broker URL",type:"string",placeholder:"mqtt://localhost:1883",group:"MQTT Integration"},mqttUsername:{title:"MQTT Username",type:"string",group:"MQTT Integration"},mqttPassword:{title:"MQTT Password",type:"password",group:"MQTT Integration"},mqttBaseTopic:{title:"MQTT Base Topic",type:"string",defaultValue:"scrypted/spatial-awareness",group:"MQTT Integration"},enableAlerts:{title:"Enable Alerts",type:"boolean",defaultValue:!0,group:"Alerts"},defaultNotifiers:{title:"Notifiers",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${a.ScryptedInterface.Notifier}')`,description:"Select one or more notifiers to receive alerts",group:"Alerts"},trackedCameras:{title:"Cameras to Track",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${a.ScryptedInterface.ObjectDetector}')`,group:"Cameras",description:"Select cameras with object detection to track"},alertRules:{title:"Alert Rules",type:"string",hide:!0}});constructor(e){super(e),this.trackingState=new h.TrackingState(this.storage,this.console),this.alertManager=new g.AlertManager(this.console,this.storage),process.nextTick(()=>this.initialize())}async initialize(){this.console.log("Initializing Spatial Awareness Plugin"),await w.onDeviceDiscovered({nativeId:C,name:"Global Object Tracker",type:a.ScryptedDeviceType.Sensor,interfaces:[a.ScryptedInterface.OccupancySensor,a.ScryptedInterface.Settings,a.ScryptedInterface.Readme]});const e=this.storage.getItem("topology");if(e)try{const t=JSON.parse(e);await this.startTrackingEngine(t)}catch(e){this.console.error("Failed to parse topology:",e)}const t=this.storage.getItem("alertRules");if(t)try{const e=JSON.parse(t);this.alertManager.setRules(e)}catch(e){this.console.error("Failed to parse alert rules:",e),this.alertManager.setRules((0,p.createDefaultRules)())}else this.alertManager.setRules((0,p.createDefaultRules)());this.storageSettings.values.enableMqtt&&await this.initializeMqtt(),this.console.log("Spatial Awareness Plugin initialized")}async initializeMqtt(){const e=this.storageSettings.values.mqttBroker;if(!e)return void this.console.warn("MQTT enabled but no broker URL configured");const t={broker:e,username:this.storageSettings.values.mqttUsername,password:this.storageSettings.values.mqttPassword,baseTopic:this.storageSettings.values.mqttBaseTopic||"scrypted/spatial-awareness"};this.mqttPublisher=new b.MqttPublisher(t,this.console),await this.mqttPublisher.connect(),this.trackingState.onStateChange(e=>{this.mqttPublisher?.publishState(e)}),this.console.log("MQTT publisher initialized")}async startTrackingEngine(e){this.trackingEngine&&await this.trackingEngine.stopTracking();const t={correlationWindow:1e3*(this.storageSettings.values.correlationWindow||30),correlationThreshold:this.storageSettings.values.correlationThreshold||.35,lostTimeout:1e3*(this.storageSettings.values.lostTimeout||300),useVisualMatching:this.storageSettings.values.useVisualMatching??!0,loiteringThreshold:1e3*(this.storageSettings.values.loiteringThreshold||3),objectAlertCooldown:1e3*(this.storageSettings.values.objectAlertCooldown||30),useLlmDescriptions:this.storageSettings.values.useLlmDescriptions??!0,llmDebounceInterval:1e3*(this.storageSettings.values.llmDebounceInterval||10),llmFallbackEnabled:this.storageSettings.values.llmFallbackEnabled??!0,llmFallbackTimeout:1e3*(this.storageSettings.values.llmFallbackTimeout||3),enableTransitTimeLearning:this.storageSettings.values.enableTransitTimeLearning??!0,enableConnectionSuggestions:this.storageSettings.values.enableConnectionSuggestions??!0,enableLandmarkLearning:this.storageSettings.values.enableLandmarkLearning??!0,landmarkConfidenceThreshold:this.storageSettings.values.landmarkConfidenceThreshold??.7};this.trackingEngine=new f.TrackingEngine(e,this.trackingState,this.alertManager,t,this.console),this.trackingEngine.setTopologyChangeCallback(e=>{this.storage.setItem("topology",JSON.stringify(e)),this.console.log("Topology auto-saved after change")}),await this.trackingEngine.startTracking(),this.console.log("Tracking engine started"),await this.initializeDiscoveryEngine(e)}async initializeDiscoveryEngine(e){const t={discoveryIntervalHours:this.storageSettings.values.discoveryIntervalHours??0,autoAcceptThreshold:this.storageSettings.values.autoAcceptThreshold??.85,minLandmarkConfidence:this.storageSettings.values.minLandmarkConfidence??.6,minConnectionConfidence:this.storageSettings.values.minConnectionConfidence??.5};this.discoveryEngine?(this.discoveryEngine.updateConfig(t),this.discoveryEngine.updateTopology(e)):(this.discoveryEngine=new _.TopologyDiscoveryEngine(t,this.console),this.discoveryEngine.updateTopology(e),t.discoveryIntervalHours>0&&this.discoveryEngine.startPeriodicDiscovery())}async getDevice(e){let t=this.devices.get(e);return t||(e===C?t=new m.GlobalTrackerSensor(this,e,this.trackingState):e.startsWith(x)&&(t=new y.TrackingZone(this,e,this.trackingState)),t&&this.devices.set(e,t)),t}async releaseDevice(e,t){this.devices.delete(t)}async getCreateDeviceSettings(){return[{key:"name",title:"Zone Name",description:"Name for this tracking zone",type:"string"},{key:"type",title:"Zone Type",type:"string",choices:["entry","exit","dwell","restricted"],value:"entry"},{key:"cameras",title:"Cameras",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${a.ScryptedInterface.ObjectDetector}')`}]}async createDevice(e){const t=x+Date.now().toString();return await w.onDeviceDiscovered({nativeId:t,name:e.name||"Tracking Zone",type:a.ScryptedDeviceType.Sensor,interfaces:[a.ScryptedInterface.OccupancySensor,a.ScryptedInterface.MotionSensor,a.ScryptedInterface.Settings]}),this.storage.setItem(`zone:${t}`,JSON.stringify({type:e.type,cameras:e.cameras})),t}async getSettings(){const e=await this.storageSettings.getSettings(),t=[],n=n=>{e.filter(e=>e.group===n).forEach(e=>t.push(e))};t.push({key:"trainingMode",title:"Training Mode",type:"html",value:"\n <style>\n .sa-training-container {\n padding: 16px;\n background: rgba(255,255,255,0.03);\n border-radius: 4px;\n border: 1px solid rgba(255,255,255,0.08);\n }\n .sa-training-title {\n color: #4fc3f7;\n font-size: 14px;\n font-weight: 500;\n margin-bottom: 8px;\n font-family: inherit;\n }\n .sa-training-desc {\n color: rgba(255,255,255,0.6);\n margin-bottom: 12px;\n font-size: 13px;\n line-height: 1.5;\n font-family: inherit;\n }\n .sa-training-btn {\n background: #4fc3f7;\n color: #000;\n border: none;\n padding: 10px 20px;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n transition: background 0.2s;\n font-family: inherit;\n }\n .sa-training-btn:hover {\n background: #81d4fa;\n }\n .sa-training-steps {\n color: rgba(255,255,255,0.5);\n font-size: 12px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid rgba(255,255,255,0.05);\n font-family: inherit;\n }\n .sa-training-steps ol {\n margin: 6px 0 0 16px;\n padding: 0;\n }\n .sa-training-steps li {\n margin-bottom: 2px;\n }\n </style>\n <div class=\"sa-training-container\">\n <div class=\"sa-training-title\">Guided Property Training</div>\n <p class=\"sa-training-desc\">Walk your property while the system learns your camera layout, transit times, and landmarks automatically.</p>\n <button class=\"sa-training-btn\" onclick=\"(function(){var e=document.getElementById('sa-training-modal');if(e)e.remove();var m=document.createElement('div');m.id='sa-training-modal';m.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.85);z-index:2147483647;display:flex;align-items:center;justify-content:center;';var c=document.createElement('div');c.style.cssText='width:min(420px,95vw);height:92vh;max-height:900px;background:#121212;border-radius:8px;overflow:hidden;position:relative;box-shadow:0 8px 32px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.1);';var b=document.createElement('button');b.innerHTML='×';b.style.cssText='position:absolute;top:8px;right:8px;z-index:2147483647;background:rgba(255,255,255,0.1);color:white;border:none;width:32px;height:32px;border-radius:4px;font-size:18px;cursor:pointer;line-height:1;';b.onclick=function(){m.remove();};var f=document.createElement('iframe');f.src='/endpoint/@blueharford/scrypted-spatial-awareness/ui/training';f.style.cssText='width:100%;height:100%;border:none;';c.appendChild(b);c.appendChild(f);m.appendChild(c);m.onclick=function(ev){if(ev.target===m)m.remove();};document.body.appendChild(m);})()\">\n Start Training Mode\n </button>\n <div class=\"sa-training-steps\">\n <strong>How it works:</strong>\n <ol>\n <li>Start training and walk to each camera</li>\n <li>System auto-detects you and records transit times</li>\n <li>Mark landmarks as you encounter them</li>\n <li>Apply results to generate your topology</li>\n </ol>\n </div>\n </div>\n ",group:"Getting Started"});t.push({key:"topologyEditor",title:"Topology Editor",type:"html",value:"\n <style>\n .sa-open-btn {\n background: #4fc3f7;\n color: #000;\n border: none;\n padding: 10px 20px;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n transition: background 0.2s;\n font-family: inherit;\n }\n .sa-open-btn:hover {\n background: #81d4fa;\n }\n .sa-btn-container {\n padding: 16px;\n background: rgba(255,255,255,0.03);\n border-radius: 4px;\n text-align: center;\n border: 1px solid rgba(255,255,255,0.08);\n }\n .sa-btn-desc {\n color: rgba(255,255,255,0.6);\n margin-bottom: 12px;\n font-size: 13px;\n font-family: inherit;\n }\n </style>\n <div class=\"sa-btn-container\">\n <p class=\"sa-btn-desc\">Configure camera positions, connections, and transit times</p>\n <button class=\"sa-open-btn\" onclick=\"(function(){var e=document.getElementById('sa-topology-modal');if(e)e.remove();var m=document.createElement('div');m.id='sa-topology-modal';m.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.85);z-index:2147483647;display:flex;align-items:center;justify-content:center;';var c=document.createElement('div');c.style.cssText='width:95vw;height:92vh;max-width:1800px;background:#121212;border-radius:8px;overflow:hidden;position:relative;box-shadow:0 8px 32px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.1);';var b=document.createElement('button');b.innerHTML='×';b.style.cssText='position:absolute;top:8px;right:8px;z-index:2147483647;background:rgba(255,255,255,0.1);color:white;border:none;width:32px;height:32px;border-radius:4px;font-size:18px;cursor:pointer;line-height:1;';b.onclick=function(){m.remove();};var f=document.createElement('iframe');f.src='/endpoint/@blueharford/scrypted-spatial-awareness/ui/editor';f.style.cssText='width:100%;height:100%;border:none;';c.appendChild(b);c.appendChild(f);m.appendChild(c);m.onclick=function(ev){if(ev.target===m)m.remove();};document.body.appendChild(m);})()\">\n Open Topology Editor\n </button>\n </div>\n ",group:"Topology"}),n("Cameras");const i=this.trackingState.getActiveCount(),r=this.storage.getItem("topology");let o="Not configured - add cameras and configure topology";if(this.trackingEngine)o=`Active: Tracking ${i} object${1!==i?"s":""}`;else if(r)try{const e=JSON.parse(r);e.cameras&&e.cameras.length>0&&(o=`Configured (${e.cameras.length} cameras) - Starting...`,this.startTrackingEngine(e).catch(e=>{this.console.error("Failed to restart tracking engine:",e)}))}catch(e){o="Error loading topology"}t.push({key:"status",title:"Tracking Status",type:"string",readonly:!0,value:o,group:"Status"});const s=this.alertManager.getRecentAlerts(5);s.length>0&&t.push({key:"recentAlerts",title:"Recent Alerts",type:"string",readonly:!0,value:s.map(e=>`${e.type}: ${e.message}`).join("\n"),group:"Status"}),n("Tracking"),n("AI & Spatial Reasoning"),n("Auto-Topology Discovery"),n("Alerts");const a=this.alertManager.getRules(),c=this.generateAlertRulesHtml(a);return t.push({key:"alertRulesEditor",title:"Alert Rules",type:"html",value:c,group:"Alerts"}),n("MQTT Integration"),t}generateAlertRulesHtml(e){return`\n <style>\n .sa-rules-table { width:100%; border-collapse:collapse; margin-top:10px; }\n .sa-rules-table th { text-align:left; padding:10px 8px; border-bottom:2px solid #e94560; color:#e94560; font-size:13px; }\n .sa-save-rules-btn {\n background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);\n color: white;\n border: none;\n padding: 10px 20px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n margin-top: 15px;\n }\n .sa-save-rules-btn:hover { opacity: 0.9; }\n .sa-rules-container { background:#16213e; border-radius:8px; padding:15px; }\n .sa-rules-desc { color:#888; font-size:13px; margin-bottom:10px; }\n </style>\n <div class="sa-rules-container">\n <p class="sa-rules-desc">Enable or disable alert types. Movement alerts notify you when someone moves between cameras.</p>\n <table class="sa-rules-table">\n <thead>\n <tr>\n <th style="width:40px;">On</th>\n <th>Alert Type</th>\n <th>Event</th>\n <th>Severity</th>\n <th>Cooldown</th>\n </tr>\n </thead>\n <tbody>\n ${e.map(e=>`\n <tr data-rule-id="${e.id}">\n <td style="padding:8px;border-bottom:1px solid #333;">\n <input type="checkbox" ${e.enabled?"checked":""}\n onchange="(function(el){var rules=JSON.parse(localStorage.getItem('sa-temp-rules')||'[]');var r=rules.find(x=>x.id==='${e.id}');if(r)r.enabled=el.checked;localStorage.setItem('sa-temp-rules',JSON.stringify(rules));})(this)" />\n </td>\n <td style="padding:8px;border-bottom:1px solid #333;color:#fff;">${e.name}</td>\n <td style="padding:8px;border-bottom:1px solid #333;color:#888;">${e.type}</td>\n <td style="padding:8px;border-bottom:1px solid #333;">\n <span style="padding:2px 8px;border-radius:4px;font-size:12px;background:${"critical"===e.severity?"#e94560":"warning"===e.severity?"#f39c12":"#3498db"};color:white;">${e.severity}</span>\n </td>\n <td style="padding:8px;border-bottom:1px solid #333;color:#888;">${Math.round(e.cooldown/1e3)}s</td>\n </tr>\n `).join("")}\n </tbody>\n </table>\n <button class="sa-save-rules-btn" onclick="(function(){var rules=JSON.parse(localStorage.getItem('sa-temp-rules')||'[]');fetch('/endpoint/@blueharford/scrypted-spatial-awareness/api/alert-rules',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(rules)}).then(r=>r.json()).then(d=>{if(d.success)alert('Alert rules saved!');else alert('Error: '+d.error);}).catch(e=>alert('Error: '+e));})()">Save Alert Rules</button>\n <script>(function(){${`localStorage.setItem('sa-temp-rules',JSON.stringify(${JSON.stringify(e)}))`}})();<\/script>\n </div>\n `}async putSetting(e,t){if(await this.storageSettings.putSetting(e,t),"trackedCameras"===e||"correlationWindow"===e||"correlationThreshold"===e||"lostTimeout"===e||"useVisualMatching"===e||"loiteringThreshold"===e||"objectAlertCooldown"===e||"useLlmDescriptions"===e||"llmDebounceInterval"===e||"llmFallbackEnabled"===e||"llmFallbackTimeout"===e||"enableTransitTimeLearning"===e||"enableConnectionSuggestions"===e||"enableLandmarkLearning"===e||"landmarkConfidenceThreshold"===e){const e=this.storage.getItem("topology");if(e)try{const t=JSON.parse(e);await this.startTrackingEngine(t)}catch(e){this.console.error("Failed to restart tracking engine:",e)}}"enableMqtt"!==e&&"mqttBroker"!==e&&"mqttUsername"!==e&&"mqttPassword"!==e&&"mqttBaseTopic"!==e||(this.mqttPublisher&&(this.mqttPublisher.disconnect(),this.mqttPublisher=null),this.storageSettings.values.enableMqtt&&await this.initializeMqtt())}async onRequest(e,t){const n=new URL(e.url,"http://localhost").pathname;try{if(n.endsWith("/api/tracked-objects"))return this.handleTrackedObjectsRequest(e,t);if(n.match(/\/api\/journey\/[\w-]+$/)){const e=n.split("/").pop();return this.handleJourneyRequest(e,t)}if(n.endsWith("/api/topology"))return await this.handleTopologyRequest(e,t);if(n.endsWith("/api/alerts"))return this.handleAlertsRequest(e,t);if(n.endsWith("/api/alert-rules"))return this.handleAlertRulesRequest(e,t);if(n.endsWith("/api/cameras"))return this.handleCamerasRequest(t);if(n.endsWith("/api/floor-plan"))return this.handleFloorPlanRequest(e,t);if(n.endsWith("/api/landmarks"))return this.handleLandmarksRequest(e,t);if(n.match(/\/api\/landmarks\/[\w-]+$/)){const i=n.split("/").pop();return this.handleLandmarkRequest(i,e,t)}if(n.endsWith("/api/landmark-suggestions"))return this.handleLandmarkSuggestionsRequest(e,t);if(n.match(/\/api\/landmark-suggestions\/[\w-]+\/(accept|reject)$/)){const e=n.split("/"),i=e.pop(),r=e.pop();return this.handleSuggestionActionRequest(r,i,t)}if(n.endsWith("/api/landmark-templates"))return this.handleLandmarkTemplatesRequest(t);if(n.endsWith("/api/infer-relationships"))return this.handleInferRelationshipsRequest(t);if(n.endsWith("/api/connection-suggestions"))return this.handleConnectionSuggestionsRequest(e,t);if(n.match(/\/api\/connection-suggestions\/[\w->]+\/(accept|reject)$/)){const e=n.split("/"),i=e.pop(),r=e.pop();return this.handleConnectionSuggestionActionRequest(r,i,t)}if(n.endsWith("/api/live-tracking"))return this.handleLiveTrackingRequest(t);if(n.match(/\/api\/journey-path\/[\w-]+$/)){const e=n.split("/").pop();return this.handleJourneyPathRequest(e,t)}if(n.endsWith("/api/training/start"))return this.handleTrainingStartRequest(e,t);if(n.endsWith("/api/training/pause"))return this.handleTrainingPauseRequest(t);if(n.endsWith("/api/training/resume"))return this.handleTrainingResumeRequest(t);if(n.endsWith("/api/training/end"))return this.handleTrainingEndRequest(t);if(n.endsWith("/api/training/status"))return this.handleTrainingStatusRequest(t);if(n.endsWith("/api/training/landmark"))return this.handleTrainingLandmarkRequest(e,t);if(n.endsWith("/api/training/apply"))return this.handleTrainingApplyRequest(t);if(n.endsWith("/api/discovery/scan"))return this.handleDiscoveryScanRequest(t);if(n.endsWith("/api/discovery/status"))return this.handleDiscoveryStatusRequest(t);if(n.endsWith("/api/discovery/suggestions"))return this.handleDiscoverySuggestionsRequest(t);if(n.match(/\/api\/discovery\/suggestions\/[\w-]+\/(accept|reject)$/)){const e=n.split("/"),i=e.pop(),r=e.pop();return this.handleDiscoverySuggestionActionRequest(r,i,t)}if(n.match(/\/api\/discovery\/camera\/[\w-]+$/)){const e=n.split("/").pop();return this.handleDiscoveryCameraAnalysisRequest(e,t)}if(n.endsWith("/ui/editor")||n.endsWith("/ui/editor/"))return this.serveEditorUI(t);if(n.endsWith("/ui/training")||n.endsWith("/ui/training/"))return this.serveTrainingUI(t);if(n.includes("/ui/"))return this.serveStaticFile(n,t);t.send(JSON.stringify({name:"Spatial Awareness Plugin",version:"0.5.0-beta",endpoints:{api:{trackedObjects:"/api/tracked-objects",journey:"/api/journey/{globalId}",journeyPath:"/api/journey-path/{globalId}",topology:"/api/topology",alerts:"/api/alerts",floorPlan:"/api/floor-plan",liveTracking:"/api/live-tracking",connectionSuggestions:"/api/connection-suggestions",landmarkSuggestions:"/api/landmark-suggestions",training:{start:"/api/training/start",pause:"/api/training/pause",resume:"/api/training/resume",end:"/api/training/end",status:"/api/training/status",landmark:"/api/training/landmark",apply:"/api/training/apply"},discovery:{scan:"/api/discovery/scan",status:"/api/discovery/status",suggestions:"/api/discovery/suggestions",camera:"/api/discovery/camera/{cameraId}"}},ui:{editor:"/ui/editor",training:"/ui/training"}}}),{headers:{"Content-Type":"application/json"}})}catch(e){this.console.error("HTTP request error:",e),t.send(JSON.stringify({error:e.message}),{code:500,headers:{"Content-Type":"application/json"}})}}handleTrackedObjectsRequest(e,t){const n=this.trackingState.getAllObjects();t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}handleJourneyRequest(e,t){const n=this.trackingState.getObject(e);n?t.send(JSON.stringify({globalId:n.globalId,className:n.className,label:n.label,journey:n.journey,sightings:n.sightings.map(e=>({cameraId:e.cameraId,cameraName:e.cameraName,timestamp:e.timestamp})),firstSeen:n.firstSeen,lastSeen:n.lastSeen,state:n.state}),{headers:{"Content-Type":"application/json"}}):t.send(JSON.stringify({error:"Object not found"}),{code:404,headers:{"Content-Type":"application/json"}})}async handleTopologyRequest(e,t){if("GET"===e.method){const e=this.storage.getItem("topology"),n=e?JSON.parse(e):(0,u.createEmptyTopology)();t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}else if("PUT"===e.method||"POST"===e.method)try{const n=JSON.parse(e.body);this.storage.setItem("topology",JSON.stringify(n)),await this.startTrackingEngine(n),t.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid topology JSON"}),{code:400,headers:{"Content-Type":"application/json"}})}}handleAlertsRequest(e,t){const n=this.alertManager.getRecentAlerts();t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}handleAlertRulesRequest(e,t){if("GET"===e.method){const e=this.alertManager.getRules();t.send(JSON.stringify(e),{headers:{"Content-Type":"application/json"}})}else if("PUT"===e.method||"POST"===e.method)try{const n=JSON.parse(e.body);this.alertManager.setRules(n),t.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid rules JSON"}),{code:400,headers:{"Content-Type":"application/json"}})}}handleCamerasRequest(e){try{const t=[];for(const e of Object.keys(k.getSystemState()))try{const n=k.getDeviceById(e);n&&n.interfaces?.includes(a.ScryptedInterface.ObjectDetector)&&t.push({id:e,name:n.name||`Camera ${e}`})}catch(e){}e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}catch(t){this.console.error("Error getting cameras:",t),e.send(JSON.stringify([]),{headers:{"Content-Type":"application/json"}})}}async getFloorPlanPath(){const e=await I.getFilesPath();return this.console.log("Files path from mediaManager:",e),l.existsSync(e)||l.mkdirSync(e,{recursive:!0}),d.join(e,"floorplan.jpg")}async handleFloorPlanRequest(e,t){if("GET"===e.method)try{const e=await this.getFloorPlanPath();if(this.console.log("Loading floor plan from:",e,"exists:",l.existsSync(e)),l.existsSync(e)){const n=l.readFileSync(e),i="data:image/jpeg;base64,"+n.toString("base64");this.console.log("Floor plan loaded, size:",n.length),t.send(JSON.stringify({imageData:i}),{headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({imageData:null}),{headers:{"Content-Type":"application/json"}})}catch(e){this.console.error("Failed to read floor plan:",e),t.send(JSON.stringify({imageData:null}),{headers:{"Content-Type":"application/json"}})}else if("POST"===e.method)try{const n=JSON.parse(e.body),i=n.imageData.replace(/^data:image\/\w+;base64,/,""),r=Buffer.from(i,"base64"),o=await this.getFloorPlanPath();l.writeFileSync(o,r),this.console.log("Floor plan saved to:",o,"size:",r.length),t.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}catch(e){this.console.error("Failed to save floor plan:",e),t.send(JSON.stringify({error:"Failed to save floor plan"}),{code:500,headers:{"Content-Type":"application/json"}})}}handleLandmarksRequest(e,t){const n=this.getTopology();if(n){if("GET"===e.method)t.send(JSON.stringify({landmarks:n.landmarks||[]}),{headers:{"Content-Type":"application/json"}});else if("POST"===e.method)try{const i=JSON.parse(e.body);i.id||(i.id=`landmark_${Date.now()}`),n.landmarks||(n.landmarks=[]),n.landmarks.push(i),this.storage.setItem("topology",JSON.stringify(n)),this.trackingEngine&&this.trackingEngine.updateTopology(n),t.send(JSON.stringify({success:!0,landmark:i}),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid landmark data"}),{code:400,headers:{"Content-Type":"application/json"}})}}else t.send(JSON.stringify({landmarks:[]}),{headers:{"Content-Type":"application/json"}})}handleLandmarkRequest(e,t,n){const i=this.getTopology();if(!i)return void n.send(JSON.stringify({error:"No topology configured"}),{code:404,headers:{"Content-Type":"application/json"}});const r=i.landmarks?.findIndex(t=>t.id===e)??-1;if("GET"===t.method){const e=i.landmarks?.[r];e?n.send(JSON.stringify(e),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Landmark not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("PUT"===t.method)try{const o=JSON.parse(t.body);r>=0?(i.landmarks[r]={...i.landmarks[r],...o,id:e},this.storage.setItem("topology",JSON.stringify(i)),this.trackingEngine&&this.trackingEngine.updateTopology(i),n.send(JSON.stringify({success:!0,landmark:i.landmarks[r]}),{headers:{"Content-Type":"application/json"}})):n.send(JSON.stringify({error:"Landmark not found"}),{code:404,headers:{"Content-Type":"application/json"}})}catch(e){n.send(JSON.stringify({error:"Invalid landmark data"}),{code:400,headers:{"Content-Type":"application/json"}})}else"DELETE"===t.method&&(r>=0?(i.landmarks.splice(r,1),this.storage.setItem("topology",JSON.stringify(i)),this.trackingEngine&&this.trackingEngine.updateTopology(i),n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})):n.send(JSON.stringify({error:"Landmark not found"}),{code:404,headers:{"Content-Type":"application/json"}}))}handleLandmarkSuggestionsRequest(e,t){if(!this.trackingEngine)return void t.send(JSON.stringify({suggestions:[]}),{headers:{"Content-Type":"application/json"}});const n=this.trackingEngine.getPendingLandmarkSuggestions();t.send(JSON.stringify({suggestions:n,count:n.length}),{headers:{"Content-Type":"application/json"}})}handleSuggestionActionRequest(e,t,n){if(this.trackingEngine)if("accept"===t){const t=this.trackingEngine.acceptLandmarkSuggestion(e);t?n.send(JSON.stringify({success:!0,landmark:t}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("reject"===t){this.trackingEngine.rejectLandmarkSuggestion(e)?n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Invalid action"}),{code:400,headers:{"Content-Type":"application/json"}});else n.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}})}handleLandmarkTemplatesRequest(e){e.send(JSON.stringify({templates:u.LANDMARK_TEMPLATES}),{headers:{"Content-Type":"application/json"}})}handleInferRelationshipsRequest(e){const t=this.getTopology();if(!t)return void e.send(JSON.stringify({relationships:[]}),{headers:{"Content-Type":"application/json"}});const n=(0,u.inferRelationships)(t);e.send(JSON.stringify({relationships:n,count:n.length}),{headers:{"Content-Type":"application/json"}})}handleConnectionSuggestionsRequest(e,t){if(!this.trackingEngine)return void t.send(JSON.stringify({suggestions:[]}),{headers:{"Content-Type":"application/json"}});const n=this.trackingEngine.getConnectionSuggestions();t.send(JSON.stringify({suggestions:n,count:n.length}),{headers:{"Content-Type":"application/json"}})}handleConnectionSuggestionActionRequest(e,t,n){if(this.trackingEngine)if("accept"===t){const t=this.trackingEngine.acceptConnectionSuggestion(e);if(t){const e=this.trackingEngine.getTopology();this.storage.setItem("topology",JSON.stringify(e)),n.send(JSON.stringify({success:!0,connection:t}),{headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("reject"===t){this.trackingEngine.rejectConnectionSuggestion(e)?n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Invalid action"}),{code:400,headers:{"Content-Type":"application/json"}});else n.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}})}handleLiveTrackingRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({objects:[],timestamp:Date.now()}),{headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.getLiveTrackingState();e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}handleJourneyPathRequest(e,t){if(!this.trackingEngine)return void t.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});const n=this.trackingEngine.getJourneyPath(e);n?t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}):t.send(JSON.stringify({error:"Object not found"}),{code:404,headers:{"Content-Type":"application/json"}})}handleTrainingStartRequest(e,t){if(this.trackingEngine)try{let n,i;if(e.body){const t=JSON.parse(e.body);i=t.trainerName,n=t.config}const r=this.trackingEngine.startTrainingSession(i,n);t.send(JSON.stringify(r),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:e.message}),{code:500,headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({error:"Tracking engine not running. Configure topology first."}),{code:500,headers:{"Content-Type":"application/json"}})}handleTrainingPauseRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});this.trackingEngine.pauseTrainingSession()?e.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):e.send(JSON.stringify({error:"No active training session to pause"}),{code:400,headers:{"Content-Type":"application/json"}})}handleTrainingResumeRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});this.trackingEngine.resumeTrainingSession()?e.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):e.send(JSON.stringify({error:"No paused training session to resume"}),{code:400,headers:{"Content-Type":"application/json"}})}async handleTrainingEndRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.endTrainingSession();if(t){const n=[...new Set(t.visits.map(e=>e.cameraId))];if(this.discoveryEngine&&n.length>0){this.console.log(`[Training] Running discovery analysis on ${n.length} visited cameras...`);let e=0,t=0;for(const i of n)try{const n=await this.discoveryEngine.analyzeScene(i);n.isValid&&(e+=n.landmarks.length,t+=n.zones.length,this.console.log(`[Training] ${i}: Found ${n.landmarks.length} landmarks, ${n.zones.length} zones`))}catch(e){this.console.warn(`[Training] Failed to analyze ${i}:`,e)}const i=this.discoveryEngine.getPendingSuggestions();for(const e of i)this.applyDiscoverySuggestion(e),this.discoveryEngine.acceptSuggestion(e.id);if(i.length>0&&this.trackingEngine){const n=this.trackingEngine.getTopology();await this.storageSettings.putSetting("topology",JSON.stringify(n)),this.console.log(`[Training] Auto-applied ${i.length} discoveries (${e} landmarks, ${t} zones)`)}}e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}else e.send(JSON.stringify({error:"No training session to end"}),{code:400,headers:{"Content-Type":"application/json"}})}handleTrainingStatusRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({state:"idle",stats:null}),{headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.getTrainingStatus();t?e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}}):e.send(JSON.stringify({state:"idle",stats:null}),{headers:{"Content-Type":"application/json"}})}handleTrainingLandmarkRequest(e,t){if(this.trackingEngine)try{const n=JSON.parse(e.body),i=this.trackingEngine.markTrainingLandmark(n);i?t.send(JSON.stringify({success:!0,landmark:i}),{headers:{"Content-Type":"application/json"}}):t.send(JSON.stringify({error:"No active training session"}),{code:400,headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid request body"}),{code:400,headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}})}handleTrainingApplyRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.applyTrainingToTopology();if(t.success){const e=this.trackingEngine.getTopology();this.storage.setItem("topology",JSON.stringify(e))}e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}async handleDiscoveryScanRequest(e){if(this.discoveryEngine)try{this.console.log("[Discovery] Manual scan triggered via API");const t=await this.discoveryEngine.runFullDiscovery(),n=this.discoveryEngine.getStatus(),i=this.discoveryEngine.getPendingSuggestions();e.send(JSON.stringify({success:!0,status:n,correlation:t,suggestions:i}),{headers:{"Content-Type":"application/json"}})}catch(t){this.console.error("[Discovery] Scan failed:",t),e.send(JSON.stringify({error:`Scan failed: ${t.message}`}),{code:500,headers:{"Content-Type":"application/json"}})}else e.send(JSON.stringify({error:"Discovery engine not initialized. Configure topology first."}),{code:500,headers:{"Content-Type":"application/json"}})}handleDiscoveryStatusRequest(e){if(!this.discoveryEngine)return void e.send(JSON.stringify({isRunning:!1,isScanning:!1,lastScanTime:null,nextScanTime:null,camerasAnalyzed:0,pendingSuggestions:0}),{headers:{"Content-Type":"application/json"}});const t=this.discoveryEngine.getStatus();e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}handleDiscoverySuggestionsRequest(e){if(!this.discoveryEngine)return void e.send(JSON.stringify({suggestions:[]}),{headers:{"Content-Type":"application/json"}});const t=this.discoveryEngine.getPendingSuggestions();e.send(JSON.stringify({suggestions:t}),{headers:{"Content-Type":"application/json"}})}handleDiscoverySuggestionActionRequest(e,t,n){if(this.discoveryEngine)if("accept"===t){const t=this.discoveryEngine.acceptSuggestion(e);t?(this.applyDiscoverySuggestion(t),n.send(JSON.stringify({success:!0,suggestion:t}),{headers:{"Content-Type":"application/json"}})):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("reject"===t){this.discoveryEngine.rejectSuggestion(e)?n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Invalid action"}),{code:400,headers:{"Content-Type":"application/json"}});else n.send(JSON.stringify({error:"Discovery engine not initialized"}),{code:500,headers:{"Content-Type":"application/json"}})}async handleDiscoveryCameraAnalysisRequest(e,t){if(this.discoveryEngine)try{const n=await this.discoveryEngine.analyzeScene(e);t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:`Analysis failed: ${e.message}`}),{code:500,headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({error:"Discovery engine not initialized"}),{code:500,headers:{"Content-Type":"application/json"}})}applyDiscoverySuggestion(e){if(!this.trackingEngine)return;const t=this.trackingEngine.getTopology();let n=!1;if("landmark"===e.type&&e.landmark){let i=e.landmark.position;if(!i||0===i.x&&0===i.y){this.console.log(`[Discovery] Processing landmark "${e.landmark.name}"`),this.console.log(`[Discovery] sourceCameras: ${JSON.stringify(e.sourceCameras)}`),this.console.log(`[Discovery] visibleFromCameras: ${JSON.stringify(e.landmark.visibleFromCameras)}`),this.console.log(`[Discovery] Available cameras: ${t.cameras.map(e=>`${e.name}(${e.deviceId})`).join(", ")}`);const n=e.sourceCameras?.[0],r=e.landmark.visibleFromCameras?.[0],o=n||r,s=o?t.cameras.find(e=>e.deviceId===o||e.name===o||e.name.toLowerCase()===o.toLowerCase()):null;if(s?(this.console.log(`[Discovery] Matched camera: ${s.name} (${s.deviceId})`),this.console.log(`[Discovery] Camera position: ${JSON.stringify(s.floorPlanPosition)}`),this.console.log(`[Discovery] Camera FOV: ${JSON.stringify(s.fov)}`)):this.console.warn(`[Discovery] No camera matched for ref="${o}" (source="${n}", visible="${r}")`),s?.floorPlanPosition){const n=s.fov||{mode:"simple",angle:90,direction:0,range:80},r=n.direction||0,o=n.range||80,a=n.angle||90,c=(r-90)*Math.PI/180,l=a/2*Math.PI/180,d=e.landmark.type,u=["neighbor","boundary","street"].includes(d||""),p=e.landmark.boundingBox;let h,f;if(p&&p.length>=2){if(h=2*(p[0]+(p[2]||0)/2-.5)*l,u)f=1.5+.5*Math.random(),this.console.log(`[Discovery] Far-type landmark "${d}" placed BEYOND FOV (${(100*f).toFixed(0)}% of range)`);else{const e=p[1]+(p[3]||0)/2;f=Math.max(.4,.9-.5*e)}this.console.log(`[Discovery] Using bounding box [${p.join(",")}] for horizontal position`)}else{const e=s.deviceId,n=(t.landmarks||[]).filter(t=>t.visibleFromCameras?.includes(e)||t.visibleFromCameras?.includes(s.name)).length;h=(n%3-1)*l*.6,u?(f=1.5+.5*Math.random(),this.console.log(`[Discovery] Far-type landmark "${d}" (no bbox) placed BEYOND FOV`)):(f=.5+n%2*.3,this.console.log(`[Discovery] No bounding box, using fallback spread (existing: ${n})`))}const g=c+h,m=o*f;i={x:s.floorPlanPosition.x+Math.cos(g)*m,y:s.floorPlanPosition.y+Math.sin(g)*m},this.console.log(`[Discovery] Placing landmark "${e.landmark.name}" in ${s.name}'s FOV: dir=${r}°, angle=${(180*h/Math.PI).toFixed(1)}°, dist=${m.toFixed(0)}px`)}else{const e=t.landmarks?.length||0,n=80,r=5;i={x:200+e%r*n,y:100+Math.floor(e/r)*n}}}const r={id:`landmark_${Date.now()}`,name:e.landmark.name,type:e.landmark.type,position:i,description:e.landmark.description,visibleFromCameras:e.landmark.visibleFromCameras,aiSuggested:!0,aiConfidence:e.confidence};t.landmarks||(t.landmarks=[]),t.landmarks.push(r),n=!0,this.console.log(`[Discovery] Added landmark: ${r.name} at (${i.x}, ${i.y})`)}if("zone"===e.type&&e.zone){const i=e.zone,r=e.sourceCameras||[],o=r[0],s=o?t.cameras.find(e=>e.deviceId===o||e.name===o||e.name.toLowerCase()===o.toLowerCase()):null;this.console.log(`[Discovery] Processing zone "${i.name}" from camera ref="${o}"`),s?this.console.log(`[Discovery] Matched camera: ${s.name} (${s.deviceId})`):o&&this.console.warn(`[Discovery] No camera matched for zone source ref="${o}"`);let a=[];const c=Date.now();if(s?.floorPlanPosition){const e=s.fov||{mode:"simple",angle:90,direction:0,range:80},n=e.direction||0,o=e.range||80,c=e.angle||90,l=(n-90)*Math.PI/180,d=c/2*Math.PI/180,u=s.floorPlanPosition.x,p=s.floorPlanPosition.y,h=i.boundingBox;let f,g,m,y;if(h&&h.length>=4){const e=h[0],t=h[0]+h[2],n=h[1];m=l+2*(e-.5)*d,y=l+2*(t-.5)*d,f=o*(.9-.6*(h[1]+h[3])),g=o*(.9-.6*n),g-f<20&&(g=f+20),this.console.log(`[Discovery] Zone "${i.name}" using bbox [${h.join(",")}] → angles ${(180*m/Math.PI).toFixed(1)}° to ${(180*y/Math.PI).toFixed(1)}°`)}else{const e=(t.drawnZones||[]).filter(e=>e.linkedCameras?.includes(r[0])).length;f=.3*o+20*e,g=.8*o+20*e,m=l-.7*d,y=l+.7*d,this.console.log(`[Discovery] Zone "${i.name}" using fallback spread (existing: ${e})`)}const b=8;for(let e=0;e<=b;e++){const t=m+(y-m)*e/b;a.push({x:u+Math.cos(t)*f,y:p+Math.sin(t)*f})}for(let e=b;e>=0;e--){const t=m+(y-m)*e/b;a.push({x:u+Math.cos(t)*g,y:p+Math.sin(t)*g})}this.console.log(`[Discovery] Creating zone "${i.name}" in ${s.name}'s FOV: dir=${n}°`)}else{const e=300+120*(t.drawnZones?.length||0),n=200,i=100;a=[{x:e-i/2,y:n-i/2},{x:e+i/2,y:n-i/2},{x:e+i/2,y:n+i/2},{x:e-i/2,y:n+i/2}]}const l={id:`zone_${c}`,name:i.name,type:i.type||"custom",description:i.description,polygon:a,linkedCameras:r};t.drawnZones||(t.drawnZones=[]),t.drawnZones.push(l);const d=this.mapZoneTypeToGlobalType(i.type),u=r.map(e=>{const n=t.cameras.find(t=>t.deviceId===e||t.name===e||t.name.toLowerCase()===e.toLowerCase());return n?{cameraId:n.deviceId,zone:[[0,0],[100,0],[100,100],[0,100]]}:(this.console.warn(`[Discovery] GlobalZone: No camera matched for ref="${e}"`),null)}).filter(e=>null!==e);if(u.length>0){const e={id:`global_${c}`,name:i.name,type:d,cameraZones:u};t.globalZones||(t.globalZones=[]),t.globalZones.push(e),this.console.log(`[Discovery] Added zone: ${i.name} (${i.type}) - DrawnZone and GlobalZone created`)}else this.console.log(`[Discovery] Added zone: ${i.name} (${i.type}) - DrawnZone only (no cameras matched)`);n=!0}if("connection"===e.type&&e.connection){const i=e.connection,r=t.cameras.find(e=>e.deviceId===i.fromCameraId||e.name===i.fromCameraId||e.name.toLowerCase()===i.fromCameraId.toLowerCase()),o=t.cameras.find(e=>e.deviceId===i.toCameraId||e.name===i.toCameraId||e.name.toLowerCase()===i.toCameraId.toLowerCase());if(!r||!o)return this.console.warn(`[Discovery] Cannot create connection: camera not found. from="${i.fromCameraId}" to="${i.toCameraId}"`),void this.console.warn(`[Discovery] Available cameras: ${t.cameras.map(e=>`${e.name} (${e.deviceId})`).join(", ")}`);if(t.connections.find(e=>e.fromCameraId===r.deviceId&&e.toCameraId===o.deviceId||e.bidirectional&&e.fromCameraId===o.deviceId&&e.toCameraId===r.deviceId))return void this.console.log(`[Discovery] Connection already exists between ${r.name} and ${o.name}`);r.floorPlanPosition&&o.floorPlanPosition||this.console.warn("[Discovery] Note: One or both cameras not positioned on floor plan yet");const s={id:`conn_${Date.now()}`,fromCameraId:r.deviceId,toCameraId:o.deviceId,bidirectional:i.bidirectional,exitZone:[[0,0],[100,0],[100,100],[0,100]],entryZone:[[0,0],[100,0],[100,100],[0,100]],transitTime:{typical:1e3*i.transitSeconds,min:Math.max(1e3,500*i.transitSeconds),max:2e3*i.transitSeconds},name:i.via?`Via ${i.via}`:void 0};t.connections.push(s),n=!0,this.console.log(`[Discovery] Added connection: ${r.name} (${r.deviceId}) -> ${o.name} (${o.deviceId})`)}n&&(this.storage.setItem("topology",JSON.stringify(t)),this.trackingEngine.updateTopology(t))}mapZoneTypeToGlobalType(e){return{yard:"dwell",driveway:"entry",street:"entry",patio:"dwell",walkway:"entry",parking:"dwell",garden:"dwell",pool:"restricted",entrance:"entry",garage:"entry",deck:"dwell",custom:"dwell"}[e]||"dwell"}serveEditorUI(e){e.send(v.EDITOR_HTML,{headers:{"Content-Type":"text/html"}})}serveTrainingUI(e){e.send(S.TRAINING_HTML,{headers:{"Content-Type":"text/html"}})}serveStaticFile(e,t){t.send("Not found",{code:404})}async getReadmeMarkdown(){return"\n# Spatial Awareness Plugin\n\nThis plugin enables cross-camera object tracking across your entire NVR system.\n\n## Features\n\n- **Cross-Camera Tracking**: Correlate objects as they move between cameras\n- **Journey History**: Complete path history for each tracked object\n- **Entry/Exit Detection**: Know when objects enter or leave your property\n- **Visual Floor Plan**: Configure camera topology with a visual editor\n- **MQTT Integration**: Export tracking data to Home Assistant\n- **REST API**: Query tracked objects and journeys programmatically\n- **Smart Alerts**: Get notified about property entry/exit, unusual paths, and more\n\n## Setup\n\n1. **Add Cameras**: Select cameras with object detection in the plugin settings\n2. **Configure Topology**: Define camera relationships and transit times\n3. **Enable Integrations**: Optionally enable MQTT for Home Assistant\n4. **Create Zones**: Add tracking zones for specific area monitoring\n\n## API Endpoints\n\n- `GET /api/tracked-objects` - List all tracked objects\n- `GET /api/journey/{id}` - Get journey for specific object\n- `GET /api/topology` - Get camera topology\n- `PUT /api/topology` - Update camera topology\n- `GET /api/alerts` - Get recent alerts\n\n## Visual Editor\n\nAccess the visual topology editor at `/ui/editor` to configure camera relationships using a floor plan.\n\n## Alert Types\n\n- **Property Entry**: Object entered the property\n- **Property Exit**: Object exited the property\n- **Unusual Path**: Object took an unexpected route\n- **Dwell Time**: Object lingered too long in an area\n- **Restricted Zone**: Object entered a restricted area\n"}getTrackingState(){return this.trackingState}getAlertManager(){return this.alertManager}getTopology(){const e=this.storage.getItem("topology");return e?JSON.parse(e):null}}t.SpatialAwarenessPlugin=E,t.default=E},7969(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(4478),r={objectMode:!0},o={clean:!0};t.default=class{options;_inflights;constructor(e){this.options=e||{},this.options={...o,...e},this._inflights=new Map}put(e,t){return this._inflights.set(e.messageId,e),t&&t(),this}createStream(){const e=new i.Readable(r),t=[];let n=!1,o=0;return this._inflights.forEach((e,n)=>{t.push(e)}),e._read=()=>{!n&&o<t.length?e.push(t[o++]):e.push(null)},e.destroy=t=>{if(!n)return n=!0,setTimeout(()=>{e.emit("close")},0),e},e}del(e,t){const n=this._inflights.get(e.messageId);return n?(this._inflights.delete(e.messageId),t(null,n)):t&&t(new Error("missing packet")),this}get(e,t){const n=this._inflights.get(e.messageId);return n?t(null,n):t&&t(new Error("missing packet")),this}close(e){this.options.clean&&(this._inflights=null),e&&e()}}},8194(e,t,n){"use strict";n.d(t,{CD:()=>_});var i,r=(i=function(e,t){return i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},i(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),o=function(){function e(e,t){this.ee=1,this.u=void 0,this.p=void 0,this.K=void 0,this.N=void 0,this.rr=void 0,this.u=e,this.p=t}return e.prototype.L=function(){var e=this;if(1===e.ee&&e.rr.rr===e)e=e.N;else if(e.K)for(e=e.K;e.N;)e=e.N;else{for(var t=e.rr;t.K===e;)t=(e=t).rr;e=t}return e},e.prototype.m=function(){var e=this;if(e.N){for(e=e.N;e.K;)e=e.K;return e}for(var t=e.rr;t.N===e;)t=(e=t).rr;return e.N!==t?t:e},e.prototype.ne=function(){var e=this.rr,t=this.N,n=t.K;return e.rr===this?e.rr=t:e.K===this?e.K=t:e.N=t,t.rr=e,t.K=this,this.rr=t,this.N=n,n&&(n.rr=this),t},e.prototype.te=function(){var e=this.rr,t=this.K,n=t.N;return e.rr===this?e.rr=t:e.K===this?e.K=t:e.N=t,t.rr=e,t.N=this,this.rr=t,this.K=n,n&&(n.rr=this),t},e}(),s=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.tr=1,t}return r(t,e),t.prototype.ne=function(){var t=e.prototype.ne.call(this);return this.ie(),t.ie(),t},t.prototype.te=function(){var t=e.prototype.te.call(this);return this.ie(),t.ie(),t},t.prototype.ie=function(){this.tr=1,this.K&&(this.tr+=this.K.tr),this.N&&(this.tr+=this.N.tr)},t}(o),a=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),c=function(){function e(e){void 0===e&&(e=0),this.iteratorType=e}return e.prototype.equals=function(e){return this.o===e.o},e}(),l=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return a(t,e),t}(function(){function e(){this.M=0}return Object.defineProperty(e.prototype,"length",{get:function(){return this.M},enumerable:!1,configurable:!0}),e.prototype.size=function(){return this.M},e.prototype.empty=function(){return 0===this.M},e}());function d(){throw new RangeError("Iterator access denied!")}var u=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),p=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var i,r,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(i=o.next()).done;)s.push(i.value)}catch(e){r={error:e}}finally{try{i&&!i.done&&(n=o.return)&&n.call(o)}finally{if(r)throw r.error}}return s},h=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&i>=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};const f=function(e){function t(t,n){void 0===t&&(t=function(e,t){return e<t?-1:e>t?1:0}),void 0===n&&(n=!1);var i=e.call(this)||this;return i.W=void 0,i.$=t,n?(i.re=s,i.v=function(e,t,n){var i=this.se(e,t,n);if(i){for(var r=i.rr;r!==this.h;)r.tr+=1,r=r.rr;var o=this.fe(i);if(o){var s=o,a=s.parentNode,c=s.grandParent,l=s.curNode;a.ie(),c.ie(),l.ie()}}return this.M},i.G=function(e){for(var t=this.he(e);t!==this.h;)t.tr-=1,t=t.rr}):(i.re=o,i.v=function(e,t,n){var i=this.se(e,t,n);return i&&this.fe(i),this.M},i.G=i.he),i.h=new i.re,i}return u(t,e),t.prototype.U=function(e,t){for(var n=this.h;e;){var i=this.$(e.u,t);if(i<0)e=e.N;else{if(!(i>0))return e;n=e,e=e.K}}return n},t.prototype.X=function(e,t){for(var n=this.h;e;){this.$(e.u,t)<=0?e=e.N:(n=e,e=e.K)}return n},t.prototype.Y=function(e,t){for(var n=this.h;e;){var i=this.$(e.u,t);if(i<0)n=e,e=e.N;else{if(!(i>0))return e;e=e.K}}return n},t.prototype.Z=function(e,t){for(var n=this.h;e;){this.$(e.u,t)<0?(n=e,e=e.N):e=e.K}return n},t.prototype.ue=function(e){for(;;){var t,n=e.rr;if(n===this.h)return;if(1===e.ee)return void(e.ee=0);if(e===n.K)if(1===(t=n.N).ee)t.ee=0,n.ee=1,n===this.W?this.W=n.ne():n.ne();else{if(t.N&&1===t.N.ee)return t.ee=n.ee,n.ee=0,t.N.ee=0,void(n===this.W?this.W=n.ne():n.ne());t.K&&1===t.K.ee?(t.ee=1,t.K.ee=0,t.te()):(t.ee=1,e=n)}else if(1===(t=n.K).ee)t.ee=0,n.ee=1,n===this.W?this.W=n.te():n.te();else{if(t.K&&1===t.K.ee)return t.ee=n.ee,n.ee=0,t.K.ee=0,void(n===this.W?this.W=n.te():n.te());t.N&&1===t.N.ee?(t.ee=1,t.N.ee=0,t.ne()):(t.ee=1,e=n)}}},t.prototype.he=function(e){var t,n;if(1===this.M)return this.clear(),this.h;for(var i=e;i.K||i.N;){if(i.N)for(i=i.N;i.K;)i=i.K;else i=i.K;t=p([i.u,e.u],2),e.u=t[0],i.u=t[1],n=p([i.p,e.p],2),e.p=n[0],i.p=n[1],e=i}this.h.K===i?this.h.K=i.rr:this.h.N===i&&(this.h.N=i.rr),this.ue(i);var r=i.rr;return i===r.K?r.K=void 0:r.N=void 0,this.M-=1,this.W.ee=0,r},t.prototype.ae=function(e,t){return void 0!==e&&(!!this.ae(e.K,t)||(!!t(e)||this.ae(e.N,t)))},t.prototype.fe=function(e){for(;;){var t=e.rr;if(0===t.ee)return;var n=t.rr;if(t===n.K){if((i=n.N)&&1===i.ee){if(i.ee=t.ee=0,n===this.W)return;n.ee=1,e=n;continue}if(e===t.N){if(e.ee=0,e.K&&(e.K.rr=t),e.N&&(e.N.rr=n),t.N=e.K,n.K=e.N,e.K=t,e.N=n,n===this.W)this.W=e,this.h.rr=e;else(r=n.rr).K===n?r.K=e:r.N=e;return e.rr=n.rr,t.rr=e,n.rr=e,n.ee=1,{parentNode:t,grandParent:n,curNode:e}}t.ee=0,n===this.W?this.W=n.te():n.te(),n.ee=1}else{var i;if((i=n.K)&&1===i.ee){if(i.ee=t.ee=0,n===this.W)return;n.ee=1,e=n;continue}if(e===t.K){var r;if(e.ee=0,e.K&&(e.K.rr=n),e.N&&(e.N.rr=t),n.N=e.K,t.K=e.N,e.K=n,e.N=t,n===this.W)this.W=e,this.h.rr=e;else(r=n.rr).K===n?r.K=e:r.N=e;return e.rr=n.rr,t.rr=e,n.rr=e,n.ee=1,{parentNode:t,grandParent:n,curNode:e}}t.ee=0,n===this.W?this.W=n.ne():n.ne(),n.ee=1}return}},t.prototype.se=function(e,t,n){if(void 0===this.W)return this.M+=1,this.W=new this.re(e,t),this.W.ee=0,this.W.rr=this.h,this.h.rr=this.W,this.h.K=this.W,void(this.h.N=this.W);var i,r=this.h.K,o=this.$(r.u,e);if(0!==o){if(o>0)r.K=new this.re(e,t),r.K.rr=r,i=r.K,this.h.K=i;else{var s=this.h.N,a=this.$(s.u,e);if(0===a)return void(s.p=t);if(a<0)s.N=new this.re(e,t),s.N.rr=s,i=s.N,this.h.N=i;else{if(void 0!==n){var c=n.o;if(c!==this.h){var l=this.$(c.u,e);if(0===l)return void(c.p=t);if(l>0){var d=c.L(),u=this.$(d.u,e);if(0===u)return void(d.p=t);u<0&&(i=new this.re(e,t),void 0===d.N?(d.N=i,i.rr=d):(c.K=i,i.rr=c))}}}if(void 0===i)for(i=this.W;;){var p=this.$(i.u,e);if(p>0){if(void 0===i.K){i.K=new this.re(e,t),i.K.rr=i,i=i.K;break}i=i.K}else{if(!(p<0))return void(i.p=t);if(void 0===i.N){i.N=new this.re(e,t),i.N.rr=i,i=i.N;break}i=i.N}}}}return this.M+=1,i}r.p=t},t.prototype.g=function(e,t){for(;e;){var n=this.$(e.u,t);if(n<0)e=e.N;else{if(!(n>0))return e;e=e.K}}return e||this.h},t.prototype.clear=function(){this.M=0,this.W=void 0,this.h.rr=void 0,this.h.K=this.h.N=void 0},t.prototype.updateKeyByIterator=function(e,t){var n=e.o;if(n===this.h&&d(),1===this.M)return n.u=t,!0;if(n===this.h.K)return this.$(n.m().u,t)>0&&(n.u=t,!0);if(n===this.h.N)return this.$(n.L().u,t)<0&&(n.u=t,!0);var i=n.L().u;if(this.$(i,t)>=0)return!1;var r=n.m().u;return!(this.$(r,t)<=0)&&(n.u=t,!0)},t.prototype.eraseElementByPos=function(e){if(e<0||e>this.M-1)throw new RangeError;var t=0,n=this;return this.ae(this.W,function(i){return e===t?(n.G(i),!0):(t+=1,!1)}),this.M},t.prototype.eraseElementByKey=function(e){if(0===this.M)return!1;var t=this.g(this.W,e);return t!==this.h&&(this.G(t),!0)},t.prototype.eraseElementByIterator=function(e){var t=e.o;t===this.h&&d();var n=void 0===t.N;return 0===e.iteratorType?n&&e.next():n&&void 0!==t.K||e.next(),this.G(t),e},t.prototype.forEach=function(e){var t,n,i=0;try{for(var r=h(this),o=r.next();!o.done;o=r.next()){e(o.value,i++,this)}}catch(e){t={error:e}}finally{try{o&&!o.done&&(n=r.return)&&n.call(r)}finally{if(t)throw t.error}}},t.prototype.getElementByPos=function(e){var t,n,i;if(e<0||e>this.M-1)throw new RangeError;var r=0;try{for(var o=h(this),s=o.next();!s.done;s=o.next()){var a=s.value;if(r===e){i=a;break}r+=1}}catch(e){t={error:e}}finally{try{s&&!s.done&&(n=o.return)&&n.call(o)}finally{if(t)throw t.error}}return i},t.prototype.getHeight=function(){if(0===this.M)return 0;var e=function(t){return t?Math.max(e(t.K),e(t.N))+1:0};return e(this.W)},t}(l);var g=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}();const m=function(e){function t(t,n,i){var r=e.call(this,i)||this;return r.o=t,r.h=n,0===r.iteratorType?(r.pre=function(){return this.o===this.h.K&&d(),this.o=this.o.L(),this},r.next=function(){return this.o===this.h&&d(),this.o=this.o.m(),this}):(r.pre=function(){return this.o===this.h.N&&d(),this.o=this.o.m(),this},r.next=function(){return this.o===this.h&&d(),this.o=this.o.L(),this}),r}return g(t,e),Object.defineProperty(t.prototype,"index",{get:function(){var e=this.o,t=this.h.rr;if(e===this.h)return t?t.tr-1:0;var n=0;for(e.K&&(n+=e.K.tr);e!==t;){var i=e.rr;e===i.N&&(n+=1,i.K&&(n+=i.K.tr)),e=i}return n},enumerable:!1,configurable:!0}),t}(c);var y=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),b=function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(e){return function(t){return c([e,t])}}function c(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=s.trys,(r=r.length>0&&r[r.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]<r[3])){s.label=o[1];break}if(6===o[0]&&s.label<r[1]){s.label=r[1],r=o;break}if(r&&s.label<r[2]){s.label=r[2],s.ops.push(o);break}r[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],i=0}finally{n=r=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}},v=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&i>=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},S=function(e){function t(t,n,i,r){var o=e.call(this,t,n,r)||this;return o.container=i,o}return y(t,e),Object.defineProperty(t.prototype,"pointer",{get:function(){return this.o===this.h&&d(),this.o.u},enumerable:!1,configurable:!0}),t.prototype.copy=function(){return new t(this.o,this.h,this.container,this.iteratorType)},t}(m);const _=function(e){function t(t,n,i){void 0===t&&(t=[]);var r=e.call(this,n,i)||this,o=r;return t.forEach(function(e){o.insert(e)}),r}return y(t,e),t.prototype.P=function(e){return b(this,function(t){switch(t.label){case 0:return void 0===e?[2]:[5,v(this.P(e.K))];case 1:return t.sent(),[4,e.u];case 2:return t.sent(),[5,v(this.P(e.N))];case 3:return t.sent(),[2]}})},t.prototype.begin=function(){return new S(this.h.K||this.h,this.h,this)},t.prototype.end=function(){return new S(this.h,this.h,this)},t.prototype.rBegin=function(){return new S(this.h.N||this.h,this.h,this,1)},t.prototype.rEnd=function(){return new S(this.h,this.h,this,1)},t.prototype.front=function(){return this.h.K?this.h.K.u:void 0},t.prototype.back=function(){return this.h.N?this.h.N.u:void 0},t.prototype.insert=function(e,t){return this.v(e,void 0,t)},t.prototype.find=function(e){var t=this.g(this.W,e);return new S(t,this.h,this)},t.prototype.lowerBound=function(e){var t=this.U(this.W,e);return new S(t,this.h,this)},t.prototype.upperBound=function(e){var t=this.X(this.W,e);return new S(t,this.h,this)},t.prototype.reverseLowerBound=function(e){var t=this.Y(this.W,e);return new S(t,this.h,this)},t.prototype.reverseUpperBound=function(e){var t=this.Z(this.W,e);return new S(t,this.h,this)},t.prototype.union=function(e){var t=this;return e.forEach(function(e){t.insert(e)}),this.M},t.prototype[Symbol.iterator]=function(){return this.P(this.W)},t}(f)},8203(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.streamBuilder=t.browserStreamBuilder=void 0;const r=n(181),o=i(n(7699)),s=i(n(5753)),a=n(4478),c=i(n(6887)),l=n(2635),d=(0,s.default)("mqttjs:ws"),u=["rejectUnauthorized","ca","cert","key","pfx","passphrase"];function p(e,t){let n=`${e.protocol}://${e.hostname}:${e.port}${e.path}`;return"function"==typeof e.transformWsUrl&&(n=e.transformWsUrl(n,e,t)),n}function h(e){const t=e;return e.port||("wss"===e.protocol?t.port=443:t.port=80),e.path||(t.path="/"),e.wsOptions||(t.wsOptions={}),c.default||e.forceNativeWebSocket||"wss"!==e.protocol||u.forEach(n=>{Object.prototype.hasOwnProperty.call(e,n)&&!Object.prototype.hasOwnProperty.call(e.wsOptions,n)&&(t.wsOptions[n]=e[n])}),t}t.streamBuilder=(e,t)=>{d("streamBuilder");const n=h(t);n.hostname=n.hostname||n.host||"localhost";const i=p(n,e),r=function(e,t,n){d("createWebSocket"),d(`protocol: ${n.protocolId} ${n.protocolVersion}`);const i="MQIsdp"===n.protocolId&&3===n.protocolVersion?"mqttv3.1":"mqtt";let r;return d(`creating new Websocket for url: ${t} and protocol: ${i}`),r=n.createWebsocket?n.createWebsocket(t,[i],n):new o.default(t,[i],n.wsOptions),r}(0,i,n),s=o.default.createWebSocketStream(r,n.wsOptions);return s.url=i,r.on("close",()=>{s.destroy()}),s};t.browserStreamBuilder=(e,t)=>{let n;d("browserStreamBuilder");const i=function(e){const t=h(e);if(t.hostname||(t.hostname=t.host),!t.hostname){if("undefined"==typeof document)throw new Error("Could not determine host. Specify host manually.");const e=new URL(document.URL);t.hostname=e.hostname,t.port||(t.port=Number(e.port))}return void 0===t.objectMode&&(t.objectMode=!(!0===t.binary||void 0===t.binary)),t}(t),o=i.browserBufferSize||524288,s=t.browserBufferTimeout||1e3,c=!t.objectMode,u=function(e,t){const n="MQIsdp"===t.protocolId&&3===t.protocolVersion?"mqttv3.1":"mqtt",i=p(t,e);let r;return r=t.createWebsocket?t.createWebsocket(i,[n],t):new WebSocket(i,[n]),r.binaryType="arraybuffer",r}(e,t),f=function(e,t,n){const i=new a.Transform({objectMode:e.objectMode});return i._write=t,i._flush=n,i}(t,function e(t,n,i){if(u.bufferedAmount>o)return void setTimeout(e,s,t,n,i);c&&"string"==typeof t&&(t=r.Buffer.from(t,"utf8"));try{u.send(t)}catch(e){return i(e)}i()},function(e){u.close(),e()});t.objectMode||(f._writev=l.writev.bind(f)),f.on("close",()=>{u.close()});const g="undefined"!=typeof u.addEventListener;function m(){d("WebSocket onOpen"),n instanceof l.BufferedDuplex&&n.socketReady()}function y(e){d("WebSocket onClose",e),n.end(),n.destroy()}function b(e){d("WebSocket onError",e);const t=new Error("WebSocket error");t.event=e,n.destroy(t)}async function v(e){if(!f||!f.readable||!f.writable)return;let{data:t}=e;t=t instanceof ArrayBuffer?r.Buffer.from(t):t instanceof Blob?r.Buffer.from(await new Response(t).arrayBuffer()):r.Buffer.from(t,"utf8"),f.push(t)}return u.readyState===u.OPEN?(n=f,n.socket=u):(n=new l.BufferedDuplex(t,f,u),g?u.addEventListener("open",m):u.onopen=m),g?(u.addEventListener("close",y),u.addEventListener("error",b),u.addEventListener("message",v)):(u.onclose=y,u.onerror=b,u.onmessage=v),n}},8237(e,t,n){"use strict";const{tokenChars:i}=n(5880);e.exports={parse:function(e){const t=new Set;let n=-1,r=-1,o=0;for(;o<e.length;o++){const s=e.charCodeAt(o);if(-1===r&&1===i[s])-1===n&&(n=o);else if(0===o||32!==s&&9!==s){if(44!==s)throw new SyntaxError(`Unexpected character at index ${o}`);{if(-1===n)throw new SyntaxError(`Unexpected character at index ${o}`);-1===r&&(r=o);const i=e.slice(n,r);if(t.has(i))throw new SyntaxError(`The "${i}" subprotocol is duplicated`);t.add(i),n=r=-1}}else-1===r&&-1!==n&&(r=o)}if(-1===n||-1!==r)throw new SyntaxError("Unexpected end of input");const s=e.slice(n,o);if(t.has(s))throw new SyntaxError(`The "${s}" subprotocol is duplicated`);return t.add(s),t}}},8462(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.TopologyDiscoveryEngine=void 0;const a=s(n(7562)),c=n(2881),l=n(1554),d=n(6687),{systemManager:u}=a.default,p='I have scene analyses from multiple security cameras at the same property. Help me correlate them to understand the property layout.\n\nCAMERA SCENES:\n{scenes}\n\nIdentify:\n1. Shared landmarks - Features that appear in multiple camera views\n2. Camera connections - How someone could move between camera views and estimated walking time\n3. Overall layout - Describe the property layout based on what you see\n\nIMPORTANT: For camera references, use the EXACT device ID shown in parentheses (e.g., "device_123"), NOT the camera name.\n\nRespond with ONLY valid JSON:\n{\n "sharedLandmarks": [\n {"name": "Driveway", "type": "access", "seenByCameras": ["device_123", "device_456"], "confidence": 0.8, "description": "Concrete driveway"}\n ],\n "connections": [\n {"from": "device_123", "to": "device_456", "transitSeconds": 10, "via": "driveway", "confidence": 0.7, "bidirectional": true}\n ],\n "layoutDescription": "Single-story house with front yard facing street, driveway on the left side, backyard accessible through side gate"\n}';t.TopologyDiscoveryEngine=class{config;console;topology=null;llmDevice=null;llmSearched=!1;llmProviderType="unknown";sceneCache=new Map;suggestions=new Map;status={...c.DEFAULT_DISCOVERY_STATUS};discoveryTimer=null;constructor(e,t){this.config={...c.DEFAULT_DISCOVERY_CONFIG,...e},this.console=t}updateConfig(e){this.config={...this.config,...e},this.status.isRunning&&(this.stopPeriodicDiscovery(),this.config.discoveryIntervalHours>0&&this.startPeriodicDiscovery())}updateTopology(e){this.topology=e}getStatus(){return{...this.status}}getPendingSuggestions(){return Array.from(this.suggestions.values()).filter(e=>"pending"===e.status).sort((e,t)=>t.confidence-e.confidence)}getSceneAnalysis(e){return this.sceneCache.get(e)||null}shouldShowRateLimitWarning(){return this.config.discoveryIntervalHours>0&&this.config.discoveryIntervalHours<c.RATE_LIMIT_WARNING_THRESHOLD}isEnabled(){return this.config.discoveryIntervalHours>0}async findLlmDevice(){if(this.llmDevice)return this.llmDevice;if(this.llmSearched)return null;this.llmSearched=!0;try{for(const e of Object.keys(u.getSystemState())){const t=u.getDeviceById(e);if(t&&t.interfaces?.includes("ChatCompletion")){const e=t.name?.toLowerCase()||"";return e.includes("openai")||e.includes("gpt")?this.llmProviderType="openai":e.includes("anthropic")||e.includes("claude")?this.llmProviderType="anthropic":e.includes("ollama")||e.includes("gemini")||e.includes("google")||e.includes("llama")?this.llmProviderType="openai":this.llmProviderType="unknown",this.llmDevice=t,this.console.log(`[Discovery] Connected to LLM: ${t.name}`),this.console.log(`[Discovery] Image format: ${this.llmProviderType}`),this.llmDevice}}this.console.warn("[Discovery] No ChatCompletion device found. Vision-based discovery unavailable.")}catch(e){this.console.error("[Discovery] Error finding LLM device:",e)}return null}async getCameraSnapshot(e){try{const t=u.getDeviceById(e);if(!t?.interfaces?.includes(a.ScryptedInterface.Camera))return this.console.warn(`[Discovery] Camera ${e} doesn't have Camera interface`),null;this.console.log(`[Discovery] Taking snapshot from camera: ${t.name||e}`);const n=await t.takePicture();if(!n)return this.console.warn(`[Discovery] takePicture() returned null for ${t.name}`),null;this.console.log(`[Discovery] MediaObject received: mimeType=${n.mimeType}`);const i=await(0,d.mediaObjectToBase64)(n);return i||this.console.warn(`[Discovery] Failed to convert MediaObject to base64 for ${t.name}`),i}catch(t){return this.console.warn(`[Discovery] Failed to get snapshot from camera ${e}:`,t),null}}async analyzeScene(e){const t=this.topology?(0,l.findCamera)(this.topology,e):null,n=t?.name||e,i={cameraId:e,cameraName:n,timestamp:Date.now(),landmarks:[],zones:[],edges:{top:"",left:"",right:"",bottom:""},orientation:"unknown",potentialOverlaps:[],isValid:!1},r=await this.findLlmDevice();if(!r?.getChatCompletion)return i.error="No LLM device available",i;const o=await this.getCameraSnapshot(e);if(!o)return i.error="Failed to capture camera snapshot",i;const s=[];s.push(this.llmProviderType),"openai"===this.llmProviderType?s.push("scrypted","anthropic"):"anthropic"===this.llmProviderType?s.push("scrypted","openai"):"scrypted"===this.llmProviderType?s.push("anthropic","openai"):s.push("scrypted","anthropic","openai");let a=null;for(const e of s)try{this.console.log(`[Discovery] Trying ${e} image format for ${n}...`);const t=await r.getChatCompletion({messages:[{role:"user",content:[{type:"text",text:'Analyze this security camera image and identify what you see.\n\n1. LANDMARKS - Identify fixed features visible:\n - Structures (house, garage, shed, porch, deck)\n - Features (mailbox, tree, pool, garden, fountain)\n - Access points (door, gate, driveway entrance, walkway)\n - Boundaries (fence, wall, hedge)\n\n2. ZONES - Identify area types visible:\n - What type of area is this? (front yard, backyard, driveway, street, patio, walkway)\n - Estimate what percentage of the frame each zone covers (0.0 to 1.0)\n\n3. EDGES - What\'s visible at the frame edges:\n - Top edge: (sky, roof, trees, etc.)\n - Left edge: (fence, neighbor, street, etc.)\n - Right edge: (fence, garage, etc.)\n - Bottom edge: (ground, driveway, grass, etc.)\n\n4. ORIENTATION - Estimate camera facing direction based on shadows, sun position, or landmarks\n\nRespond with ONLY valid JSON in this exact format:\n{\n "landmarks": [\n {"name": "Front Door", "type": "access", "confidence": 0.9, "description": "White front door with black frame"}\n ],\n "zones": [\n {"name": "Front Yard", "type": "yard", "coverage": 0.4, "description": "Grass lawn area"}\n ],\n "edges": {"top": "sky with clouds", "left": "fence and trees", "right": "garage wall", "bottom": "concrete walkway"},\n "orientation": "north"\n}'},(0,d.buildImageContent)(o,e)]}],max_tokens:1500,temperature:.3}),s=t?.choices?.[0]?.message?.content;if(s&&"string"==typeof s)try{let t=s.trim();t.startsWith("```")&&(t=t.replace(/```json?\n?/g,"").replace(/```$/g,"").trim());const r=JSON.parse(t);return Array.isArray(r.landmarks)&&(i.landmarks=r.landmarks.map(e=>({name:e.name||"Unknown",type:this.mapLandmarkType(e.type),confidence:"number"==typeof e.confidence?e.confidence:.7,description:e.description||"",boundingBox:e.boundingBox}))),Array.isArray(r.zones)&&(i.zones=r.zones.map(e=>({name:e.name||"Unknown",type:this.mapZoneType(e.type),coverage:"number"==typeof e.coverage?e.coverage:.5,description:e.description||"",boundingBox:e.boundingBox}))),r.edges&&"object"==typeof r.edges&&(i.edges={top:r.edges.top||"",left:r.edges.left||"",right:r.edges.right||"",bottom:r.edges.bottom||""}),r.orientation&&(i.orientation=this.mapOrientation(r.orientation)),i.isValid=!0,this.console.log(`[Discovery] Analyzed ${n}: ${i.landmarks.length} landmarks, ${i.zones.length} zones (using ${e} format)`),e!==this.llmProviderType&&(this.console.log(`[Discovery] Switching to ${e} format for future requests`),this.llmProviderType=e),i}catch(e){return this.console.warn(`[Discovery] Failed to parse LLM response for ${n}:`,e),i.error="Failed to parse LLM response",i}}catch(t){if(a=t,(0,d.isVisionFormatError)(t)){this.console.warn(`[Discovery] ${e} format failed, trying fallback...`);continue}this.console.warn(`[Discovery] Scene analysis failed for ${n}:`,t);break}if(a){const e=String(a);(0,d.isVisionFormatError)(a)?i.error="Vision/image analysis failed with all formats. Ensure you have a vision-capable model (e.g., gpt-4o, gpt-4-turbo, claude-3-sonnet) configured and the @scrypted/llm plugin supports vision.":i.error=`Analysis failed: ${e}`}return this.sceneCache.set(e,i),i}mapLandmarkType(e){return{structure:"structure",feature:"feature",boundary:"boundary",access:"access",vehicle:"vehicle",neighbor:"neighbor",zone:"zone",street:"street"}[e?.toLowerCase()]||"feature"}mapZoneType(e){return{yard:"yard",driveway:"driveway",street:"street",patio:"patio",deck:"patio",walkway:"walkway",parking:"parking",garden:"garden",pool:"pool"}[e?.toLowerCase()]||"unknown"}mapOrientation(e){const t=e?.toLowerCase();return t?.includes("north")&&t?.includes("east")?"northeast":t?.includes("north")&&t?.includes("west")?"northwest":t?.includes("south")&&t?.includes("east")?"southeast":t?.includes("south")&&t?.includes("west")?"southwest":t?.includes("north")?"north":t?.includes("south")?"south":t?.includes("east")?"east":t?.includes("west")?"west":"unknown"}resolveCameraRef(e){if(!this.topology?.cameras||!e)return null;const t=this.topology.cameras.find(t=>t.deviceId===e);if(t)return t.deviceId;const n=this.topology.cameras.find(t=>t.name===e);if(n)return n.deviceId;const i=e.toLowerCase(),r=this.topology.cameras.find(e=>e.name.toLowerCase()===i);if(r)return r.deviceId;const o=this.topology.cameras.find(e=>e.name.toLowerCase().includes(i)||i.includes(e.name.toLowerCase()));return o?o.deviceId:(this.console.warn(`[Discovery] Could not resolve camera reference: "${e}"`),null)}normalizeCameraRefs(e){return e.map(e=>this.resolveCameraRef(e)).filter(e=>null!==e)}async runFullDiscovery(){if(!this.topology?.cameras?.length)return this.console.warn("[Discovery] No cameras in topology"),null;this.status.isScanning=!0,this.status.lastError=void 0;try{this.console.log(`[Discovery] Starting full discovery scan of ${this.topology.cameras.length} cameras`);const e=[];for(const t of this.topology.cameras){const n=await this.analyzeScene(t.deviceId);n.isValid&&e.push(n),await new Promise(e=>setTimeout(e,2e3))}if(this.status.camerasAnalyzed=e.length,this.console.log(`[Discovery] Analyzed ${e.length} cameras successfully`),0===e.length)return this.console.warn("[Discovery] No cameras were successfully analyzed"),this.status.lastError="No cameras were successfully analyzed - check LLM configuration",this.status.lastScanTime=Date.now(),null;let t=null;return e.length>=2?(t=await this.correlateScenes(e),t&&this.generateSuggestionsFromCorrelation(t)):1===e.length&&this.generateSuggestionsFromAnalysis(e[0]),this.status.lastScanTime=Date.now(),this.status.pendingSuggestions=this.getPendingSuggestions().length,t}catch(e){return this.console.error("[Discovery] Full discovery failed:",e),this.status.lastError=`Discovery failed: ${e}`,null}finally{this.status.isScanning=!1}}async correlateScenes(e){const t=await this.findLlmDevice();if(!t?.getChatCompletion)return null;try{const n=e.map(e=>{const t=e.landmarks.map(e=>`${e.name} (${e.type})`).join(", "),n=e.zones.map(e=>`${e.name} (${e.type}, ${Math.round(100*e.coverage)}%)`).join(", ");return`Camera "${e.cameraName}" (${e.cameraId}):\n - Landmarks: ${t||"None identified"}\n - Zones: ${n||"None identified"}\n - Edges: Top=${e.edges.top}, Left=${e.edges.left}, Right=${e.edges.right}, Bottom=${e.edges.bottom}\n - Orientation: ${e.orientation}`}).join("\n\n"),i=p.replace("{scenes}",n),r=await t.getChatCompletion({messages:[{role:"user",content:i}],max_tokens:2e3,temperature:.4}),o=r?.choices?.[0]?.message?.content;if(o&&"string"==typeof o)try{let e=o.trim();e.startsWith("```")&&(e=e.replace(/```json?\n?/g,"").replace(/```$/g,"").trim());const t=JSON.parse(e),n={sharedLandmarks:[],suggestedConnections:[],layoutDescription:t.layoutDescription||"",timestamp:Date.now()};return Array.isArray(t.sharedLandmarks)&&(n.sharedLandmarks=t.sharedLandmarks.map(e=>{const t=Array.isArray(e.seenByCameras)?e.seenByCameras:[],n=this.normalizeCameraRefs(t);return t.length>0&&0===n.length&&this.console.warn(`[Discovery] Landmark "${e.name}" has no resolvable camera refs: ${JSON.stringify(t)}`),{name:e.name||"Unknown",type:this.mapLandmarkType(e.type),seenByCameras:n,confidence:"number"==typeof e.confidence?e.confidence:.7,description:e.description}})),Array.isArray(t.connections)&&(n.suggestedConnections=t.connections.map(e=>{const t=e.from||e.fromCameraId||"",n=e.to||e.toCameraId||"",i=this.resolveCameraRef(t),r=this.resolveCameraRef(n);return i&&r||this.console.warn(`[Discovery] Connection has unresolvable camera refs: from="${t}" to="${n}"`),{fromCameraId:i||t,toCameraId:r||n,transitSeconds:"number"==typeof e.transitSeconds?e.transitSeconds:15,via:e.via||"",confidence:"number"==typeof e.confidence?e.confidence:.6,bidirectional:!1!==e.bidirectional}})),this.console.log(`[Discovery] Correlation found ${n.sharedLandmarks.length} shared landmarks, ${n.suggestedConnections.length} connections`),n}catch(e){this.console.warn("[Discovery] Failed to parse correlation response:",e)}}catch(e){this.console.warn("[Discovery] Correlation failed:",e)}return null}generateSuggestionsFromAnalysis(e){if(e.isValid){for(const t of e.landmarks)if(t.confidence>=this.config.minLandmarkConfidence){const n={id:`landmark_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"landmark",timestamp:Date.now(),sourceCameras:[e.cameraId],confidence:t.confidence,status:"pending",landmark:{name:t.name,type:t.type,description:t.description,visibleFromCameras:[e.cameraId],boundingBox:t.boundingBox}};this.suggestions.set(n.id,n)}for(const t of e.zones)if(t.coverage>=.2){const n={id:`zone_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"zone",timestamp:Date.now(),sourceCameras:[e.cameraId],confidence:.7,status:"pending",zone:t};this.suggestions.set(n.id,n)}}}generateSuggestionsFromCorrelation(e){for(const t of e.sharedLandmarks){const e={id:`shared_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"landmark",timestamp:Date.now(),sourceCameras:t.seenByCameras,confidence:t.confidence,status:"pending",landmark:{name:t.name,type:t.type,description:t.description,visibleFromCameras:t.seenByCameras}};this.suggestions.set(e.id,e)}for(const t of e.suggestedConnections){const e={id:`conn_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"connection",timestamp:Date.now(),sourceCameras:[t.fromCameraId,t.toCameraId],confidence:t.confidence,status:"pending",connection:t};this.suggestions.set(e.id,e)}}acceptSuggestion(e){const t=this.suggestions.get(e);return t&&"pending"===t.status?(t.status="accepted",this.status.pendingSuggestions=this.getPendingSuggestions().length,t):null}rejectSuggestion(e){const t=this.suggestions.get(e);return!(!t||"pending"!==t.status)&&(t.status="rejected",this.status.pendingSuggestions=this.getPendingSuggestions().length,!0)}startPeriodicDiscovery(){if(this.discoveryTimer&&clearInterval(this.discoveryTimer),this.config.discoveryIntervalHours<=0)return void this.console.log("[Discovery] Periodic discovery disabled (interval = 0)");this.status.isRunning=!0;const e=60*this.config.discoveryIntervalHours*60*1e3;this.console.log(`[Discovery] Starting periodic discovery every ${this.config.discoveryIntervalHours} hours`),this.status.nextScanTime=Date.now()+e,this.discoveryTimer=setInterval(async()=>{this.status.isScanning||(await this.runFullDiscovery(),this.status.nextScanTime=Date.now()+e)},e)}stopPeriodicDiscovery(){this.discoveryTimer&&(clearInterval(this.discoveryTimer),this.discoveryTimer=null),this.status.isRunning=!1,this.status.nextScanTime=null,this.console.log("[Discovery] Stopped periodic discovery")}clearCache(){this.sceneCache.clear(),this.suggestions.clear(),this.status.pendingSuggestions=0,this.status.camerasAnalyzed=0}}},8584(e,t,n){"use strict";const i=n(4422),{ArrayPrototypeSlice:r,Error:o,FunctionPrototypeSymbolHasInstance:s,ObjectDefineProperty:a,ObjectDefineProperties:c,ObjectSetPrototypeOf:l,StringPrototypeToLowerCase:d,Symbol:u,SymbolHasInstance:p}=n(4134);e.exports=L,L.WritableState=R;const{EventEmitter:h}=n(4434),f=n(4259).Stream,{Buffer:g}=n(181),m=n(5896),{addAbortSignal:y}=n(4147),{getHighWaterMark:b,getDefaultHighWaterMark:v}=n(5291),{ERR_INVALID_ARG_TYPE:S,ERR_METHOD_NOT_IMPLEMENTED:_,ERR_MULTIPLE_CALLBACK:w,ERR_STREAM_CANNOT_PIPE:k,ERR_STREAM_DESTROYED:I,ERR_STREAM_ALREADY_FINISHED:x,ERR_STREAM_NULL_VALUES:C,ERR_STREAM_WRITE_AFTER_END:E,ERR_UNKNOWN_ENCODING:T}=n(6371).codes,{errorOrDestroy:O}=m;function P(){}l(L.prototype,f.prototype),l(L,f);const A=u("kOnFinished");function R(e,t,i){"boolean"!=typeof i&&(i=t instanceof n(3370)),this.objectMode=!(!e||!e.objectMode),i&&(this.objectMode=this.objectMode||!(!e||!e.writableObjectMode)),this.highWaterMark=e?b(this,e,"writableHighWaterMark",i):v(!1),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;const r=!(!e||!1!==e.decodeStrings);this.decodeStrings=!r,this.defaultEncoding=e&&e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=j.bind(void 0,t),this.writecb=null,this.writelen=0,this.afterWriteTickInfo=null,M(this),this.pendingcb=0,this.constructed=!0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!e||!1!==e.emitClose,this.autoDestroy=!e||!1!==e.autoDestroy,this.errored=null,this.closed=!1,this.closeEmitted=!1,this[A]=[]}function M(e){e.buffered=[],e.bufferedIndex=0,e.allBuffers=!0,e.allNoop=!0}function L(e){const t=this instanceof n(3370);if(!t&&!s(L,this))return new L(e);this._writableState=new R(e,this,t),e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final),"function"==typeof e.construct&&(this._construct=e.construct),e.signal&&y(e.signal,this)),f.call(this,e),m.construct(this,()=>{const e=this._writableState;e.writing||z(this,e),H(this,e)})}function N(e,t,n,r){const o=e._writableState;if("function"==typeof n)r=n,n=o.defaultEncoding;else{if(n){if("buffer"!==n&&!g.isEncoding(n))throw new T(n)}else n=o.defaultEncoding;"function"!=typeof r&&(r=P)}if(null===t)throw new C;if(!o.objectMode)if("string"==typeof t)!1!==o.decodeStrings&&(t=g.from(t,n),n="buffer");else if(t instanceof g)n="buffer";else{if(!f._isUint8Array(t))throw new S("chunk",["string","Buffer","Uint8Array"],t);t=f._uint8ArrayToBuffer(t),n="buffer"}let s;return o.ending?s=new E:o.destroyed&&(s=new I("write")),s?(i.nextTick(r,s),O(e,s,!0),s):(o.pendingcb++,function(e,t,n,i,r){const o=t.objectMode?1:n.length;t.length+=o;const s=t.length<t.highWaterMark;s||(t.needDrain=!0);t.writing||t.corked||t.errored||!t.constructed?(t.buffered.push({chunk:n,encoding:i,callback:r}),t.allBuffers&&"buffer"!==i&&(t.allBuffers=!1),t.allNoop&&r!==P&&(t.allNoop=!1)):(t.writelen=o,t.writecb=r,t.writing=!0,t.sync=!0,e._write(n,i,t.onwrite),t.sync=!1);return s&&!t.errored&&!t.destroyed}(e,o,t,n,r))}function D(e,t,n,i,r,o,s){t.writelen=i,t.writecb=s,t.writing=!0,t.sync=!0,t.destroyed?t.onwrite(new I("write")):n?e._writev(r,t.onwrite):e._write(r,o,t.onwrite),t.sync=!1}function B(e,t,n,i){--t.pendingcb,i(n),U(t),O(e,n)}function j(e,t){const n=e._writableState,r=n.sync,o=n.writecb;"function"==typeof o?(n.writing=!1,n.writecb=null,n.length-=n.writelen,n.writelen=0,t?(t.stack,n.errored||(n.errored=t),e._readableState&&!e._readableState.errored&&(e._readableState.errored=t),r?i.nextTick(B,e,n,t,o):B(e,n,t,o)):(n.buffered.length>n.bufferedIndex&&z(e,n),r?null!==n.afterWriteTickInfo&&n.afterWriteTickInfo.cb===o?n.afterWriteTickInfo.count++:(n.afterWriteTickInfo={count:1,cb:o,stream:e,state:n},i.nextTick($,n.afterWriteTickInfo)):F(e,n,1,o))):O(e,new w)}function $({stream:e,state:t,count:n,cb:i}){return t.afterWriteTickInfo=null,F(e,t,n,i)}function F(e,t,n,i){for(!t.ending&&!e.destroyed&&0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"));n-- >0;)t.pendingcb--,i();t.destroyed&&U(t),H(e,t)}function U(e){if(e.writing)return;for(let n=e.bufferedIndex;n<e.buffered.length;++n){var t;const{chunk:i,callback:r}=e.buffered[n],o=e.objectMode?1:i.length;e.length-=o,r(null!==(t=e.errored)&&void 0!==t?t:new I("write"))}const n=e[A].splice(0);for(let t=0;t<n.length;t++){var i;n[t](null!==(i=e.errored)&&void 0!==i?i:new I("end"))}M(e)}function z(e,t){if(t.corked||t.bufferProcessing||t.destroyed||!t.constructed)return;const{buffered:n,bufferedIndex:i,objectMode:o}=t,s=n.length-i;if(!s)return;let a=i;if(t.bufferProcessing=!0,s>1&&e._writev){t.pendingcb-=s-1;const i=t.allNoop?P:e=>{for(let t=a;t<n.length;++t)n[t].callback(e)},o=t.allNoop&&0===a?n:r(n,a);o.allBuffers=t.allBuffers,D(e,t,!0,t.length,o,"",i),M(t)}else{do{const{chunk:i,encoding:r,callback:s}=n[a];n[a++]=null;D(e,t,!1,o?1:i.length,i,r,s)}while(a<n.length&&!t.writing);a===n.length?M(t):a>256?(n.splice(0,a),t.bufferedIndex=0):t.bufferedIndex=a}t.bufferProcessing=!1}function V(e){return e.ending&&!e.destroyed&&e.constructed&&0===e.length&&!e.errored&&0===e.buffered.length&&!e.finished&&!e.writing&&!e.errorEmitted&&!e.closeEmitted}function W(e,t){t.prefinished||t.finalCalled||("function"!=typeof e._final||t.destroyed?(t.prefinished=!0,e.emit("prefinish")):(t.finalCalled=!0,function(e,t){let n=!1;function r(r){if(n)O(e,null!=r?r:w());else if(n=!0,t.pendingcb--,r){const n=t[A].splice(0);for(let e=0;e<n.length;e++)n[e](r);O(e,r,t.sync)}else V(t)&&(t.prefinished=!0,e.emit("prefinish"),t.pendingcb++,i.nextTick(q,e,t))}t.sync=!0,t.pendingcb++;try{e._final(r)}catch(e){r(e)}t.sync=!1}(e,t)))}function H(e,t,n){V(t)&&(W(e,t),0===t.pendingcb&&(n?(t.pendingcb++,i.nextTick((e,t)=>{V(t)?q(e,t):t.pendingcb--},e,t)):V(t)&&(t.pendingcb++,q(e,t))))}function q(e,t){t.pendingcb--,t.finished=!0;const n=t[A].splice(0);for(let e=0;e<n.length;e++)n[e]();if(e.emit("finish"),t.autoDestroy){const t=e._readableState;(!t||t.autoDestroy&&(t.endEmitted||!1===t.readable))&&e.destroy()}}R.prototype.getBuffer=function(){return r(this.buffered,this.bufferedIndex)},a(R.prototype,"bufferedRequestCount",{__proto__:null,get(){return this.buffered.length-this.bufferedIndex}}),a(L,p,{__proto__:null,value:function(e){return!!s(this,e)||this===L&&(e&&e._writableState instanceof R)}}),L.prototype.pipe=function(){O(this,new k)},L.prototype.write=function(e,t,n){return!0===N(this,e,t,n)},L.prototype.cork=function(){this._writableState.corked++},L.prototype.uncork=function(){const e=this._writableState;e.corked&&(e.corked--,e.writing||z(this,e))},L.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=d(e)),!g.isEncoding(e))throw new T(e);return this._writableState.defaultEncoding=e,this},L.prototype._write=function(e,t,n){if(!this._writev)throw new _("_write()");this._writev([{chunk:e,encoding:t}],n)},L.prototype._writev=null,L.prototype.end=function(e,t,n){const r=this._writableState;let s;if("function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e){const n=N(this,e,t);n instanceof o&&(s=n)}return r.corked&&(r.corked=1,this.uncork()),s||(r.errored||r.ending?r.finished?s=new x("end"):r.destroyed&&(s=new I("end")):(r.ending=!0,H(this,r,!0),r.ended=!0)),"function"==typeof n&&(s||r.finished?i.nextTick(n,s):r[A].push(n)),this},c(L.prototype,{closed:{__proto__:null,get(){return!!this._writableState&&this._writableState.closed}},destroyed:{__proto__:null,get(){return!!this._writableState&&this._writableState.destroyed},set(e){this._writableState&&(this._writableState.destroyed=e)}},writable:{__proto__:null,get(){const e=this._writableState;return!(!e||!1===e.writable||e.destroyed||e.errored||e.ending||e.ended)},set(e){this._writableState&&(this._writableState.writable=!!e)}},writableFinished:{__proto__:null,get(){return!!this._writableState&&this._writableState.finished}},writableObjectMode:{__proto__:null,get(){return!!this._writableState&&this._writableState.objectMode}},writableBuffer:{__proto__:null,get(){return this._writableState&&this._writableState.getBuffer()}},writableEnded:{__proto__:null,get(){return!!this._writableState&&this._writableState.ending}},writableNeedDrain:{__proto__:null,get(){const e=this._writableState;return!!e&&(!e.destroyed&&!e.ending&&e.needDrain)}},writableHighWaterMark:{__proto__:null,get(){return this._writableState&&this._writableState.highWaterMark}},writableCorked:{__proto__:null,get(){return this._writableState?this._writableState.corked:0}},writableLength:{__proto__:null,get(){return this._writableState&&this._writableState.length}},errored:{__proto__:null,enumerable:!1,get(){return this._writableState?this._writableState.errored:null}},writableAborted:{__proto__:null,enumerable:!1,get:function(){return!(!1===this._writableState.writable||!this._writableState.destroyed&&!this._writableState.errored||this._writableState.finished)}}});const G=m.destroy;let K;function Z(){return void 0===K&&(K={}),K}L.prototype.destroy=function(e,t){const n=this._writableState;return!n.destroyed&&(n.bufferedIndex<n.buffered.length||n[A].length)&&i.nextTick(U,n),G.call(this,e,t),this},L.prototype._undestroy=m.undestroy,L.prototype._destroy=function(e,t){t(e)},L.prototype[h.captureRejectionSymbol]=function(e){this.destroy(e)},L.fromWeb=function(e,t){return Z().newStreamWritableFromWritableStream(e,t)},L.toWeb=function(e){return Z().newWritableStreamFromStreamWritable(e)}},8600(e,t,n){"use strict";n.r(t),n.d(t,{clearInterval:()=>S,clearTimeout:()=>_,setInterval:()=>w,setTimeout:()=>k});const i=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,r=536870912,o=1073741824,s=new WeakMap;var a;const c=((e,t)=>n=>{const s=t.get(n);let a=void 0===s?n.size:s<o?s+1:0;if(!n.has(a))return e(n,a);if(n.size<r){for(;n.has(a);)a=Math.floor(Math.random()*o);return e(n,a)}if(n.size>i)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;n.has(a);)a=Math.floor(Math.random()*i);return e(n,a)})((a=s,(e,t)=>(a.set(e,t),t)),s),l=((e=>{})(c),((e,t,n,i)=>r=>{const o=t(r);return t=>{const r=e(t);t.addEventListener("message",({data:e})=>{const{id:t}=e;if(null!==t&&r.has(t)){const{reject:n,resolve:i}=r.get(t);r.delete(t),void 0===e.error?i(e.result):n(new Error(e.error.message))}}),i(t)&&t.start();const s=(e,i=null,o=[])=>new Promise((s,a)=>{const c=n(r);r.set(c,{reject:a,resolve:s}),null===i?t.postMessage({id:c,method:e},o):t.postMessage({id:c,method:e,params:i},o)}),a=(e,n,i=[])=>{t.postMessage({id:null,method:e,params:n},i)};let c={};for(const[e,t]of Object.entries(o))c={...c,[e]:t({call:s,notify:a})};return{...c}}})((u=new WeakMap,e=>{if(u.has(e))return u.get(e);const t=new Map;return u.set(e,t),t}),(d=new WeakMap,e=>({...e,connect:({call:e})=>async()=>{const{port1:t,port2:n}=new MessageChannel,i=await e("connect",{port:t},[t]);return d.set(n,i),n},disconnect:({call:e})=>async t=>{const n=d.get(t);if(void 0===n)throw new Error("The given port is not connected.");await e("disconnect",{portId:n})},isSupported:({call:e})=>()=>e("isSupported")})),c,e=>"function"==typeof e.start));var d,u;const p=new Map([[0,null]]),h=new Map([[0,null]]),f=(e=>t=>n=>{"symbol"==typeof e.get(n)&&(e.set(n,null),t(n).then(()=>{e.delete(n)}))})(p),g=(e=>t=>n=>{"symbol"==typeof e.get(n)&&(e.set(n,null),t(n).then(()=>{e.delete(n)}))})(h),m=((e,t)=>n=>(i,r=0,...o)=>{const s=Symbol(),a=e(t);t.set(a,s);const c=()=>n(r,a).then(()=>{const e=t.get(a);if(void 0===e)throw new Error("The timer is in an undefined state.");e===s&&(i(...o),t.get(a)===s&&c())});return c(),a})(c,p),y=((e,t)=>n=>(i,r=0,...o)=>{const s=Symbol(),a=e(t);return t.set(a,s),n(r,a).then(()=>{const e=t.get(a);if(void 0===e)throw new Error("The timer is in an undefined state.");e===s&&(t.delete(a),i(...o))}),a})(c,h),b=l({clearInterval:({call:e})=>f(t=>e("clear",{timerId:t,timerType:"interval"})),clearTimeout:({call:e})=>g(t=>e("clear",{timerId:t,timerType:"timeout"})),setInterval:({call:e})=>m((t,n)=>e("set",{delay:t,now:performance.timeOrigin+performance.now(),timerId:n,timerType:"interval"})),setTimeout:({call:e})=>y((t,n)=>e("set",{delay:t,now:performance.timeOrigin+performance.now(),timerId:n,timerType:"timeout"}))}),v=((e,t)=>{let n=null;return()=>{if(null!==n)return n;const i=new Blob([t],{type:"application/javascript; charset=utf-8"}),r=URL.createObjectURL(i);return n=e(r),setTimeout(()=>URL.revokeObjectURL(r)),n}})(e=>{const t=new Worker(e);return b(t)},'(()=>{var e={455(e,t){!function(e){"use strict";var t=function(e){return function(t){var r=e(t);return t.add(r),r}},r=function(e){return function(t,r){return e.set(t,r),r}},n=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,o=536870912,s=2*o,a=function(e,t){return function(r){var a=t.get(r),i=void 0===a?r.size:a<s?a+1:0;if(!r.has(i))return e(r,i);if(r.size<o){for(;r.has(i);)i=Math.floor(Math.random()*s);return e(r,i)}if(r.size>n)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;r.has(i);)i=Math.floor(Math.random()*n);return e(r,i)}},i=new WeakMap,u=r(i),c=a(u,i),l=t(c);e.addUniqueNumber=l,e.generateUniqueNumber=c}(t)}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var s=t[n]={exports:{}};return e[n].call(s.exports,s,s.exports,r),s.exports}(()=>{"use strict";const e=-32603,t=-32602,n=-32601,o=(e,t)=>Object.assign(new Error(e),{status:t}),s=t=>o(\'The handler of the method called "\'.concat(t,\'" returned an unexpected result.\'),e),a=(t,r)=>async({data:{id:a,method:i,params:u}})=>{const c=r[i];try{if(void 0===c)throw(e=>o(\'The requested method called "\'.concat(e,\'" is not supported.\'),n))(i);const r=void 0===u?c():c(u);if(void 0===r)throw(t=>o(\'The handler of the method called "\'.concat(t,\'" returned no required result.\'),e))(i);const l=r instanceof Promise?await r:r;if(null===a){if(void 0!==l.result)throw s(i)}else{if(void 0===l.result)throw s(i);const{result:e,transferables:r=[]}=l;t.postMessage({id:a,result:e},r)}}catch(e){const{message:r,status:n=-32603}=e;t.postMessage({error:{code:n,message:r},id:a})}};var i=r(455);const u=new Map,c=(e,r,n)=>({...r,connect:({port:t})=>{t.start();const n=e(t,r),o=(0,i.generateUniqueNumber)(u);return u.set(o,()=>{n(),t.close(),u.delete(o)}),{result:o}},disconnect:({portId:e})=>{const r=u.get(e);if(void 0===r)throw(e=>o(\'The specified parameter called "portId" with the given value "\'.concat(e,\'" does not identify a port connected to this worker.\'),t))(e);return r(),{result:null}},isSupported:async()=>{if(await new Promise(e=>{const t=new ArrayBuffer(0),{port1:r,port2:n}=new MessageChannel;r.onmessage=({data:t})=>e(null!==t),n.postMessage(t,[t])})){const e=n();return{result:e instanceof Promise?await e:e}}return{result:!1}}}),l=(e,t,r=()=>!0)=>{const n=c(l,t,r),o=a(e,n);return e.addEventListener("message",o),()=>e.removeEventListener("message",o)},d=(e,t)=>r=>{const n=t.get(r);if(void 0===n)return Promise.resolve(!1);const[o,s]=n;return e(o),t.delete(r),s(!1),Promise.resolve(!0)},m=(e,t,r,n)=>(o,s,a)=>{const i=o+s-t.timeOrigin,u=i-t.now();return new Promise(t=>{e.set(a,[r(n,u,i,e,t,a),t])})},f=new Map,h=d(globalThis.clearTimeout,f),p=new Map,v=d(globalThis.clearTimeout,p),w=((e,t)=>{const r=(n,o,s,a)=>{const i=n-e.now();i>0?o.set(a,[t(r,i,n,o,s,a),s]):(o.delete(a),s(!0))};return r})(performance,globalThis.setTimeout),g=m(f,performance,globalThis.setTimeout,w),T=m(p,performance,globalThis.setTimeout,w);l(self,{clear:async({timerId:e,timerType:t})=>({result:await("interval"===t?h(e):v(e))}),set:async({delay:e,now:t,timerId:r,timerType:n})=>({result:await("interval"===n?g:T)(e,t,r)})})})()})();'),S=e=>v().clearInterval(e),_=e=>v().clearTimeout(e),w=(...e)=>v().setInterval(...e),k=(...e)=>v().setTimeout(...e)},8611(e){"use strict";e.exports=require("http")},8914(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RE_URL_WITH_PORT=t.RE_URL=t.RE_ZONE_STRING=t.RE_SUBNET_STRING=t.RE_BAD_ADDRESS=t.RE_BAD_CHARACTERS=t.TYPES=t.SCOPES=t.GROUPS=t.BITS=void 0,t.BITS=128,t.GROUPS=8,t.SCOPES={0:"Reserved",1:"Interface local",2:"Link local",4:"Admin local",5:"Site local",8:"Organization local",14:"Global",15:"Reserved"},t.TYPES={"ff01::1/128":"Multicast (All nodes on this interface)","ff01::2/128":"Multicast (All routers on this interface)","ff02::1/128":"Multicast (All nodes on this link)","ff02::2/128":"Multicast (All routers on this link)","ff05::2/128":"Multicast (All routers in this site)","ff02::5/128":"Multicast (OSPFv3 AllSPF routers)","ff02::6/128":"Multicast (OSPFv3 AllDR routers)","ff02::9/128":"Multicast (RIP routers)","ff02::a/128":"Multicast (EIGRP routers)","ff02::d/128":"Multicast (PIM routers)","ff02::16/128":"Multicast (MLDv2 reports)","ff01::fb/128":"Multicast (mDNSv6)","ff02::fb/128":"Multicast (mDNSv6)","ff05::fb/128":"Multicast (mDNSv6)","ff02::1:2/128":"Multicast (All DHCP servers and relay agents on this link)","ff05::1:2/128":"Multicast (All DHCP servers and relay agents in this site)","ff02::1:3/128":"Multicast (All DHCP servers on this link)","ff05::1:3/128":"Multicast (All DHCP servers in this site)","::/128":"Unspecified","::1/128":"Loopback","ff00::/8":"Multicast","fe80::/10":"Link-local unicast"},t.RE_BAD_CHARACTERS=/([^0-9a-f:/%])/gi,t.RE_BAD_ADDRESS=/([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi,t.RE_SUBNET_STRING=/\/\d{1,3}(?=%|$)/,t.RE_ZONE_STRING=/%.*$/,t.RE_URL=/^\[{0,1}([0-9a-f:]+)\]{0,1}/,t.RE_URL_WITH_PORT=/\[([0-9a-f:]+)\]:([0-9]{1,5})/},9023(e){"use strict";e.exports=require("util")},9231(e){"use strict";e.exports={format:(e,...t)=>e.replace(/%([sdifj])/g,function(...[e,n]){const i=t.shift();if("f"===n)return i.toFixed(6);if("j"===n)return JSON.stringify(i);if("s"===n&&"object"==typeof i){return`${i.constructor!==Object?i.constructor.name:""} {}`.trim()}return i.toString()}),inspect(e){switch(typeof e){case"string":if(e.includes("'")){if(!e.includes('"'))return`"${e}"`;if(!e.includes("`")&&!e.includes("${"))return`\`${e}\``}return`'${e}'`;case"number":return isNaN(e)?"NaN":Object.is(e,-0)?String(e):e;case"bigint":return`${String(e)}n`;case"boolean":case"undefined":return String(e);case"object":return"{}"}}}},9278(e){"use strict";e.exports=require("net")},9291(e,t,n){"use strict";const i=n(8194).CD,r=n(5753)("number-allocator:trace"),o=n(5753)("number-allocator:error");function s(e,t){this.low=e,this.high=t}function a(e,t){if(!(this instanceof a))return new a(e,t);this.min=e,this.max=t,this.ss=new i([],(e,t)=>e.compare(t)),r("Create"),this.clear()}s.prototype.equals=function(e){return this.low===e.low&&this.high===e.high},s.prototype.compare=function(e){return this.low<e.low&&this.high<e.low?-1:e.low<this.low&&e.high<this.low?1:0},a.prototype.firstVacant=function(){return 0===this.ss.size()?null:this.ss.front().low},a.prototype.alloc=function(){if(0===this.ss.size())return r("alloc():empty"),null;const e=this.ss.begin(),t=e.pointer.low,n=e.pointer.high,i=t;return i+1<=n?this.ss.updateKeyByIterator(e,new s(t+1,n)):this.ss.eraseElementByPos(0),r("alloc():"+i),i},a.prototype.use=function(e){const t=new s(e,e),n=this.ss.lowerBound(t);if(!n.equals(this.ss.end())){const i=n.pointer.low,o=n.pointer.high;return n.pointer.equals(t)?(this.ss.eraseElementByIterator(n),r("use():"+e),!0):!(i>e)&&(i===e?(this.ss.updateKeyByIterator(n,new s(i+1,o)),r("use():"+e),!0):o===e?(this.ss.updateKeyByIterator(n,new s(i,o-1)),r("use():"+e),!0):(this.ss.updateKeyByIterator(n,new s(e+1,o)),this.ss.insert(new s(i,e-1)),r("use():"+e),!0))}return r("use():failed"),!1},a.prototype.free=function(e){if(e<this.min||e>this.max)return void o("free():"+e+" is out of range");const t=new s(e,e),n=this.ss.upperBound(t);if(n.equals(this.ss.end())){if(n.equals(this.ss.begin()))return void this.ss.insert(t);n.pre();const i=n.pointer.high;n.pointer.high+1===e?this.ss.updateKeyByIterator(n,new s(i,e)):this.ss.insert(t)}else if(n.equals(this.ss.begin()))if(e+1===n.pointer.low){const t=n.pointer.high;this.ss.updateKeyByIterator(n,new s(e,t))}else this.ss.insert(t);else{const i=n.pointer.low,r=n.pointer.high;n.pre();const o=n.pointer.low;n.pointer.high+1===e?e+1===i?(this.ss.eraseElementByIterator(n),this.ss.updateKeyByIterator(n,new s(o,r))):this.ss.updateKeyByIterator(n,new s(o,e)):e+1===i?(this.ss.eraseElementByIterator(n.next()),this.ss.insert(new s(e,r))):this.ss.insert(t)}r("free():"+e)},a.prototype.clear=function(){r("clear()"),this.ss.clear(),this.ss.insert(new s(this.min,this.max))},a.prototype.intervalCount=function(){return this.ss.size()},a.prototype.dump=function(){console.log("length:"+this.ss.size());for(const e of this.ss)console.log(e)},e.exports=a},9372(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0});const c=s(n(1676));t.default=c,a(n(1676),t)},9424(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.v6=t.AddressError=t.Address6=t.Address4=void 0;var s=n(2839);Object.defineProperty(t,"Address4",{enumerable:!0,get:function(){return s.Address4}});var a=n(6329);Object.defineProperty(t,"Address6",{enumerable:!0,get:function(){return a.Address6}});var c=n(2437);Object.defineProperty(t,"AddressError",{enumerable:!0,get:function(){return c.AddressError}});const l=o(n(465));t.v6={helpers:l}},9576(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RE_SUBNET_STRING=t.RE_ADDRESS=t.GROUPS=t.BITS=void 0,t.BITS=32,t.GROUPS=4,t.RE_ADDRESS=/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g,t.RE_SUBNET_STRING=/\/\d{1,2}$/},9777(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const c=a(n(1278)),l=n(4478),d=a(n(3885)),u=a(n(5753)),p=s(n(128)),h=a(n(7969)),f=a(n(6912)),g=a(n(579)),m=a(n(2639)),y=n(4723),b=n(4152),v=a(n(3175)),S=s(n(6887)),_=globalThis.setImmediate||((...e)=>{const t=e.shift();(0,y.nextTick)(()=>{t(...e)})}),w={keepalive:60,reschedulePings:!0,protocolId:"MQTT",protocolVersion:4,reconnectPeriod:1e3,connectTimeout:3e4,clean:!0,resubscribe:!0,subscribeBatchSize:null,writeCache:!0,timerVariant:"auto"};class k extends b.TypedEventEmitter{static VERSION=y.MQTTJS_VERSION;connected;disconnecting;disconnected;reconnecting;incomingStore;outgoingStore;options;queueQoSZero;_reconnectCount;log;messageIdProvider;outgoing;messageIdToTopic;noop;keepaliveManager;stream;queue;streamBuilder;_resubscribeTopics;connackTimer;reconnectTimer;_storeProcessing;_packetIdsDuringStoreProcessing;_storeProcessingQueue;_firstConnection;topicAliasRecv;topicAliasSend;_deferredReconnect;connackPacket;static defaultId(){return`mqttjs_${Math.random().toString(16).substr(2,8)}`}constructor(e,t){super(),this.options=t||{};for(const e in w)"undefined"==typeof this.options[e]?this.options[e]=w[e]:this.options[e]=t[e];this.log=this.options.log||(0,u.default)("mqttjs:client"),this.noop=this._noop.bind(this),this.log("MqttClient :: version:",k.VERSION),S.isWebWorker?this.log("MqttClient :: environment","webworker"):this.log("MqttClient :: environment",S.default?"browser":"node"),this.log("MqttClient :: options.protocol",t.protocol),this.log("MqttClient :: options.protocolVersion",t.protocolVersion),this.log("MqttClient :: options.username",t.username),this.log("MqttClient :: options.keepalive",t.keepalive),this.log("MqttClient :: options.reconnectPeriod",t.reconnectPeriod),this.log("MqttClient :: options.rejectUnauthorized",t.rejectUnauthorized),this.log("MqttClient :: options.properties.topicAliasMaximum",t.properties?t.properties.topicAliasMaximum:void 0),this.options.clientId="string"==typeof t.clientId?t.clientId:k.defaultId(),this.log("MqttClient :: clientId",this.options.clientId),this.options.customHandleAcks=5===t.protocolVersion&&t.customHandleAcks?t.customHandleAcks:(...e)=>{e[3](null,0)},this.options.writeCache||(c.default.writeToStream.cacheNumbers=!1),this.streamBuilder=e,this.messageIdProvider="undefined"==typeof this.options.messageIdProvider?new g.default:this.options.messageIdProvider,this.outgoingStore=t.outgoingStore||new h.default,this.incomingStore=t.incomingStore||new h.default,this.queueQoSZero=void 0===t.queueQoSZero||t.queueQoSZero,this._resubscribeTopics={},this.messageIdToTopic={},this.keepaliveManager=null,this.connected=!1,this.disconnecting=!1,this.reconnecting=!1,this.queue=[],this.connackTimer=null,this.reconnectTimer=null,this._storeProcessing=!1,this._packetIdsDuringStoreProcessing={},this._storeProcessingQueue=[],this.outgoing={},this._firstConnection=!0,t.properties&&t.properties.topicAliasMaximum>0&&(t.properties.topicAliasMaximum>65535?this.log("MqttClient :: options.properties.topicAliasMaximum is out of range"):this.topicAliasRecv=new m.default(t.properties.topicAliasMaximum)),this.on("connect",()=>{const{queue:e}=this,t=()=>{const n=e.shift();this.log("deliver :: entry %o",n);let i=null;if(!n)return void this._resubscribe();i=n.packet,this.log("deliver :: call _sendPacket for %o",i);let r=!0;i.messageId&&0!==i.messageId&&(this.messageIdProvider.register(i.messageId)||(r=!1)),r?this._sendPacket(i,e=>{n.cb&&n.cb(e),t()}):(this.log("messageId: %d has already used. The message is skipped and removed.",i.messageId),t())};this.log("connect :: sending queued packets"),t()}),this.on("close",()=>{this.log("close :: connected set to `false`"),this.connected=!1,this.log("close :: clearing connackTimer"),clearTimeout(this.connackTimer),this._destroyKeepaliveManager(),this.topicAliasRecv&&this.topicAliasRecv.clear(),this.log("close :: calling _setupReconnect"),this._setupReconnect()}),this.options.manualConnect||(this.log("MqttClient :: setting up stream"),this.connect())}handleAuth(e,t){t()}handleMessage(e,t){t()}_nextId(){return this.messageIdProvider.allocate()}getLastMessageId(){return this.messageIdProvider.getLastAllocated()}connect(){const e=new l.Writable,t=c.default.parser(this.options);let n=null;const i=[];this.log("connect :: calling method to clear reconnect"),this._clearReconnect(),this.disconnected&&!this.reconnecting&&(this.incomingStore=this.options.incomingStore||new h.default,this.outgoingStore=this.options.outgoingStore||new h.default,this.disconnecting=!1,this.disconnected=!1),this.log("connect :: using streamBuilder provided to client to create stream"),this.stream=this.streamBuilder(this),t.on("packet",e=>{this.log("parser :: on packet push to packets array."),i.push(e)});const r=()=>{this.log("work :: getting next packet in queue");const e=i.shift();if(e)this.log("work :: packet pulled from queue"),(0,f.default)(this,e,o);else{this.log("work :: no packets in queue");const e=n;n=null,this.log("work :: done flag is %s",!!e),e&&e()}},o=()=>{if(i.length)(0,y.nextTick)(r);else{const e=n;n=null,e()}};e._write=(e,i,o)=>{n=o,this.log("writable stream :: parsing buffer"),t.parse(e),r()};this.log("connect :: pipe stream to writable stream"),this.stream.pipe(e),this.stream.on("error",e=>{this.log("streamErrorHandler :: error",e.message),e.code?(this.log("streamErrorHandler :: emitting error"),this.emit("error",e)):this.noop(e)}),this.stream.on("close",()=>{this.log("(%s)stream :: on close",this.options.clientId),this._flushVolatile(),this.log("stream: emit close to MqttClient"),this.emit("close")}),this.log("connect: sending packet `connect`");const s={cmd:"connect",protocolId:this.options.protocolId,protocolVersion:this.options.protocolVersion,clean:this.options.clean,clientId:this.options.clientId,keepalive:this.options.keepalive,username:this.options.username,password:this.options.password,properties:this.options.properties};if(this.options.will&&(s.will={...this.options.will,payload:this.options.will?.payload}),this.topicAliasRecv&&(s.properties||(s.properties={}),this.topicAliasRecv&&(s.properties.topicAliasMaximum=this.topicAliasRecv.max)),this._writePacket(s),t.on("error",this.emit.bind(this,"error")),this.options.properties){if(!this.options.properties.authenticationMethod&&this.options.properties.authenticationData)return this.end(()=>this.emit("error",new Error("Packet has no Authentication Method"))),this;if(this.options.properties.authenticationMethod&&this.options.authPacket&&"object"==typeof this.options.authPacket){const e={cmd:"auth",reasonCode:0,...this.options.authPacket};this._writePacket(e)}}return this.stream.setMaxListeners(1e3),clearTimeout(this.connackTimer),this.connackTimer=setTimeout(()=>{this.log("!!connectTimeout hit!! Calling _cleanUp with force `true`"),this.emit("error",new Error("connack timeout")),this._cleanUp(!0)},this.options.connectTimeout),this}publish(e,t,n,i){this.log("publish :: message `%s` to topic `%s`",t,e);const{options:r}=this;"function"==typeof n&&(i=n,n=null),n=n||{};n={qos:0,retain:!1,dup:!1,...n};const{qos:o,retain:s,dup:a,properties:c,cbStorePut:l}=n;if(this._checkDisconnecting(i))return this;const d=()=>{let n=0;if((1===o||2===o)&&(n=this._nextId(),null===n))return this.log("No messageId left"),!1;const d={cmd:"publish",topic:e,payload:t,qos:o,retain:s,messageId:n,dup:a};switch(5===r.protocolVersion&&(d.properties=c),this.log("publish :: qos",o),o){case 1:case 2:this.outgoing[d.messageId]={volatile:!1,cb:i||this.noop},this.log("MqttClient:publish: packet cmd: %s",d.cmd),this._sendPacket(d,void 0,l);break;default:this.log("MqttClient:publish: packet cmd: %s",d.cmd),this._sendPacket(d,i,l)}return!0};return(this._storeProcessing||this._storeProcessingQueue.length>0||!d())&&this._storeProcessingQueue.push({invoke:d,cbStorePut:n.cbStorePut,callback:i}),this}publishAsync(e,t,n){return new Promise((i,r)=>{this.publish(e,t,n,(e,t)=>{e?r(e):i(t)})})}subscribe(e,t,n){const i=this.options.protocolVersion;"function"==typeof t&&(n=t),n=n||this.noop;let r=!1,o=[];"string"==typeof e?o=e=[e]:Array.isArray(e)?o=e:"object"==typeof e&&(r=e.resubscribe,delete e.resubscribe,o=Object.keys(e));const s=p.validateTopics(o);if(null!==s)return _(n,new Error(`Invalid topic ${s}`)),this;if(this._checkDisconnecting(n))return this.log("subscribe: discconecting true"),this;const a={qos:0};5===i&&(a.nl=!1,a.rap=!1,a.rh=0),t={...a,...t};const{properties:c}=t,l=[],d=(e,n)=>{if(n=n||t,!Object.prototype.hasOwnProperty.call(this._resubscribeTopics,e)||this._resubscribeTopics[e].qos<n.qos||r){const t={topic:e,qos:n.qos};5===i&&(t.nl=n.nl,t.rap=n.rap,t.rh=n.rh,t.properties=c),this.log("subscribe: pushing topic `%s` and qos `%s` to subs list",t.topic,t.qos),l.push(t)}};if(Array.isArray(e)?e.forEach(e=>{this.log("subscribe: array topic %s",e),d(e)}):Object.keys(e).forEach(t=>{this.log("subscribe: object topic %s, %o",t,e[t]),d(t,e[t])}),!l.length)return n(null,[]),this;const u=(e,t)=>{const n={cmd:"subscribe",subscriptions:e,messageId:t};if(c&&(n.properties=c),this.options.resubscribe){this.log("subscribe :: resubscribe true");const t=[];e.forEach(e=>{if(this.options.reconnectPeriod>0){const n={qos:e.qos};5===i&&(n.nl=e.nl||!1,n.rap=e.rap||!1,n.rh=e.rh||0,n.properties=e.properties),this._resubscribeTopics[e.topic]=n,t.push(e.topic)}}),this.messageIdToTopic[n.messageId]=t}const r=new Promise((t,i)=>{this.outgoing[n.messageId]={volatile:!0,cb(n,r){if(!n){const{granted:t}=r;for(let n=0;n<t.length;n+=1)e[n].qos=t[n]}n?i(new y.ErrorWithSubackPacket(n.message,r)):t(r)}}});return this.log("subscribe :: call _sendPacket"),this._sendPacket(n),r},h=()=>{const e=this.options.subscribeBatchSize??l.length,t=[];for(let n=0;n<l.length;n+=e){const i=l.slice(n,n+e),r=this._nextId();if(null===r)return this.log("No messageId left"),!1;t.push(u(i,r))}return Promise.all(t).then(e=>{n(null,l,e.at(-1))}).catch(e=>{n(e,l,e.packet)}),!0};return(this._storeProcessing||this._storeProcessingQueue.length>0||!h())&&this._storeProcessingQueue.push({invoke:h,callback:n}),this}subscribeAsync(e,t){return new Promise((n,i)=>{this.subscribe(e,t,(e,t)=>{e?i(e):n(t)})})}unsubscribe(e,t,n){"string"==typeof e&&(e=[e]),"function"==typeof t&&(n=t),n=n||this.noop;const i=p.validateTopics(e);if(null!==i)return _(n,new Error(`Invalid topic ${i}`)),this;if(this._checkDisconnecting(n))return this;const r=()=>{const i=this._nextId();if(null===i)return this.log("No messageId left"),!1;const r={cmd:"unsubscribe",messageId:i,unsubscriptions:[]};return"string"==typeof e?r.unsubscriptions=[e]:Array.isArray(e)&&(r.unsubscriptions=e),this.options.resubscribe&&r.unsubscriptions.forEach(e=>{delete this._resubscribeTopics[e]}),"object"==typeof t&&t.properties&&(r.properties=t.properties),this.outgoing[r.messageId]={volatile:!0,cb:n},this.log("unsubscribe: call _sendPacket"),this._sendPacket(r),!0};return(this._storeProcessing||this._storeProcessingQueue.length>0||!r())&&this._storeProcessingQueue.push({invoke:r,callback:n}),this}unsubscribeAsync(e,t){return new Promise((n,i)=>{this.unsubscribe(e,t,(e,t)=>{e?i(e):n(t)})})}end(e,t,n){this.log("end :: (%s)",this.options.clientId),null!=e&&"boolean"==typeof e||(n=n||t,t=e,e=!1),"object"!=typeof t&&(n=n||t,t=null),this.log("end :: cb? %s",!!n),n&&"function"==typeof n||(n=this.noop);const i=()=>{this.log("end :: closeStores: closing incoming and outgoing stores"),this.disconnected=!0,this.incomingStore.close(e=>{this.outgoingStore.close(t=>{if(this.log("end :: closeStores: emitting end"),this.emit("end"),n){const i=e||t;this.log("end :: closeStores: invoking callback with args"),n(i)}})}),this._deferredReconnect?this._deferredReconnect():(0===this.options.reconnectPeriod||this.options.manualConnect)&&(this.disconnecting=!1)},r=()=>{this.log("end :: (%s) :: finish :: calling _cleanUp with force %s",this.options.clientId,e),this._cleanUp(e,()=>{this.log("end :: finish :: calling process.nextTick on closeStores"),(0,y.nextTick)(i)},t)};return this.disconnecting?(n(),this):(this._clearReconnect(),this.disconnecting=!0,!e&&Object.keys(this.outgoing).length>0?(this.log("end :: (%s) :: calling finish in 10ms once outgoing is empty",this.options.clientId),this.once("outgoingEmpty",setTimeout.bind(null,r,10))):(this.log("end :: (%s) :: immediately calling finish",this.options.clientId),r()),this)}endAsync(e,t){return new Promise((n,i)=>{this.end(e,t,e=>{e?i(e):n()})})}removeOutgoingMessage(e){if(this.outgoing[e]){const{cb:t}=this.outgoing[e];this._removeOutgoingAndStoreMessage(e,()=>{t(new Error("Message removed"))})}return this}reconnect(e){this.log("client reconnect");const t=()=>{e?(this.options.incomingStore=e.incomingStore,this.options.outgoingStore=e.outgoingStore):(this.options.incomingStore=null,this.options.outgoingStore=null),this.incomingStore=this.options.incomingStore||new h.default,this.outgoingStore=this.options.outgoingStore||new h.default,this.disconnecting=!1,this.disconnected=!1,this._deferredReconnect=null,this._reconnect()};return this.disconnecting&&!this.disconnected?this._deferredReconnect=t:t(),this}_flushVolatile(){this.outgoing&&(this.log("_flushVolatile :: deleting volatile messages from the queue and setting their callbacks as error function"),Object.keys(this.outgoing).forEach(e=>{this.outgoing[e].volatile&&"function"==typeof this.outgoing[e].cb&&(this.outgoing[e].cb(new Error("Connection closed")),delete this.outgoing[e])}))}_flush(){this.outgoing&&(this.log("_flush: queue exists? %b",!!this.outgoing),Object.keys(this.outgoing).forEach(e=>{"function"==typeof this.outgoing[e].cb&&(this.outgoing[e].cb(new Error("Connection closed")),delete this.outgoing[e])}))}_removeTopicAliasAndRecoverTopicName(e){let t;e.properties&&(t=e.properties.topicAlias);let n=e.topic.toString();if(this.log("_removeTopicAliasAndRecoverTopicName :: alias %d, topic %o",t,n),0===n.length){if("undefined"==typeof t)return new Error("Unregistered Topic Alias");if(n=this.topicAliasSend.getTopicByAlias(t),"undefined"==typeof n)return new Error("Unregistered Topic Alias");e.topic=n}t&&delete e.properties.topicAlias}_checkDisconnecting(e){return this.disconnecting&&(e&&e!==this.noop?e(new Error("client disconnecting")):this.emit("error",new Error("client disconnecting"))),this.disconnecting}_reconnect(){this.log("_reconnect: emitting reconnect to client"),this.emit("reconnect"),this.connected?(this.end(()=>{this.connect()}),this.log("client already connected. disconnecting first.")):(this.log("_reconnect: calling connect"),this.connect())}_setupReconnect(){!this.disconnecting&&!this.reconnectTimer&&this.options.reconnectPeriod>0?(this.reconnecting||(this.log("_setupReconnect :: emit `offline` state"),this.emit("offline"),this.log("_setupReconnect :: set `reconnecting` to `true`"),this.reconnecting=!0),this.log("_setupReconnect :: setting reconnectTimer for %d ms",this.options.reconnectPeriod),this.reconnectTimer=setInterval(()=>{this.log("reconnectTimer :: reconnect triggered!"),this._reconnect()},this.options.reconnectPeriod)):this.log("_setupReconnect :: doing nothing...")}_clearReconnect(){this.log("_clearReconnect : clearing reconnect timer"),this.reconnectTimer&&(clearInterval(this.reconnectTimer),this.reconnectTimer=null)}_cleanUp(e,t,n={}){if(t&&(this.log("_cleanUp :: done callback provided for on stream close"),this.stream.on("close",t)),this.log("_cleanUp :: forced? %s",e),e)0===this.options.reconnectPeriod&&this.options.clean&&this._flush(),this.log("_cleanUp :: (%s) :: destroying stream",this.options.clientId),this.stream.destroy();else{const e={cmd:"disconnect",...n};this.log("_cleanUp :: (%s) :: call _sendPacket with disconnect packet",this.options.clientId),this._sendPacket(e,()=>{this.log("_cleanUp :: (%s) :: destroying stream",this.options.clientId),_(()=>{this.stream.end(()=>{this.log("_cleanUp :: (%s) :: stream destroyed",this.options.clientId)})})})}this.disconnecting||this.reconnecting||(this.log("_cleanUp :: client not disconnecting/reconnecting. Clearing and resetting reconnect."),this._clearReconnect(),this._setupReconnect()),this._destroyKeepaliveManager(),t&&!this.connected&&(this.log("_cleanUp :: (%s) :: removing stream `done` callback `close` listener",this.options.clientId),this.stream.removeListener("close",t),t())}_storeAndSend(e,t,n){this.log("storeAndSend :: store packet with cmd %s to outgoingStore",e.cmd);let i,r=e;if("publish"===r.cmd&&(r=(0,d.default)(e),i=this._removeTopicAliasAndRecoverTopicName(r),i))return t&&t(i);this.outgoingStore.put(r,i=>{if(i)return t&&t(i);n(),this._writePacket(e,t)})}_applyTopicAlias(e){if(5===this.options.protocolVersion&&"publish"===e.cmd){let t;e.properties&&(t=e.properties.topicAlias);const n=e.topic.toString();if(this.topicAliasSend)if(t){if(0!==n.length&&(this.log("applyTopicAlias :: register topic: %s - alias: %d",n,t),!this.topicAliasSend.put(n,t)))return this.log("applyTopicAlias :: error out of range. topic: %s - alias: %d",n,t),new Error("Sending Topic Alias out of range")}else 0!==n.length&&(this.options.autoAssignTopicAlias?(t=this.topicAliasSend.getAliasByTopic(n),t?(e.topic="",e.properties={...e.properties,topicAlias:t},this.log("applyTopicAlias :: auto assign(use) topic: %s - alias: %d",n,t)):(t=this.topicAliasSend.getLruAlias(),this.topicAliasSend.put(n,t),e.properties={...e.properties,topicAlias:t},this.log("applyTopicAlias :: auto assign topic: %s - alias: %d",n,t))):this.options.autoUseTopicAlias&&(t=this.topicAliasSend.getAliasByTopic(n),t&&(e.topic="",e.properties={...e.properties,topicAlias:t},this.log("applyTopicAlias :: auto use topic: %s - alias: %d",n,t))));else if(t)return this.log("applyTopicAlias :: error out of range. topic: %s - alias: %d",n,t),new Error("Sending Topic Alias out of range")}}_noop(e){this.log("noop ::",e)}_writePacket(e,t){this.log("_writePacket :: packet: %O",e),this.log("_writePacket :: emitting `packetsend`"),this.emit("packetsend",e),this.log("_writePacket :: writing to stream");const n=c.default.writeToStream(e,this.stream,this.options);this.log("_writePacket :: writeToStream result %s",n),!n&&t&&t!==this.noop?(this.log("_writePacket :: handle events on `drain` once through callback."),this.stream.once("drain",t)):t&&(this.log("_writePacket :: invoking cb"),t())}_sendPacket(e,t,n,i){this.log("_sendPacket :: (%s) :: start",this.options.clientId),n=n||this.noop,t=t||this.noop;const r=this._applyTopicAlias(e);if(r)t(r);else{if(!this.connected)return"auth"===e.cmd?void this._writePacket(e,t):(this.log("_sendPacket :: client not connected. Storing packet offline."),void this._storePacket(e,t,n));if(i)this._writePacket(e,t);else{switch(e.cmd){case"publish":break;case"pubrel":return void this._storeAndSend(e,t,n);default:return void this._writePacket(e,t)}switch(e.qos){case 2:case 1:this._storeAndSend(e,t,n);break;default:this._writePacket(e,t)}this.log("_sendPacket :: (%s) :: end",this.options.clientId)}}}_storePacket(e,t,n){this.log("_storePacket :: packet: %o",e),this.log("_storePacket :: cb? %s",!!t),n=n||this.noop;let i=e;if("publish"===i.cmd){i=(0,d.default)(e);const n=this._removeTopicAliasAndRecoverTopicName(i);if(n)return t&&t(n)}const r=i.qos||0;0===r&&this.queueQoSZero||"publish"!==i.cmd?this.queue.push({packet:i,cb:t}):r>0?(t=this.outgoing[i.messageId]?this.outgoing[i.messageId].cb:null,this.outgoingStore.put(i,e=>{if(e)return t&&t(e);n()})):t&&t(new Error("No connection to broker"))}_setupKeepaliveManager(){this.log("_setupKeepaliveManager :: keepalive %d (seconds)",this.options.keepalive),!this.keepaliveManager&&this.options.keepalive&&(this.keepaliveManager=new v.default(this,this.options.timerVariant))}_destroyKeepaliveManager(){this.keepaliveManager&&(this.log("_destroyKeepaliveManager :: destroying keepalive manager"),this.keepaliveManager.destroy(),this.keepaliveManager=null)}reschedulePing(e=!1){this.keepaliveManager&&this.options.keepalive&&(e||this.options.reschedulePings)&&this._reschedulePing()}_reschedulePing(){this.log("_reschedulePing :: rescheduling ping"),this.keepaliveManager.reschedule()}sendPing(){this.log("_sendPing :: sending pingreq"),this._sendPacket({cmd:"pingreq"})}onKeepaliveTimeout(){this.emit("error",new Error("Keepalive timeout")),this.log("onKeepaliveTimeout :: calling _cleanUp with force true"),this._cleanUp(!0)}_resubscribe(){this.log("_resubscribe");const e=Object.keys(this._resubscribeTopics);if(!this._firstConnection&&(this.options.clean||this.options.protocolVersion>=4&&!this.connackPacket.sessionPresent)&&e.length>0)if(this.options.resubscribe)if(5===this.options.protocolVersion){this.log("_resubscribe: protocolVersion 5");for(let t=0;t<e.length;t++){const n={};n[e[t]]=this._resubscribeTopics[e[t]],n.resubscribe=!0,this.subscribe(n,{properties:n[e[t]].properties})}}else this._resubscribeTopics.resubscribe=!0,this.subscribe(this._resubscribeTopics);else this._resubscribeTopics={};this._firstConnection=!1}_onConnect(e){if(this.disconnected)return void this.emit("connect",e);this.connackPacket=e,this.messageIdProvider.clear(),this._setupKeepaliveManager(),this.connected=!0;const t=()=>{let n=this.outgoingStore.createStream();const i=()=>{n.destroy(),n=null,this._flushStoreProcessingQueue(),r()},r=()=>{this._storeProcessing=!1,this._packetIdsDuringStoreProcessing={}};this.once("close",i),n.on("error",e=>{r(),this._flushStoreProcessingQueue(),this.removeListener("close",i),this.emit("error",e)});const o=()=>{if(!n)return;const e=n.read(1);let t;e?(this._storeProcessing=!0,this._packetIdsDuringStoreProcessing[e.messageId]?o():this.disconnecting||this.reconnectTimer?n.destroy&&n.destroy():(t=this.outgoing[e.messageId]?this.outgoing[e.messageId].cb:null,this.outgoing[e.messageId]={volatile:!1,cb(e,n){t&&t(e,n),o()}},this._packetIdsDuringStoreProcessing[e.messageId]=!0,this.messageIdProvider.register(e.messageId)?this._sendPacket(e,void 0,void 0,!0):this.log("messageId: %d has already used.",e.messageId))):n.once("readable",o)};n.on("end",()=>{let n=!0;for(const e in this._packetIdsDuringStoreProcessing)if(!this._packetIdsDuringStoreProcessing[e]){n=!1;break}this.removeListener("close",i),n?(r(),this._invokeAllStoreProcessingQueue(),this.emit("connect",e)):t()}),o()};t()}_invokeStoreProcessingQueue(){if(!this._storeProcessing&&this._storeProcessingQueue.length>0){const e=this._storeProcessingQueue[0];if(e&&e.invoke())return this._storeProcessingQueue.shift(),!0}return!1}_invokeAllStoreProcessingQueue(){for(;this._invokeStoreProcessingQueue(););}_flushStoreProcessingQueue(){for(const e of this._storeProcessingQueue)e.cbStorePut&&e.cbStorePut(new Error("Connection closed")),e.callback&&e.callback(new Error("Connection closed"));this._storeProcessingQueue.splice(0)}_removeOutgoingAndStoreMessage(e,t){delete this.outgoing[e],this.outgoingStore.del({messageId:e},(n,i)=>{t(n,i),this.messageIdProvider.deallocate(e),this._invokeStoreProcessingQueue()})}}t.default=k},9844(e){"use strict";function t(e){return e instanceof Buffer?Buffer.from(e):new e.constructor(e.buffer.slice(),e.byteOffset,e.length)}e.exports=function(e){if((e=e||{}).circles)return function(e){const n=[],i=[],r=new Map;if(r.set(Date,e=>new Date(e)),r.set(Map,(e,t)=>new Map(s(Array.from(e),t))),r.set(Set,(e,t)=>new Set(s(Array.from(e),t))),e.constructorHandlers)for(const t of e.constructorHandlers)r.set(t[0],t[1]);let o=null;return e.proto?c:a;function s(e,s){const a=Object.keys(e),c=new Array(a.length);for(let l=0;l<a.length;l++){const d=a[l],u=e[d];if("object"!=typeof u||null===u)c[d]=u;else if(u.constructor!==Object&&(o=r.get(u.constructor)))c[d]=o(u,s);else if(ArrayBuffer.isView(u))c[d]=t(u);else{const e=n.indexOf(u);c[d]=-1!==e?i[e]:s(u)}}return c}function a(e){if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return s(e,a);if(e.constructor!==Object&&(o=r.get(e.constructor)))return o(e,a);const c={};n.push(e),i.push(c);for(const s in e){if(!1===Object.hasOwnProperty.call(e,s))continue;const l=e[s];if("object"!=typeof l||null===l)c[s]=l;else if(l.constructor!==Object&&(o=r.get(l.constructor)))c[s]=o(l,a);else if(ArrayBuffer.isView(l))c[s]=t(l);else{const e=n.indexOf(l);c[s]=-1!==e?i[e]:a(l)}}return n.pop(),i.pop(),c}function c(e){if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return s(e,c);if(e.constructor!==Object&&(o=r.get(e.constructor)))return o(e,c);const a={};n.push(e),i.push(a);for(const s in e){const l=e[s];if("object"!=typeof l||null===l)a[s]=l;else if(l.constructor!==Object&&(o=r.get(l.constructor)))a[s]=o(l,c);else if(ArrayBuffer.isView(l))a[s]=t(l);else{const e=n.indexOf(l);a[s]=-1!==e?i[e]:c(l)}}return n.pop(),i.pop(),a}}(e);const n=new Map;if(n.set(Date,e=>new Date(e)),n.set(Map,(e,t)=>new Map(r(Array.from(e),t))),n.set(Set,(e,t)=>new Set(r(Array.from(e),t))),e.constructorHandlers)for(const t of e.constructorHandlers)n.set(t[0],t[1]);let i=null;return e.proto?function e(o){if("object"!=typeof o||null===o)return o;if(Array.isArray(o))return r(o,e);if(o.constructor!==Object&&(i=n.get(o.constructor)))return i(o,e);const s={};for(const r in o){const a=o[r];"object"!=typeof a||null===a?s[r]=a:a.constructor!==Object&&(i=n.get(a.constructor))?s[r]=i(a,e):ArrayBuffer.isView(a)?s[r]=t(a):s[r]=e(a)}return s}:function e(o){if("object"!=typeof o||null===o)return o;if(Array.isArray(o))return r(o,e);if(o.constructor!==Object&&(i=n.get(o.constructor)))return i(o,e);const s={};for(const r in o){if(!1===Object.hasOwnProperty.call(o,r))continue;const a=o[r];"object"!=typeof a||null===a?s[r]=a:a.constructor!==Object&&(i=n.get(a.constructor))?s[r]=i(a,e):ArrayBuffer.isView(a)?s[r]=t(a):s[r]=e(a)}return s};function r(e,r){const o=Object.keys(e),s=new Array(o.length);for(let a=0;a<o.length;a++){const c=o[a],l=e[c];"object"!=typeof l||null===l?s[c]=l:l.constructor!==Object&&(i=n.get(l.constructor))?s[c]=i(l,r):ArrayBuffer.isView(l)?s[c]=t(l):s[c]=r(l)}return s}}},9896(e){"use strict";e.exports=require("fs")}},t={};function n(i){var r=t[i];if(void 0!==r)return r.exports;var o=t[i]={exports:{}};return e[i].call(o.exports,o,o.exports,n),o.exports}n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i=n(7927),r=exports="undefined"==typeof exports?{}:exports;for(var o in i)r[o]=i[o];i.__esModule&&Object.defineProperty(r,"__esModule",{value:!0})})();
|
|
2
|
+
(()=>{var e={128(e,t){"use strict";function n(e){const t=e.split("/");for(let e=0;e<t.length;e++)if("+"!==t[e]){if("#"===t[e])return e===t.length-1;if(-1!==t[e].indexOf("+")||-1!==t[e].indexOf("#"))return!1}return!0}Object.defineProperty(t,"__esModule",{value:!0}),t.validateTopic=n,t.validateTopics=function(e){if(0===e.length)return"empty_topic_list";for(let t=0;t<e.length;t++)if(!n(e[t]))return e[t];return null}},181(e){"use strict";e.exports=require("buffer")},277(e,t,n){"use strict";const{ArrayIsArray:i,ArrayPrototypeIncludes:r,ArrayPrototypeJoin:o,ArrayPrototypeMap:s,NumberIsInteger:a,NumberIsNaN:c,NumberMAX_SAFE_INTEGER:l,NumberMIN_SAFE_INTEGER:d,NumberParseInt:u,ObjectPrototypeHasOwnProperty:p,RegExpPrototypeExec:h,String:f,StringPrototypeToUpperCase:g,StringPrototypeTrim:m}=n(4134),{hideStackFrames:y,codes:{ERR_SOCKET_BAD_PORT:b,ERR_INVALID_ARG_TYPE:v,ERR_INVALID_ARG_VALUE:S,ERR_OUT_OF_RANGE:_,ERR_UNKNOWN_SIGNAL:w}}=n(6371),{normalizeEncoding:k}=n(7760),{isAsyncFunction:I,isArrayBufferView:x}=n(7760).types,C={};const E=/^[0-7]+$/;const T=y((e,t,n=d,i=l)=>{if("number"!=typeof e)throw new v(t,"number",e);if(!a(e))throw new _(t,"an integer",e);if(e<n||e>i)throw new _(t,`>= ${n} && <= ${i}`,e)}),O=y((e,t,n=-2147483648,i=2147483647)=>{if("number"!=typeof e)throw new v(t,"number",e);if(!a(e))throw new _(t,"an integer",e);if(e<n||e>i)throw new _(t,`>= ${n} && <= ${i}`,e)}),P=y((e,t,n=!1)=>{if("number"!=typeof e)throw new v(t,"number",e);if(!a(e))throw new _(t,"an integer",e);const i=n?1:0,r=4294967295;if(e<i||e>r)throw new _(t,`>= ${i} && <= ${r}`,e)});function A(e,t){if("string"!=typeof e)throw new v(t,"string",e)}const R=y((e,t,n)=>{if(!r(n,e)){const i=o(s(n,e=>"string"==typeof e?`'${e}'`:f(e)),", ");throw new S(t,e,"must be one of: "+i)}});function M(e,t){if("boolean"!=typeof e)throw new v(t,"boolean",e)}function L(e,t,n){return null!=e&&p(e,t)?e[t]:n}const N=y((e,t,n=null)=>{const r=L(n,"allowArray",!1),o=L(n,"allowFunction",!1);if(!L(n,"nullable",!1)&&null===e||!r&&i(e)||"object"!=typeof e&&(!o||"function"!=typeof e))throw new v(t,"Object",e)}),D=y((e,t)=>{if(null!=e&&"object"!=typeof e&&"function"!=typeof e)throw new v(t,"a dictionary",e)}),B=y((e,t,n=0)=>{if(!i(e))throw new v(t,"Array",e);if(e.length<n){throw new S(t,e,`must be longer than ${n}`)}});const j=y((e,t="buffer")=>{if(!x(e))throw new v(t,["Buffer","TypedArray","DataView"],e)});const $=y((e,t)=>{if(void 0!==e&&(null===e||"object"!=typeof e||!("aborted"in e)))throw new v(t,"AbortSignal",e)}),F=y((e,t)=>{if("function"!=typeof e)throw new v(t,"Function",e)}),U=y((e,t)=>{if("function"!=typeof e||I(e))throw new v(t,"Function",e)}),z=y((e,t)=>{if(void 0!==e)throw new v(t,"undefined",e)});const V=/^(?:<[^>]*>)(?:\s*;\s*[^;"\s]+(?:=(")?[^;"\s]*\1)?)*$/;function W(e,t){if("undefined"==typeof e||!h(V,e))throw new S(t,e,'must be an array or string of format "</styles.css>; rel=preload; as=style"')}e.exports={isInt32:function(e){return e===(0|e)},isUint32:function(e){return e===e>>>0},parseFileMode:function(e,t,n){if("undefined"==typeof e&&(e=n),"string"==typeof e){if(null===h(E,e))throw new S(t,e,"must be a 32-bit unsigned integer or an octal string");e=u(e,8)}return P(e,t),e},validateArray:B,validateStringArray:function(e,t){B(e,t);for(let n=0;n<e.length;n++)A(e[n],`${t}[${n}]`)},validateBooleanArray:function(e,t){B(e,t);for(let n=0;n<e.length;n++)M(e[n],`${t}[${n}]`)},validateAbortSignalArray:function(e,t){B(e,t);for(let n=0;n<e.length;n++){const i=e[n],r=`${t}[${n}]`;if(null==i)throw new v(r,"AbortSignal",i);$(i,r)}},validateBoolean:M,validateBuffer:j,validateDictionary:D,validateEncoding:function(e,t){const n=k(t),i=e.length;if("hex"===n&&i%2!=0)throw new S("encoding",t,`is invalid for data of length ${i}`)},validateFunction:F,validateInt32:O,validateInteger:T,validateNumber:function(e,t,n=void 0,i){if("number"!=typeof e)throw new v(t,"number",e);if(null!=n&&e<n||null!=i&&e>i||(null!=n||null!=i)&&c(e))throw new _(t,`${null!=n?`>= ${n}`:""}${null!=n&&null!=i?" && ":""}${null!=i?`<= ${i}`:""}`,e)},validateObject:N,validateOneOf:R,validatePlainFunction:U,validatePort:function(e,t="Port",n=!0){if("number"!=typeof e&&"string"!=typeof e||"string"==typeof e&&0===m(e).length||+e!==+e>>>0||e>65535||0===e&&!n)throw new b(t,e,n);return 0|e},validateSignalName:function(e,t="signal"){if(A(e,t),void 0===C[e]){if(void 0!==C[g(e)])throw new w(e+" (signals must use all capital letters)");throw new w(e)}},validateString:A,validateUint32:P,validateUndefined:z,validateUnion:function(e,t,n){if(!r(n,e))throw new v(t,`('${o(n,"|")}')`,e)},validateAbortSignal:$,validateLinkHeaderValue:function(e){if("string"==typeof e)return W(e,"hints"),e;if(i(e)){const t=e.length;let n="";if(0===t)return n;for(let i=0;i<t;i++){const r=e[i];W(r,"hints"),n+=r,i!==t-1&&(n+=", ")}return n}throw new S("hints",e,'must be an array or string of format "</styles.css>; rel=preload; as=style"')}}},321(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.ADDRESS_BOUNDARY=void 0,t.groupPossibilities=a,t.padGroup=c,t.simpleRegularExpression=function(e){const t=[];e.forEach((e,n)=>{0===parseInt(e,16)&&t.push(n)});const n=t.map(t=>e.map((e,n)=>{if(n===t){const t=0===n||n===s.GROUPS-1?":":"";return a([c(e),t])}return c(e)}).join(":"));return n.push(e.map(c).join(":")),a(n)},t.possibleElisions=function(e,t,n){const i=t?"":":",r=n?"":":",o=[];t||n||o.push("::");t&&n&&o.push("");(n&&!t||!n&&t)&&o.push(":");o.push(`${i}(:0{1,4}){1,${e-1}}`),o.push(`(0{1,4}:){1,${e-1}}${r}`),o.push(`(0{1,4}:){${e-1}}0{1,4}`);for(let t=1;t<e-1;t++)for(let n=1;n<e-t;n++)o.push(`(0{1,4}:){${n}}:(0{1,4}:){${e-n-t-1}}0{1,4}`);return a(o)};const s=o(n(8914));function a(e){return`(${e.join("|")})`}function c(e){return e.length<4?`0{0,${4-e.length}}${e}`:e}t.ADDRESS_BOUNDARY="[^A-Fa-f0-9:]"},345(e,t,n){"use strict";const{StringPrototypeSlice:i,SymbolIterator:r,TypedArrayPrototypeSet:o,Uint8Array:s}=n(4134),{Buffer:a}=n(181),{inspect:c}=n(7760);e.exports=class{constructor(){this.head=null,this.tail=null,this.length=0}push(e){const t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length}unshift(e){const t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length}shift(){if(0===this.length)return;const e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}clear(){this.head=this.tail=null,this.length=0}join(e){if(0===this.length)return"";let t=this.head,n=""+t.data;for(;null!==(t=t.next);)n+=e+t.data;return n}concat(e){if(0===this.length)return a.alloc(0);const t=a.allocUnsafe(e>>>0);let n=this.head,i=0;for(;n;)o(t,n.data,i),i+=n.data.length,n=n.next;return t}consume(e,t){const n=this.head.data;if(e<n.length){const t=n.slice(0,e);return this.head.data=n.slice(e),t}return e===n.length?this.shift():t?this._getString(e):this._getBuffer(e)}first(){return this.head.data}*[r](){for(let e=this.head;e;e=e.next)yield e.data}_getString(e){let t="",n=this.head,r=0;do{const o=n.data;if(!(e>o.length)){e===o.length?(t+=o,++r,n.next?this.head=n.next:this.head=this.tail=null):(t+=i(o,0,e),this.head=n,n.data=i(o,e));break}t+=o,e-=o.length,++r}while(null!==(n=n.next));return this.length-=r,t}_getBuffer(e){const t=a.allocUnsafe(e),n=e;let i=this.head,r=0;do{const a=i.data;if(!(e>a.length)){e===a.length?(o(t,a,n-e),++r,i.next?this.head=i.next:this.head=this.tail=null):(o(t,new s(a.buffer,a.byteOffset,e),n-e),this.head=i,i.data=a.slice(e));break}o(t,a,n-e),e-=a.length,++r}while(null!==(i=i.next));return this.length-=r,t}[Symbol.for("nodejs.util.inspect.custom")](e,t){return c(this,{...t,depth:0,customInspect:!1})}}},397(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_TRAINING_CONFIG=void 0,t.createTrainingSession=function(e){const t=Date.now();return{id:`training-${t}-${Math.random().toString(36).substr(2,9)}`,state:"idle",startedAt:t,updatedAt:t,trainerName:e,visits:[],transits:[],landmarks:[],overlaps:[],structures:[],stats:{totalDuration:0,camerasVisited:0,transitsRecorded:0,landmarksMarked:0,overlapsDetected:0,structuresMarked:0,averageTransitTime:0,coveragePercentage:0}}},t.calculateTrainingStats=function(e,t){const n=new Set(e.visits.map(e=>e.cameraId)),i=e.transits.map(e=>e.transitSeconds),r=i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0;return{totalDuration:(e.completedAt||Date.now())-e.startedAt,camerasVisited:n.size,transitsRecorded:e.transits.length,landmarksMarked:e.landmarks.length,overlapsDetected:e.overlaps.length,structuresMarked:e.structures.length,averageTransitTime:Math.round(r),coveragePercentage:t>0?Math.round(n.size/t*100):0}},t.DEFAULT_TRAINING_CONFIG={minDetectionConfidence:.7,maxTransitWait:120,autoDetectOverlaps:!0,autoSuggestLandmarks:!0,minOverlapDuration:2}},441(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createTrackedObject=function(e,t,n){return{globalId:e,className:t.detection.className,label:t.detection.label,sightings:[t],journey:[],firstSeen:t.timestamp,lastSeen:t.timestamp,activeOnCameras:[t.cameraId],entryCamera:n?t.cameraId:void 0,entryCameraName:n?t.cameraName:void 0,hasExited:!1,totalDwellTime:0,state:"active",visualDescriptor:t.embedding,bestThumbnailId:t.detectionId}},t.addSighting=function(e,t){e.sightings.push(t),e.lastSeen=t.timestamp,e.activeOnCameras.includes(t.cameraId)||e.activeOnCameras.push(t.cameraId);t.embedding&&!e.visualDescriptor&&(e.visualDescriptor=t.embedding);t.detectionId&&t.confidence>.8&&(e.bestThumbnailId=t.detectionId);t.detection.label&&!e.label&&(e.label=t.detection.label)},t.addJourneySegment=function(e,t){e.journey.push(t),e.activeOnCameras=e.activeOnCameras.filter(e=>e!==t.fromCameraId),e.activeOnCameras.includes(t.toCameraId)||e.activeOnCameras.push(t.toCameraId)},t.calculateDwellTime=function(e){return 0===e.sightings.length?0:e.lastSeen-e.firstSeen},t.getLastCamera=function(e){return 0===e.sightings.length?void 0:e.sightings[e.sightings.length-1].cameraId},t.getLastSighting=function(e){return 0===e.sightings.length?void 0:e.sightings[e.sightings.length-1]},t.getJourneySummary=function(e){const t=[];e.entryCamera&&t.push(e.entryCameraName||e.entryCamera);for(const n of e.journey)t.includes(n.toCameraName||n.toCameraId)||t.push(n.toCameraName||n.toCameraId);e.exitCamera&&!t.includes(e.exitCameraName||e.exitCamera)&&t.push(e.exitCameraName||e.exitCamera);return t.join(" → ")}},465(e,t){"use strict";function n(e){return e.replace(/(0+)/g,'<span class="zero">$1</span>')}function i(e){return e.replace(/^(0+)/,'<span class="zero">$1</span>')}Object.defineProperty(t,"__esModule",{value:!0}),t.spanAllZeroes=n,t.spanAll=function(e,t=0){return e.split("").map((e,i)=>`<span class="digit value-${e} position-${i+t}">${n(e)}</span>`).join("")},t.spanLeadingZeroes=function(e){return e.split(":").map(e=>i(e)).join(":")},t.simpleGroup=function(e,t=0){return e.split(":").map((e,n)=>/group-v4/.test(e)?e:`<span class="hover-group group-${n+t}">${i(e)}</span>`)}},495(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=n(1021),o=i(n(3497)),s=n(4723);t.default=(e,t)=>{e.log("_handleConnack");const{options:n}=e,i=5===n.protocolVersion?t.reasonCode:t.returnCode;if(clearTimeout(e.connackTimer),delete e.topicAliasSend,t.properties){if(t.properties.topicAliasMaximum){if(t.properties.topicAliasMaximum>65535)return void e.emit("error",new Error("topicAliasMaximum from broker is out of range"));t.properties.topicAliasMaximum>0&&(e.topicAliasSend=new o.default(t.properties.topicAliasMaximum))}t.properties.serverKeepAlive&&n.keepalive&&(n.keepalive=t.properties.serverKeepAlive),t.properties.maximumPacketSize&&(n.properties||(n.properties={}),n.properties.maximumPacketSize=t.properties.maximumPacketSize)}if(0===i)e.reconnecting=!1,e._onConnect(t);else if(i>0){const t=new s.ErrorWithReasonCode(`Connection refused: ${r.ReasonCodes[i]}`,i);e.emit("error",t),e.options.reconnectOnConnackError&&e._cleanUp(!0)}}},576(e){e.exports=class{constructor(){this.cmd=null,this.retain=!1,this.qos=0,this.dup=!1,this.length=-1,this.topic=null,this.payload=null}}},579(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=class{nextId;constructor(){this.nextId=Math.max(1,Math.floor(65535*Math.random()))}allocate(){const e=this.nextId++;return 65536===this.nextId&&(this.nextId=1),e}getLastAllocated(){return 1===this.nextId?65535:this.nextId-1}register(e){return!0}deallocate(e){}clear(){}}},597(e,t,n){"use strict";const{kForOnEventAttribute:i,kListener:r}=n(2614),o=Symbol("kCode"),s=Symbol("kData"),a=Symbol("kError"),c=Symbol("kMessage"),l=Symbol("kReason"),d=Symbol("kTarget"),u=Symbol("kType"),p=Symbol("kWasClean");class h{constructor(e){this[d]=null,this[u]=e}get target(){return this[d]}get type(){return this[u]}}Object.defineProperty(h.prototype,"target",{enumerable:!0}),Object.defineProperty(h.prototype,"type",{enumerable:!0});class f extends h{constructor(e,t={}){super(e),this[o]=void 0===t.code?0:t.code,this[l]=void 0===t.reason?"":t.reason,this[p]=void 0!==t.wasClean&&t.wasClean}get code(){return this[o]}get reason(){return this[l]}get wasClean(){return this[p]}}Object.defineProperty(f.prototype,"code",{enumerable:!0}),Object.defineProperty(f.prototype,"reason",{enumerable:!0}),Object.defineProperty(f.prototype,"wasClean",{enumerable:!0});class g extends h{constructor(e,t={}){super(e),this[a]=void 0===t.error?null:t.error,this[c]=void 0===t.message?"":t.message}get error(){return this[a]}get message(){return this[c]}}Object.defineProperty(g.prototype,"error",{enumerable:!0}),Object.defineProperty(g.prototype,"message",{enumerable:!0});class m extends h{constructor(e,t={}){super(e),this[s]=void 0===t.data?null:t.data}get data(){return this[s]}}Object.defineProperty(m.prototype,"data",{enumerable:!0});const y={addEventListener(e,t,n={}){for(const o of this.listeners(e))if(!n[i]&&o[r]===t&&!o[i])return;let o;if("message"===e)o=function(e,n){const i=new m("message",{data:n?e:e.toString()});i[d]=this,b(t,this,i)};else if("close"===e)o=function(e,n){const i=new f("close",{code:e,reason:n.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});i[d]=this,b(t,this,i)};else if("error"===e)o=function(e){const n=new g("error",{error:e,message:e.message});n[d]=this,b(t,this,n)};else{if("open"!==e)return;o=function(){const e=new h("open");e[d]=this,b(t,this,e)}}o[i]=!!n[i],o[r]=t,n.once?this.once(e,o):this.on(e,o)},removeEventListener(e,t){for(const n of this.listeners(e))if(n[r]===t&&!n[i]){this.removeListener(e,n);break}}};function b(e,t,n){"object"==typeof e&&e.handleEvent?e.handleEvent.call(e,n):e.call(t,n)}e.exports={CloseEvent:f,ErrorEvent:g,Event:h,EventTarget:y,MessageEvent:m}},720(e,t,n){const i=n(9291);e.exports.NumberAllocator=i},736(e,t,n){e.exports=function(e){function t(e){let n,r,o,s=null;function a(...e){if(!a.enabled)return;const i=a,r=Number(new Date),o=r-(n||r);i.diff=o,i.prev=n,i.curr=r,n=r,e[0]=t.coerce(e[0]),"string"!=typeof e[0]&&e.unshift("%O");let s=0;e[0]=e[0].replace(/%([a-zA-Z%])/g,(n,r)=>{if("%%"===n)return"%";s++;const o=t.formatters[r];if("function"==typeof o){const t=e[s];n=o.call(i,t),e.splice(s,1),s--}return n}),t.formatArgs.call(i,e);(i.log||t.log).apply(i,e)}return a.namespace=e,a.useColors=t.useColors(),a.color=t.selectColor(e),a.extend=i,a.destroy=t.destroy,Object.defineProperty(a,"enabled",{enumerable:!0,configurable:!1,get:()=>null!==s?s:(r!==t.namespaces&&(r=t.namespaces,o=t.enabled(e)),o),set:e=>{s=e}}),"function"==typeof t.init&&t.init(a),a}function i(e,n){const i=t(this.namespace+("undefined"==typeof n?":":n)+e);return i.log=this.log,i}function r(e,t){let n=0,i=0,r=-1,o=0;for(;n<e.length;)if(i<t.length&&(t[i]===e[n]||"*"===t[i]))"*"===t[i]?(r=i,o=n,i++):(n++,i++);else{if(-1===r)return!1;i=r+1,o++,n=o}for(;i<t.length&&"*"===t[i];)i++;return i===t.length}return t.debug=t,t.default=t,t.coerce=function(e){if(e instanceof Error)return e.stack||e.message;return e},t.disable=function(){const e=[...t.names,...t.skips.map(e=>"-"+e)].join(",");return t.enable(""),e},t.enable=function(e){t.save(e),t.namespaces=e,t.names=[],t.skips=[];const n=("string"==typeof e?e:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(const e of n)"-"===e[0]?t.skips.push(e.slice(1)):t.names.push(e)},t.enabled=function(e){for(const n of t.skips)if(r(e,n))return!1;for(const n of t.names)if(r(e,n))return!0;return!1},t.humanize=n(6585),t.destroy=function(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")},Object.keys(e).forEach(n=>{t[n]=e[n]}),t.names=[],t.skips=[],t.formatters={},t.selectColor=function(e){let n=0;for(let t=0;t<e.length;t++)n=(n<<5)-n+e.charCodeAt(t),n|=0;return t.colors[Math.abs(n)%t.colors.length]},t.enable(t.load()),t}},778(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=i(n(9278)),o=i(n(5753)),s=i(n(6968)),a=(0,o.default)("mqttjs:tcp");t.default=(e,t)=>{if(t.port=t.port||1883,t.hostname=t.hostname||t.host||"localhost",t.socksProxy)return(0,s.default)(t.hostname,t.port,t.socksProxy,{timeout:t.socksTimeout});const{port:n,path:i}=t,o=t.hostname;return a("port %d and host %s",n,o),r.default.createConnection({port:n,host:o,path:i})}},823(e,t,n){"use strict";const i=globalThis.AbortController||n(6584).AbortController,{codes:{ERR_INVALID_ARG_VALUE:r,ERR_INVALID_ARG_TYPE:o,ERR_MISSING_ARGS:s,ERR_OUT_OF_RANGE:a},AbortError:c}=n(6371),{validateAbortSignal:l,validateInteger:d,validateObject:u}=n(277),p=n(4134).Symbol("kWeak"),h=n(4134).Symbol("kResistStopPropagation"),{finished:f}=n(6238),g=n(7830),{addAbortSignalNoValidate:m}=n(4147),{isWritable:y,isNodeStream:b}=n(6115),{deprecate:v}=n(7760),{ArrayPrototypePush:S,Boolean:_,MathFloor:w,Number:k,NumberIsNaN:I,Promise:x,PromiseReject:C,PromiseResolve:E,PromisePrototypeThen:T,Symbol:O}=n(4134),P=O("kEmpty"),A=O("kEof");function R(e,t){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal");let i=1;null!=(null==t?void 0:t.concurrency)&&(i=w(t.concurrency));let r=i-1;return null!=(null==t?void 0:t.highWaterMark)&&(r=w(t.highWaterMark)),d(i,"options.concurrency",1),d(r,"options.highWaterMark",0),r+=i,async function*(){const o=n(7760).AbortSignalAny([null==t?void 0:t.signal].filter(_)),s=this,a=[],l={signal:o};let d,u,p=!1,h=0;function f(){p=!0,g()}function g(){h-=1,m()}function m(){u&&!p&&h<i&&a.length<r&&(u(),u=null)}!async function(){try{for await(let t of s){if(p)return;if(o.aborted)throw new c;try{if(t=e(t,l),t===P)continue;t=E(t)}catch(e){t=C(e)}h+=1,T(t,g,f),a.push(t),d&&(d(),d=null),!p&&(a.length>=r||h>=i)&&await new x(e=>{u=e})}a.push(A)}catch(e){const t=C(e);T(t,g,f),a.push(t)}finally{p=!0,d&&(d(),d=null)}}();try{for(;;){for(;a.length>0;){const e=await a[0];if(e===A)return;if(o.aborted)throw new c;e!==P&&(yield e),a.shift(),m()}await new x(e=>{d=e})}}finally{p=!0,u&&(u(),u=null)}}.call(this)}async function M(e,t=void 0){for await(const n of L.call(this,e,t))return!0;return!1}function L(e,t){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);return R.call(this,async function(t,n){return await e(t,n)?t:P},t)}class N extends s{constructor(){super("reduce"),this.message="Reduce of an empty stream requires an initial value"}}function D(e){if(e=k(e),I(e))return 0;if(e<0)throw new a("number",">= 0",e);return e}e.exports.streamReturningOperators={asIndexedPairs:v(function(e=void 0){return null!=e&&u(e,"options"),null!=(null==e?void 0:e.signal)&&l(e.signal,"options.signal"),async function*(){let t=0;for await(const i of this){var n;if(null!=e&&null!==(n=e.signal)&&void 0!==n&&n.aborted)throw new c({cause:e.signal.reason});yield[t++,i]}}.call(this)},"readable.asIndexedPairs will be removed in a future version."),drop:function(e,t=void 0){return null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal"),e=D(e),async function*(){var n;if(null!=t&&null!==(n=t.signal)&&void 0!==n&&n.aborted)throw new c;for await(const n of this){var i;if(null!=t&&null!==(i=t.signal)&&void 0!==i&&i.aborted)throw new c;e--<=0&&(yield n)}}.call(this)},filter:L,flatMap:function(e,t){const n=R.call(this,e,t);return async function*(){for await(const e of n)yield*e}.call(this)},map:R,take:function(e,t=void 0){return null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal"),e=D(e),async function*(){var n;if(null!=t&&null!==(n=t.signal)&&void 0!==n&&n.aborted)throw new c;for await(const n of this){var i;if(null!=t&&null!==(i=t.signal)&&void 0!==i&&i.aborted)throw new c;if(e-- >0&&(yield n),e<=0)return}}.call(this)},compose:function(e,t){if(null!=t&&u(t,"options"),null!=(null==t?void 0:t.signal)&&l(t.signal,"options.signal"),b(e)&&!y(e))throw new r("stream",e,"must be writable");const n=g(this,e);return null!=t&&t.signal&&m(t.signal,n),n}},e.exports.promiseReturningOperators={every:async function(e,t=void 0){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);return!await M.call(this,async(...t)=>!await e(...t),t)},forEach:async function(e,t){if("function"!=typeof e)throw new o("fn",["Function","AsyncFunction"],e);for await(const n of R.call(this,async function(t,n){return await e(t,n),P},t));},reduce:async function(e,t,n){var r;if("function"!=typeof e)throw new o("reducer",["Function","AsyncFunction"],e);null!=n&&u(n,"options"),null!=(null==n?void 0:n.signal)&&l(n.signal,"options.signal");let s=arguments.length>1;if(null!=n&&null!==(r=n.signal)&&void 0!==r&&r.aborted){const e=new c(void 0,{cause:n.signal.reason});throw this.once("error",()=>{}),await f(this.destroy(e)),e}const a=new i,d=a.signal;if(null!=n&&n.signal){const e={once:!0,[p]:this,[h]:!0};n.signal.addEventListener("abort",()=>a.abort(),e)}let g=!1;try{for await(const i of this){var m;if(g=!0,null!=n&&null!==(m=n.signal)&&void 0!==m&&m.aborted)throw new c;s?t=await e(t,i,{signal:d}):(t=i,s=!0)}if(!g&&!s)throw new N}finally{a.abort()}return t},toArray:async function(e){null!=e&&u(e,"options"),null!=(null==e?void 0:e.signal)&&l(e.signal,"options.signal");const t=[];for await(const i of this){var n;if(null!=e&&null!==(n=e.signal)&&void 0!==n&&n.aborted)throw new c(void 0,{cause:e.signal.reason});S(t,i)}return t},some:M,find:async function(e,t){for await(const n of L.call(this,e,t))return n}}},837(e,t){"use strict";function n(e){return e.toString(16).padStart(2,"0")}Object.defineProperty(t,"__esModule",{value:!0}),t.isInSubnet=function(e){if(this.subnetMask<e.subnetMask)return!1;if(this.mask(e.subnetMask)===e.mask())return!0;return!1},t.isCorrect=function(e){return function(){return this.addressMinusSuffix===this.correctForm()&&(this.subnetMask===e&&!this.parsedSubnet||this.parsedSubnet===String(this.subnetMask))}},t.numberToPaddedHex=n,t.stringToPaddedHex=function(e){return n(parseInt(e,10))},t.testBit=function(e,t){const{length:n}=e;if(t>n)return!1;const i=n-t;return"1"===e.substring(i,i+1)}},857(e){"use strict";e.exports=require("os")},914(e,t,n){"use strict";const{Duplex:i}=n(2203),{randomFillSync:r}=n(6982),o=n(2971),{EMPTY_BUFFER:s,kWebSocket:a,NOOP:c}=n(2614),{isBlob:l,isValidStatusCode:d}=n(5880),{mask:u,toBuffer:p}=n(3338),h=Symbol("kByteLength"),f=Buffer.alloc(4),g=8192;let m,y=g;class b{constructor(e,t,n){this._extensions=t||{},n&&(this._generateMask=n,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=0,this.onerror=c,this[a]=void 0}static frame(e,t){let n,i,o=!1,s=2,a=!1;t.mask&&(n=t.maskBuffer||f,t.generateMask?t.generateMask(n):(y===g&&(void 0===m&&(m=Buffer.alloc(g)),r(m,0,g),y=0),n[0]=m[y++],n[1]=m[y++],n[2]=m[y++],n[3]=m[y++]),a=0===(n[0]|n[1]|n[2]|n[3]),s=6),"string"==typeof e?i=t.mask&&!a||void 0===t[h]?(e=Buffer.from(e)).length:t[h]:(i=e.length,o=t.mask&&t.readOnly&&!a);let c=i;i>=65536?(s+=8,c=127):i>125&&(s+=2,c=126);const l=Buffer.allocUnsafe(o?i+s:s);return l[0]=t.fin?128|t.opcode:t.opcode,t.rsv1&&(l[0]|=64),l[1]=c,126===c?l.writeUInt16BE(i,2):127===c&&(l[2]=l[3]=0,l.writeUIntBE(i,4,6)),t.mask?(l[1]|=128,l[s-4]=n[0],l[s-3]=n[1],l[s-2]=n[2],l[s-1]=n[3],a?[l,e]:o?(u(e,n,l,s,i),[l]):(u(e,n,e,0,i),[l,e])):[l,e]}close(e,t,n,i){let r;if(void 0===e)r=s;else{if("number"!=typeof e||!d(e))throw new TypeError("First argument must be a valid error code number");if(void 0!==t&&t.length){const n=Buffer.byteLength(t);if(n>123)throw new RangeError("The message must not be greater than 123 bytes");r=Buffer.allocUnsafe(2+n),r.writeUInt16BE(e,0),"string"==typeof t?r.write(t,2):r.set(t,2)}else r=Buffer.allocUnsafe(2),r.writeUInt16BE(e,0)}const o={[h]:r.length,fin:!0,generateMask:this._generateMask,mask:n,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};0!==this._state?this.enqueue([this.dispatch,r,!1,o,i]):this.sendFrame(b.frame(r,o),i)}ping(e,t,n){let i,r;if("string"==typeof e?(i=Buffer.byteLength(e),r=!1):l(e)?(i=e.size,r=!1):(i=(e=p(e)).length,r=p.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");const o={[h]:i,fin:!0,generateMask:this._generateMask,mask:t,maskBuffer:this._maskBuffer,opcode:9,readOnly:r,rsv1:!1};l(e)?0!==this._state?this.enqueue([this.getBlobData,e,!1,o,n]):this.getBlobData(e,!1,o,n):0!==this._state?this.enqueue([this.dispatch,e,!1,o,n]):this.sendFrame(b.frame(e,o),n)}pong(e,t,n){let i,r;if("string"==typeof e?(i=Buffer.byteLength(e),r=!1):l(e)?(i=e.size,r=!1):(i=(e=p(e)).length,r=p.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");const o={[h]:i,fin:!0,generateMask:this._generateMask,mask:t,maskBuffer:this._maskBuffer,opcode:10,readOnly:r,rsv1:!1};l(e)?0!==this._state?this.enqueue([this.getBlobData,e,!1,o,n]):this.getBlobData(e,!1,o,n):0!==this._state?this.enqueue([this.dispatch,e,!1,o,n]):this.sendFrame(b.frame(e,o),n)}send(e,t,n){const i=this._extensions[o.extensionName];let r,s,a=t.binary?2:1,c=t.compress;"string"==typeof e?(r=Buffer.byteLength(e),s=!1):l(e)?(r=e.size,s=!1):(r=(e=p(e)).length,s=p.readOnly),this._firstFragment?(this._firstFragment=!1,c&&i&&i.params[i._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(c=r>=i._threshold),this._compress=c):(c=!1,a=0),t.fin&&(this._firstFragment=!0);const d={[h]:r,fin:t.fin,generateMask:this._generateMask,mask:t.mask,maskBuffer:this._maskBuffer,opcode:a,readOnly:s,rsv1:c};l(e)?0!==this._state?this.enqueue([this.getBlobData,e,this._compress,d,n]):this.getBlobData(e,this._compress,d,n):0!==this._state?this.enqueue([this.dispatch,e,this._compress,d,n]):this.dispatch(e,this._compress,d,n)}getBlobData(e,t,n,i){this._bufferedBytes+=n[h],this._state=2,e.arrayBuffer().then(e=>{if(this._socket.destroyed){const e=new Error("The socket was closed while the blob was being read");return void process.nextTick(v,this,e,i)}this._bufferedBytes-=n[h];const r=p(e);t?this.dispatch(r,t,n,i):(this._state=0,this.sendFrame(b.frame(r,n),i),this.dequeue())}).catch(e=>{process.nextTick(S,this,e,i)})}dispatch(e,t,n,i){if(!t)return void this.sendFrame(b.frame(e,n),i);const r=this._extensions[o.extensionName];this._bufferedBytes+=n[h],this._state=1,r.compress(e,n.fin,(e,t)=>{if(this._socket.destroyed){return void v(this,new Error("The socket was closed while data was being compressed"),i)}this._bufferedBytes-=n[h],this._state=0,n.readOnly=!1,this.sendFrame(b.frame(t,n),i),this.dequeue()})}dequeue(){for(;0===this._state&&this._queue.length;){const e=this._queue.shift();this._bufferedBytes-=e[3][h],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][h],this._queue.push(e)}sendFrame(e,t){2===e.length?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],t),this._socket.uncork()):this._socket.write(e[0],t)}}function v(e,t,n){"function"==typeof n&&n(t);for(let n=0;n<e._queue.length;n++){const i=e._queue[n],r=i[i.length-1];"function"==typeof r&&r(t)}}function S(e,t,n){v(e,t,n),e.onerror(t)}e.exports=b},1021(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ReasonCodes=void 0;const i=n(4723);t.ReasonCodes={0:"",1:"Unacceptable protocol version",2:"Identifier rejected",3:"Server unavailable",4:"Bad username or password",5:"Not authorized",16:"No matching subscribers",17:"No subscription existed",128:"Unspecified error",129:"Malformed Packet",130:"Protocol Error",131:"Implementation specific error",132:"Unsupported Protocol Version",133:"Client Identifier not valid",134:"Bad User Name or Password",135:"Not authorized",136:"Server unavailable",137:"Server busy",138:"Banned",139:"Server shutting down",140:"Bad authentication method",141:"Keep Alive timeout",142:"Session taken over",143:"Topic Filter invalid",144:"Topic Name invalid",145:"Packet identifier in use",146:"Packet Identifier not found",147:"Receive Maximum exceeded",148:"Topic Alias invalid",149:"Packet too large",150:"Message rate too high",151:"Quota exceeded",152:"Administrative action",153:"Payload format invalid",154:"Retain not supported",155:"QoS not supported",156:"Use another server",157:"Server moved",158:"Shared Subscriptions not supported",159:"Connection rate exceeded",160:"Maximum connect time",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"};t.default=(e,n)=>{const{messageId:r}=n,o=n.cmd;let s=null;const a=e.outgoing[r]?e.outgoing[r].cb:null;let c=null;if(a){switch(e.log("_handleAck :: packet type",o),o){case"pubcomp":case"puback":{const o=n.reasonCode;o&&o>0&&16!==o?(c=new i.ErrorWithReasonCode(`Publish error: ${t.ReasonCodes[o]}`,o),e._removeOutgoingAndStoreMessage(r,()=>{a(c,n)})):e._removeOutgoingAndStoreMessage(r,a);break}case"pubrec":{s={cmd:"pubrel",qos:2,messageId:r};const o=n.reasonCode;o&&o>0&&16!==o?(c=new i.ErrorWithReasonCode(`Publish error: ${t.ReasonCodes[o]}`,o),e._removeOutgoingAndStoreMessage(r,()=>{a(c,n)})):e._sendPacket(s);break}case"suback":{delete e.outgoing[r],e.messageIdProvider.deallocate(r);const i=n.granted;for(let n=0;n<i.length;n++){const o=i[n];if(128&o){c=new Error(`Subscribe error: ${t.ReasonCodes[o]}`),c.code=o;const n=e.messageIdToTopic[r];n&&n.forEach(t=>{delete e._resubscribeTopics[t]})}}delete e.messageIdToTopic[r],e._invokeStoreProcessingQueue(),a(c,n);break}case"unsuback":delete e.outgoing[r],e.messageIdProvider.deallocate(r),e._invokeStoreProcessingQueue(),a(null,n);break;default:e.emit("error",new Error("unrecognized packet type"))}e.disconnecting&&0===Object.keys(e.outgoing).length&&e.emit("outgoingEmpty")}else e.log("_handleAck :: Server sent an ack in error. Ignoring.")}},1060(e,t,n){"use strict";const i=n(4434),r=n(5692),o=n(8611),s=n(9278),a=n(4756),{randomBytes:c,createHash:l}=n(6982),{Duplex:d,Readable:u}=n(2203),{URL:p}=n(7016),h=n(2971),f=n(6286),g=n(914),{isBlob:m}=n(5880),{BINARY_TYPES:y,EMPTY_BUFFER:b,GUID:v,kForOnEventAttribute:S,kListener:_,kStatusCode:w,kWebSocket:k,NOOP:I}=n(2614),{EventTarget:{addEventListener:x,removeEventListener:C}}=n(597),{format:E,parse:T}=n(5926),{toBuffer:O}=n(3338),P=Symbol("kAborted"),A=[8,13],R=["CONNECTING","OPEN","CLOSING","CLOSED"],M=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;class L extends i{constructor(e,t,n){super(),this._binaryType=y[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=b,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=L.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,null!==e?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,void 0===t?t=[]:Array.isArray(t)||("object"==typeof t&&null!==t?(n=t,t=[]):t=[t]),N(this,e,t,n)):(this._autoPong=n.autoPong,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){y.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,t,n){const i=new f({allowSynchronousEvents:n.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation}),r=new g(e,this._extensions,n.generateMask);this._receiver=i,this._sender=r,this._socket=e,i[k]=this,r[k]=this,e[k]=this,i.on("conclude",U),i.on("drain",z),i.on("error",V),i.on("message",H),i.on("ping",q),i.on("pong",G),r.onerror=Z,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),t.length>0&&e.unshift(t),e.on("close",Q),e.on("data",Y),e.on("end",X),e.on("error",ee),this._readyState=L.OPEN,this.emit("open")}emitClose(){if(!this._socket)return this._readyState=L.CLOSED,void this.emit("close",this._closeCode,this._closeMessage);this._extensions[h.extensionName]&&this._extensions[h.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=L.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,t){if(this.readyState!==L.CLOSED){if(this.readyState===L.CONNECTING){const e="WebSocket was closed before the connection was established";return void $(this,this._req,e)}this.readyState!==L.CLOSING?(this._readyState=L.CLOSING,this._sender.close(e,t,!this._isServer,e=>{e||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),J(this)):this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end()}}pause(){this.readyState!==L.CONNECTING&&this.readyState!==L.CLOSED&&(this._paused=!0,this._socket.pause())}ping(e,t,n){if(this.readyState===L.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");"function"==typeof e?(n=e,e=t=void 0):"function"==typeof t&&(n=t,t=void 0),"number"==typeof e&&(e=e.toString()),this.readyState===L.OPEN?(void 0===t&&(t=!this._isServer),this._sender.ping(e||b,t,n)):F(this,e,n)}pong(e,t,n){if(this.readyState===L.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");"function"==typeof e?(n=e,e=t=void 0):"function"==typeof t&&(n=t,t=void 0),"number"==typeof e&&(e=e.toString()),this.readyState===L.OPEN?(void 0===t&&(t=!this._isServer),this._sender.pong(e||b,t,n)):F(this,e,n)}resume(){this.readyState!==L.CONNECTING&&this.readyState!==L.CLOSED&&(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,t,n){if(this.readyState===L.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if("function"==typeof t&&(n=t,t={}),"number"==typeof e&&(e=e.toString()),this.readyState!==L.OPEN)return void F(this,e,n);const i={binary:"string"!=typeof e,mask:!this._isServer,compress:!0,fin:!0,...t};this._extensions[h.extensionName]||(i.compress=!1),this._sender.send(e||b,i,n)}terminate(){if(this.readyState!==L.CLOSED){if(this.readyState===L.CONNECTING){const e="WebSocket was closed before the connection was established";return void $(this,this._req,e)}this._socket&&(this._readyState=L.CLOSING,this._socket.destroy())}}}function N(e,t,n,i){const s={allowSynchronousEvents:!0,autoPong:!0,protocolVersion:A[1],maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...i,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(e._autoPong=s.autoPong,!A.includes(s.protocolVersion))throw new RangeError(`Unsupported protocol version: ${s.protocolVersion} (supported versions: ${A.join(", ")})`);let a;if(t instanceof p)a=t;else try{a=new p(t)}catch(e){throw new SyntaxError(`Invalid URL: ${t}`)}"http:"===a.protocol?a.protocol="ws:":"https:"===a.protocol&&(a.protocol="wss:"),e._url=a.href;const d="wss:"===a.protocol,u="ws+unix:"===a.protocol;let f;if("ws:"===a.protocol||d||u?u&&!a.pathname?f="The URL's pathname is empty":a.hash&&(f="The URL contains a fragment identifier"):f='The URL\'s protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"',f){const t=new SyntaxError(f);if(0===e._redirects)throw t;return void D(e,t)}const g=d?443:80,m=c(16).toString("base64"),y=d?r.request:o.request,b=new Set;let S,_;if(s.createConnection=s.createConnection||(d?j:B),s.defaultPort=s.defaultPort||g,s.port=a.port||g,s.host=a.hostname.startsWith("[")?a.hostname.slice(1,-1):a.hostname,s.headers={...s.headers,"Sec-WebSocket-Version":s.protocolVersion,"Sec-WebSocket-Key":m,Connection:"Upgrade",Upgrade:"websocket"},s.path=a.pathname+a.search,s.timeout=s.handshakeTimeout,s.perMessageDeflate&&(S=new h(!0!==s.perMessageDeflate?s.perMessageDeflate:{},!1,s.maxPayload),s.headers["Sec-WebSocket-Extensions"]=E({[h.extensionName]:S.offer()})),n.length){for(const e of n){if("string"!=typeof e||!M.test(e)||b.has(e))throw new SyntaxError("An invalid or duplicated subprotocol was specified");b.add(e)}s.headers["Sec-WebSocket-Protocol"]=n.join(",")}if(s.origin&&(s.protocolVersion<13?s.headers["Sec-WebSocket-Origin"]=s.origin:s.headers.Origin=s.origin),(a.username||a.password)&&(s.auth=`${a.username}:${a.password}`),u){const e=s.path.split(":");s.socketPath=e[0],s.path=e[1]}if(s.followRedirects){if(0===e._redirects){e._originalIpc=u,e._originalSecure=d,e._originalHostOrSocketPath=u?s.socketPath:a.host;const t=i&&i.headers;if(i={...i,headers:{}},t)for(const[e,n]of Object.entries(t))i.headers[e.toLowerCase()]=n}else if(0===e.listenerCount("redirect")){const t=u?!!e._originalIpc&&s.socketPath===e._originalHostOrSocketPath:!e._originalIpc&&a.host===e._originalHostOrSocketPath;(!t||e._originalSecure&&!d)&&(delete s.headers.authorization,delete s.headers.cookie,t||delete s.headers.host,s.auth=void 0)}s.auth&&!i.headers.authorization&&(i.headers.authorization="Basic "+Buffer.from(s.auth).toString("base64")),_=e._req=y(s),e._redirects&&e.emit("redirect",e.url,_)}else _=e._req=y(s);s.timeout&&_.on("timeout",()=>{$(e,_,"Opening handshake has timed out")}),_.on("error",t=>{null===_||_[P]||(_=e._req=null,D(e,t))}),_.on("response",r=>{const o=r.headers.location,a=r.statusCode;if(o&&s.followRedirects&&a>=300&&a<400){if(++e._redirects>s.maxRedirects)return void $(e,_,"Maximum redirects exceeded");let r;_.abort();try{r=new p(o,t)}catch(t){const n=new SyntaxError(`Invalid URL: ${o}`);return void D(e,n)}N(e,r,n,i)}else e.emit("unexpected-response",_,r)||$(e,_,`Unexpected server response: ${r.statusCode}`)}),_.on("upgrade",(t,n,i)=>{if(e.emit("upgrade",t),e.readyState!==L.CONNECTING)return;_=e._req=null;const r=t.headers.upgrade;if(void 0===r||"websocket"!==r.toLowerCase())return void $(e,n,"Invalid Upgrade header");const o=l("sha1").update(m+v).digest("base64");if(t.headers["sec-websocket-accept"]!==o)return void $(e,n,"Invalid Sec-WebSocket-Accept header");const a=t.headers["sec-websocket-protocol"];let c;if(void 0!==a?b.size?b.has(a)||(c="Server sent an invalid subprotocol"):c="Server sent a subprotocol but none was requested":b.size&&(c="Server sent no subprotocol"),c)return void $(e,n,c);a&&(e._protocol=a);const d=t.headers["sec-websocket-extensions"];if(void 0!==d){if(!S){return void $(e,n,"Server sent a Sec-WebSocket-Extensions header but no extension was requested")}let t;try{t=T(d)}catch(t){return void $(e,n,"Invalid Sec-WebSocket-Extensions header")}const i=Object.keys(t);if(1!==i.length||i[0]!==h.extensionName){return void $(e,n,"Server indicated an extension that was not requested")}try{S.accept(t[h.extensionName])}catch(t){return void $(e,n,"Invalid Sec-WebSocket-Extensions header")}e._extensions[h.extensionName]=S}e.setSocket(n,i,{allowSynchronousEvents:s.allowSynchronousEvents,generateMask:s.generateMask,maxPayload:s.maxPayload,skipUTF8Validation:s.skipUTF8Validation})}),s.finishRequest?s.finishRequest(_,e):_.end()}function D(e,t){e._readyState=L.CLOSING,e._errorEmitted=!0,e.emit("error",t),e.emitClose()}function B(e){return e.path=e.socketPath,s.connect(e)}function j(e){return e.path=void 0,e.servername||""===e.servername||(e.servername=s.isIP(e.host)?"":e.host),a.connect(e)}function $(e,t,n){e._readyState=L.CLOSING;const i=new Error(n);Error.captureStackTrace(i,$),t.setHeader?(t[P]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(D,e,i)):(t.destroy(i),t.once("error",e.emit.bind(e,"error")),t.once("close",e.emitClose.bind(e)))}function F(e,t,n){if(t){const n=m(t)?t.size:O(t).length;e._socket?e._sender._bufferedBytes+=n:e._bufferedAmount+=n}if(n){const t=new Error(`WebSocket is not open: readyState ${e.readyState} (${R[e.readyState]})`);process.nextTick(n,t)}}function U(e,t){const n=this[k];n._closeFrameReceived=!0,n._closeMessage=t,n._closeCode=e,void 0!==n._socket[k]&&(n._socket.removeListener("data",Y),process.nextTick(K,n._socket),1005===e?n.close():n.close(e,t))}function z(){const e=this[k];e.isPaused||e._socket.resume()}function V(e){const t=this[k];void 0!==t._socket[k]&&(t._socket.removeListener("data",Y),process.nextTick(K,t._socket),t.close(e[w])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e))}function W(){this[k].emitClose()}function H(e,t){this[k].emit("message",e,t)}function q(e){const t=this[k];t._autoPong&&t.pong(e,!this._isServer,I),t.emit("ping",e)}function G(e){this[k].emit("pong",e)}function K(e){e.resume()}function Z(e){const t=this[k];t.readyState!==L.CLOSED&&(t.readyState===L.OPEN&&(t._readyState=L.CLOSING,J(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",e)))}function J(e){e._closeTimer=setTimeout(e._socket.destroy.bind(e._socket),3e4)}function Q(){const e=this[k];let t;this.removeListener("close",Q),this.removeListener("data",Y),this.removeListener("end",X),e._readyState=L.CLOSING,this._readableState.endEmitted||e._closeFrameReceived||e._receiver._writableState.errorEmitted||null===(t=e._socket.read())||e._receiver.write(t),e._receiver.end(),this[k]=void 0,clearTimeout(e._closeTimer),e._receiver._writableState.finished||e._receiver._writableState.errorEmitted?e.emitClose():(e._receiver.on("error",W),e._receiver.on("finish",W))}function Y(e){this[k]._receiver.write(e)||this.pause()}function X(){const e=this[k];e._readyState=L.CLOSING,e._receiver.end(),this.end()}function ee(){const e=this[k];this.removeListener("error",ee),this.on("error",I),e&&(e._readyState=L.CLOSING,this.destroy())}Object.defineProperty(L,"CONNECTING",{enumerable:!0,value:R.indexOf("CONNECTING")}),Object.defineProperty(L.prototype,"CONNECTING",{enumerable:!0,value:R.indexOf("CONNECTING")}),Object.defineProperty(L,"OPEN",{enumerable:!0,value:R.indexOf("OPEN")}),Object.defineProperty(L.prototype,"OPEN",{enumerable:!0,value:R.indexOf("OPEN")}),Object.defineProperty(L,"CLOSING",{enumerable:!0,value:R.indexOf("CLOSING")}),Object.defineProperty(L.prototype,"CLOSING",{enumerable:!0,value:R.indexOf("CLOSING")}),Object.defineProperty(L,"CLOSED",{enumerable:!0,value:R.indexOf("CLOSED")}),Object.defineProperty(L.prototype,"CLOSED",{enumerable:!0,value:R.indexOf("CLOSED")}),["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(e=>{Object.defineProperty(L.prototype,e,{enumerable:!0})}),["open","error","close","message"].forEach(e=>{Object.defineProperty(L.prototype,`on${e}`,{enumerable:!0,get(){for(const t of this.listeners(e))if(t[S])return t[_];return null},set(t){for(const t of this.listeners(e))if(t[S]){this.removeListener(e,t);break}"function"==typeof t&&this.addEventListener(e,t,{[S]:!0})}})}),L.prototype.addEventListener=x,L.prototype.removeEventListener=C,e.exports=L},1278(e,t,n){t.parser=n(3079).parser,t.generate=n(2535),t.writeToStream=n(3132)},1554(e,t){"use strict";function n(e,t){return e.cameras.find(e=>e.deviceId===t)}function i(e,t){return e.landmarks?.find(e=>e.id===t)}function r(e,t,n){return e.connections.filter(e=>e.fromCameraId===t&&e.toCameraId===n||e.bidirectional&&e.fromCameraId===n&&e.toCameraId===t)[0]}function o(e,t){const r=n(e,t);return r?.context?.visibleLandmarks?r.context.visibleLandmarks.map(t=>i(e,t)).filter(e=>void 0!==e):[]}function s(e,t){const n=t.x-e.x,i=t.y-e.y;return Math.sqrt(n*n+i*i)}Object.defineProperty(t,"__esModule",{value:!0}),t.ZONE_TYPE_COLORS=t.LANDMARK_TEMPLATES=void 0,t.createEmptyTopology=function(){return{version:"2.0",cameras:[],connections:[],landmarks:[],relationships:[],globalZones:[]}},t.findCamera=n,t.findLandmark=i,t.findConnectionsFrom=function(e,t){return e.connections.filter(e=>e.fromCameraId===t||e.bidirectional&&e.toCameraId===t)},t.findConnection=r,t.getEntryPoints=function(e){return e.cameras.filter(e=>e.isEntryPoint)},t.getExitPoints=function(e){return e.cameras.filter(e=>e.isExitPoint)},t.getLandmarksVisibleFromCamera=o,t.getCamerasWithLandmarkVisibility=function(e,t){return e.cameras.filter(e=>e.context?.visibleLandmarks?.includes(t))},t.getAdjacentLandmarks=function(e,t){const n=i(e,t);return n?.adjacentTo?n.adjacentTo.map(t=>i(e,t)).filter(e=>void 0!==e):[]},t.calculateDistance=s,t.inferRelationships=function(e,t=50){const n=[],i=[];for(const t of e.cameras)t.floorPlanPosition&&i.push({id:t.deviceId,position:t.floorPlanPosition,type:"camera"});for(const t of e.landmarks||[])i.push({id:t.id,position:t.position,type:"landmark"});for(let e=0;e<i.length;e++)for(let r=e+1;r<i.length;r++){const o=s(i[e].position,i[r].position);o<=t&&n.push({id:`auto_${i[e].id}_${i[r].id}`,type:o<=t/2?"adjacent":"near",entityA:i[e].id,entityB:i[r].id,autoInferred:!0})}return n},t.generateTopologyDescription=function(e){const t=[];e.property?.description&&t.push(`Property: ${e.property.description}`);e.property?.frontFacing&&t.push(`Front of property faces ${e.property.frontFacing}.`);if(e.landmarks?.length>0){t.push("\nLandmarks on property:");for(const n of e.landmarks||[]){let e=`- ${n.name} (${n.type})`;n.description&&(e+=`: ${n.description}`),n.isEntryPoint&&(e+=" [Entry point]"),n.isExitPoint&&(e+=" [Exit point]"),t.push(e)}}if(e.cameras.length>0){t.push("\nCamera coverage:");for(const n of e.cameras){let r=`- ${n.name}`;if(n.context?.mountLocation&&(r+=` (mounted at ${n.context.mountLocation})`),n.context?.coverageDescription&&(r+=`: ${n.context.coverageDescription}`),n.isEntryPoint&&(r+=" [Watches entry point]"),n.isExitPoint&&(r+=" [Watches exit point]"),n.context?.visibleLandmarks&&n.context.visibleLandmarks.length>0){const t=n.context.visibleLandmarks.map(t=>i(e,t)?.name).filter(Boolean);t.length>0&&(r+=` Can see: ${t.join(", ")}`)}t.push(r)}}if(e.connections.length>0){t.push("\nMovement paths:");for(const i of e.connections){const r=n(e,i.fromCameraId),o=n(e,i.toCameraId);if(r&&o){let e=`- ${r.name} → ${o.name}`;i.name&&(e+=` (${i.name})`),e+=` [${i.transitTime.min/1e3}-${i.transitTime.max/1e3}s transit]`,i.bidirectional&&(e+=" [bidirectional]"),t.push(e)}}}return t.join("\n")},t.generateMovementContext=function(e,t,s,a){const c=n(e,t),l=n(e,s),d=r(e,t,s);if(!c||!l)return`${a} moving between cameras`;const u=[];u.push(`Origin: ${c.name}`),c.context?.coverageDescription&&u.push(` Coverage: ${c.context.coverageDescription}`);u.push(`Destination: ${l.name}`),l.context?.coverageDescription&&u.push(` Coverage: ${l.context.coverageDescription}`);if(d&&(d.name&&u.push(`Path: ${d.name}`),d.pathLandmarks&&d.pathLandmarks.length>0)){const t=d.pathLandmarks.map(t=>i(e,t)?.name).filter(Boolean);t.length>0&&u.push(`Passing: ${t.join(" → ")}`)}const p=o(e,s);p.length>0&&u.push(`Near: ${p.map(e=>e.name).join(", ")}`);return u.join("\n")},t.LANDMARK_TEMPLATES=[{type:"structure",suggestions:["House","Garage","Shed","Porch","Deck","Patio","Gazebo","Pool House"]},{type:"feature",suggestions:["Mailbox","Tree","Firepit","Pool","Hot Tub","Garden","Fountain","Flagpole"]},{type:"boundary",suggestions:["Front Fence","Back Fence","Side Fence","Hedge","Wall","Property Line"]},{type:"access",suggestions:["Driveway","Front Walkway","Back Walkway","Front Door","Back Door","Side Door","Gate","Stairs"]},{type:"vehicle",suggestions:["Car Parking","Boat","RV Pad","Motorcycle Spot"]},{type:"neighbor",suggestions:["Neighbor's House","Neighbor's Driveway","Neighbor's Yard"]},{type:"zone",suggestions:["Front Yard","Back Yard","Side Yard","Courtyard"]},{type:"street",suggestions:["Street","Sidewalk","Alley","Cul-de-sac"]}],t.ZONE_TYPE_COLORS={yard:"rgba(76, 175, 80, 0.3)",driveway:"rgba(158, 158, 158, 0.3)",street:"rgba(96, 96, 96, 0.3)",patio:"rgba(255, 152, 0, 0.3)",walkway:"rgba(121, 85, 72, 0.3)",parking:"rgba(189, 189, 189, 0.3)",garden:"rgba(139, 195, 74, 0.3)",pool:"rgba(33, 150, 243, 0.3)",garage:"rgba(117, 117, 117, 0.3)",entrance:"rgba(233, 30, 99, 0.3)",custom:"rgba(156, 39, 176, 0.3)"}},1676(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)},c=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.ReasonCodes=t.KeepaliveManager=t.UniqueMessageIdProvider=t.DefaultMessageIdProvider=t.Store=t.MqttClient=t.connectAsync=t.connect=t.Client=void 0;const l=c(n(9777));t.MqttClient=l.default;const d=c(n(579));t.DefaultMessageIdProvider=d.default;const u=c(n(2099));t.UniqueMessageIdProvider=u.default;const p=c(n(7969));t.Store=p.default;const h=s(n(2793));t.connect=h.default,Object.defineProperty(t,"connectAsync",{enumerable:!0,get:function(){return h.connectAsync}});const f=c(n(3175));t.KeepaliveManager=f.default,t.Client=l.default,a(n(9777),t),a(n(4723),t);var g=n(1021);Object.defineProperty(t,"ReasonCodes",{enumerable:!0,get:function(){return g.ReasonCodes}})},1711(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TRAINING_HTML=void 0,t.TRAINING_HTML='<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">\n <meta name="apple-mobile-web-app-capable" content="yes">\n <meta name="mobile-web-app-capable" content="yes">\n <title>Spatial Awareness - Training Mode</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }\n html, body { height: 100%; overflow: hidden; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n background: #121212;\n color: rgba(255,255,255,0.87);\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n }\n\n /* Header */\n .header {\n background: rgba(255,255,255,0.03);\n padding: 12px 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-bottom: 1px solid rgba(255,255,255,0.08);\n }\n .header h1 { font-size: 16px; font-weight: 500; }\n .header-status {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n }\n .status-badge {\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n text-transform: uppercase;\n }\n .status-badge.idle { background: rgba(255,255,255,0.1); color: rgba(255,255,255,0.6); }\n .status-badge.active { background: #4fc3f7; color: #000; animation: pulse 2s infinite; }\n .status-badge.paused { background: #ffb74d; color: #000; }\n .status-badge.completed { background: #81c784; color: #000; }\n @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }\n\n /* Main content area */\n .main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 12px;\n overflow-y: auto;\n gap: 12px;\n }\n\n /* Camera detection card */\n .detection-card {\n background: rgba(255,255,255,0.03);\n border-radius: 8px;\n padding: 16px;\n border: 1px solid rgba(255,255,255,0.08);\n transition: all 0.3s;\n }\n .detection-card.detecting {\n border-color: #4fc3f7;\n background: rgba(79, 195, 247, 0.1);\n }\n .detection-card.in-transit {\n border-color: #ffb74d;\n background: rgba(255, 183, 77, 0.1);\n }\n\n .detection-icon {\n width: 64px;\n height: 64px;\n border-radius: 8px;\n background: rgba(255,255,255,0.05);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 12px;\n font-size: 28px;\n }\n .detection-card.detecting .detection-icon {\n background: #4fc3f7;\n animation: detectPulse 1.5s infinite;\n }\n @keyframes detectPulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.03); }\n }\n\n .detection-title {\n font-size: 18px;\n font-weight: 500;\n text-align: center;\n margin-bottom: 4px;\n }\n .detection-subtitle {\n font-size: 13px;\n color: rgba(255,255,255,0.5);\n text-align: center;\n }\n .detection-confidence {\n margin-top: 8px;\n text-align: center;\n font-size: 12px;\n color: rgba(255,255,255,0.4);\n }\n\n /* Transit timer */\n .transit-timer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 12px;\n padding: 10px;\n background: rgba(0,0,0,0.2);\n border-radius: 6px;\n }\n .transit-timer-icon { font-size: 18px; }\n .transit-timer-text { font-size: 16px; font-weight: 500; }\n .transit-timer-from { font-size: 12px; color: rgba(255,255,255,0.5); }\n\n /* Stats grid */\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n }\n .stat-item {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 12px 8px;\n text-align: center;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .stat-value {\n font-size: 24px;\n font-weight: 500;\n color: #4fc3f7;\n }\n .stat-label {\n font-size: 10px;\n color: rgba(255,255,255,0.4);\n text-transform: uppercase;\n margin-top: 2px;\n }\n\n /* Progress bar */\n .progress-section {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 12px;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .progress-header {\n display: flex;\n justify-content: space-between;\n margin-bottom: 8px;\n font-size: 13px;\n }\n .progress-bar {\n height: 6px;\n background: rgba(255,255,255,0.1);\n border-radius: 3px;\n overflow: hidden;\n }\n .progress-fill {\n height: 100%;\n background: #4fc3f7;\n border-radius: 3px;\n transition: width 0.5s;\n }\n\n /* Suggestions */\n .suggestions-section {\n background: rgba(79, 195, 247, 0.08);\n border: 1px solid rgba(79, 195, 247, 0.2);\n border-radius: 6px;\n padding: 12px;\n }\n .suggestions-title {\n font-size: 11px;\n text-transform: uppercase;\n color: #4fc3f7;\n margin-bottom: 6px;\n font-weight: 500;\n }\n .suggestion-item {\n font-size: 13px;\n padding: 6px 0;\n border-bottom: 1px solid rgba(255,255,255,0.05);\n color: rgba(255,255,255,0.7);\n }\n .suggestion-item:last-child { border-bottom: none; }\n .suggestion-item::before {\n content: "→ ";\n color: #4fc3f7;\n }\n\n /* Action buttons */\n .action-buttons {\n display: flex;\n gap: 8px;\n padding: 8px 0;\n }\n .btn {\n flex: 1;\n padding: 14px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n }\n .btn:active { transform: scale(0.98); }\n .btn-primary { background: #4fc3f7; color: #000; }\n .btn-secondary { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.87); }\n .btn-danger { background: #ef5350; color: #fff; }\n .btn-warning { background: #ffb74d; color: #000; }\n .btn:disabled { opacity: 0.4; cursor: not-allowed; }\n\n /* Full-width button */\n .btn-full { flex: none; width: 100%; }\n\n /* Mark landmark/structure panel */\n .mark-panel {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 16px;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .mark-panel-title {\n font-size: 14px;\n font-weight: 500;\n margin-bottom: 12px;\n }\n .mark-type-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 6px;\n margin-bottom: 12px;\n }\n .mark-type-btn {\n padding: 10px 6px;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n background: transparent;\n color: rgba(255,255,255,0.7);\n font-size: 10px;\n text-align: center;\n cursor: pointer;\n transition: all 0.2s;\n }\n .mark-type-btn.selected {\n border-color: #4fc3f7;\n background: rgba(79, 195, 247, 0.15);\n color: #fff;\n }\n .mark-type-btn .icon { font-size: 18px; margin-bottom: 2px; display: block; }\n\n /* Input field */\n .input-group { margin-bottom: 12px; }\n .input-group label {\n display: block;\n font-size: 12px;\n color: rgba(255,255,255,0.5);\n margin-bottom: 4px;\n }\n .input-group input {\n width: 100%;\n padding: 12px;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n background: rgba(0,0,0,0.2);\n color: #fff;\n font-size: 14px;\n }\n .input-group input:focus {\n outline: none;\n border-color: #4fc3f7;\n }\n\n /* History list */\n .history-section {\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 12px;\n max-height: 180px;\n overflow-y: auto;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .history-title {\n font-size: 13px;\n font-weight: 500;\n margin-bottom: 8px;\n display: flex;\n justify-content: space-between;\n }\n .history-item {\n padding: 8px;\n border-bottom: 1px solid rgba(255,255,255,0.05);\n font-size: 13px;\n }\n .history-item:last-child { border-bottom: none; }\n .history-item-time {\n font-size: 10px;\n color: rgba(255,255,255,0.4);\n }\n .history-item-camera { color: #4fc3f7; font-weight: 500; }\n .history-item-transit { color: #ffb74d; }\n\n /* Bottom action bar */\n .bottom-bar {\n background: rgba(255,255,255,0.03);\n padding: 12px 16px;\n padding-bottom: max(12px, env(safe-area-inset-bottom));\n border-top: 1px solid rgba(255,255,255,0.08);\n }\n\n /* Tabs */\n .tabs {\n display: flex;\n background: rgba(0,0,0,0.2);\n border-radius: 6px;\n padding: 3px;\n margin-bottom: 12px;\n }\n .tab {\n flex: 1;\n padding: 10px;\n border: none;\n background: transparent;\n color: rgba(255,255,255,0.5);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.2s;\n }\n .tab.active {\n background: rgba(255,255,255,0.08);\n color: rgba(255,255,255,0.87);\n }\n\n /* Tab content */\n .tab-content { display: none; }\n .tab-content.active { display: block; }\n\n /* Apply results modal */\n .modal-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0,0,0,0.85);\n z-index: 100;\n align-items: center;\n justify-content: center;\n padding: 16px;\n }\n .modal-overlay.active { display: flex; }\n .modal {\n background: #1e1e1e;\n border-radius: 8px;\n padding: 20px;\n max-width: 360px;\n width: 100%;\n border: 1px solid rgba(255,255,255,0.1);\n }\n .modal h2 { font-size: 18px; margin-bottom: 12px; font-weight: 500; }\n .modal-result-item {\n display: flex;\n justify-content: space-between;\n padding: 8px 0;\n border-bottom: 1px solid rgba(255,255,255,0.08);\n font-size: 13px;\n }\n .modal-result-value { color: #4fc3f7; font-weight: 500; }\n .modal-buttons { display: flex; gap: 8px; margin-top: 16px; }\n\n /* Idle state */\n .idle-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 32px 16px;\n }\n .idle-icon {\n font-size: 56px;\n margin-bottom: 16px;\n opacity: 0.7;\n }\n .idle-title {\n font-size: 20px;\n font-weight: 500;\n margin-bottom: 8px;\n }\n .idle-desc {\n font-size: 14px;\n color: rgba(255,255,255,0.5);\n max-width: 280px;\n line-height: 1.5;\n }\n .idle-instructions {\n margin-top: 24px;\n text-align: left;\n background: rgba(255,255,255,0.03);\n border-radius: 6px;\n padding: 16px;\n border: 1px solid rgba(255,255,255,0.05);\n }\n .idle-instructions h3 {\n font-size: 12px;\n margin-bottom: 10px;\n color: #4fc3f7;\n font-weight: 500;\n }\n .idle-instructions ol {\n padding-left: 18px;\n font-size: 13px;\n line-height: 1.8;\n color: rgba(255,255,255,0.6);\n }\n </style>\n</head>\n<body>\n <div class="header">\n <h1>Training Mode</h1>\n <div class="header-status">\n <span class="status-badge" id="status-badge">Idle</span>\n </div>\n </div>\n\n \x3c!-- Idle State --\x3e\n <div class="main-content" id="idle-content">\n <div class="idle-content">\n <div class="idle-icon">🚶</div>\n <div class="idle-title">Train Your System</div>\n <div class="idle-desc">Walk around your property to teach the system about camera positions, transit times, and landmarks.</div>\n\n <div class="idle-instructions">\n <h3>How it works:</h3>\n <ol>\n <li>Tap <strong>Start Training</strong> below</li>\n <li>Walk to each camera on your property</li>\n <li>The system detects you automatically</li>\n <li>Mark landmarks as you encounter them</li>\n <li>End training when you\'re done</li>\n </ol>\n </div>\n </div>\n\n <div class="bottom-bar">\n <button class="btn btn-primary btn-full" onclick="startTraining()">\n ▶ Start Training\n </button>\n </div>\n </div>\n\n \x3c!-- Active Training State --\x3e\n <div class="main-content" id="active-content" style="display: none;">\n \x3c!-- Detection Card --\x3e\n <div class="detection-card" id="detection-card">\n <div class="detection-icon" id="detection-icon">👤</div>\n <div class="detection-title" id="detection-title">Waiting for detection...</div>\n <div class="detection-subtitle" id="detection-subtitle">Walk to any camera to begin</div>\n <div class="detection-confidence" id="detection-confidence"></div>\n\n <div class="transit-timer" id="transit-timer" style="display: none;">\n <span class="transit-timer-icon">⏱</span>\n <span class="transit-timer-text" id="transit-time">0s</span>\n <span class="transit-timer-from" id="transit-from"></span>\n </div>\n </div>\n\n \x3c!-- Tabs --\x3e\n <div class="tabs">\n <button class="tab active" onclick="switchTab(\'status\')">Status</button>\n <button class="tab" onclick="switchTab(\'mark\')">Mark</button>\n <button class="tab" onclick="switchTab(\'history\')">History</button>\n </div>\n\n \x3c!-- Status Tab --\x3e\n <div class="tab-content active" id="tab-status">\n \x3c!-- Stats --\x3e\n <div class="stats-grid">\n <div class="stat-item">\n <div class="stat-value" id="stat-cameras">0</div>\n <div class="stat-label">Cameras</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="stat-transits">0</div>\n <div class="stat-label">Transits</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="stat-landmarks">0</div>\n <div class="stat-label">Landmarks</div>\n </div>\n </div>\n\n \x3c!-- Progress --\x3e\n <div class="progress-section" style="margin-top: 15px;">\n <div class="progress-header">\n <span>Coverage</span>\n <span id="progress-percent">0%</span>\n </div>\n <div class="progress-bar">\n <div class="progress-fill" id="progress-fill" style="width: 0%"></div>\n </div>\n </div>\n\n \x3c!-- Suggestions --\x3e\n <div class="suggestions-section" style="margin-top: 15px;" id="suggestions-section">\n <div class="suggestions-title">Suggestions</div>\n <div id="suggestions-list">\n <div class="suggestion-item">Start walking to a camera</div>\n </div>\n </div>\n </div>\n\n \x3c!-- Mark Tab --\x3e\n <div class="tab-content" id="tab-mark">\n <div class="mark-panel">\n <div class="mark-panel-title">Mark a Landmark</div>\n <div class="mark-type-grid" id="landmark-type-grid">\n <button class="mark-type-btn selected" data-type="mailbox" onclick="selectLandmarkType(\'mailbox\')">\n <span class="icon">📬</span>\n Mailbox\n </button>\n <button class="mark-type-btn" data-type="garage" onclick="selectLandmarkType(\'garage\')">\n <span class="icon">🏠</span>\n Garage\n </button>\n <button class="mark-type-btn" data-type="shed" onclick="selectLandmarkType(\'shed\')">\n <span class="icon">🏚</span>\n Shed\n </button>\n <button class="mark-type-btn" data-type="tree" onclick="selectLandmarkType(\'tree\')">\n <span class="icon">🌳</span>\n Tree\n </button>\n <button class="mark-type-btn" data-type="gate" onclick="selectLandmarkType(\'gate\')">\n <span class="icon">🚪</span>\n Gate\n </button>\n <button class="mark-type-btn" data-type="driveway" onclick="selectLandmarkType(\'driveway\')">\n <span class="icon">🛣</span>\n Driveway\n </button>\n <button class="mark-type-btn" data-type="pool" onclick="selectLandmarkType(\'pool\')">\n <span class="icon">🏊</span>\n Pool\n </button>\n <button class="mark-type-btn" data-type="other" onclick="selectLandmarkType(\'other\')">\n <span class="icon">📍</span>\n Other\n </button>\n </div>\n\n <div class="input-group">\n <label>Landmark Name</label>\n <input type="text" id="landmark-name" placeholder="e.g., Front Mailbox">\n </div>\n\n <button class="btn btn-primary btn-full" onclick="markLandmark()">\n 📍 Mark Landmark Here\n </button>\n </div>\n </div>\n\n \x3c!-- History Tab --\x3e\n <div class="tab-content" id="tab-history">\n <div class="history-section">\n <div class="history-title">\n <span>Recent Activity</span>\n <span id="history-count">0 events</span>\n </div>\n <div id="history-list">\n <div class="history-item" style="color: rgba(255,255,255,0.4); text-align: center;">\n No activity yet\n </div>\n </div>\n </div>\n </div>\n\n \x3c!-- Bottom Actions --\x3e\n <div class="bottom-bar">\n <div class="action-buttons">\n <button class="btn btn-warning" id="pause-btn" onclick="togglePause()">\n ⏸ Pause\n </button>\n <button class="btn btn-danger" onclick="endTraining()">\n ⏹ End\n </button>\n </div>\n </div>\n </div>\n\n \x3c!-- Completed State --\x3e\n <div class="main-content" id="completed-content" style="display: none;">\n <div class="idle-content">\n <div class="idle-icon">✅</div>\n <div class="idle-title">Training Complete!</div>\n <div class="idle-desc">Review the results and apply them to your topology.</div>\n </div>\n\n \x3c!-- Final Stats --\x3e\n <div class="stats-grid">\n <div class="stat-item">\n <div class="stat-value" id="final-cameras">0</div>\n <div class="stat-label">Cameras</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-transits">0</div>\n <div class="stat-label">Transits</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-landmarks">0</div>\n <div class="stat-label">Landmarks</div>\n </div>\n </div>\n\n <div class="stats-grid" style="margin-top: 10px;">\n <div class="stat-item">\n <div class="stat-value" id="final-overlaps">0</div>\n <div class="stat-label">Overlaps</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-avg-transit">0s</div>\n <div class="stat-label">Avg Transit</div>\n </div>\n <div class="stat-item">\n <div class="stat-value" id="final-coverage">0%</div>\n <div class="stat-label">Coverage</div>\n </div>\n </div>\n\n <div class="bottom-bar" style="margin-top: auto;">\n <div class="action-buttons">\n <button class="btn btn-secondary" onclick="resetTraining()">\n ↻ Start Over\n </button>\n <button class="btn btn-primary" onclick="applyTraining()">\n ✓ Apply Results\n </button>\n </div>\n </div>\n </div>\n\n \x3c!-- Apply Results Modal --\x3e\n <div class="modal-overlay" id="results-modal">\n <div class="modal">\n <h2>Training Applied!</h2>\n <div id="results-content">\n <div class="modal-result-item">\n <span>Connections Created</span>\n <span class="modal-result-value" id="result-connections">0</span>\n </div>\n <div class="modal-result-item">\n <span>Connections Updated</span>\n <span class="modal-result-value" id="result-updated">0</span>\n </div>\n <div class="modal-result-item">\n <span>Landmarks Added</span>\n <span class="modal-result-value" id="result-landmarks">0</span>\n </div>\n <div class="modal-result-item">\n <span>Zones Created</span>\n <span class="modal-result-value" id="result-zones">0</span>\n </div>\n </div>\n <div class="modal-buttons">\n <button class="btn btn-secondary" style="flex: 1;" onclick="closeResultsModal()">Close</button>\n <button class="btn btn-primary" style="flex: 1;" onclick="openEditor()">Open Editor</button>\n </div>\n </div>\n </div>\n\n <script>\n let trainingState = \'idle\'; // idle, active, paused, completed\n let session = null;\n let pollInterval = null;\n let transitInterval = null;\n let selectedLandmarkType = \'mailbox\';\n let historyItems = [];\n\n // Initialize\n async function init() {\n // Check if there\'s an existing session\n const status = await fetchTrainingStatus();\n if (status && (status.state === \'active\' || status.state === \'paused\')) {\n session = status;\n trainingState = status.state;\n updateUI();\n startPolling();\n }\n }\n\n // API calls\n async function fetchTrainingStatus() {\n try {\n const response = await fetch(\'../api/training/status\');\n if (response.ok) {\n return await response.json();\n }\n } catch (e) { console.error(\'Failed to fetch status:\', e); }\n return null;\n }\n\n async function startTraining() {\n try {\n const response = await fetch(\'../api/training/start\', { method: \'POST\' });\n if (response.ok) {\n session = await response.json();\n trainingState = \'active\';\n updateUI();\n startPolling();\n addHistoryItem(\'Training started\', \'start\');\n }\n } catch (e) {\n console.error(\'Failed to start training:\', e);\n alert(\'Failed to start training. Please try again.\');\n }\n }\n\n async function togglePause() {\n const endpoint = trainingState === \'active\' ? \'pause\' : \'resume\';\n try {\n const response = await fetch(\'../api/training/\' + endpoint, { method: \'POST\' });\n if (response.ok) {\n trainingState = trainingState === \'active\' ? \'paused\' : \'active\';\n updateUI();\n addHistoryItem(\'Training \' + (trainingState === \'paused\' ? \'paused\' : \'resumed\'), \'control\');\n }\n } catch (e) { console.error(\'Failed to toggle pause:\', e); }\n }\n\n async function endTraining() {\n if (!confirm(\'End training session?\')) return;\n try {\n const response = await fetch(\'../api/training/end\', { method: \'POST\' });\n if (response.ok) {\n session = await response.json();\n trainingState = \'completed\';\n stopPolling();\n updateUI();\n }\n } catch (e) { console.error(\'Failed to end training:\', e); }\n }\n\n async function applyTraining() {\n try {\n const response = await fetch(\'../api/training/apply\', { method: \'POST\' });\n if (response.ok) {\n const result = await response.json();\n document.getElementById(\'result-connections\').textContent = result.connectionsCreated;\n document.getElementById(\'result-updated\').textContent = result.connectionsUpdated;\n document.getElementById(\'result-landmarks\').textContent = result.landmarksAdded;\n document.getElementById(\'result-zones\').textContent = result.zonesCreated;\n document.getElementById(\'results-modal\').classList.add(\'active\');\n }\n } catch (e) {\n console.error(\'Failed to apply training:\', e);\n alert(\'Failed to apply training results.\');\n }\n }\n\n function closeResultsModal() {\n document.getElementById(\'results-modal\').classList.remove(\'active\');\n }\n\n function openEditor() {\n window.location.href = \'../ui/editor\';\n }\n\n function resetTraining() {\n trainingState = \'idle\';\n session = null;\n historyItems = [];\n updateUI();\n }\n\n async function markLandmark() {\n const name = document.getElementById(\'landmark-name\').value.trim();\n if (!name) {\n alert(\'Please enter a landmark name\');\n return;\n }\n\n const currentCameraId = session?.currentCamera?.id;\n const visibleFromCameras = currentCameraId ? [currentCameraId] : [];\n\n try {\n const response = await fetch(\'../api/training/landmark\', {\n method: \'POST\',\n headers: { \'Content-Type\': \'application/json\' },\n body: JSON.stringify({\n name,\n type: selectedLandmarkType,\n visibleFromCameras,\n position: { x: 50, y: 50 }, // Will be refined when applied\n })\n });\n if (response.ok) {\n document.getElementById(\'landmark-name\').value = \'\';\n addHistoryItem(\'Marked: \' + name + \' (\' + selectedLandmarkType + \')\', \'landmark\');\n // Refresh status\n const status = await fetchTrainingStatus();\n if (status) {\n session = status;\n updateStatsUI();\n }\n }\n } catch (e) { console.error(\'Failed to mark landmark:\', e); }\n }\n\n function selectLandmarkType(type) {\n selectedLandmarkType = type;\n document.querySelectorAll(\'.mark-type-btn\').forEach(btn => {\n btn.classList.toggle(\'selected\', btn.dataset.type === type);\n });\n }\n\n // Polling\n function startPolling() {\n if (pollInterval) clearInterval(pollInterval);\n pollInterval = setInterval(async () => {\n const status = await fetchTrainingStatus();\n if (status) {\n session = status;\n updateDetectionUI();\n updateStatsUI();\n updateSuggestionsUI();\n }\n }, 1000);\n }\n\n function stopPolling() {\n if (pollInterval) {\n clearInterval(pollInterval);\n pollInterval = null;\n }\n if (transitInterval) {\n clearInterval(transitInterval);\n transitInterval = null;\n }\n }\n\n // UI Updates\n function updateUI() {\n // Show/hide content sections\n document.getElementById(\'idle-content\').style.display = trainingState === \'idle\' ? \'flex\' : \'none\';\n document.getElementById(\'active-content\').style.display = (trainingState === \'active\' || trainingState === \'paused\') ? \'flex\' : \'none\';\n document.getElementById(\'completed-content\').style.display = trainingState === \'completed\' ? \'flex\' : \'none\';\n\n // Update status badge\n const badge = document.getElementById(\'status-badge\');\n badge.textContent = trainingState.charAt(0).toUpperCase() + trainingState.slice(1);\n badge.className = \'status-badge \' + trainingState;\n\n // Update pause button\n const pauseBtn = document.getElementById(\'pause-btn\');\n if (pauseBtn) {\n pauseBtn.innerHTML = trainingState === \'paused\' ? \'▶ Resume\' : \'⏸ Pause\';\n }\n\n // Update completed stats\n if (trainingState === \'completed\' && session) {\n document.getElementById(\'final-cameras\').textContent = session.stats?.camerasVisited || 0;\n document.getElementById(\'final-transits\').textContent = session.stats?.transitsRecorded || 0;\n document.getElementById(\'final-landmarks\').textContent = session.stats?.landmarksMarked || 0;\n document.getElementById(\'final-overlaps\').textContent = session.stats?.overlapsDetected || 0;\n document.getElementById(\'final-avg-transit\').textContent = (session.stats?.averageTransitTime || 0) + \'s\';\n document.getElementById(\'final-coverage\').textContent = (session.stats?.coveragePercentage || 0) + \'%\';\n }\n }\n\n function updateDetectionUI() {\n if (!session) return;\n\n const card = document.getElementById(\'detection-card\');\n const icon = document.getElementById(\'detection-icon\');\n const title = document.getElementById(\'detection-title\');\n const subtitle = document.getElementById(\'detection-subtitle\');\n const confidence = document.getElementById(\'detection-confidence\');\n const transitTimer = document.getElementById(\'transit-timer\');\n\n if (session.currentCamera) {\n // Detected on a camera\n card.className = \'detection-card detecting\';\n icon.textContent = \'📷\';\n title.textContent = session.currentCamera.name;\n subtitle.textContent = \'You are visible on this camera\';\n confidence.textContent = \'Confidence: \' + Math.round(session.currentCamera.confidence * 100) + \'%\';\n transitTimer.style.display = \'none\';\n\n // Check for new camera detection to add to history\n const lastHistoryCamera = historyItems.find(h => h.type === \'camera\');\n if (!lastHistoryCamera || lastHistoryCamera.cameraId !== session.currentCamera.id) {\n addHistoryItem(\'Detected on: \' + session.currentCamera.name, \'camera\', session.currentCamera.id);\n }\n } else if (session.activeTransit) {\n // In transit\n card.className = \'detection-card in-transit\';\n icon.textContent = \'🚶\';\n title.textContent = \'In Transit\';\n subtitle.textContent = \'Walking to next camera...\';\n confidence.textContent = \'\';\n transitTimer.style.display = \'flex\';\n document.getElementById(\'transit-from\').textContent = \'from \' + session.activeTransit.fromCameraName;\n\n // Start transit timer if not already running\n if (!transitInterval) {\n transitInterval = setInterval(() => {\n if (session?.activeTransit) {\n document.getElementById(\'transit-time\').textContent = session.activeTransit.elapsedSeconds + \'s\';\n }\n }, 1000);\n }\n } else {\n // Waiting\n card.className = \'detection-card\';\n icon.textContent = \'👤\';\n title.textContent = \'Waiting for detection...\';\n subtitle.textContent = \'Walk to any camera to begin\';\n confidence.textContent = \'\';\n transitTimer.style.display = \'none\';\n\n if (transitInterval) {\n clearInterval(transitInterval);\n transitInterval = null;\n }\n }\n }\n\n function updateStatsUI() {\n if (!session?.stats) return;\n\n document.getElementById(\'stat-cameras\').textContent = session.stats.camerasVisited;\n document.getElementById(\'stat-transits\').textContent = session.stats.transitsRecorded;\n document.getElementById(\'stat-landmarks\').textContent = session.stats.landmarksMarked;\n document.getElementById(\'progress-percent\').textContent = session.stats.coveragePercentage + \'%\';\n document.getElementById(\'progress-fill\').style.width = session.stats.coveragePercentage + \'%\';\n }\n\n function updateSuggestionsUI() {\n if (!session?.suggestions || session.suggestions.length === 0) return;\n\n const list = document.getElementById(\'suggestions-list\');\n list.innerHTML = session.suggestions.map(s =>\n \'<div class="suggestion-item">\' + s + \'</div>\'\n ).join(\'\');\n }\n\n function addHistoryItem(text, type, cameraId) {\n const time = new Date().toLocaleTimeString();\n historyItems.unshift({ text, type, time, cameraId });\n if (historyItems.length > 50) historyItems.pop();\n\n const list = document.getElementById(\'history-list\');\n document.getElementById(\'history-count\').textContent = historyItems.length + \' events\';\n\n list.innerHTML = historyItems.map(item => {\n let className = \'\';\n if (item.type === \'camera\') className = \'history-item-camera\';\n if (item.type === \'transit\') className = \'history-item-transit\';\n return \'<div class="history-item"><span class="\' + className + \'">\' + item.text + \'</span>\' +\n \'<div class="history-item-time">\' + item.time + \'</div></div>\';\n }).join(\'\');\n }\n\n function switchTab(tabName) {\n document.querySelectorAll(\'.tab\').forEach(tab => {\n tab.classList.toggle(\'active\', tab.textContent.toLowerCase() === tabName);\n });\n document.querySelectorAll(\'.tab-content\').forEach(content => {\n content.classList.toggle(\'active\', content.id === \'tab-\' + tabName);\n });\n }\n\n // Initialize on load\n init();\n <\/script>\n</body>\n</html>'},1722(e,t,n){"use strict";const i=n(4434),r=n(8611),{Duplex:o}=n(2203),{createHash:s}=n(6982),a=n(5926),c=n(2971),l=n(8237),d=n(1060),{GUID:u,kWebSocket:p}=n(2614),h=/^[+/0-9A-Za-z]{22}==$/;function f(e){e._state=2,e.emit("close")}function g(){this.destroy()}function m(e,t,n,i){n=n||r.STATUS_CODES[t],i={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(n),...i},e.once("finish",e.destroy),e.end(`HTTP/1.1 ${t} ${r.STATUS_CODES[t]}\r\n`+Object.keys(i).map(e=>`${e}: ${i[e]}`).join("\r\n")+"\r\n\r\n"+n)}function y(e,t,n,i,r,o){if(e.listenerCount("wsClientError")){const i=new Error(r);Error.captureStackTrace(i,y),e.emit("wsClientError",i,n,t)}else m(n,i,r,o)}e.exports=class extends i{constructor(e,t){if(super(),null==(e={allowSynchronousEvents:!0,autoPong:!0,maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:d,...e}).port&&!e.server&&!e.noServer||null!=e.port&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(null!=e.port?(this._server=r.createServer((e,t)=>{const n=r.STATUS_CODES[426];t.writeHead(426,{"Content-Length":n.length,"Content-Type":"text/plain"}),t.end(n)}),this._server.listen(e.port,e.host,e.backlog,t)):e.server&&(this._server=e.server),this._server){const e=this.emit.bind(this,"connection");this._removeListeners=function(e,t){for(const n of Object.keys(t))e.on(n,t[n]);return function(){for(const n of Object.keys(t))e.removeListener(n,t[n])}}(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(t,n,i)=>{this.handleUpgrade(t,n,i,e)}})}!0===e.perMessageDeflate&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=0}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(2===this._state)return e&&this.once("close",()=>{e(new Error("The server is not running"))}),void process.nextTick(f,this);if(e&&this.once("close",e),1!==this._state)if(this._state=1,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients&&this.clients.size?this._shouldEmitClose=!0:process.nextTick(f,this);else{const e=this._server;this._removeListeners(),this._removeListeners=this._server=null,e.close(()=>{f(this)})}}shouldHandle(e){if(this.options.path){const t=e.url.indexOf("?");if((-1!==t?e.url.slice(0,t):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,t,n,i){t.on("error",g);const r=e.headers["sec-websocket-key"],o=e.headers.upgrade,s=+e.headers["sec-websocket-version"];if("GET"!==e.method){return void y(this,e,t,405,"Invalid HTTP method")}if(void 0===o||"websocket"!==o.toLowerCase()){return void y(this,e,t,400,"Invalid Upgrade header")}if(void 0===r||!h.test(r)){return void y(this,e,t,400,"Missing or invalid Sec-WebSocket-Key header")}if(13!==s&&8!==s){return void y(this,e,t,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"})}if(!this.shouldHandle(e))return void m(t,400);const d=e.headers["sec-websocket-protocol"];let u=new Set;if(void 0!==d)try{u=l.parse(d)}catch(n){return void y(this,e,t,400,"Invalid Sec-WebSocket-Protocol header")}const p=e.headers["sec-websocket-extensions"],f={};if(this.options.perMessageDeflate&&void 0!==p){const n=new c(this.options.perMessageDeflate,!0,this.options.maxPayload);try{const e=a.parse(p);e[c.extensionName]&&(n.accept(e[c.extensionName]),f[c.extensionName]=n)}catch(n){return void y(this,e,t,400,"Invalid or unacceptable Sec-WebSocket-Extensions header")}}if(this.options.verifyClient){const o={origin:e.headers[""+(8===s?"sec-websocket-origin":"origin")],secure:!(!e.socket.authorized&&!e.socket.encrypted),req:e};if(2===this.options.verifyClient.length)return void this.options.verifyClient(o,(o,s,a,c)=>{if(!o)return m(t,s||401,a,c);this.completeUpgrade(f,r,u,e,t,n,i)});if(!this.options.verifyClient(o))return m(t,401)}this.completeUpgrade(f,r,u,e,t,n,i)}completeUpgrade(e,t,n,i,r,o,l){if(!r.readable||!r.writable)return r.destroy();if(r[p])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>0)return m(r,503);const d=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${s("sha1").update(t+u).digest("base64")}`],h=new this.options.WebSocket(null,void 0,this.options);if(n.size){const e=this.options.handleProtocols?this.options.handleProtocols(n,i):n.values().next().value;e&&(d.push(`Sec-WebSocket-Protocol: ${e}`),h._protocol=e)}if(e[c.extensionName]){const t=e[c.extensionName].params,n=a.format({[c.extensionName]:[t]});d.push(`Sec-WebSocket-Extensions: ${n}`),h._extensions=e}this.emit("headers",d,i),r.write(d.concat("\r\n").join("\r\n")),r.removeListener("error",g),h.setSocket(r,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(h),h.on("close",()=>{this.clients.delete(h),this._shouldEmitClose&&!this.clients.size&&process.nextTick(f,this)})),l(h,i)}}},1725(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(181),r={INVALID_ENCODING:"Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.",INVALID_SMARTBUFFER_SIZE:"Invalid size provided. Size must be a valid integer greater than zero.",INVALID_SMARTBUFFER_BUFFER:"Invalid Buffer provided in SmartBufferOptions.",INVALID_SMARTBUFFER_OBJECT:"Invalid SmartBufferOptions object supplied to SmartBuffer constructor or factory methods.",INVALID_OFFSET:"An invalid offset value was provided.",INVALID_OFFSET_NON_NUMBER:"An invalid offset value was provided. A numeric value is required.",INVALID_LENGTH:"An invalid length value was provided.",INVALID_LENGTH_NON_NUMBER:"An invalid length value was provived. A numeric value is required.",INVALID_TARGET_OFFSET:"Target offset is beyond the bounds of the internal SmartBuffer data.",INVALID_TARGET_LENGTH:"Specified length value moves cursor beyong the bounds of the internal SmartBuffer data.",INVALID_READ_BEYOND_BOUNDS:"Attempted to read beyond the bounds of the managed data.",INVALID_WRITE_BEYOND_BOUNDS:"Attempted to write beyond the bounds of the managed data."};function o(e){return"number"==typeof e&&isFinite(e)&&function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}(e)}function s(e,t){if("number"!=typeof e)throw new Error(t?r.INVALID_OFFSET_NON_NUMBER:r.INVALID_LENGTH_NON_NUMBER);if(!o(e)||e<0)throw new Error(t?r.INVALID_OFFSET:r.INVALID_LENGTH)}t.ERRORS=r,t.checkEncoding=function(e){if(!i.Buffer.isEncoding(e))throw new Error(r.INVALID_ENCODING)},t.isFiniteInteger=o,t.checkLengthValue=function(e){s(e,!1)},t.checkOffsetValue=function(e){s(e,!0)},t.checkTargetOffset=function(e,t){if(e<0||e>t.length)throw new Error(r.INVALID_TARGET_OFFSET)},t.bigIntAndBufferInt64Check=function(e){if("undefined"==typeof BigInt)throw new Error("Platform does not support JS BigInt type.");if("undefined"==typeof i.Buffer.prototype[e])throw new Error(`Platform does not support Buffer.prototype.${e}.`)}},2017(e,t,n){try{var i=n(9023);if("function"!=typeof i.inherits)throw"";e.exports=i.inherits}catch(t){e.exports=n(6698)}},2018(e){"use strict";e.exports=require("tty")},2099(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(720);t.default=class{numberAllocator;lastId;constructor(){this.numberAllocator=new i.NumberAllocator(1,65535)}allocate(){return this.lastId=this.numberAllocator.alloc(),this.lastId}getLastAllocated(){return this.lastId}register(e){return this.numberAllocator.use(e)}deallocate(e){this.numberAllocator.free(e)}clear(){this.numberAllocator.clear()}}},2203(e){"use strict";e.exports=require("stream")},2250(e){"use strict";e.exports=require("dns")},2437(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.AddressError=void 0;class n extends Error{constructor(e,t){super(e),this.name="AddressError",this.parseMessage=t}}t.AddressError=n},2535(e,t,n){const i=n(3132),{EventEmitter:r}=n(4434),{Buffer:o}=n(181);class s extends r{constructor(){super(),this._array=new Array(20),this._i=0}write(e){return this._array[this._i++]=e,!0}concat(){let e=0;const t=new Array(this._array.length),n=this._array;let i,r=0;for(i=0;i<n.length&&void 0!==n[i];i++)"string"!=typeof n[i]?t[i]=n[i].length:t[i]=o.byteLength(n[i]),e+=t[i];const s=o.allocUnsafe(e);for(i=0;i<n.length&&void 0!==n[i];i++)"string"!=typeof n[i]?(n[i].copy(s,r),r+=t[i]):(s.write(n[i],r),r+=t[i]);return s}destroy(e){e&&this.emit("error",e)}}e.exports=function(e,t){const n=new s;return i(e,n,t),n.concat()}},2613(e){"use strict";e.exports=require("assert")},2614(e){"use strict";const t=["nodebuffer","arraybuffer","fragments"],n="undefined"!=typeof Blob;n&&t.push("blob"),e.exports={BINARY_TYPES:t,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:n,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}},2635(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BufferedDuplex=void 0,t.writev=o;const i=n(4478),r=n(181);function o(e,t){const n=new Array(e.length);for(let t=0;t<e.length;t++)"string"==typeof e[t].chunk?n[t]=r.Buffer.from(e[t].chunk,"utf8"):n[t]=e[t].chunk;this._write(r.Buffer.concat(n),"binary",t)}class s extends i.Duplex{socket;proxy;isSocketOpen;writeQueue;constructor(e,t,n){super({objectMode:!0}),this.proxy=t,this.socket=n,this.writeQueue=[],e.objectMode||(this._writev=o.bind(this)),this.isSocketOpen=!1,this.proxy.on("data",e=>{!this.destroyed&&this.readable&&this.push(e)})}_read(e){this.proxy.read(e)}_write(e,t,n){this.isSocketOpen?this.writeToProxy(e,t,n):this.writeQueue.push({chunk:e,encoding:t,cb:n})}_final(e){this.writeQueue=[],this.proxy.end(e)}_destroy(e,t){this.writeQueue=[],this.proxy.destroy(),t(e)}socketReady(){this.emit("connect"),this.isSocketOpen=!0,this.processWriteQueue()}writeToProxy(e,t,n){!1===this.proxy.write(e,t)?this.proxy.once("drain",n):n()}processWriteQueue(){for(;this.writeQueue.length>0;){const{chunk:e,encoding:t,cb:n}=this.writeQueue.shift();this.writeToProxy(e,t,n)}}}t.BufferedDuplex=s},2639(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=class{aliasToTopic;max;length;constructor(e){this.aliasToTopic={},this.max=e}put(e,t){return!(0===t||t>this.max)&&(this.aliasToTopic[t]=e,this.length=Object.keys(this.aliasToTopic).length,!0)}getTopicByAlias(e){return this.aliasToTopic[e]}clear(){this.aliasToTopic={}}}},2778(e,t,n){"use strict";const i=n(181),r=n(4478),o=n(2635);let s,a,c,l=!1;t.A=(e,t)=>{if(t.hostname=t.hostname||t.host,!t.hostname)throw new Error("Could not determine host. Specify host manually.");const n="MQIsdp"===t.protocolId&&3===t.protocolVersion?"mqttv3.1":"mqtt";!function(e){e.hostname||(e.hostname="localhost"),e.path||(e.path="/"),e.wsOptions||(e.wsOptions={})}(t);const d=function(e,t){const n="alis"===e.protocol?"wss":"ws";let i=`${n}://${e.hostname}${e.path}`;return e.port&&80!==e.port&&443!==e.port&&(i=`${n}://${e.hostname}:${e.port}${e.path}`),"function"==typeof e.transformWsUrl&&(i=e.transformWsUrl(i,e,t)),i}(t,e);return s=t.my,s.connectSocket({url:d,protocols:n}),a=function(){const e=new r.Transform;return e._write=(e,t,n)=>{s.sendSocketMessage({data:e.buffer,success(){n()},fail(){n(new Error)}})},e._flush=e=>{s.closeSocket({success(){e()}})},e}(),c=new o.BufferedDuplex(t,a,s),l||(l=!0,s.onSocketOpen(()=>{c.socketReady()}),s.onSocketMessage(e=>{if("string"==typeof e.data){const t=i.Buffer.from(e.data,"base64");a.push(t)}else{const t=new FileReader;t.addEventListener("load",()=>{t.result instanceof ArrayBuffer?a.push(i.Buffer.from(t.result)):a.push(i.Buffer.from(t.result,"utf-8"))}),t.readAsArrayBuffer(e.data)}}),s.onSocketClose(()=>{c.end(),c.destroy()}),s.onSocketError(e=>{c.destroy(e)})),c}},2793(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.connectAsync=function(e,t,n=!0){return new Promise((i,r)=>{const o=d(e,t),s={connect:e=>{a(),i(o)},end:()=>{a(),i(o)},error:e=>{a(),o.end(),r(e)}};function a(){Object.keys(s).forEach(e=>{o.off(e,s[e])})}!1===n&&(s.close=()=>{s.error(new Error("Couldn't connect to server"))}),Object.keys(s).forEach(e=>{o.on(e,s[e])})})};const r=i(n(5753)),o=i(n(7016)),s=i(n(9777)),a=i(n(6887));"function"!=typeof process?.nextTick&&(process.nextTick=setImmediate);const c=(0,r.default)("mqttjs");let l=null;function d(e,t){if(c("connecting to an MQTT broker..."),"object"!=typeof e||t||(t=e,e=""),t=t||{},e&&"string"==typeof e){const n=o.default.parse(e,!0),i={};if(null!=n.port&&(i.port=Number(n.port)),i.host=n.hostname,i.query=n.query,i.auth=n.auth,i.protocol=n.protocol,i.path=n.path,!(t={...i,...t}).protocol)throw new Error("Missing protocol");t.protocol=t.protocol.replace(/:$/,"")}if(t.unixSocket=t.unixSocket||t.protocol?.includes("+unix"),t.unixSocket?t.protocol=t.protocol.replace("+unix",""):t.protocol?.startsWith("ws")||t.protocol?.startsWith("wx")||delete t.path,function(e){let t;if(e.auth)if(t=e.auth.match(/^(.+):(.+)$/),t){const[,n,i]=t;e.username=n,e.password=i}else e.username=e.auth}(t),t.query&&"string"==typeof t.query.clientId&&(t.clientId=t.query.clientId),a.default||t.unixSocket?t.socksProxy=void 0:void 0===t.socksProxy&&"undefined"!=typeof process&&(t.socksProxy=process.env.MQTTJS_SOCKS_PROXY),t.cert&&t.key){if(!t.protocol)throw new Error("Missing secure protocol key");if(-1===["mqtts","wss","wxs","alis"].indexOf(t.protocol))switch(t.protocol){case"mqtt":t.protocol="mqtts";break;case"ws":t.protocol="wss";break;case"wx":t.protocol="wxs";break;case"ali":t.protocol="alis";break;default:throw new Error(`Unknown protocol for secure connection: "${t.protocol}"!`)}}if(l||(l={},a.default||t.forceNativeWebSocket?(l.ws=n(8203).browserStreamBuilder,l.wss=n(8203).browserStreamBuilder,l.wx=n(5670).A,l.wxs=n(5670).A,l.ali=n(2778).A,l.alis=n(2778).A):(l.ws=n(8203).streamBuilder,l.wss=n(8203).streamBuilder,l.mqtt=n(778).default,l.tcp=n(778).default,l.ssl=n(3936).default,l.tls=l.ssl,l.mqtts=n(3936).default)),!l[t.protocol]){const e=-1!==["mqtts","wss"].indexOf(t.protocol);t.protocol=["mqtt","mqtts","ws","wss","wx","wxs","ali","alis"].filter((t,n)=>(!e||n%2!=0)&&"function"==typeof l[t])[0]}if(!1===t.clean&&!t.clientId)throw new Error("Missing clientId for unclean clients");t.protocol&&(t.defaultProtocol=t.protocol);const i=new s.default(function(e){return t.servers&&(e._reconnectCount&&e._reconnectCount!==t.servers.length||(e._reconnectCount=0),t.host=t.servers[e._reconnectCount].host,t.port=t.servers[e._reconnectCount].port,t.protocol=t.servers[e._reconnectCount].protocol?t.servers[e._reconnectCount].protocol:t.defaultProtocol,t.hostname=t.host,e._reconnectCount++),c("calling streambuilder for",t.protocol),l[t.protocol](e,t)},t);return i.on("error",()=>{}),i}t.default=d},2839(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Address4=void 0;const s=o(n(837)),a=o(n(9576)),c=n(2437);class l{constructor(e){this.groups=a.GROUPS,this.parsedAddress=[],this.parsedSubnet="",this.subnet="/32",this.subnetMask=32,this.v4=!0,this.isCorrect=s.isCorrect(a.BITS),this.isInSubnet=s.isInSubnet,this.address=e;const t=a.RE_SUBNET_STRING.exec(e);if(t){if(this.parsedSubnet=t[0].replace("/",""),this.subnetMask=parseInt(this.parsedSubnet,10),this.subnet=`/${this.subnetMask}`,this.subnetMask<0||this.subnetMask>a.BITS)throw new c.AddressError("Invalid subnet mask.");e=e.replace(a.RE_SUBNET_STRING,"")}this.addressMinusSuffix=e,this.parsedAddress=this.parse(e)}static isValid(e){try{return new l(e),!0}catch(e){return!1}}parse(e){const t=e.split(".");if(!e.match(a.RE_ADDRESS))throw new c.AddressError("Invalid IPv4 address.");return t}correctForm(){return this.parsedAddress.map(e=>parseInt(e,10)).join(".")}static fromHex(e){const t=e.replace(/:/g,"").padStart(8,"0"),n=[];let i;for(i=0;i<8;i+=2){const e=t.slice(i,i+2);n.push(parseInt(e,16))}return new l(n.join("."))}static fromInteger(e){return l.fromHex(e.toString(16))}static fromArpa(e){const t=e.replace(/(\.in-addr\.arpa)?\.$/,"").split(".").reverse().join(".");return new l(t)}toHex(){return this.parsedAddress.map(e=>s.stringToPaddedHex(e)).join(":")}toArray(){return this.parsedAddress.map(e=>parseInt(e,10))}toGroup6(){const e=[];let t;for(t=0;t<a.GROUPS;t+=2)e.push(`${s.stringToPaddedHex(this.parsedAddress[t])}${s.stringToPaddedHex(this.parsedAddress[t+1])}`);return e.join(":")}bigInt(){return BigInt(`0x${this.parsedAddress.map(e=>s.stringToPaddedHex(e)).join("")}`)}_startAddress(){return BigInt(`0b${this.mask()+"0".repeat(a.BITS-this.subnetMask)}`)}startAddress(){return l.fromBigInt(this._startAddress())}startAddressExclusive(){const e=BigInt("1");return l.fromBigInt(this._startAddress()+e)}_endAddress(){return BigInt(`0b${this.mask()+"1".repeat(a.BITS-this.subnetMask)}`)}endAddress(){return l.fromBigInt(this._endAddress())}endAddressExclusive(){const e=BigInt("1");return l.fromBigInt(this._endAddress()-e)}static fromBigInt(e){return l.fromHex(e.toString(16))}static fromByteArray(e){if(4!==e.length)throw new c.AddressError("IPv4 addresses require exactly 4 bytes");for(let t=0;t<e.length;t++)if(!Number.isInteger(e[t])||e[t]<0||e[t]>255)throw new c.AddressError("All bytes must be integers between 0 and 255");return this.fromUnsignedByteArray(e)}static fromUnsignedByteArray(e){if(4!==e.length)throw new c.AddressError("IPv4 addresses require exactly 4 bytes");const t=e.join(".");return new l(t)}mask(e){return void 0===e&&(e=this.subnetMask),this.getBitsBase2(0,e)}getBitsBase2(e,t){return this.binaryZeroPad().slice(e,t)}reverseForm(e){e||(e={});const t=this.correctForm().split(".").reverse().join(".");return e.omitSuffix?t:`${t}.in-addr.arpa.`}isMulticast(){return this.isInSubnet(new l("224.0.0.0/4"))}binaryZeroPad(){return this.bigInt().toString(2).padStart(a.BITS,"0")}groupForV6(){const e=this.parsedAddress;return this.address.replace(a.RE_ADDRESS,`<span class="hover-group group-v4 group-6">${e.slice(0,2).join(".")}</span>.<span class="hover-group group-v4 group-7">${e.slice(2,4).join(".")}</span>`)}}t.Address4=l},2846(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TrackingZone=void 0;const i=n(7562),r=n(6117);class o extends i.ScryptedDeviceBase{trackingState;plugin;config={type:"entry",cameras:[]};storageSettings=new r.StorageSettings(this,{zoneType:{title:"Zone Type",type:"string",choices:["entry","exit","dwell","restricted"],defaultValue:"entry",description:"Type of zone for alerting purposes"},cameras:{title:"Cameras",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${i.ScryptedInterface.ObjectDetector}')`,description:"Cameras that make up this zone"},dwellThreshold:{title:"Dwell Time Threshold (seconds)",type:"number",defaultValue:60,description:"For dwell zones: alert if object stays longer than this"},trackClasses:{title:"Track Object Types",type:"string",multiple:!0,choices:["person","car","vehicle","animal","package"],description:"Object types to monitor in this zone (empty = all)"}});constructor(e,t,n){super(t),this.plugin=e,this.trackingState=n,this.loadConfig(),n.onStateChange(()=>this.evaluateZone()),this.evaluateZone()}loadConfig(){try{const e=this.storage.getItem("zoneConfig");e&&(this.config=JSON.parse(e))}catch(e){this.console.error("Failed to load zone config:",e)}}saveConfig(){try{this.storage.setItem("zoneConfig",JSON.stringify(this.config))}catch(e){this.console.error("Failed to save zone config:",e)}}configure(e){this.config={...this.config,...e},this.saveConfig(),this.evaluateZone()}evaluateZone(){const e=this.getCameraIds();if(0===e.length)return this.occupied=!1,void(this.motionDetected=!1);const t=this.storageSettings.values.trackClasses||[];let n=!1,i=!1;const r=Date.now();for(const o of e){const e=this.trackingState.getObjectsOnCamera(o);for(const s of e){if(t.length>0&&!t.includes(s.className))continue;n=!0;s.sightings.filter(e=>e.cameraId===o&&r-e.timestamp<5e3).some(e=>e.detection.movement?.moving)&&(i=!0)}}this.occupied=n,this.motionDetected=i}getCameraIds(){const e=this.storageSettings.values.cameras;return Array.isArray(e)?e:e?[e]:this.config.cameras||[]}getObjectsInZone(){const e=this.getCameraIds(),t=this.storageSettings.values.trackClasses||[],n=[],i=new Set;for(const r of e)for(const e of this.trackingState.getObjectsOnCamera(r))i.has(e.globalId)||(i.add(e.globalId),(0===t.length||t.includes(e.className))&&n.push(e));return n}async getSettings(){const e=await this.storageSettings.getSettings(),t=this.getObjectsInZone();return e.push({key:"currentStatus",title:"Current Status",type:"string",readonly:!0,value:this.occupied?`Occupied: ${t.length} object${1!==t.length?"s":""}`:"Empty",group:"Status"}),t.length>0&&e.push({key:"objectsList",title:"Objects in Zone",type:"string",readonly:!0,value:t.map(e=>`${e.className}${e.label?` (${e.label})`:""}`).join(", "),group:"Status"}),e}async putSetting(e,t){await this.storageSettings.putSetting(e,t),this.config.type=this.storageSettings.values.zoneType||"entry",this.config.cameras=this.getCameraIds(),this.config.dwellThreshold=1e3*(this.storageSettings.values.dwellThreshold||60),this.saveConfig(),this.evaluateZone()}}t.TrackingZone=o},2860(e){"use strict";e.exports={version:"5.14.1"}},2861(e,t,n){var i=n(181),r=i.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return r(e,t,n)}r.from&&r.alloc&&r.allocUnsafe&&r.allocUnsafeSlow?e.exports=i:(o(i,t),t.Buffer=s),s.prototype=Object.create(r.prototype),o(r,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return r(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var i=r(e);return void 0!==t?"string"==typeof n?i.fill(t,n):i.fill(t):i.fill(0),i},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return i.SlowBuffer(e)}},2881(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_DISCOVERY_STATUS=t.RATE_LIMIT_WARNING_THRESHOLD=t.DEFAULT_DISCOVERY_CONFIG=void 0,t.DEFAULT_DISCOVERY_CONFIG={discoveryIntervalHours:0,autoAcceptThreshold:.85,minLandmarkConfidence:.6,minConnectionConfidence:.5},t.RATE_LIMIT_WARNING_THRESHOLD=1,t.DEFAULT_DISCOVERY_STATUS={isRunning:!1,isScanning:!1,lastScanTime:null,nextScanTime:null,camerasAnalyzed:0,pendingSuggestions:0}},2971(e,t,n){"use strict";const i=n(3106),r=n(3338),o=n(4759),{kStatusCode:s}=n(2614),a=Buffer[Symbol.species],c=Buffer.from([0,0,255,255]),l=Symbol("permessage-deflate"),d=Symbol("total-length"),u=Symbol("callback"),p=Symbol("buffers"),h=Symbol("error");let f;function g(e){this[p].push(e),this[d]+=e.length}function m(e){this[d]+=e.length,this[l]._maxPayload<1||this[d]<=this[l]._maxPayload?this[p].push(e):(this[h]=new RangeError("Max payload size exceeded"),this[h].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[h][s]=1009,this.removeListener("data",m),this.reset())}function y(e){this[l]._inflate=null,this[h]?this[u](this[h]):(e[s]=1007,this[u](e))}e.exports=class{constructor(e,t,n){if(this._maxPayload=0|n,this._options=e||{},this._threshold=void 0!==this._options.threshold?this._options.threshold:1024,this._isServer=!!t,this._deflate=null,this._inflate=null,this.params=null,!f){const e=void 0!==this._options.concurrencyLimit?this._options.concurrencyLimit:10;f=new o(e)}}static get extensionName(){return"permessage-deflate"}offer(){const e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:null==this._options.clientMaxWindowBits&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){const e=this._deflate[u];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){const t=this._options,n=e.find(e=>!(!1===t.serverNoContextTakeover&&e.server_no_context_takeover||e.server_max_window_bits&&(!1===t.serverMaxWindowBits||"number"==typeof t.serverMaxWindowBits&&t.serverMaxWindowBits>e.server_max_window_bits)||"number"==typeof t.clientMaxWindowBits&&!e.client_max_window_bits));if(!n)throw new Error("None of the extension offers can be accepted");return t.serverNoContextTakeover&&(n.server_no_context_takeover=!0),t.clientNoContextTakeover&&(n.client_no_context_takeover=!0),"number"==typeof t.serverMaxWindowBits&&(n.server_max_window_bits=t.serverMaxWindowBits),"number"==typeof t.clientMaxWindowBits?n.client_max_window_bits=t.clientMaxWindowBits:!0!==n.client_max_window_bits&&!1!==t.clientMaxWindowBits||delete n.client_max_window_bits,n}acceptAsClient(e){const t=e[0];if(!1===this._options.clientNoContextTakeover&&t.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(t.client_max_window_bits){if(!1===this._options.clientMaxWindowBits||"number"==typeof this._options.clientMaxWindowBits&&t.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"')}else"number"==typeof this._options.clientMaxWindowBits&&(t.client_max_window_bits=this._options.clientMaxWindowBits);return t}normalizeParams(e){return e.forEach(e=>{Object.keys(e).forEach(t=>{let n=e[t];if(n.length>1)throw new Error(`Parameter "${t}" must have only a single value`);if(n=n[0],"client_max_window_bits"===t){if(!0!==n){const e=+n;if(!Number.isInteger(e)||e<8||e>15)throw new TypeError(`Invalid value for parameter "${t}": ${n}`);n=e}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${t}": ${n}`)}else if("server_max_window_bits"===t){const e=+n;if(!Number.isInteger(e)||e<8||e>15)throw new TypeError(`Invalid value for parameter "${t}": ${n}`);n=e}else{if("client_no_context_takeover"!==t&&"server_no_context_takeover"!==t)throw new Error(`Unknown parameter "${t}"`);if(!0!==n)throw new TypeError(`Invalid value for parameter "${t}": ${n}`)}e[t]=n})}),e}decompress(e,t,n){f.add(i=>{this._decompress(e,t,(e,t)=>{i(),n(e,t)})})}compress(e,t,n){f.add(i=>{this._compress(e,t,(e,t)=>{i(),n(e,t)})})}_decompress(e,t,n){const o=this._isServer?"client":"server";if(!this._inflate){const e=`${o}_max_window_bits`,t="number"!=typeof this.params[e]?i.Z_DEFAULT_WINDOWBITS:this.params[e];this._inflate=i.createInflateRaw({...this._options.zlibInflateOptions,windowBits:t}),this._inflate[l]=this,this._inflate[d]=0,this._inflate[p]=[],this._inflate.on("error",y),this._inflate.on("data",m)}this._inflate[u]=n,this._inflate.write(e),t&&this._inflate.write(c),this._inflate.flush(()=>{const e=this._inflate[h];if(e)return this._inflate.close(),this._inflate=null,void n(e);const i=r.concat(this._inflate[p],this._inflate[d]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[d]=0,this._inflate[p]=[],t&&this.params[`${o}_no_context_takeover`]&&this._inflate.reset()),n(null,i)})}_compress(e,t,n){const o=this._isServer?"server":"client";if(!this._deflate){const e=`${o}_max_window_bits`,t="number"!=typeof this.params[e]?i.Z_DEFAULT_WINDOWBITS:this.params[e];this._deflate=i.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:t}),this._deflate[d]=0,this._deflate[p]=[],this._deflate.on("data",g)}this._deflate[u]=n,this._deflate.write(e),this._deflate.flush(i.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let e=r.concat(this._deflate[p],this._deflate[d]);t&&(e=new a(e.buffer,e.byteOffset,e.length-4)),this._deflate[u]=null,this._deflate[d]=0,this._deflate[p]=[],t&&this.params[`${o}_no_context_takeover`]&&this._deflate.reset(),n(null,e)})}}},3079(e,t,n){const i=n(4829),{EventEmitter:r}=n(4434),o=n(576),s=n(5399),a=n(5753)("mqtt-packet:parser");class c extends r{constructor(){super(),this.parser=this.constructor.parser}static parser(e){return this instanceof c?(this.settings=e||{},this._states=["_parseHeader","_parseLength","_parsePayload","_newPacket"],this._resetState(),this):(new c).parser(e)}_resetState(){a("_resetState: resetting packet, error, _list, and _stateCounter"),this.packet=new o,this.error=null,this._list=i(),this._stateCounter=0}parse(e){for(this.error&&this._resetState(),this._list.append(e),a("parse: current state: %s",this._states[this._stateCounter]);(-1!==this.packet.length||this._list.length>0)&&this[this._states[this._stateCounter]]()&&!this.error;)this._stateCounter++,a("parse: state complete. _stateCounter is now: %d",this._stateCounter),a("parse: packet.length: %d, buffer list length: %d",this.packet.length,this._list.length),this._stateCounter>=this._states.length&&(this._stateCounter=0);return a("parse: exited while loop. packet: %d, buffer list length: %d",this.packet.length,this._list.length),this._list.length}_parseHeader(){const e=this._list.readUInt8(0),t=e>>s.CMD_SHIFT;this.packet.cmd=s.types[t];const n=15&e,i=s.requiredHeaderFlags[t];return null!=i&&n!==i?this._emitError(new Error(s.requiredHeaderFlagsErrors[t])):(this.packet.retain=0!==(e&s.RETAIN_MASK),this.packet.qos=e>>s.QOS_SHIFT&s.QOS_MASK,this.packet.qos>2?this._emitError(new Error("Packet must not have both QoS bits set to 1")):(this.packet.dup=0!==(e&s.DUP_MASK),a("_parseHeader: packet: %o",this.packet),this._list.consume(1),!0))}_parseLength(){const e=this._parseVarByteNum(!0);return e&&(this.packet.length=e.value,this._list.consume(e.bytes)),a("_parseLength %d",e.value),!!e}_parsePayload(){a("_parsePayload: payload %O",this._list);let e=!1;if(0===this.packet.length||this._list.length>=this.packet.length){switch(this._pos=0,this.packet.cmd){case"connect":this._parseConnect();break;case"connack":this._parseConnack();break;case"publish":this._parsePublish();break;case"puback":case"pubrec":case"pubrel":case"pubcomp":this._parseConfirmation();break;case"subscribe":this._parseSubscribe();break;case"suback":this._parseSuback();break;case"unsubscribe":this._parseUnsubscribe();break;case"unsuback":this._parseUnsuback();break;case"pingreq":case"pingresp":break;case"disconnect":this._parseDisconnect();break;case"auth":this._parseAuth();break;default:this._emitError(new Error("Not supported"))}e=!0}return a("_parsePayload complete result: %s",e),e}_parseConnect(){let e,t,n,i;a("_parseConnect");const r={},o=this.packet,c=this._parseString();if(null===c)return this._emitError(new Error("Cannot parse protocolId"));if("MQTT"!==c&&"MQIsdp"!==c)return this._emitError(new Error("Invalid protocolId"));if(o.protocolId=c,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(o.protocolVersion=this._list.readUInt8(this._pos),o.protocolVersion>=128&&(o.bridgeMode=!0,o.protocolVersion=o.protocolVersion-128),3!==o.protocolVersion&&4!==o.protocolVersion&&5!==o.protocolVersion)return this._emitError(new Error("Invalid protocol version"));if(this._pos++,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(1&this._list.readUInt8(this._pos))return this._emitError(new Error("Connect flag bit 0 must be 0, but got 1"));r.username=this._list.readUInt8(this._pos)&s.USERNAME_MASK,r.password=this._list.readUInt8(this._pos)&s.PASSWORD_MASK,r.will=this._list.readUInt8(this._pos)&s.WILL_FLAG_MASK;const l=!!(this._list.readUInt8(this._pos)&s.WILL_RETAIN_MASK),d=(this._list.readUInt8(this._pos)&s.WILL_QOS_MASK)>>s.WILL_QOS_SHIFT;if(r.will)o.will={},o.will.retain=l,o.will.qos=d;else{if(l)return this._emitError(new Error("Will Retain Flag must be set to zero when Will Flag is set to 0"));if(d)return this._emitError(new Error("Will QoS must be set to zero when Will Flag is set to 0"))}if(o.clean=0!==(this._list.readUInt8(this._pos)&s.CLEAN_SESSION_MASK),this._pos++,o.keepalive=this._parseNum(),-1===o.keepalive)return this._emitError(new Error("Packet too short"));if(5===o.protocolVersion){const e=this._parseProperties();Object.getOwnPropertyNames(e).length&&(o.properties=e)}const u=this._parseString();if(null===u)return this._emitError(new Error("Packet too short"));if(o.clientId=u,a("_parseConnect: packet.clientId: %s",o.clientId),r.will){if(5===o.protocolVersion){const e=this._parseProperties();Object.getOwnPropertyNames(e).length&&(o.will.properties=e)}if(e=this._parseString(),null===e)return this._emitError(new Error("Cannot parse will topic"));if(o.will.topic=e,a("_parseConnect: packet.will.topic: %s",o.will.topic),t=this._parseBuffer(),null===t)return this._emitError(new Error("Cannot parse will payload"));o.will.payload=t,a("_parseConnect: packet.will.paylaod: %s",o.will.payload)}if(r.username){if(i=this._parseString(),null===i)return this._emitError(new Error("Cannot parse username"));o.username=i,a("_parseConnect: packet.username: %s",o.username)}if(r.password){if(n=this._parseBuffer(),null===n)return this._emitError(new Error("Cannot parse password"));o.password=n}return this.settings=o,a("_parseConnect: complete"),o}_parseConnack(){a("_parseConnack");const e=this.packet;if(this._list.length<1)return null;const t=this._list.readUInt8(this._pos++);if(t>1)return this._emitError(new Error("Invalid connack flags, bits 7-1 must be set to 0"));if(e.sessionPresent=!!(t&s.SESSIONPRESENT_MASK),5===this.settings.protocolVersion)this._list.length>=2?e.reasonCode=this._list.readUInt8(this._pos++):e.reasonCode=0;else{if(this._list.length<2)return null;e.returnCode=this._list.readUInt8(this._pos++)}if(-1===e.returnCode||-1===e.reasonCode)return this._emitError(new Error("Cannot parse return code"));if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}a("_parseConnack: complete")}_parsePublish(){a("_parsePublish");const e=this.packet;if(e.topic=this._parseString(),null===e.topic)return this._emitError(new Error("Cannot parse topic"));if(!(e.qos>0)||this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}e.payload=this._list.slice(this._pos,e.length),a("_parsePublish: payload from buffer list: %o",e.payload)}}_parseSubscribe(){a("_parseSubscribe");const e=this.packet;let t,n,i,r,o,c,l;if(e.subscriptions=[],this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}if(e.length<=0)return this._emitError(new Error("Malformed subscribe, no payload specified"));for(;this._pos<e.length;){if(t=this._parseString(),null===t)return this._emitError(new Error("Cannot parse topic"));if(this._pos>=e.length)return this._emitError(new Error("Malformed Subscribe Payload"));if(n=this._parseByte(),5===this.settings.protocolVersion){if(192&n)return this._emitError(new Error("Invalid subscribe topic flag bits, bits 7-6 must be 0"))}else if(252&n)return this._emitError(new Error("Invalid subscribe topic flag bits, bits 7-2 must be 0"));if(i=n&s.SUBSCRIBE_OPTIONS_QOS_MASK,i>2)return this._emitError(new Error("Invalid subscribe QoS, must be <= 2"));if(c=0!==(n>>s.SUBSCRIBE_OPTIONS_NL_SHIFT&s.SUBSCRIBE_OPTIONS_NL_MASK),o=0!==(n>>s.SUBSCRIBE_OPTIONS_RAP_SHIFT&s.SUBSCRIBE_OPTIONS_RAP_MASK),r=n>>s.SUBSCRIBE_OPTIONS_RH_SHIFT&s.SUBSCRIBE_OPTIONS_RH_MASK,r>2)return this._emitError(new Error("Invalid retain handling, must be <= 2"));l={topic:t,qos:i},5===this.settings.protocolVersion?(l.nl=c,l.rap=o,l.rh=r):this.settings.bridgeMode&&(l.rh=0,l.rap=!0,l.nl=!0),a("_parseSubscribe: push subscription `%s` to subscription",l),e.subscriptions.push(l)}}}_parseSuback(){a("_parseSuback");const e=this.packet;if(this.packet.granted=[],this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}if(e.length<=0)return this._emitError(new Error("Malformed suback, no payload specified"));for(;this._pos<this.packet.length;){const e=this._list.readUInt8(this._pos++);if(5===this.settings.protocolVersion){if(!s.MQTT5_SUBACK_CODES[e])return this._emitError(new Error("Invalid suback code"))}else if(e>2&&128!==e)return this._emitError(new Error("Invalid suback QoS, must be 0, 1, 2 or 128"));this.packet.granted.push(e)}}}_parseUnsubscribe(){a("_parseUnsubscribe");const e=this.packet;if(e.unsubscriptions=[],this._parseMessageId()){if(5===this.settings.protocolVersion){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}if(e.length<=0)return this._emitError(new Error("Malformed unsubscribe, no payload specified"));for(;this._pos<e.length;){const t=this._parseString();if(null===t)return this._emitError(new Error("Cannot parse topic"));a("_parseUnsubscribe: push topic `%s` to unsubscriptions",t),e.unsubscriptions.push(t)}}}_parseUnsuback(){a("_parseUnsuback");const e=this.packet;if(!this._parseMessageId())return this._emitError(new Error("Cannot parse messageId"));if((3===this.settings.protocolVersion||4===this.settings.protocolVersion)&&2!==e.length)return this._emitError(new Error("Malformed unsuback, payload length must be 2"));if(e.length<=0)return this._emitError(new Error("Malformed unsuback, no payload specified"));if(5===this.settings.protocolVersion){const t=this._parseProperties();for(Object.getOwnPropertyNames(t).length&&(e.properties=t),e.granted=[];this._pos<this.packet.length;){const e=this._list.readUInt8(this._pos++);if(!s.MQTT5_UNSUBACK_CODES[e])return this._emitError(new Error("Invalid unsuback code"));this.packet.granted.push(e)}}}_parseConfirmation(){a("_parseConfirmation: packet.cmd: `%s`",this.packet.cmd);const e=this.packet;if(this._parseMessageId(),5===this.settings.protocolVersion){if(e.length>2){switch(e.reasonCode=this._parseByte(),this.packet.cmd){case"puback":case"pubrec":if(!s.MQTT5_PUBACK_PUBREC_CODES[e.reasonCode])return this._emitError(new Error("Invalid "+this.packet.cmd+" reason code"));break;case"pubrel":case"pubcomp":if(!s.MQTT5_PUBREL_PUBCOMP_CODES[e.reasonCode])return this._emitError(new Error("Invalid "+this.packet.cmd+" reason code"))}a("_parseConfirmation: packet.reasonCode `%d`",e.reasonCode)}else e.reasonCode=0;if(e.length>3){const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}}return!0}_parseDisconnect(){const e=this.packet;if(a("_parseDisconnect"),5===this.settings.protocolVersion){this._list.length>0?(e.reasonCode=this._parseByte(),s.MQTT5_DISCONNECT_CODES[e.reasonCode]||this._emitError(new Error("Invalid disconnect reason code"))):e.reasonCode=0;const t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}return a("_parseDisconnect result: true"),!0}_parseAuth(){a("_parseAuth");const e=this.packet;if(5!==this.settings.protocolVersion)return this._emitError(new Error("Not supported auth packet for this version MQTT"));if(e.reasonCode=this._parseByte(),!s.MQTT5_AUTH_CODES[e.reasonCode])return this._emitError(new Error("Invalid auth reason code"));const t=this._parseProperties();return Object.getOwnPropertyNames(t).length&&(e.properties=t),a("_parseAuth: result: true"),!0}_parseMessageId(){const e=this.packet;return e.messageId=this._parseNum(),null===e.messageId?(this._emitError(new Error("Cannot parse messageId")),!1):(a("_parseMessageId: packet.messageId %d",e.messageId),!0)}_parseString(e){const t=this._parseNum(),n=t+this._pos;if(-1===t||n>this._list.length||n>this.packet.length)return null;const i=this._list.toString("utf8",this._pos,n);return this._pos+=t,a("_parseString: result: %s",i),i}_parseStringPair(){return a("_parseStringPair"),{name:this._parseString(),value:this._parseString()}}_parseBuffer(){const e=this._parseNum(),t=e+this._pos;if(-1===e||t>this._list.length||t>this.packet.length)return null;const n=this._list.slice(this._pos,t);return this._pos+=e,a("_parseBuffer: result: %o",n),n}_parseNum(){if(this._list.length-this._pos<2)return-1;const e=this._list.readUInt16BE(this._pos);return this._pos+=2,a("_parseNum: result: %s",e),e}_parse4ByteNum(){if(this._list.length-this._pos<4)return-1;const e=this._list.readUInt32BE(this._pos);return this._pos+=4,a("_parse4ByteNum: result: %s",e),e}_parseVarByteNum(e){a("_parseVarByteNum");let t,n=0,i=1,r=0,o=!1;const c=this._pos?this._pos:0;for(;n<4&&c+n<this._list.length;){if(t=this._list.readUInt8(c+n++),r+=i*(t&s.VARBYTEINT_MASK),i*=128,0===(t&s.VARBYTEINT_FIN_MASK)){o=!0;break}if(this._list.length<=n)break}return!o&&4===n&&this._list.length>=n&&this._emitError(new Error("Invalid variable byte integer")),c&&(this._pos+=n),o=!!o&&(e?{bytes:n,value:r}:r),a("_parseVarByteNum: result: %o",o),o}_parseByte(){let e;return this._pos<this._list.length&&(e=this._list.readUInt8(this._pos),this._pos++),a("_parseByte: result: %o",e),e}_parseByType(e){switch(a("_parseByType: type: %s",e),e){case"byte":return 0!==this._parseByte();case"int8":return this._parseByte();case"int16":return this._parseNum();case"int32":return this._parse4ByteNum();case"var":return this._parseVarByteNum();case"string":return this._parseString();case"pair":return this._parseStringPair();case"binary":return this._parseBuffer()}}_parseProperties(){a("_parseProperties");const e=this._parseVarByteNum(),t=this._pos+e,n={};for(;this._pos<t;){const e=this._parseByte();if(!e)return this._emitError(new Error("Cannot parse property code type")),!1;const t=s.propertiesCodes[e];if(!t)return this._emitError(new Error("Unknown property")),!1;if("userProperties"===t){n[t]||(n[t]=Object.create(null));const e=this._parseByType(s.propertiesTypes[t]);if(n[t][e.name])if(Array.isArray(n[t][e.name]))n[t][e.name].push(e.value);else{const i=n[t][e.name];n[t][e.name]=[i],n[t][e.name].push(e.value)}else n[t][e.name]=e.value;continue}n[t]?(Array.isArray(n[t])||(n[t]=[n[t]]),n[t].push(this._parseByType(s.propertiesTypes[t]))):n[t]=this._parseByType(s.propertiesTypes[t])}return n}_newPacket(){return a("_newPacket"),this.packet&&(this._list.consume(this.packet.length),a("_newPacket: parser emit packet: packet.cmd: %s, packet.payload: %s, packet.length: %d",this.packet.cmd,this.packet.payload,this.packet.length),this.emit("packet",this.packet)),a("_newPacket: new packet"),this.packet=new o,this._pos=0,!0}_emitError(e){a("_emitError",e),this.error=e,this.emit("error",e)}}e.exports=c},3095(e,t,n){"use strict";const{ArrayPrototypePop:i,Promise:r}=n(4134),{isIterable:o,isNodeStream:s,isWebStream:a}=n(6115),{pipelineImpl:c}=n(7758),{finished:l}=n(6238);n(5506),e.exports={finished:l,pipeline:function(...e){return new r((t,n)=>{let r,l;const d=e[e.length-1];if(d&&"object"==typeof d&&!s(d)&&!o(d)&&!a(d)){const t=i(e);r=t.signal,l=t.end}c(e,(e,i)=>{e?n(e):t(i)},{signal:r,end:l})})}}},3106(e){"use strict";e.exports=require("zlib")},3132(e,t,n){const i=n(5399),{Buffer:r}=n(181),o=r.allocUnsafe(0),s=r.from([0]),a=n(6172),c=n(3225).nextTick,l=n(5753)("mqtt-packet:writeToStream"),d=a.cache,u=a.generateNumber,p=a.generateCache,h=a.genBufVariableByteInt,f=a.generate4ByteBuffer;let g=k,m=!0;function y(e,t,n){switch(l("generate called"),t.cork&&(t.cork(),c(b,t)),m&&(m=!1,p()),l("generate: packet.cmd: %s",e.cmd),e.cmd){case"connect":return function(e,t){const n=e||{},o=n.protocolId||"MQTT";let s=n.protocolVersion||4;const a=n.will;let c=n.clean;const l=n.keepalive||0,d=n.clientId||"",u=n.username,p=n.password,h=n.properties;void 0===c&&(c=!0);let f,m,y=0;if(!o||"string"!=typeof o&&!r.isBuffer(o))return t.destroy(new Error("Invalid protocolId")),!1;y+=o.length+2;if(3!==s&&4!==s&&5!==s)return t.destroy(new Error("Invalid protocol version")),!1;y+=1;if(("string"==typeof d||r.isBuffer(d))&&(d||s>=4)&&(d||c))y+=r.byteLength(d)+2;else{if(s<4)return t.destroy(new Error("clientId must be supplied before 3.1.1")),!1;if(1*c==0)return t.destroy(new Error("clientId must be given if cleanSession set to 0")),!1}if("number"!=typeof l||l<0||l>65535||l%1!=0)return t.destroy(new Error("Invalid keepalive")),!1;y+=2;if(y+=1,5===s){if(f=C(t,h),!f)return!1;y+=f.length}if(a){if("object"!=typeof a)return t.destroy(new Error("Invalid will")),!1;if(!a.topic||"string"!=typeof a.topic)return t.destroy(new Error("Invalid will topic")),!1;if(y+=r.byteLength(a.topic)+2,y+=2,a.payload){if(!(a.payload.length>=0))return t.destroy(new Error("Invalid will payload")),!1;"string"==typeof a.payload?y+=r.byteLength(a.payload):y+=a.payload.length}if(m={},5===s){if(m=C(t,a.properties),!m)return!1;y+=m.length}}let b=!1;if(null!=u){if(!A(u))return t.destroy(new Error("Invalid username")),!1;b=!0,y+=r.byteLength(u)+2}if(null!=p){if(!b)return t.destroy(new Error("Username is required to use password")),!1;if(!A(p))return t.destroy(new Error("Invalid password")),!1;y+=P(p)+2}t.write(i.CONNECT_HEADER),S(t,y),x(t,o),n.bridgeMode&&(s+=128);t.write(131===s?i.VERSION131:132===s?i.VERSION132:4===s?i.VERSION4:5===s?i.VERSION5:i.VERSION3);let v=0;v|=null!=u?i.USERNAME_MASK:0,v|=null!=p?i.PASSWORD_MASK:0,v|=a&&a.retain?i.WILL_RETAIN_MASK:0,v|=a&&a.qos?a.qos<<i.WILL_QOS_SHIFT:0,v|=a?i.WILL_FLAG_MASK:0,v|=c?i.CLEAN_SESSION_MASK:0,t.write(r.from([v])),g(t,l),5===s&&f.write();x(t,d),a&&(5===s&&m.write(),_(t,a.topic),x(t,a.payload));null!=u&&x(t,u);null!=p&&x(t,p);return!0}(e,t);case"connack":return function(e,t,n){const o=n?n.protocolVersion:4,a=e||{},c=5===o?a.reasonCode:a.returnCode,l=a.properties;let d=2;if("number"!=typeof c)return t.destroy(new Error("Invalid return code")),!1;let u=null;if(5===o){if(u=C(t,l),!u)return!1;d+=u.length}t.write(i.CONNACK_HEADER),S(t,d),t.write(a.sessionPresent?i.SESSIONPRESENT_HEADER:s),t.write(r.from([c])),null!=u&&u.write();return!0}(e,t,n);case"publish":return function(e,t,n){l("publish: packet: %o",e);const s=n?n.protocolVersion:4,a=e||{},c=a.qos||0,d=a.retain?i.RETAIN_MASK:0,u=a.topic,p=a.payload||o,h=a.messageId,f=a.properties;let m=0;if("string"==typeof u)m+=r.byteLength(u)+2;else{if(!r.isBuffer(u))return t.destroy(new Error("Invalid topic")),!1;m+=u.length+2}r.isBuffer(p)?m+=p.length:m+=r.byteLength(p);if(c&&"number"!=typeof h)return t.destroy(new Error("Invalid messageId")),!1;c&&(m+=2);let y=null;if(5===s){if(y=C(t,f),!y)return!1;m+=y.length}t.write(i.PUBLISH_HEADER[c][a.dup?1:0][d?1:0]),S(t,m),g(t,P(u)),t.write(u),c>0&&g(t,h);null!=y&&y.write();return l("publish: payload: %o",p),t.write(p)}(e,t,n);case"puback":case"pubrec":case"pubrel":case"pubcomp":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.cmd||"puback",c=s.messageId,l=s.dup&&"pubrel"===a?i.DUP_MASK:0;let d=0;const u=s.reasonCode,p=s.properties;let h=5===o?3:2;"pubrel"===a&&(d=1);if("number"!=typeof c)return t.destroy(new Error("Invalid messageId")),!1;let f=null;if(5===o&&"object"==typeof p){if(f=E(t,p,n,h),!f)return!1;h+=f.length}t.write(i.ACKS[a][d][l][0]),3===h&&(h+=0!==u?1:-1);S(t,h),g(t,c),5===o&&2!==h&&t.write(r.from([u]));null!==f?f.write():4===h&&t.write(r.from([0]));return!0}(e,t,n);case"subscribe":return function(e,t,n){l("subscribe: packet: ");const o=n?n.protocolVersion:4,s=e||{},a=s.dup?i.DUP_MASK:0,c=s.messageId,d=s.subscriptions,u=s.properties;let p=0;if("number"!=typeof c)return t.destroy(new Error("Invalid messageId")),!1;p+=2;let h=null;if(5===o){if(h=C(t,u),!h)return!1;p+=h.length}if("object"!=typeof d||!d.length)return t.destroy(new Error("Invalid subscriptions")),!1;for(let e=0;e<d.length;e+=1){const n=d[e].topic,i=d[e].qos;if("string"!=typeof n)return t.destroy(new Error("Invalid subscriptions - invalid topic")),!1;if("number"!=typeof i)return t.destroy(new Error("Invalid subscriptions - invalid qos")),!1;if(5===o){if("boolean"!=typeof(d[e].nl||!1))return t.destroy(new Error("Invalid subscriptions - invalid No Local")),!1;if("boolean"!=typeof(d[e].rap||!1))return t.destroy(new Error("Invalid subscriptions - invalid Retain as Published")),!1;const n=d[e].rh||0;if("number"!=typeof n||n>2)return t.destroy(new Error("Invalid subscriptions - invalid Retain Handling")),!1}p+=r.byteLength(n)+2+1}l("subscribe: writing to stream: %o",i.SUBSCRIBE_HEADER),t.write(i.SUBSCRIBE_HEADER[1][a?1:0][0]),S(t,p),g(t,c),null!==h&&h.write();let f=!0;for(const e of d){const n=e.topic,s=e.qos,a=+e.nl,c=+e.rap,l=e.rh;let d;_(t,n),d=i.SUBSCRIBE_OPTIONS_QOS[s],5===o&&(d|=a?i.SUBSCRIBE_OPTIONS_NL:0,d|=c?i.SUBSCRIBE_OPTIONS_RAP:0,d|=l?i.SUBSCRIBE_OPTIONS_RH[l]:0),f=t.write(r.from([d]))}return f}(e,t,n);case"suback":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.messageId,c=s.granted,l=s.properties;let d=0;if("number"!=typeof a)return t.destroy(new Error("Invalid messageId")),!1;d+=2;if("object"!=typeof c||!c.length)return t.destroy(new Error("Invalid qos vector")),!1;for(let e=0;e<c.length;e+=1){if("number"!=typeof c[e])return t.destroy(new Error("Invalid qos vector")),!1;d+=1}let u=null;if(5===o){if(u=E(t,l,n,d),!u)return!1;d+=u.length}t.write(i.SUBACK_HEADER),S(t,d),g(t,a),null!==u&&u.write();return t.write(r.from(c))}(e,t,n);case"unsubscribe":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.messageId,c=s.dup?i.DUP_MASK:0,l=s.unsubscriptions,d=s.properties;let u=0;if("number"!=typeof a)return t.destroy(new Error("Invalid messageId")),!1;u+=2;if("object"!=typeof l||!l.length)return t.destroy(new Error("Invalid unsubscriptions")),!1;for(let e=0;e<l.length;e+=1){if("string"!=typeof l[e])return t.destroy(new Error("Invalid unsubscriptions")),!1;u+=r.byteLength(l[e])+2}let p=null;if(5===o){if(p=C(t,d),!p)return!1;u+=p.length}t.write(i.UNSUBSCRIBE_HEADER[1][c?1:0][0]),S(t,u),g(t,a),null!==p&&p.write();let h=!0;for(let e=0;e<l.length;e++)h=_(t,l[e]);return h}(e,t,n);case"unsuback":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.messageId,c=s.dup?i.DUP_MASK:0,l=s.granted,d=s.properties,u=s.cmd,p=0;let h=2;if("number"!=typeof a)return t.destroy(new Error("Invalid messageId")),!1;if(5===o){if("object"!=typeof l||!l.length)return t.destroy(new Error("Invalid qos vector")),!1;for(let e=0;e<l.length;e+=1){if("number"!=typeof l[e])return t.destroy(new Error("Invalid qos vector")),!1;h+=1}}let f=null;if(5===o){if(f=E(t,d,n,h),!f)return!1;h+=f.length}t.write(i.ACKS[u][p][c][0]),S(t,h),g(t,a),null!==f&&f.write();5===o&&t.write(r.from(l));return!0}(e,t,n);case"pingreq":case"pingresp":return function(e,t){return t.write(i.EMPTY[e.cmd])}(e,t);case"disconnect":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.reasonCode,c=s.properties;let l=5===o?1:0,d=null;if(5===o){if(d=E(t,c,n,l),!d)return!1;l+=d.length}t.write(r.from([i.codes.disconnect<<4])),S(t,l),5===o&&t.write(r.from([a]));null!==d&&d.write();return!0}(e,t,n);case"auth":return function(e,t,n){const o=n?n.protocolVersion:4,s=e||{},a=s.reasonCode,c=s.properties;let l=5===o?1:0;5!==o&&t.destroy(new Error("Invalid mqtt version for auth packet"));const d=E(t,c,n,l);if(!d)return!1;l+=d.length,t.write(r.from([i.codes.auth<<4])),S(t,l),t.write(r.from([a])),null!==d&&d.write();return!0}(e,t,n);default:return t.destroy(new Error("Unknown command")),!1}}function b(e){e.uncork()}Object.defineProperty(y,"cacheNumbers",{get:()=>g===k,set(e){e?(d&&0!==Object.keys(d).length||(m=!0),g=k):(m=!1,g=I)}});const v={};function S(e,t){if(t>i.VARBYTEINT_MAX)return e.destroy(new Error(`Invalid variable byte integer: ${t}`)),!1;let n=v[t];return n||(n=h(t),t<16384&&(v[t]=n)),l("writeVarByteInt: writing to stream: %o",n),e.write(n)}function _(e,t){const n=r.byteLength(t);return g(e,n),l("writeString: %s",t),e.write(t,"utf8")}function w(e,t,n){_(e,t),_(e,n)}function k(e,t){return l("writeNumberCached: number: %d",t),l("writeNumberCached: %o",d[t]),e.write(d[t])}function I(e,t){const n=u(t);return l("writeNumberGenerated: %o",n),e.write(n)}function x(e,t){"string"==typeof t?_(e,t):t?(g(e,t.length),e.write(t)):g(e,0)}function C(e,t){if("object"!=typeof t||null!=t.length)return{length:1,write(){O(e,{},0)}};let n=0;function o(t,n){let o=0;switch(i.propertiesTypes[t]){case"byte":if("boolean"!=typeof n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=2;break;case"int8":if("number"!=typeof n||n<0||n>255)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=2;break;case"binary":if(n&&null===n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=1+r.byteLength(n)+2;break;case"int16":if("number"!=typeof n||n<0||n>65535)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=3;break;case"int32":if("number"!=typeof n||n<0||n>4294967295)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=5;break;case"var":if("number"!=typeof n||n<0||n>268435455)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=1+r.byteLength(h(n));break;case"string":if("string"!=typeof n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=3+r.byteLength(n.toString());break;case"pair":if("object"!=typeof n)return e.destroy(new Error(`Invalid ${t}: ${n}`)),!1;o+=Object.getOwnPropertyNames(n).reduce((e,t)=>{const i=n[t];return Array.isArray(i)?e+=i.reduce((e,n)=>e+=3+r.byteLength(t.toString())+2+r.byteLength(n.toString()),0):e+=3+r.byteLength(t.toString())+2+r.byteLength(n[t].toString()),e},0);break;default:return e.destroy(new Error(`Invalid property ${t}: ${n}`)),!1}return o}if(t)for(const e in t){let i=0,r=0;const s=t[e];if(void 0!==s){if(Array.isArray(s))for(let t=0;t<s.length;t++){if(r=o(e,s[t]),!r)return!1;i+=r}else{if(r=o(e,s),!r)return!1;i=r}if(!i)return!1;n+=i}}return{length:r.byteLength(h(n))+n,write(){O(e,t,n)}}}function E(e,t,n,i){const r=["reasonString","userProperties"],o=n&&n.properties&&n.properties.maximumPacketSize?n.properties.maximumPacketSize:0;let s=C(e,t);if(o)for(;i+s.length>o;){const n=r.shift();if(!n||!t[n])return!1;delete t[n],s=C(e,t)}return s}function T(e,t,n){switch(i.propertiesTypes[t]){case"byte":e.write(r.from([i.properties[t]])),e.write(r.from([+n]));break;case"int8":e.write(r.from([i.properties[t]])),e.write(r.from([n]));break;case"binary":e.write(r.from([i.properties[t]])),x(e,n);break;case"int16":e.write(r.from([i.properties[t]])),g(e,n);break;case"int32":e.write(r.from([i.properties[t]])),function(e,t){const n=f(t);l("write4ByteNumber: %o",n),e.write(n)}(e,n);break;case"var":e.write(r.from([i.properties[t]])),S(e,n);break;case"string":e.write(r.from([i.properties[t]])),_(e,n);break;case"pair":Object.getOwnPropertyNames(n).forEach(o=>{const s=n[o];Array.isArray(s)?s.forEach(n=>{e.write(r.from([i.properties[t]])),w(e,o.toString(),n.toString())}):(e.write(r.from([i.properties[t]])),w(e,o.toString(),s.toString()))});break;default:return e.destroy(new Error(`Invalid property ${t} value: ${n}`)),!1}}function O(e,t,n){S(e,n);for(const n in t)if(Object.prototype.hasOwnProperty.call(t,n)&&null!=t[n]){const i=t[n];if(Array.isArray(i))for(let t=0;t<i.length;t++)T(e,n,i[t]);else T(e,n,i)}}function P(e){return e?e instanceof r?e.length:r.byteLength(e):0}function A(e){return"string"==typeof e||e instanceof r}e.exports=y},3141(e,t,n){"use strict";var i=n(2861).Buffer,r=i.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function o(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(i.isEncoding===r||!r(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=l,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=d,this.end=u,t=3;break;default:return this.write=p,void(this.end=h)}this.lastNeed=0,this.lastTotal=0,this.lastChar=i.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,n=function(e,t){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var i=n.charCodeAt(n.length-1);if(i>=55296&&i<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function l(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function d(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function u(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function p(e){return e.toString(this.encoding)}function h(e){return e&&e.length?this.write(e):""}t.StringDecoder=o,o.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||""},o.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},o.prototype.text=function(e,t){var n=function(e,t,n){var i=t.length-1;if(i<n)return 0;var r=s(t[i]);if(r>=0)return r>0&&(e.lastNeed=r-1),r;if(--i<n||-2===r)return 0;if(r=s(t[i]),r>=0)return r>0&&(e.lastNeed=r-2),r;if(--i<n||-2===r)return 0;if(r=s(t[i]),r>=0)return r>0&&(2===r?r=0:e.lastNeed=r-3),r;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var i=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,i),e.toString("utf8",t,i)},o.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},3175(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=i(n(7732));t.default=class{_keepalive;timerId;timer;destroyed=!1;counter;client;_keepaliveTimeoutTimestamp;_intervalEvery;get keepaliveTimeoutTimestamp(){return this._keepaliveTimeoutTimestamp}get intervalEvery(){return this._intervalEvery}get keepalive(){return this._keepalive}constructor(e,t){this.client=e,this.timer="object"==typeof t&&"set"in t&&"clear"in t?t:(0,r.default)(t),this.setKeepalive(e.options.keepalive)}clear(){this.timerId&&(this.timer.clear(this.timerId),this.timerId=null)}setKeepalive(e){if(e*=1e3,isNaN(e)||e<=0||e>2147483647)throw new Error(`Keepalive value must be an integer between 0 and 2147483647. Provided value is ${e}`);this._keepalive=e,this.reschedule(),this.client.log(`KeepaliveManager: set keepalive to ${e}ms`)}destroy(){this.clear(),this.destroyed=!0}reschedule(){if(this.destroyed)return;this.clear(),this.counter=0;const e=Math.ceil(1.5*this._keepalive);this._keepaliveTimeoutTimestamp=Date.now()+e,this._intervalEvery=Math.ceil(this._keepalive/2),this.timerId=this.timer.set(()=>{this.destroyed||(this.counter+=1,2===this.counter?this.client.sendPing():this.counter>2&&this.client.onKeepaliveTimeout())},this._intervalEvery)}}},3225(e){"use strict";"undefined"==typeof process||!process.version||0===process.version.indexOf("v0.")||0===process.version.indexOf("v1.")&&0!==process.version.indexOf("v1.8.")?e.exports={nextTick:function(e,t,n,i){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var r,o,s=arguments.length;switch(s){case 0:case 1:return process.nextTick(e);case 2:return process.nextTick(function(){e.call(null,t)});case 3:return process.nextTick(function(){e.call(null,t,n)});case 4:return process.nextTick(function(){e.call(null,t,n,i)});default:for(r=new Array(s-1),o=0;o<r.length;)r[o++]=arguments[o];return process.nextTick(function(){e.apply(null,r)})}}}:e.exports=process},3338(e,t,n){"use strict";const{EMPTY_BUFFER:i}=n(2614),r=Buffer[Symbol.species];function o(e,t,n,i,r){for(let o=0;o<r;o++)n[i+o]=e[o]^t[3&o]}function s(e,t){for(let n=0;n<e.length;n++)e[n]^=t[3&n]}if(e.exports={concat:function(e,t){if(0===e.length)return i;if(1===e.length)return e[0];const n=Buffer.allocUnsafe(t);let o=0;for(let t=0;t<e.length;t++){const i=e[t];n.set(i,o),o+=i.length}return o<t?new r(n.buffer,n.byteOffset,o):n},mask:o,toArrayBuffer:function(e){return e.length===e.buffer.byteLength?e.buffer:e.buffer.slice(e.byteOffset,e.byteOffset+e.length)},toBuffer:function e(t){if(e.readOnly=!0,Buffer.isBuffer(t))return t;let n;return t instanceof ArrayBuffer?n=new r(t):ArrayBuffer.isView(t)?n=new r(t.buffer,t.byteOffset,t.byteLength):(n=Buffer.from(t),e.readOnly=!1),n},unmask:s},!process.env.WS_NO_BUFFER_UTIL)try{const t=n(Object(function(){var e=new Error("Cannot find module 'bufferutil'");throw e.code="MODULE_NOT_FOUND",e}()));e.exports.mask=function(e,n,i,r,s){s<48?o(e,n,i,r,s):t.mask(e,n,i,r,s)},e.exports.unmask=function(e,n){e.length<32?s(e,n):t.unmask(e,n)}}catch(e){}},3339(e){"use strict";e.exports=require("module")},3370(e,t,n){"use strict";const{ObjectDefineProperties:i,ObjectGetOwnPropertyDescriptor:r,ObjectKeys:o,ObjectSetPrototypeOf:s}=n(4134);e.exports=l;const a=n(7576),c=n(8584);s(l.prototype,a.prototype),s(l,a);{const e=o(c.prototype);for(let t=0;t<e.length;t++){const n=e[t];l.prototype[n]||(l.prototype[n]=c.prototype[n])}}function l(e){if(!(this instanceof l))return new l(e);a.call(this,e),c.call(this,e),e?(this.allowHalfOpen=!1!==e.allowHalfOpen,!1===e.readable&&(this._readableState.readable=!1,this._readableState.ended=!0,this._readableState.endEmitted=!0),!1===e.writable&&(this._writableState.writable=!1,this._writableState.ending=!0,this._writableState.ended=!0,this._writableState.finished=!0)):this.allowHalfOpen=!0}let d,u;function p(){return void 0===d&&(d={}),d}i(l.prototype,{writable:{__proto__:null,...r(c.prototype,"writable")},writableHighWaterMark:{__proto__:null,...r(c.prototype,"writableHighWaterMark")},writableObjectMode:{__proto__:null,...r(c.prototype,"writableObjectMode")},writableBuffer:{__proto__:null,...r(c.prototype,"writableBuffer")},writableLength:{__proto__:null,...r(c.prototype,"writableLength")},writableFinished:{__proto__:null,...r(c.prototype,"writableFinished")},writableCorked:{__proto__:null,...r(c.prototype,"writableCorked")},writableEnded:{__proto__:null,...r(c.prototype,"writableEnded")},writableNeedDrain:{__proto__:null,...r(c.prototype,"writableNeedDrain")},destroyed:{__proto__:null,get(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set(e){this._readableState&&this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}}),l.fromWeb=function(e,t){return p().newStreamDuplexFromReadableWritablePair(e,t)},l.toWeb=function(e){return p().newReadableWritablePairFromDuplex(e)},l.from=function(e){return u||(u=n(6706)),u(e,"body")}},3497(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(4966),r=n(720);t.default=class{aliasToTopic;topicToAlias;max;numberAllocator;length;constructor(e){e>0&&(this.aliasToTopic=new i.LRUCache({max:e}),this.topicToAlias={},this.numberAllocator=new r.NumberAllocator(1,e),this.max=e,this.length=0)}put(e,t){if(0===t||t>this.max)return!1;const n=this.aliasToTopic.get(t);return n&&delete this.topicToAlias[n],this.aliasToTopic.set(t,e),this.topicToAlias[e]=t,this.numberAllocator.use(t),this.length=this.aliasToTopic.size,!0}getTopicByAlias(e){return this.aliasToTopic.get(e)}getAliasByTopic(e){const t=this.topicToAlias[e];return"undefined"!=typeof t&&this.aliasToTopic.get(t),t}clear(){this.aliasToTopic.clear(),this.topicToAlias={},this.numberAllocator.clear(),this.length=0}getLruAlias(){const e=this.numberAllocator.firstVacant();return e||[...this.aliasToTopic.keys()][this.aliasToTopic.size-1]}}},3719(e,t,n){"use strict";n(1060);const{Duplex:i}=n(2203);function r(e){e.emit("close")}function o(){!this.destroyed&&this._writableState.finished&&this.destroy()}function s(e){this.removeListener("error",s),this.destroy(),0===this.listenerCount("error")&&this.emit("error",e)}e.exports=function(e,t){let n=!0;const a=new i({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return e.on("message",function(t,n){const i=!n&&a._readableState.objectMode?t.toString():t;a.push(i)||e.pause()}),e.once("error",function(e){a.destroyed||(n=!1,a.destroy(e))}),e.once("close",function(){a.destroyed||a.push(null)}),a._destroy=function(t,i){if(e.readyState===e.CLOSED)return i(t),void process.nextTick(r,a);let o=!1;e.once("error",function(e){o=!0,i(e)}),e.once("close",function(){o||i(t),process.nextTick(r,a)}),n&&e.terminate()},a._final=function(t){e.readyState!==e.CONNECTING?null!==e._socket&&(e._socket._writableState.finished?(t(),a._readableState.endEmitted&&a.destroy()):(e._socket.once("finish",function(){t()}),e.close())):e.once("open",function(){a._final(t)})},a._read=function(){e.isPaused&&e.resume()},a._write=function(t,n,i){e.readyState!==e.CONNECTING?e.send(t,i):e.once("open",function(){a._write(t,n,i)})},a.on("end",o),a.on("error",s),a}},3763(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shuffleArray=t.SocksClientError=void 0;class n extends Error{constructor(e,t){super(e),this.options=t}}t.SocksClientError=n,t.shuffleArray=function(e){for(let t=e.length-1;t>0;t--){const n=Math.floor(Math.random()*(t+1));[e[t],e[n]]=[e[n],e[t]]}}},3874(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EDITOR_HTML=void 0,t.EDITOR_HTML="<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Spatial Awareness - Topology Editor</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, sans-serif; background: #1a1a2e; color: #eee; min-height: 100vh; }\n .container { display: flex; height: 100vh; }\n .sidebar { width: 300px; background: #16213e; border-right: 1px solid #0f3460; display: flex; flex-direction: column; overflow: hidden; }\n .sidebar-header { padding: 20px; border-bottom: 1px solid #0f3460; }\n .sidebar-header h1 { font-size: 18px; font-weight: 600; margin-bottom: 5px; }\n .sidebar-header p { font-size: 12px; color: #888; }\n .sidebar-content { flex: 1; overflow-y: auto; padding: 15px; }\n .section { margin-bottom: 20px; }\n .section-title { font-size: 12px; font-weight: 600; text-transform: uppercase; color: #888; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }\n .btn { background: #0f3460; color: #fff; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 13px; transition: background 0.2s; }\n .btn:hover { background: #1a4a7a; }\n .btn-primary { background: #e94560; }\n .btn-primary:hover { background: #ff6b6b; }\n .btn-small { padding: 4px 8px; font-size: 11px; }\n .camera-item, .connection-item { background: #0f3460; border-radius: 6px; padding: 12px; margin-bottom: 8px; cursor: pointer; transition: background 0.2s; }\n .camera-item:hover, .connection-item:hover { background: #1a4a7a; }\n .camera-item.selected, .connection-item.selected { outline: 2px solid #e94560; }\n .camera-name { font-weight: 500; margin-bottom: 4px; }\n .camera-info { font-size: 11px; color: #888; }\n .editor { flex: 1; display: flex; flex-direction: column; overflow: hidden; }\n .toolbar { background: #16213e; border-bottom: 1px solid #0f3460; padding: 10px 20px; display: flex; gap: 10px; align-items: center; }\n .toolbar-group { display: flex; gap: 5px; padding-right: 15px; border-right: 1px solid #0f3460; margin-right: 5px; }\n .toolbar-group:last-child { border-right: none; }\n .canvas-container { flex: 1; position: relative; overflow: hidden; background: #0f0f1a; }\n #floor-plan-canvas { position: absolute; top: 0; left: 0; }\n .canvas-placeholder { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #666; }\n .canvas-placeholder h2 { margin-bottom: 15px; }\n .properties-panel { width: 280px; background: #16213e; border-left: 1px solid #0f3460; overflow-y: auto; padding: 15px; }\n .properties-panel h3 { font-size: 14px; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #0f3460; }\n .form-group { margin-bottom: 15px; }\n .form-group label { display: block; font-size: 12px; color: #888; margin-bottom: 5px; }\n .form-group input, .form-group select { width: 100%; padding: 8px 10px; background: #0f3460; border: 1px solid #1a4a7a; border-radius: 4px; color: #fff; font-size: 13px; }\n .form-group input:focus, .form-group select:focus { outline: none; border-color: #e94560; }\n .checkbox-group { display: flex; align-items: center; gap: 8px; }\n .checkbox-group input[type=\"checkbox\"] { width: auto; }\n .transit-time-inputs { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }\n .transit-time-inputs input { text-align: center; }\n .transit-time-labels { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; font-size: 10px; color: #666; text-align: center; }\n .modal-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.7); z-index: 1000; align-items: center; justify-content: center; }\n .modal-overlay.active { display: flex; }\n .modal { background: #16213e; border-radius: 8px; padding: 25px; max-width: 500px; width: 90%; max-height: 80vh; overflow-y: auto; }\n .modal h2 { margin-bottom: 20px; }\n .modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }\n .upload-zone { border: 2px dashed #0f3460; border-radius: 8px; padding: 40px; text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s; }\n .upload-zone:hover { border-color: #e94560; background: rgba(233, 69, 96, 0.1); }\n .upload-zone input { display: none; }\n .status-bar { background: #0f3460; padding: 8px 20px; font-size: 12px; color: #888; display: flex; justify-content: space-between; }\n .status-indicator { display: flex; align-items: center; gap: 6px; }\n .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #4caf50; }\n .status-dot.warning { background: #ff9800; }\n .status-dot.error { background: #f44336; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"sidebar\">\n <div class=\"sidebar-header\">\n <h1>Spatial Awareness</h1>\n <p>Topology Editor</p>\n </div>\n <div class=\"sidebar-content\">\n <div class=\"section\" style=\"background: #1a3a5c; margin: -10px -15px 10px -15px; padding: 15px;\">\n <div class=\"section-title\" style=\"margin-bottom: 10px;\">\n <span>Floor Plan Scale</span>\n </div>\n <div style=\"display: flex; gap: 10px; align-items: center;\">\n <input type=\"number\" id=\"scale-input\" value=\"5\" min=\"1\" max=\"50\" style=\"width: 60px; padding: 6px; background: #0f3460; border: 1px solid #1a4a7a; border-radius: 4px; color: #fff;\" onchange=\"updateScale(this.value)\">\n <span style=\"font-size: 12px; color: #888;\">pixels per foot</span>\n <button class=\"btn btn-small\" onclick=\"openScaleHelper()\" style=\"margin-left: auto;\">Help</button>\n </div>\n <div style=\"font-size: 11px; color: #666; margin-top: 8px;\">\n Tip: If your floor plan is 800px wide and represents 80ft, scale = 10 px/ft\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Cameras</span>\n <button class=\"btn btn-small\" onclick=\"openAddCameraModal()\">+ Add</button>\n </div>\n <div id=\"camera-list\">\n <div class=\"camera-item\" style=\"color: #666; text-align: center; cursor: default;\">No cameras configured</div>\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Connections</span>\n <button class=\"btn btn-small\" onclick=\"openAddConnectionModal()\">+ Add</button>\n </div>\n <div id=\"connection-list\">\n <div class=\"connection-item\" style=\"color: #666; text-align: center; cursor: default;\">No connections configured</div>\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Landmarks</span>\n <button class=\"btn btn-small\" onclick=\"openAddLandmarkModal()\">+ Add</button>\n </div>\n <div id=\"landmark-list\">\n <div class=\"landmark-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No landmarks configured</div>\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span>Zones</span>\n <button class=\"btn btn-small\" onclick=\"setTool('zone')\" style=\"background: #2e7d32;\">+ Draw</button>\n </div>\n <div id=\"zone-list\">\n <div class=\"zone-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No zones drawn</div>\n </div>\n </div>\n <div class=\"section\" id=\"suggestions-section\" style=\"display: none;\">\n <div class=\"section-title\">\n <span>AI Suggestions</span>\n <button class=\"btn btn-small\" onclick=\"loadSuggestions()\">Refresh</button>\n </div>\n <div id=\"suggestions-list\"></div>\n </div>\n <div class=\"section\" id=\"connection-suggestions-section\" style=\"display: none;\">\n <div class=\"section-title\">\n <span>Connection Suggestions</span>\n <button class=\"btn btn-small\" onclick=\"loadConnectionSuggestions()\">Refresh</button>\n </div>\n <div id=\"connection-suggestions-list\"></div>\n </div>\n <div class=\"section\" id=\"discovery-section\">\n <div class=\"section-title\">\n <span>Auto-Discovery</span>\n <button class=\"btn btn-small btn-primary\" id=\"scan-now-btn\" onclick=\"runDiscoveryScan()\">Scan Now</button>\n </div>\n <div id=\"discovery-status\" style=\"font-size: 11px; color: #888; margin-bottom: 8px;\">\n <span id=\"discovery-status-text\">Position cameras first, then scan</span>\n </div>\n <div id=\"discovery-suggestions-list\"></div>\n </div>\n <div class=\"section\" id=\"live-tracking-section\">\n <div class=\"section-title\">\n <span>Live Tracking</span>\n <label class=\"checkbox-group\" style=\"font-size: 11px; font-weight: normal; text-transform: none;\">\n <input type=\"checkbox\" id=\"live-tracking-toggle\" onchange=\"toggleLiveTracking(this.checked)\">\n Enable\n </label>\n </div>\n <div id=\"live-tracking-list\" style=\"max-height: 150px; overflow-y: auto;\"></div>\n </div>\n </div>\n </div>\n <div class=\"editor\">\n <div class=\"toolbar\">\n <div class=\"toolbar-group\">\n <button class=\"btn\" onclick=\"uploadFloorPlan()\">Upload Image</button>\n <button class=\"btn\" onclick=\"useBlankCanvas()\">Blank Canvas</button>\n </div>\n <div class=\"toolbar-group\">\n <button class=\"btn\" id=\"tool-select\" onclick=\"setTool('select')\">Select</button>\n <button class=\"btn\" id=\"tool-wall\" onclick=\"setTool('wall')\">Draw Wall</button>\n <button class=\"btn\" id=\"tool-room\" onclick=\"setTool('room')\">Draw Room</button>\n <button class=\"btn\" id=\"tool-zone\" onclick=\"setTool('zone')\" style=\"background: #2e7d32;\">Draw Zone</button>\n <button class=\"btn\" id=\"tool-camera\" onclick=\"setTool('camera')\">Place Camera</button>\n <button class=\"btn\" id=\"tool-landmark\" onclick=\"setTool('landmark')\">Place Landmark</button>\n <button class=\"btn\" id=\"tool-connect\" onclick=\"setTool('connect')\">Connect</button>\n </div>\n <div class=\"toolbar-group\">\n <button class=\"btn\" onclick=\"clearDrawings()\">Clear Drawings</button>\n <button class=\"btn\" onclick=\"clearAllTopology()\" style=\"background: #dc2626;\">Delete All</button>\n </div>\n <div class=\"toolbar-group\">\n <button class=\"btn btn-primary\" onclick=\"saveTopology()\">Save</button>\n </div>\n </div>\n <div class=\"canvas-container\">\n <canvas id=\"floor-plan-canvas\"></canvas>\n <div class=\"canvas-placeholder\" id=\"canvas-placeholder\">\n <h2>Floor Plan Editor</h2>\n <p>Upload an image or use a blank canvas to draw your floor plan</p>\n <br>\n <div style=\"display: flex; gap: 15px; justify-content: center;\">\n <button class=\"btn btn-primary\" onclick=\"uploadFloorPlan()\">Upload Image</button>\n <button class=\"btn\" onclick=\"useBlankCanvas()\">Use Blank Canvas</button>\n </div>\n </div>\n </div>\n <div class=\"status-bar\">\n <div class=\"status-indicator\">\n <div class=\"status-dot\" id=\"status-dot\"></div>\n <span id=\"status-text\">Ready</span>\n </div>\n <div>\n <span id=\"camera-count\">0</span> cameras | <span id=\"connection-count\">0</span> connections | <span id=\"landmark-count\">0</span> landmarks\n </div>\n </div>\n </div>\n <div class=\"properties-panel\" id=\"properties-panel\">\n <h3>Properties</h3>\n <p style=\"color: #666; font-size: 13px;\">Select a camera or connection to edit its properties.</p>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-camera-modal\">\n <div class=\"modal\">\n <h2>Add Camera</h2>\n <div class=\"form-group\">\n <label>Camera Device</label>\n <select id=\"camera-device-select\"><option value=\"\">Loading cameras...</option></select>\n </div>\n <div class=\"form-group\">\n <label>Display Name</label>\n <input type=\"text\" id=\"camera-name-input\" placeholder=\"e.g., Front Door Camera\">\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"camera-entry-checkbox\">\n Entry Point (objects can enter property here)\n </label>\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"camera-exit-checkbox\">\n Exit Point (objects can exit property here)\n </label>\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('add-camera-modal')\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"addCamera()\">Add Camera</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-connection-modal\">\n <div class=\"modal\">\n <h2>Add Connection</h2>\n <div class=\"form-group\">\n <label>Connection Name</label>\n <input type=\"text\" id=\"connection-name-input\" placeholder=\"e.g., Driveway to Front Door\">\n </div>\n <div class=\"form-group\">\n <label>From Camera</label>\n <select id=\"connection-from-select\"></select>\n </div>\n <div class=\"form-group\">\n <label>To Camera</label>\n <select id=\"connection-to-select\"></select>\n </div>\n <div class=\"form-group\">\n <label>Transit Time (seconds)</label>\n <div class=\"transit-time-inputs\">\n <input type=\"number\" id=\"transit-min\" placeholder=\"Min\" value=\"3\">\n <input type=\"number\" id=\"transit-typical\" placeholder=\"Typical\" value=\"10\">\n <input type=\"number\" id=\"transit-max\" placeholder=\"Max\" value=\"30\">\n </div>\n <div class=\"transit-time-labels\">\n <span>Minimum</span>\n <span>Typical</span>\n <span>Maximum</span>\n </div>\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"connection-bidirectional\" checked>\n Bidirectional (works both ways)\n </label>\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('add-connection-modal')\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"addConnection()\">Add Connection</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"upload-modal\">\n <div class=\"modal\">\n <h2>Upload Floor Plan</h2>\n <div class=\"upload-zone\" onclick=\"document.getElementById('floor-plan-input').click()\">\n <p>Click to select an image<br><small>PNG, JPG, or SVG</small></p>\n <input type=\"file\" id=\"floor-plan-input\" accept=\"image/*\" onchange=\"handleFloorPlanUpload(event)\">\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('upload-modal')\">Cancel</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-landmark-modal\">\n <div class=\"modal\">\n <h2>Add Landmark</h2>\n <div class=\"form-group\">\n <label>Landmark Type</label>\n <select id=\"landmark-type-select\" onchange=\"updateLandmarkSuggestions()\">\n <option value=\"structure\">Structure (House, Garage, Shed)</option>\n <option value=\"feature\">Feature (Mailbox, Tree, Pool)</option>\n <option value=\"boundary\">Boundary (Fence, Wall, Hedge)</option>\n <option value=\"access\">Access (Driveway, Walkway, Gate)</option>\n <option value=\"vehicle\">Vehicle (Parking, Boat, RV)</option>\n <option value=\"neighbor\">Neighbor (House, Driveway)</option>\n <option value=\"zone\">Zone (Front Yard, Back Yard)</option>\n <option value=\"street\">Street (Street, Sidewalk, Alley)</option>\n </select>\n </div>\n <div class=\"form-group\">\n <label>Quick Templates</label>\n <div id=\"landmark-templates\" style=\"display: flex; flex-wrap: wrap; gap: 5px;\"></div>\n </div>\n <div class=\"form-group\">\n <label>Name</label>\n <input type=\"text\" id=\"landmark-name-input\" placeholder=\"e.g., Front Porch, Red Shed\">\n </div>\n <div class=\"form-group\">\n <label>Description (optional)</label>\n <input type=\"text\" id=\"landmark-desc-input\" placeholder=\"Brief description for AI context\">\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"landmark-entry-checkbox\">\n Entry Point (people can enter property here)\n </label>\n </div>\n <div class=\"form-group\">\n <label class=\"checkbox-group\">\n <input type=\"checkbox\" id=\"landmark-exit-checkbox\">\n Exit Point (people can exit property here)\n </label>\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal('add-landmark-modal')\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"addLandmark()\">Add Landmark</button>\n </div>\n </div>\n </div>\n\n <div class=\"modal-overlay\" id=\"add-zone-modal\">\n <div class=\"modal\">\n <h2>Create Zone</h2>\n <p style=\"color: #888; margin-bottom: 15px; font-size: 13px;\">Click points on the canvas to draw a polygon. Double-click or press Enter to finish.</p>\n <div class=\"form-group\">\n <label>Zone Name</label>\n <input type=\"text\" id=\"zone-name-input\" placeholder=\"e.g., Front Yard\">\n </div>\n <div class=\"form-group\">\n <label>Zone Type</label>\n <select id=\"zone-type-select\">\n <option value=\"yard\">Yard</option>\n <option value=\"driveway\">Driveway</option>\n <option value=\"street\">Street</option>\n <option value=\"patio\">Patio/Deck</option>\n <option value=\"walkway\">Walkway</option>\n <option value=\"parking\">Parking</option>\n <option value=\"garden\">Garden</option>\n <option value=\"pool\">Pool Area</option>\n <option value=\"garage\">Garage</option>\n <option value=\"entrance\">Entrance</option>\n <option value=\"custom\">Custom</option>\n </select>\n </div>\n <div class=\"form-group\">\n <label>Description (optional)</label>\n <input type=\"text\" id=\"zone-desc-input\" placeholder=\"e.g., Main front lawn area\">\n </div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"cancelZoneDrawing()\">Cancel</button>\n <button class=\"btn btn-primary\" onclick=\"startZoneDrawing()\">Start Drawing</button>\n </div>\n </div>\n </div>\n\n <script>\n let topology = { version: '2.0', cameras: [], connections: [], globalZones: [], landmarks: [], relationships: [], floorPlan: null, drawings: [] };\n let selectedItem = null;\n let currentTool = 'select';\n let floorPlanImage = null;\n let availableCameras = [];\n let landmarkTemplates = [];\n let pendingSuggestions = [];\n let connectionSuggestions = [];\n let liveTrackingData = { objects: [], timestamp: 0 };\n let liveTrackingEnabled = false;\n let liveTrackingInterval = null;\n let selectedJourneyId = null;\n let journeyPath = null;\n let isDrawing = false;\n let drawStart = null;\n let currentDrawing = null;\n let blankCanvasMode = false;\n\n // Floor plan scale: pixels per foot (default assumes ~5 pixels per foot for a typical floor plan)\n // User can adjust this by setting the scale\n let floorPlanScale = 5; // pixels per foot\n\n // Helper functions for scale conversion\n function feetToPixels(feet) { return feet * floorPlanScale; }\n function pixelsToFeet(pixels) { return pixels / floorPlanScale; }\n\n // Zone drawing state\n let zoneDrawingMode = false;\n let currentZonePoints = [];\n let pendingZoneConfig = null;\n\n // Zone colors by type\n const ZONE_COLORS = {\n yard: 'rgba(76, 175, 80, 0.3)',\n driveway: 'rgba(158, 158, 158, 0.3)',\n street: 'rgba(96, 96, 96, 0.3)',\n patio: 'rgba(255, 152, 0, 0.3)',\n walkway: 'rgba(121, 85, 72, 0.3)',\n parking: 'rgba(189, 189, 189, 0.3)',\n garden: 'rgba(139, 195, 74, 0.3)',\n pool: 'rgba(33, 150, 243, 0.3)',\n garage: 'rgba(117, 117, 117, 0.3)',\n entrance: 'rgba(233, 30, 99, 0.3)',\n custom: 'rgba(156, 39, 176, 0.3)',\n };\n const ZONE_STROKE_COLORS = {\n yard: '#4caf50',\n driveway: '#9e9e9e',\n street: '#606060',\n patio: '#ff9800',\n walkway: '#795548',\n parking: '#bdbdbd',\n garden: '#8bc34a',\n pool: '#2196f3',\n garage: '#757575',\n entrance: '#e91e63',\n custom: '#9c27b0',\n };\n\n const canvas = document.getElementById('floor-plan-canvas');\n const ctx = canvas.getContext('2d');\n\n async function init() {\n await loadTopology();\n await loadAvailableCameras();\n await loadLandmarkTemplates();\n await loadSuggestions();\n await loadConnectionSuggestions();\n await loadDiscoveryStatus();\n await loadDiscoverySuggestions();\n resizeCanvas();\n render();\n updateUI();\n }\n\n async function loadTopology() {\n try {\n const response = await fetch('../api/topology');\n if (response.ok) {\n topology = await response.json();\n if (!topology.drawings) topology.drawings = [];\n // Load floor plan scale if saved\n if (topology.floorPlanScale) {\n floorPlanScale = topology.floorPlanScale;\n const scaleInput = document.getElementById('scale-input');\n if (scaleInput) scaleInput.value = floorPlanScale;\n }\n // Load floor plan from separate storage (handles legacy imageData in topology too)\n if (topology.floorPlan?.imageData) {\n // Legacy: imageData was stored in topology\n await loadFloorPlanImage(topology.floorPlan.imageData);\n } else if (topology.floorPlan?.type === 'blank') {\n blankCanvasMode = true;\n } else {\n // Always try to load from floor-plan endpoint (handles uploaded and missing cases)\n try {\n const fpResponse = await fetch('../api/floor-plan');\n if (fpResponse.ok) {\n const fpData = await fpResponse.json();\n if (fpData.imageData) {\n await loadFloorPlanImage(fpData.imageData);\n // Update topology reference if not set\n if (!topology.floorPlan || topology.floorPlan.type !== 'uploaded') {\n topology.floorPlan = { type: 'uploaded', width: floorPlanImage.width, height: floorPlanImage.height };\n }\n }\n }\n } catch (err) { console.error('Failed to load floor plan:', err); }\n }\n }\n } catch (e) { console.error('Failed to load topology:', e); }\n }\n\n async function loadAvailableCameras() {\n try {\n const response = await fetch('../api/cameras');\n if (response.ok) {\n availableCameras = await response.json();\n } else {\n availableCameras = [];\n }\n } catch (e) {\n console.error('Failed to load cameras:', e);\n availableCameras = [];\n }\n updateCameraSelects();\n }\n\n async function loadLandmarkTemplates() {\n try {\n const response = await fetch('../api/landmark-templates');\n if (response.ok) {\n const data = await response.json();\n landmarkTemplates = data.templates || [];\n }\n } catch (e) { console.error('Failed to load landmark templates:', e); }\n }\n\n async function loadSuggestions() {\n try {\n const response = await fetch('../api/landmark-suggestions');\n if (response.ok) {\n const data = await response.json();\n pendingSuggestions = data.suggestions || [];\n updateSuggestionsUI();\n }\n } catch (e) { console.error('Failed to load suggestions:', e); }\n }\n\n function updateSuggestionsUI() {\n const section = document.getElementById('suggestions-section');\n const list = document.getElementById('suggestions-list');\n if (pendingSuggestions.length === 0) {\n section.style.display = 'none';\n return;\n }\n section.style.display = 'block';\n list.innerHTML = pendingSuggestions.map(s =>\n '<div class=\"camera-item\" style=\"display: flex; justify-content: space-between; align-items: center;\">' +\n '<div><div class=\"camera-name\">' + s.landmark.name + '</div>' +\n '<div class=\"camera-info\">' + s.landmark.type + ' - ' + Math.round((s.landmark.aiConfidence || 0) * 100) + '% confidence</div></div>' +\n '<div style=\"display: flex; gap: 5px;\">' +\n '<button class=\"btn btn-small btn-primary\" onclick=\"acceptSuggestion(\\'' + s.id + '\\')\">Accept</button>' +\n '<button class=\"btn btn-small\" onclick=\"rejectSuggestion(\\'' + s.id + '\\')\">Reject</button>' +\n '</div></div>'\n ).join('');\n }\n\n async function acceptSuggestion(id) {\n try {\n const response = await fetch('../api/landmark-suggestions/' + id + '/accept', { method: 'POST' });\n if (response.ok) {\n const data = await response.json();\n if (data.landmark) {\n topology.landmarks.push(data.landmark);\n updateUI();\n render();\n }\n await loadSuggestions();\n setStatus('Landmark accepted', 'success');\n }\n } catch (e) { console.error('Failed to accept suggestion:', e); }\n }\n\n async function rejectSuggestion(id) {\n try {\n await fetch('../api/landmark-suggestions/' + id + '/reject', { method: 'POST' });\n await loadSuggestions();\n setStatus('Suggestion rejected', 'success');\n } catch (e) { console.error('Failed to reject suggestion:', e); }\n }\n\n // ==================== Connection Suggestions ====================\n async function loadConnectionSuggestions() {\n try {\n const response = await fetch('../api/connection-suggestions');\n if (response.ok) {\n const data = await response.json();\n connectionSuggestions = data.suggestions || [];\n updateConnectionSuggestionsUI();\n }\n } catch (e) { console.error('Failed to load connection suggestions:', e); }\n }\n\n function updateConnectionSuggestionsUI() {\n const section = document.getElementById('connection-suggestions-section');\n const list = document.getElementById('connection-suggestions-list');\n if (connectionSuggestions.length === 0) {\n section.style.display = 'none';\n return;\n }\n section.style.display = 'block';\n list.innerHTML = connectionSuggestions.map(s =>\n '<div class=\"camera-item\" style=\"display: flex; justify-content: space-between; align-items: center;\">' +\n '<div><div class=\"camera-name\">' + s.fromCameraName + ' → ' + s.toCameraName + '</div>' +\n '<div class=\"camera-info\">' + Math.round(s.suggestedTransitTime.typical / 1000) + 's typical, ' +\n Math.round(s.confidence * 100) + '% confidence</div></div>' +\n '<div style=\"display: flex; gap: 5px;\">' +\n '<button class=\"btn btn-small btn-primary\" onclick=\"acceptConnectionSuggestion(\\'' + s.id + '\\')\">Accept</button>' +\n '<button class=\"btn btn-small\" onclick=\"rejectConnectionSuggestion(\\'' + s.id + '\\')\">Reject</button>' +\n '</div></div>'\n ).join('');\n }\n\n async function acceptConnectionSuggestion(id) {\n try {\n const response = await fetch('../api/connection-suggestions/' + encodeURIComponent(id) + '/accept', { method: 'POST' });\n if (response.ok) {\n const data = await response.json();\n if (data.connection) {\n topology.connections.push(data.connection);\n updateUI();\n render();\n }\n await loadConnectionSuggestions();\n setStatus('Connection accepted', 'success');\n }\n } catch (e) { console.error('Failed to accept connection suggestion:', e); }\n }\n\n async function rejectConnectionSuggestion(id) {\n try {\n await fetch('../api/connection-suggestions/' + encodeURIComponent(id) + '/reject', { method: 'POST' });\n await loadConnectionSuggestions();\n setStatus('Connection suggestion rejected', 'success');\n } catch (e) { console.error('Failed to reject connection suggestion:', e); }\n }\n\n // ==================== Auto-Discovery ====================\n let discoverySuggestions = [];\n let discoveryStatus = { isScanning: false, lastScanTime: null, pendingSuggestions: 0 };\n\n async function loadDiscoveryStatus() {\n try {\n const response = await fetch('../api/discovery/status');\n if (response.ok) {\n discoveryStatus = await response.json();\n updateDiscoveryStatusUI();\n }\n } catch (e) { console.error('Failed to load discovery status:', e); }\n }\n\n async function loadDiscoverySuggestions() {\n try {\n const response = await fetch('../api/discovery/suggestions');\n if (response.ok) {\n const data = await response.json();\n discoverySuggestions = data.suggestions || [];\n updateDiscoverySuggestionsUI();\n }\n } catch (e) { console.error('Failed to load discovery suggestions:', e); }\n }\n\n function updateDiscoveryStatusUI() {\n const statusText = document.getElementById('discovery-status-text');\n const scanBtn = document.getElementById('scan-now-btn');\n\n if (discoveryStatus.isScanning) {\n statusText.textContent = 'Scanning cameras...';\n scanBtn.disabled = true;\n scanBtn.textContent = 'Scanning...';\n } else if (discoveryStatus.lastScanTime) {\n const ago = Math.round((Date.now() - discoveryStatus.lastScanTime) / 1000 / 60);\n const agoStr = ago < 1 ? 'just now' : ago + 'm ago';\n statusText.textContent = 'Last scan: ' + agoStr + ' | ' + discoveryStatus.pendingSuggestions + ' suggestions';\n scanBtn.disabled = false;\n scanBtn.textContent = 'Scan Now';\n } else {\n statusText.textContent = 'Not scanned yet';\n scanBtn.disabled = false;\n scanBtn.textContent = 'Scan Now';\n }\n }\n\n function updateDiscoverySuggestionsUI() {\n const list = document.getElementById('discovery-suggestions-list');\n if (discoverySuggestions.length === 0) {\n list.innerHTML = '<div style=\"color: #666; font-size: 11px; text-align: center; padding: 8px;\">No pending suggestions</div>';\n return;\n }\n list.innerHTML = discoverySuggestions.map(s => {\n const name = s.type === 'landmark' ? s.landmark?.name : (s.type === 'connection' ? s.connection?.via : s.zone?.name);\n const typeLabel = s.type === 'landmark' ? s.landmark?.type : s.type;\n return '<div class=\"camera-item\" style=\"display: flex; justify-content: space-between; align-items: center; padding: 8px;\">' +\n '<div><div class=\"camera-name\" style=\"font-size: 12px;\">' + (name || 'Unknown') + '</div>' +\n '<div class=\"camera-info\">' + typeLabel + ' - ' + Math.round(s.confidence * 100) + '% confidence</div></div>' +\n '<div style=\"display: flex; gap: 4px;\">' +\n '<button class=\"btn btn-small btn-primary\" onclick=\"acceptDiscoverySuggestion(\\'' + s.id + '\\')\">✓</button>' +\n '<button class=\"btn btn-small\" onclick=\"rejectDiscoverySuggestion(\\'' + s.id + '\\')\">✗</button>' +\n '</div></div>';\n }).join('');\n }\n\n let scanPollingInterval = null;\n\n async function runDiscoveryScan() {\n // Check if cameras are positioned on the floor plan\n const positionedCameras = topology.cameras.filter(c => c.floorPlanPosition);\n if (positionedCameras.length === 0) {\n alert('Please position at least one camera on the floor plan before running discovery.\\n\\nSteps:\\n1. Click \"Place Camera\" in the toolbar\\n2. Click on the floor plan where the camera is located\\n3. Select the camera from the dropdown\\n4. Drag the rotation handle to set its direction\\n5. Then run discovery to detect zones and connections');\n return;\n }\n\n const scanBtn = document.getElementById('scan-now-btn');\n const statusText = document.getElementById('discovery-status-text');\n scanBtn.disabled = true;\n scanBtn.textContent = 'Scanning...';\n setStatus('Starting discovery scan...', 'warning');\n\n // Start polling for live status updates\n let camerasDone = 0;\n scanPollingInterval = setInterval(async () => {\n try {\n const statusResp = await fetch('../api/discovery/status');\n if (statusResp.ok) {\n const status = await statusResp.json();\n if (status.isScanning) {\n statusText.textContent = 'Scanning: ' + status.camerasAnalyzed + ' cameras analyzed...';\n // Check for new suggestions during scan\n if (status.pendingSuggestions > camerasDone) {\n camerasDone = status.pendingSuggestions;\n await loadDiscoverySuggestions();\n }\n }\n }\n } catch (e) { /* ignore polling errors */ }\n }, 1000);\n\n try {\n const response = await fetch('../api/discovery/scan', { method: 'POST' });\n if (response.ok) {\n const result = await response.json();\n discoveryStatus = result.status || discoveryStatus;\n discoverySuggestions = result.suggestions || [];\n updateDiscoveryStatusUI();\n updateDiscoverySuggestionsUI();\n setStatus('Discovery scan complete: ' + discoverySuggestions.length + ' suggestions found', 'success');\n\n // Also reload topology to get any auto-accepted items\n await loadTopology();\n updateUI();\n render();\n } else {\n const error = await response.json();\n setStatus('Scan failed: ' + (error.error || 'Unknown error'), 'error');\n }\n } catch (e) {\n console.error('Discovery scan failed:', e);\n setStatus('Discovery scan failed', 'error');\n } finally {\n // Stop polling\n if (scanPollingInterval) {\n clearInterval(scanPollingInterval);\n scanPollingInterval = null;\n }\n scanBtn.disabled = false;\n scanBtn.textContent = 'Scan Now';\n }\n }\n\n async function acceptDiscoverySuggestion(id) {\n try {\n const response = await fetch('../api/discovery/suggestions/' + id + '/accept', { method: 'POST' });\n if (response.ok) {\n // Reload topology and suggestions\n await loadTopology();\n await loadDiscoverySuggestions();\n updateUI();\n render();\n setStatus('Suggestion accepted', 'success');\n }\n } catch (e) { console.error('Failed to accept discovery suggestion:', e); }\n }\n\n async function rejectDiscoverySuggestion(id) {\n try {\n await fetch('../api/discovery/suggestions/' + id + '/reject', { method: 'POST' });\n await loadDiscoverySuggestions();\n setStatus('Suggestion rejected', 'success');\n } catch (e) { console.error('Failed to reject discovery suggestion:', e); }\n }\n\n // ==================== Live Tracking ====================\n function toggleLiveTracking(enabled) {\n liveTrackingEnabled = enabled;\n if (enabled) {\n loadLiveTracking();\n liveTrackingInterval = setInterval(loadLiveTracking, 2000); // Poll every 2 seconds\n } else {\n if (liveTrackingInterval) {\n clearInterval(liveTrackingInterval);\n liveTrackingInterval = null;\n }\n liveTrackingData = { objects: [], timestamp: 0 };\n selectedJourneyId = null;\n journeyPath = null;\n updateLiveTrackingUI();\n render();\n }\n }\n\n async function loadLiveTracking() {\n try {\n const response = await fetch('../api/live-tracking');\n if (response.ok) {\n liveTrackingData = await response.json();\n updateLiveTrackingUI();\n render();\n }\n } catch (e) { console.error('Failed to load live tracking:', e); }\n }\n\n function updateLiveTrackingUI() {\n const list = document.getElementById('live-tracking-list');\n if (liveTrackingData.objects.length === 0) {\n list.innerHTML = '<div style=\"color: #666; font-size: 12px; text-align: center; padding: 10px;\">No active objects</div>';\n return;\n }\n list.innerHTML = liveTrackingData.objects.map(obj => {\n const isSelected = selectedJourneyId === obj.globalId;\n const ageSeconds = Math.round((Date.now() - obj.lastSeen) / 1000);\n const ageStr = ageSeconds < 60 ? ageSeconds + 's ago' : Math.round(ageSeconds / 60) + 'm ago';\n return '<div class=\"camera-item' + (isSelected ? ' selected' : '') + '\" ' +\n 'onclick=\"selectTrackedObject(\\'' + obj.globalId + '\\')\" ' +\n 'style=\"padding: 8px; cursor: pointer;\">' +\n '<div class=\"camera-name\" style=\"font-size: 12px;\">' +\n (obj.className.charAt(0).toUpperCase() + obj.className.slice(1)) +\n (obj.label ? ' (' + obj.label + ')' : '') + '</div>' +\n '<div class=\"camera-info\">' + obj.lastCameraName + ' • ' + ageStr + '</div>' +\n '</div>';\n }).join('');\n }\n\n async function selectTrackedObject(globalId) {\n if (selectedJourneyId === globalId) {\n // Deselect\n selectedJourneyId = null;\n journeyPath = null;\n } else {\n selectedJourneyId = globalId;\n // Load journey path\n try {\n const response = await fetch('../api/journey-path/' + globalId);\n if (response.ok) {\n journeyPath = await response.json();\n }\n } catch (e) { console.error('Failed to load journey path:', e); }\n }\n updateLiveTrackingUI();\n render();\n }\n\n function openAddLandmarkModal() {\n updateLandmarkSuggestions();\n document.getElementById('add-landmark-modal').classList.add('active');\n }\n\n function updateLandmarkSuggestions() {\n const type = document.getElementById('landmark-type-select').value;\n const template = landmarkTemplates.find(t => t.type === type);\n const container = document.getElementById('landmark-templates');\n if (template) {\n container.innerHTML = template.suggestions.map(s =>\n '<button class=\"btn btn-small\" onclick=\"setLandmarkName(\\'' + s + '\\')\" style=\"margin: 2px;\">' + s + '</button>'\n ).join('');\n } else {\n container.innerHTML = '<span style=\"color: #666; font-size: 12px;\">No templates for this type</span>';\n }\n }\n\n function setLandmarkName(name) {\n document.getElementById('landmark-name-input').value = name;\n }\n\n function addLandmark() {\n const name = document.getElementById('landmark-name-input').value;\n if (!name) { alert('Please enter a landmark name'); return; }\n const type = document.getElementById('landmark-type-select').value;\n const description = document.getElementById('landmark-desc-input').value;\n const isEntry = document.getElementById('landmark-entry-checkbox').checked;\n const isExit = document.getElementById('landmark-exit-checkbox').checked;\n const pos = topology._pendingLandmarkPos || { x: canvas.width / 2 + Math.random() * 100 - 50, y: canvas.height / 2 + Math.random() * 100 - 50 };\n delete topology._pendingLandmarkPos;\n const landmark = {\n id: 'landmark_' + Date.now(),\n name,\n type,\n position: pos,\n description: description || undefined,\n isEntryPoint: isEntry,\n isExitPoint: isExit,\n visibleFromCameras: [],\n };\n if (!topology.landmarks) topology.landmarks = [];\n topology.landmarks.push(landmark);\n closeModal('add-landmark-modal');\n document.getElementById('landmark-name-input').value = '';\n document.getElementById('landmark-desc-input').value = '';\n document.getElementById('landmark-entry-checkbox').checked = false;\n document.getElementById('landmark-exit-checkbox').checked = false;\n updateUI();\n render();\n }\n\n function selectLandmark(id) {\n selectedItem = { type: 'landmark', id };\n const landmark = topology.landmarks.find(l => l.id === id);\n showLandmarkProperties(landmark);\n updateUI();\n render();\n }\n\n function showLandmarkProperties(landmark) {\n const panel = document.getElementById('properties-panel');\n const cameraOptions = topology.cameras.map(c =>\n '<label class=\"checkbox-group\" style=\"margin-bottom: 5px;\"><input type=\"checkbox\" ' +\n ((landmark.visibleFromCameras || []).includes(c.deviceId) ? 'checked' : '') +\n ' onchange=\"toggleLandmarkCamera(\\'' + landmark.id + '\\', \\'' + c.deviceId + '\\', this.checked)\">' +\n c.name + '</label>'\n ).join('');\n panel.innerHTML = '<h3>Landmark Properties</h3>' +\n '<div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + landmark.name + '\" onchange=\"updateLandmarkName(\\'' + landmark.id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Type</label><select onchange=\"updateLandmarkType(\\'' + landmark.id + '\\', this.value)\">' +\n '<option value=\"structure\"' + (landmark.type === 'structure' ? ' selected' : '') + '>Structure</option>' +\n '<option value=\"feature\"' + (landmark.type === 'feature' ? ' selected' : '') + '>Feature</option>' +\n '<option value=\"boundary\"' + (landmark.type === 'boundary' ? ' selected' : '') + '>Boundary</option>' +\n '<option value=\"access\"' + (landmark.type === 'access' ? ' selected' : '') + '>Access</option>' +\n '<option value=\"vehicle\"' + (landmark.type === 'vehicle' ? ' selected' : '') + '>Vehicle</option>' +\n '<option value=\"neighbor\"' + (landmark.type === 'neighbor' ? ' selected' : '') + '>Neighbor</option>' +\n '<option value=\"zone\"' + (landmark.type === 'zone' ? ' selected' : '') + '>Zone</option>' +\n '<option value=\"street\"' + (landmark.type === 'street' ? ' selected' : '') + '>Street</option>' +\n '</select></div>' +\n '<div class=\"form-group\"><label>Description</label><input type=\"text\" value=\"' + (landmark.description || '') + '\" onchange=\"updateLandmarkDesc(\\'' + landmark.id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (landmark.isEntryPoint ? 'checked' : '') + ' onchange=\"updateLandmarkEntry(\\'' + landmark.id + '\\', this.checked)\">Entry Point</label></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (landmark.isExitPoint ? 'checked' : '') + ' onchange=\"updateLandmarkExit(\\'' + landmark.id + '\\', this.checked)\">Exit Point</label></div>' +\n '<div class=\"form-group\"><label>Visible from Cameras</label>' + (cameraOptions || '<span style=\"color:#666;font-size:12px;\">Add cameras first</span>') + '</div>' +\n '<div class=\"form-group\"><button class=\"btn\" style=\"width: 100%; background: #f44336;\" onclick=\"deleteLandmark(\\'' + landmark.id + '\\')\">Delete Landmark</button></div>';\n }\n\n function updateLandmarkName(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.name = value; updateUI(); }\n function updateLandmarkType(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.type = value; render(); }\n function updateLandmarkDesc(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.description = value || undefined; }\n function updateLandmarkEntry(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.isEntryPoint = value; }\n function updateLandmarkExit(id, value) { const l = topology.landmarks.find(x => x.id === id); if (l) l.isExitPoint = value; }\n function toggleLandmarkCamera(landmarkId, cameraId, visible) {\n const l = topology.landmarks.find(x => x.id === landmarkId);\n if (!l) return;\n if (!l.visibleFromCameras) l.visibleFromCameras = [];\n if (visible && !l.visibleFromCameras.includes(cameraId)) {\n l.visibleFromCameras.push(cameraId);\n } else if (!visible) {\n l.visibleFromCameras = l.visibleFromCameras.filter(id => id !== cameraId);\n }\n // Also update camera's visibleLandmarks\n const camera = topology.cameras.find(c => c.deviceId === cameraId);\n if (camera) {\n if (!camera.context) camera.context = {};\n if (!camera.context.visibleLandmarks) camera.context.visibleLandmarks = [];\n if (visible && !camera.context.visibleLandmarks.includes(landmarkId)) {\n camera.context.visibleLandmarks.push(landmarkId);\n } else if (!visible) {\n camera.context.visibleLandmarks = camera.context.visibleLandmarks.filter(id => id !== landmarkId);\n }\n }\n }\n function deleteLandmark(id) {\n if (!confirm('Delete this landmark?')) return;\n topology.landmarks = topology.landmarks.filter(l => l.id !== id);\n selectedItem = null;\n document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select an item to edit.</p>';\n updateUI();\n render();\n }\n\n async function saveTopology() {\n try {\n setStatus('Saving...', 'warning');\n const response = await fetch('../api/topology', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(topology)\n });\n if (response.ok) { setStatus('Saved successfully', 'success'); }\n else { setStatus('Failed to save', 'error'); }\n } catch (e) { console.error('Failed to save topology:', e); setStatus('Failed to save', 'error'); }\n }\n\n function resizeCanvas() {\n const container = canvas.parentElement;\n canvas.width = container.clientWidth;\n canvas.height = container.clientHeight;\n }\n\n function render() {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n // Draw grid for blank canvas\n if (blankCanvasMode && !floorPlanImage) {\n document.getElementById('canvas-placeholder').style.display = 'none';\n ctx.fillStyle = '#1a1a2e';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.strokeStyle = '#2a2a4e';\n ctx.lineWidth = 1;\n const gridSize = 40;\n for (let x = 0; x < canvas.width; x += gridSize) {\n ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke();\n }\n for (let y = 0; y < canvas.height; y += gridSize) {\n ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke();\n }\n } else if (floorPlanImage) {\n document.getElementById('canvas-placeholder').style.display = 'none';\n const scale = Math.min(canvas.width / floorPlanImage.width, canvas.height / floorPlanImage.height) * 0.9;\n const x = (canvas.width - floorPlanImage.width * scale) / 2;\n const y = (canvas.height - floorPlanImage.height * scale) / 2;\n ctx.drawImage(floorPlanImage, x, y, floorPlanImage.width * scale, floorPlanImage.height * scale);\n } else {\n document.getElementById('canvas-placeholder').style.display = 'block';\n }\n\n // Draw saved drawings (walls and rooms)\n if (topology.drawings) {\n for (const drawing of topology.drawings) {\n if (drawing.type === 'wall') {\n ctx.beginPath();\n ctx.moveTo(drawing.x1, drawing.y1);\n ctx.lineTo(drawing.x2, drawing.y2);\n ctx.strokeStyle = '#888';\n ctx.lineWidth = 4;\n ctx.stroke();\n } else if (drawing.type === 'room') {\n ctx.strokeStyle = '#666';\n ctx.lineWidth = 2;\n ctx.strokeRect(drawing.x, drawing.y, drawing.width, drawing.height);\n ctx.fillStyle = 'rgba(100, 100, 150, 0.1)';\n ctx.fillRect(drawing.x, drawing.y, drawing.width, drawing.height);\n if (drawing.label) {\n ctx.fillStyle = '#888';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'center';\n ctx.fillText(drawing.label, drawing.x + drawing.width/2, drawing.y + drawing.height/2);\n }\n }\n }\n }\n\n // Draw current drawing in progress\n if (currentDrawing) {\n if (currentDrawing.type === 'wall') {\n ctx.beginPath();\n ctx.moveTo(currentDrawing.x1, currentDrawing.y1);\n ctx.lineTo(currentDrawing.x2, currentDrawing.y2);\n ctx.strokeStyle = '#e94560';\n ctx.lineWidth = 4;\n ctx.stroke();\n } else if (currentDrawing.type === 'room') {\n ctx.strokeStyle = '#e94560';\n ctx.lineWidth = 2;\n ctx.strokeRect(currentDrawing.x, currentDrawing.y, currentDrawing.width, currentDrawing.height);\n }\n }\n\n // Draw saved zones\n if (topology.drawnZones) {\n for (const zone of topology.drawnZones) {\n drawZone(zone);\n }\n }\n\n // Draw zone currently being drawn\n if (zoneDrawingMode && currentZonePoints.length > 0) {\n const color = pendingZoneConfig ? (ZONE_COLORS[pendingZoneConfig.type] || ZONE_COLORS.custom) : 'rgba(233, 69, 96, 0.3)';\n const strokeColor = pendingZoneConfig ? (ZONE_STROKE_COLORS[pendingZoneConfig.type] || ZONE_STROKE_COLORS.custom) : '#e94560';\n\n ctx.beginPath();\n ctx.moveTo(currentZonePoints[0].x, currentZonePoints[0].y);\n for (let i = 1; i < currentZonePoints.length; i++) {\n ctx.lineTo(currentZonePoints[i].x, currentZonePoints[i].y);\n }\n // Close the polygon if we have 3+ points\n if (currentZonePoints.length >= 3) {\n ctx.closePath();\n ctx.fillStyle = color;\n ctx.fill();\n }\n ctx.strokeStyle = strokeColor;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Draw points\n for (const pt of currentZonePoints) {\n ctx.beginPath();\n ctx.arc(pt.x, pt.y, 5, 0, Math.PI * 2);\n ctx.fillStyle = strokeColor;\n ctx.fill();\n }\n\n // Draw instruction text\n ctx.fillStyle = '#fff';\n ctx.font = 'bold 12px sans-serif';\n ctx.textAlign = 'left';\n ctx.fillText('Click to add points. Double-click or press Enter to finish. Esc to cancel.', 10, canvas.height - 10);\n }\n\n // Draw landmarks first (below cameras and connections)\n for (const landmark of (topology.landmarks || [])) {\n if (landmark.position) { drawLandmark(landmark); }\n }\n for (const conn of topology.connections) {\n const fromCam = topology.cameras.find(c => c.deviceId === conn.fromCameraId);\n const toCam = topology.cameras.find(c => c.deviceId === conn.toCameraId);\n if (fromCam?.floorPlanPosition && toCam?.floorPlanPosition) {\n drawConnection(fromCam.floorPlanPosition, toCam.floorPlanPosition, conn);\n }\n }\n for (const camera of topology.cameras) {\n if (camera.floorPlanPosition) { drawCamera(camera); }\n }\n\n // Draw journey path if selected\n if (journeyPath && journeyPath.segments.length > 0) {\n drawJourneyPath();\n }\n\n // Draw live tracking objects\n if (liveTrackingEnabled && liveTrackingData.objects.length > 0) {\n drawLiveTrackingObjects();\n }\n }\n\n function drawJourneyPath() {\n if (!journeyPath) return;\n\n ctx.strokeStyle = '#ff6b6b';\n ctx.lineWidth = 3;\n ctx.setLineDash([8, 4]);\n\n // Draw path segments\n for (const segment of journeyPath.segments) {\n if (segment.fromCamera.position && segment.toCamera.position) {\n ctx.beginPath();\n ctx.moveTo(segment.fromCamera.position.x, segment.fromCamera.position.y);\n ctx.lineTo(segment.toCamera.position.x, segment.toCamera.position.y);\n ctx.stroke();\n\n // Draw timestamp indicator\n const midX = (segment.fromCamera.position.x + segment.toCamera.position.x) / 2;\n const midY = (segment.fromCamera.position.y + segment.toCamera.position.y) / 2;\n ctx.fillStyle = 'rgba(255, 107, 107, 0.9)';\n ctx.beginPath();\n ctx.arc(midX, midY, 4, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n\n ctx.setLineDash([]);\n\n // Draw current location indicator\n if (journeyPath.currentLocation?.position) {\n const pos = journeyPath.currentLocation.position;\n // Pulsing dot effect\n const pulse = (Date.now() % 1000) / 1000;\n const radius = 10 + pulse * 5;\n const alpha = 1 - pulse * 0.5;\n\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\n ctx.fillStyle = 'rgba(255, 107, 107, ' + alpha + ')';\n ctx.fill();\n\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, 6, 0, Math.PI * 2);\n ctx.fillStyle = '#ff6b6b';\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n }\n\n function drawLiveTrackingObjects() {\n const objectColors = {\n person: '#4caf50',\n car: '#2196f3',\n animal: '#ff9800',\n default: '#9c27b0'\n };\n\n for (const obj of liveTrackingData.objects) {\n if (!obj.cameraPosition) continue;\n\n // Skip if this is the selected journey object (drawn separately with path)\n if (obj.globalId === selectedJourneyId) continue;\n\n const pos = obj.cameraPosition;\n const color = objectColors[obj.className] || objectColors.default;\n const ageSeconds = (Date.now() - obj.lastSeen) / 1000;\n\n // Fade old objects\n const alpha = Math.max(0.3, 1 - ageSeconds / 60);\n\n // Draw object indicator\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, 12, 0, Math.PI * 2);\n ctx.fillStyle = color.replace(')', ', ' + alpha + ')').replace('rgb', 'rgba');\n ctx.fill();\n ctx.strokeStyle = 'rgba(255, 255, 255, ' + alpha + ')';\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Draw class icon\n ctx.fillStyle = 'rgba(255, 255, 255, ' + alpha + ')';\n ctx.font = 'bold 10px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n const icon = obj.className === 'person' ? 'P' : obj.className === 'car' ? 'C' : obj.className === 'animal' ? 'A' : '?';\n ctx.fillText(icon, pos.x, pos.y);\n\n // Draw label below\n if (obj.label) {\n ctx.font = '9px sans-serif';\n ctx.fillText(obj.label.slice(0, 10), pos.x, pos.y + 20);\n }\n }\n }\n\n function drawZone(zone) {\n if (!zone.polygon || zone.polygon.length < 3) return;\n\n const isSelected = selectedItem?.type === 'zone' && selectedItem?.id === zone.id;\n const fillColor = zone.color || ZONE_COLORS[zone.type] || ZONE_COLORS.custom;\n const strokeColor = ZONE_STROKE_COLORS[zone.type] || ZONE_STROKE_COLORS.custom;\n\n // Draw filled polygon\n ctx.beginPath();\n ctx.moveTo(zone.polygon[0].x, zone.polygon[0].y);\n for (let i = 1; i < zone.polygon.length; i++) {\n ctx.lineTo(zone.polygon[i].x, zone.polygon[i].y);\n }\n ctx.closePath();\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.strokeStyle = isSelected ? '#e94560' : strokeColor;\n ctx.lineWidth = isSelected ? 3 : 2;\n ctx.stroke();\n\n // Draw zone label at centroid\n const centroid = getPolygonCentroid(zone.polygon);\n ctx.fillStyle = isSelected ? '#e94560' : '#fff';\n ctx.font = 'bold 12px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(zone.name, centroid.x, centroid.y);\n ctx.font = '10px sans-serif';\n ctx.fillStyle = '#ccc';\n ctx.fillText(zone.type, centroid.x, centroid.y + 14);\n }\n\n function getPolygonCentroid(polygon) {\n let x = 0, y = 0;\n for (const pt of polygon) {\n x += pt.x;\n y += pt.y;\n }\n return { x: x / polygon.length, y: y / polygon.length };\n }\n\n function drawLandmark(landmark) {\n const pos = landmark.position;\n const isSelected = selectedItem?.type === 'landmark' && selectedItem?.id === landmark.id;\n // Color by type\n const colors = {\n structure: '#8b5cf6', // purple\n feature: '#10b981', // green\n boundary: '#f59e0b', // amber\n access: '#3b82f6', // blue\n vehicle: '#6366f1', // indigo\n neighbor: '#ec4899', // pink\n zone: '#14b8a6', // teal\n street: '#6b7280', // gray\n };\n const color = colors[landmark.type] || '#888';\n // Draw landmark marker\n ctx.beginPath();\n ctx.moveTo(pos.x, pos.y - 15);\n ctx.lineTo(pos.x + 12, pos.y + 8);\n ctx.lineTo(pos.x - 12, pos.y + 8);\n ctx.closePath();\n ctx.fillStyle = isSelected ? '#e94560' : color;\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n // Entry/exit indicators\n if (landmark.isEntryPoint || landmark.isExitPoint) {\n ctx.beginPath();\n ctx.arc(pos.x, pos.y - 20, 5, 0, Math.PI * 2);\n ctx.fillStyle = landmark.isEntryPoint ? '#4caf50' : '#ff9800';\n ctx.fill();\n }\n // Label\n ctx.fillStyle = '#fff';\n ctx.font = '11px sans-serif';\n ctx.textAlign = 'center';\n ctx.fillText(landmark.name, pos.x, pos.y + 25);\n }\n\n function drawCamera(camera) {\n const pos = camera.floorPlanPosition;\n const isSelected = selectedItem?.type === 'camera' && selectedItem?.id === camera.deviceId;\n\n // Get FOV settings or defaults\n const fov = camera.fov || { mode: 'simple', angle: 90, direction: 0, range: 80 };\n const direction = (fov.mode === 'simple' || !fov.mode) ? (fov.direction || 0) : 0;\n const fovAngle = (fov.mode === 'simple' || !fov.mode) ? (fov.angle || 90) : 90;\n const range = (fov.mode === 'simple' || !fov.mode) ? (fov.range || 80) : 80;\n\n // Convert direction to radians (0 = up/north, 90 = right/east)\n const dirRad = (direction - 90) * Math.PI / 180;\n const halfFov = (fovAngle / 2) * Math.PI / 180;\n\n // Draw FOV cone\n ctx.beginPath();\n ctx.moveTo(pos.x, pos.y);\n ctx.arc(pos.x, pos.y, range, dirRad - halfFov, dirRad + halfFov);\n ctx.closePath();\n ctx.fillStyle = isSelected ? 'rgba(233, 69, 96, 0.15)' : 'rgba(76, 175, 80, 0.15)';\n ctx.fill();\n ctx.strokeStyle = isSelected ? 'rgba(233, 69, 96, 0.5)' : 'rgba(76, 175, 80, 0.5)';\n ctx.lineWidth = 1;\n ctx.stroke();\n\n // Draw camera circle\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, 20, 0, Math.PI * 2);\n ctx.fillStyle = isSelected ? '#e94560' : '#0f3460';\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Draw camera icon/text\n ctx.fillStyle = '#fff';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText('CAM', pos.x, pos.y);\n ctx.fillText(camera.name, pos.x, pos.y + 35);\n\n // Draw direction handle (when selected) for rotation\n if (isSelected) {\n const handleLength = 45;\n const handleX = pos.x + Math.cos(dirRad) * handleLength;\n const handleY = pos.y + Math.sin(dirRad) * handleLength;\n\n // Handle line\n ctx.beginPath();\n ctx.moveTo(pos.x + Math.cos(dirRad) * 20, pos.y + Math.sin(dirRad) * 20);\n ctx.lineTo(handleX, handleY);\n ctx.strokeStyle = '#ff6b6b';\n ctx.lineWidth = 3;\n ctx.stroke();\n\n // Handle grip (circle at end)\n ctx.beginPath();\n ctx.arc(handleX, handleY, 8, 0, Math.PI * 2);\n ctx.fillStyle = '#ff6b6b';\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Store handle position for hit detection\n camera._handlePos = { x: handleX, y: handleY };\n }\n }\n\n function drawConnection(from, to, conn) {\n const isSelected = selectedItem?.type === 'connection' && selectedItem?.id === conn.id;\n ctx.beginPath();\n ctx.moveTo(from.x, from.y);\n ctx.lineTo(to.x, to.y);\n ctx.strokeStyle = isSelected ? '#e94560' : '#4caf50';\n ctx.lineWidth = isSelected ? 4 : 2;\n ctx.stroke();\n if (!conn.bidirectional) {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n ctx.beginPath();\n ctx.moveTo(midX, midY);\n ctx.lineTo(midX - 10 * Math.cos(angle - 0.5), midY - 10 * Math.sin(angle - 0.5));\n ctx.lineTo(midX - 10 * Math.cos(angle + 0.5), midY - 10 * Math.sin(angle + 0.5));\n ctx.closePath();\n ctx.fillStyle = isSelected ? '#e94560' : '#4caf50';\n ctx.fill();\n }\n }\n\n function uploadFloorPlan() { document.getElementById('upload-modal').classList.add('active'); }\n\n // Compress and resize image to avoid 413 errors (Scrypted has ~50KB limit)\n function compressImage(img, maxSize = 800, quality = 0.5) {\n return new Promise((resolve) => {\n const canvas = document.createElement('canvas');\n let width = img.width;\n let height = img.height;\n\n // Always resize to fit within maxSize\n if (width > maxSize || height > maxSize) {\n if (width > height) {\n height = Math.round(height * maxSize / width);\n width = maxSize;\n } else {\n width = Math.round(width * maxSize / height);\n height = maxSize;\n }\n }\n\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n ctx.drawImage(img, 0, 0, width, height);\n\n // Convert to JPEG with aggressive compression\n let compressed = canvas.toDataURL('image/jpeg', quality);\n console.log('Compressed image from', img.width, 'x', img.height, 'to', width, 'x', height, 'size:', Math.round(compressed.length / 1024), 'KB');\n\n // If still too large, compress more\n let q = quality;\n while (compressed.length > 50000 && q > 0.1) {\n q -= 0.1;\n compressed = canvas.toDataURL('image/jpeg', q);\n console.log('Re-compressed at quality', q.toFixed(1), 'size:', Math.round(compressed.length / 1024), 'KB');\n }\n\n resolve(compressed);\n });\n }\n\n async function handleFloorPlanUpload(event) {\n const file = event.target.files[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = async (e) => {\n const originalData = e.target.result;\n\n // Load image to get dimensions\n const img = new Image();\n img.onload = async () => {\n // Compress image to reduce size\n const imageData = await compressImage(img);\n await loadFloorPlanImage(imageData);\n\n // Store floor plan separately via API\n try {\n setStatus('Uploading floor plan...', 'warning');\n const response = await fetch('../api/floor-plan', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ imageData })\n });\n if (response.ok) {\n setStatus('Floor plan saved', 'success');\n } else {\n setStatus('Failed to save floor plan: ' + response.status, 'error');\n console.error('Floor plan upload failed:', response.status, response.statusText);\n }\n } catch (err) {\n console.error('Failed to save floor plan:', err);\n setStatus('Failed to save floor plan', 'error');\n }\n\n // Store reference in topology (without the large imageData)\n topology.floorPlan = { type: 'uploaded', width: floorPlanImage.width, height: floorPlanImage.height };\n closeModal('upload-modal');\n render();\n };\n img.src = originalData;\n };\n reader.readAsDataURL(file);\n }\n\n function loadFloorPlanImage(imageData) {\n return new Promise((resolve) => {\n floorPlanImage = new Image();\n floorPlanImage.onload = resolve;\n floorPlanImage.src = imageData;\n });\n }\n\n function openAddCameraModal() { document.getElementById('add-camera-modal').classList.add('active'); }\n\n function addCamera() {\n const deviceId = document.getElementById('camera-device-select').value;\n if (!deviceId) {\n alert('Please select a camera');\n return;\n }\n const selectedCam = availableCameras.find(c => c.id === deviceId);\n const customName = document.getElementById('camera-name-input').value;\n const name = customName || (selectedCam ? selectedCam.name : 'New Camera');\n const isEntry = document.getElementById('camera-entry-checkbox').checked;\n const isExit = document.getElementById('camera-exit-checkbox').checked;\n // Use pending position from click, or default to center\n const pos = topology._pendingCameraPos || { x: canvas.width / 2 + Math.random() * 100 - 50, y: canvas.height / 2 + Math.random() * 100 - 50 };\n delete topology._pendingCameraPos;\n const camera = {\n deviceId: deviceId,\n nativeId: 'cam-' + Date.now(),\n name,\n isEntryPoint: isEntry,\n isExitPoint: isExit,\n trackClasses: ['person', 'car', 'animal'],\n floorPlanPosition: pos\n };\n topology.cameras.push(camera);\n closeModal('add-camera-modal');\n // Clear form\n document.getElementById('camera-name-input').value = '';\n document.getElementById('camera-entry-checkbox').checked = false;\n document.getElementById('camera-exit-checkbox').checked = false;\n updateCameraSelects();\n updateUI();\n render();\n }\n\n function openAddConnectionModal() {\n if (topology.cameras.length < 2) { alert('Add at least 2 cameras before creating connections'); return; }\n updateCameraSelects();\n document.getElementById('add-connection-modal').classList.add('active');\n }\n\n function updateCameraSelects() {\n // Update camera device select (for adding new cameras)\n const cameraDeviceSelect = document.getElementById('camera-device-select');\n if (availableCameras.length > 0) {\n const existingIds = topology.cameras.map(c => c.deviceId);\n const available = availableCameras.filter(c => !existingIds.includes(c.id));\n if (available.length > 0) {\n cameraDeviceSelect.innerHTML = '<option value=\"\">Select a camera...</option>' +\n available.map(c => '<option value=\"' + c.id + '\">' + c.name + '</option>').join('');\n } else {\n cameraDeviceSelect.innerHTML = '<option value=\"\">All cameras already added</option>';\n }\n } else {\n cameraDeviceSelect.innerHTML = '<option value=\"\">No cameras with object detection found</option>';\n }\n\n // Update connection selects (for existing topology cameras)\n const options = topology.cameras.map(c => '<option value=\"' + c.deviceId + '\">' + c.name + '</option>').join('');\n document.getElementById('connection-from-select').innerHTML = options;\n document.getElementById('connection-to-select').innerHTML = options;\n }\n\n function addConnection() {\n const name = document.getElementById('connection-name-input').value;\n const fromId = document.getElementById('connection-from-select').value;\n const toId = document.getElementById('connection-to-select').value;\n const minTransit = parseInt(document.getElementById('transit-min').value) * 1000;\n const typicalTransit = parseInt(document.getElementById('transit-typical').value) * 1000;\n const maxTransit = parseInt(document.getElementById('transit-max').value) * 1000;\n const bidirectional = document.getElementById('connection-bidirectional').checked;\n if (fromId === toId) { alert('Please select different cameras'); return; }\n const connection = {\n id: 'conn-' + Date.now(),\n fromCameraId: fromId,\n toCameraId: toId,\n name: name || fromId + ' to ' + toId,\n exitZone: [],\n entryZone: [],\n transitTime: { min: minTransit, typical: typicalTransit, max: maxTransit },\n bidirectional\n };\n topology.connections.push(connection);\n closeModal('add-connection-modal');\n updateUI();\n render();\n }\n\n function updateUI() {\n const cameraList = document.getElementById('camera-list');\n if (topology.cameras.length === 0) {\n cameraList.innerHTML = '<div class=\"camera-item\" style=\"color: #666; text-align: center; cursor: default;\">No cameras configured</div>';\n } else {\n cameraList.innerHTML = topology.cameras.map(c => '<div class=\"camera-item ' + (selectedItem?.type === 'camera' && selectedItem?.id === c.deviceId ? 'selected' : '') + '\" onclick=\"selectCamera(\\'' + c.deviceId + '\\')\"><div class=\"camera-name\">CAM ' + c.name + '</div><div class=\"camera-info\">' + (c.isEntryPoint ? 'Entry ' : '') + (c.isExitPoint ? 'Exit' : '') + '</div></div>').join('');\n }\n const connectionList = document.getElementById('connection-list');\n if (topology.connections.length === 0) {\n connectionList.innerHTML = '<div class=\"connection-item\" style=\"color: #666; text-align: center; cursor: default;\">No connections configured</div>';\n } else {\n connectionList.innerHTML = topology.connections.map(c => '<div class=\"connection-item ' + (selectedItem?.type === 'connection' && selectedItem?.id === c.id ? 'selected' : '') + '\" onclick=\"selectConnection(\\'' + c.id + '\\')\"><div class=\"camera-name\">' + c.name + '</div><div class=\"camera-info\">' + (c.transitTime.typical / 1000) + 's typical ' + (c.bidirectional ? '<->' : '->') + '</div></div>').join('');\n }\n // Landmark list\n const landmarkList = document.getElementById('landmark-list');\n const landmarks = topology.landmarks || [];\n if (landmarks.length === 0) {\n landmarkList.innerHTML = '<div class=\"landmark-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No landmarks configured</div>';\n } else {\n landmarkList.innerHTML = landmarks.map(l => '<div class=\"camera-item ' + (selectedItem?.type === 'landmark' && selectedItem?.id === l.id ? 'selected' : '') + '\" onclick=\"selectLandmark(\\'' + l.id + '\\')\"><div class=\"camera-name\">' + l.name + '</div><div class=\"camera-info\">' + l.type + (l.isEntryPoint ? ' | Entry' : '') + (l.isExitPoint ? ' | Exit' : '') + '</div></div>').join('');\n }\n // Zone list\n const zoneList = document.getElementById('zone-list');\n const zones = topology.drawnZones || [];\n if (zones.length === 0) {\n zoneList.innerHTML = '<div class=\"zone-item\" style=\"color: #666; text-align: center; cursor: default; padding: 8px;\">No zones drawn</div>';\n } else {\n zoneList.innerHTML = zones.map(z => {\n const color = ZONE_STROKE_COLORS[z.type] || ZONE_STROKE_COLORS.custom;\n return '<div class=\"camera-item ' + (selectedItem?.type === 'zone' && selectedItem?.id === z.id ? 'selected' : '') + '\" onclick=\"selectZone(\\'' + z.id + '\\')\" style=\"border-left: 3px solid ' + color + ';\"><div class=\"camera-name\">' + z.name + '</div><div class=\"camera-info\">' + z.type + ' | ' + z.polygon.length + ' points</div></div>';\n }).join('');\n }\n document.getElementById('camera-count').textContent = topology.cameras.length;\n document.getElementById('connection-count').textContent = topology.connections.length;\n document.getElementById('landmark-count').textContent = landmarks.length;\n }\n\n function selectCamera(deviceId) {\n selectedItem = { type: 'camera', id: deviceId };\n const camera = topology.cameras.find(c => c.deviceId === deviceId);\n showCameraProperties(camera);\n updateUI();\n render();\n }\n\n function selectConnection(connId) {\n selectedItem = { type: 'connection', id: connId };\n const connection = topology.connections.find(c => c.id === connId);\n showConnectionProperties(connection);\n updateUI();\n render();\n }\n\n function showCameraProperties(camera) {\n const panel = document.getElementById('properties-panel');\n const fov = camera.fov || { mode: 'simple', angle: 90, direction: 0, range: 80 };\n // Convert stored pixel range to feet for display\n const rangeInFeet = Math.round(pixelsToFeet(fov.range || 80));\n panel.innerHTML = '<h3>Camera Properties</h3>' +\n '<div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + camera.name + '\" onchange=\"updateCameraName(\\'' + camera.deviceId + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (camera.isEntryPoint ? 'checked' : '') + ' onchange=\"updateCameraEntry(\\'' + camera.deviceId + '\\', this.checked)\">Entry Point</label></div>' +\n '<div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (camera.isExitPoint ? 'checked' : '') + ' onchange=\"updateCameraExit(\\'' + camera.deviceId + '\\', this.checked)\">Exit Point</label></div>' +\n '<h4 style=\"margin-top: 15px; margin-bottom: 10px; color: #888;\">Field of View</h4>' +\n '<div class=\"form-group\"><label>Direction (0=up, 90=right)</label><input type=\"number\" value=\"' + Math.round(fov.direction || 0) + '\" min=\"0\" max=\"359\" onchange=\"updateCameraFov(\\'' + camera.deviceId + '\\', \\'direction\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>FOV Angle (degrees)</label><input type=\"number\" value=\"' + (fov.angle || 90) + '\" min=\"30\" max=\"180\" onchange=\"updateCameraFov(\\'' + camera.deviceId + '\\', \\'angle\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Range (feet)</label><input type=\"number\" value=\"' + rangeInFeet + '\" min=\"5\" max=\"200\" onchange=\"updateCameraFovRange(\\'' + camera.deviceId + '\\', this.value)\"></div>' +\n '<div style=\"font-size: 11px; color: #666; margin-top: -10px; margin-bottom: 15px;\">~' + (fov.range || 80) + ' pixels at current scale</div>' +\n '<div class=\"form-group\"><button class=\"btn\" style=\"width: 100%; background: #f44336;\" onclick=\"deleteCamera(\\'' + camera.deviceId + '\\')\">Delete Camera</button></div>';\n }\n\n function showConnectionProperties(connection) {\n const panel = document.getElementById('properties-panel');\n panel.innerHTML = '<h3>Connection Properties</h3><div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + connection.name + '\" onchange=\"updateConnectionName(\\'' + connection.id + '\\', this.value)\"></div><div class=\"form-group\"><label>Transit Time (seconds)</label><div class=\"transit-time-inputs\"><input type=\"number\" value=\"' + (connection.transitTime.min / 1000) + '\" onchange=\"updateTransitTime(\\'' + connection.id + '\\', \\'min\\', this.value)\"><input type=\"number\" value=\"' + (connection.transitTime.typical / 1000) + '\" onchange=\"updateTransitTime(\\'' + connection.id + '\\', \\'typical\\', this.value)\"><input type=\"number\" value=\"' + (connection.transitTime.max / 1000) + '\" onchange=\"updateTransitTime(\\'' + connection.id + '\\', \\'max\\', this.value)\"></div><div class=\"transit-time-labels\"><span>Min</span><span>Typical</span><span>Max</span></div></div><div class=\"form-group\"><label class=\"checkbox-group\"><input type=\"checkbox\" ' + (connection.bidirectional ? 'checked' : '') + ' onchange=\"updateConnectionBidi(\\'' + connection.id + '\\', this.checked)\">Bidirectional</label></div><div class=\"form-group\"><button class=\"btn\" style=\"width: 100%; background: #f44336;\" onclick=\"deleteConnection(\\'' + connection.id + '\\')\">Delete Connection</button></div>';\n }\n\n function updateCameraName(id, value) { const camera = topology.cameras.find(c => c.deviceId === id); if (camera) camera.name = value; updateUI(); }\n function updateCameraEntry(id, value) { const camera = topology.cameras.find(c => c.deviceId === id); if (camera) camera.isEntryPoint = value; }\n function updateCameraExit(id, value) { const camera = topology.cameras.find(c => c.deviceId === id); if (camera) camera.isExitPoint = value; }\n function updateCameraFov(id, field, value) {\n const camera = topology.cameras.find(c => c.deviceId === id);\n if (!camera) return;\n if (!camera.fov) camera.fov = { mode: 'simple', angle: 90, direction: 0, range: 80 };\n camera.fov[field] = parseFloat(value);\n render();\n }\n function updateCameraFovRange(id, feetValue) {\n // Convert feet to pixels and store\n const camera = topology.cameras.find(c => c.deviceId === id);\n if (!camera) return;\n if (!camera.fov) camera.fov = { mode: 'simple', angle: 90, direction: 0, range: 80 };\n camera.fov.range = feetToPixels(parseFloat(feetValue));\n render();\n // Update the pixel display\n showCameraProperties(camera);\n }\n function updateScale(value) {\n floorPlanScale = parseFloat(value) || 5;\n // Store in topology for persistence\n topology.floorPlanScale = floorPlanScale;\n render();\n setStatus('Scale updated: ' + floorPlanScale + ' pixels per foot', 'success');\n }\n function openScaleHelper() {\n alert('How to determine your floor plan scale:\\n\\n' +\n '1. Measure a known distance on your floor plan in pixels\\n' +\n ' (e.g., measure a room that you know is 20 feet wide)\\n\\n' +\n '2. Divide the pixel width by the real width in feet\\n' +\n ' Example: 200 pixels / 20 feet = 10 pixels per foot\\n\\n' +\n '3. Enter that value in the scale field\\n\\n' +\n 'Common scales:\\n' +\n '- Small floor plan (fits on screen): 3-5 px/ft\\n' +\n '- Medium floor plan: 5-10 px/ft\\n' +\n '- Large/detailed floor plan: 10-20 px/ft\\n\\n' +\n 'Tip: Most outdoor cameras see 30-50 feet, indoor 15-30 feet');\n }\n function updateConnectionName(id, value) { const conn = topology.connections.find(c => c.id === id); if (conn) conn.name = value; updateUI(); }\n function updateTransitTime(id, field, value) { const conn = topology.connections.find(c => c.id === id); if (conn) conn.transitTime[field] = parseInt(value) * 1000; }\n function updateConnectionBidi(id, value) { const conn = topology.connections.find(c => c.id === id); if (conn) conn.bidirectional = value; render(); }\n function deleteCamera(id) { if (!confirm('Delete this camera?')) return; topology.cameras = topology.cameras.filter(c => c.deviceId !== id); topology.connections = topology.connections.filter(c => c.fromCameraId !== id && c.toCameraId !== id); selectedItem = null; document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select a camera or connection.</p>'; updateCameraSelects(); updateUI(); render(); }\n function deleteConnection(id) { if (!confirm('Delete this connection?')) return; topology.connections = topology.connections.filter(c => c.id !== id); selectedItem = null; document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select a camera or connection.</p>'; updateUI(); render(); }\n function setTool(tool) {\n // If switching away from zone tool while drawing, cancel\n if (currentTool === 'zone' && tool !== 'zone' && zoneDrawingMode) {\n cancelZoneDrawing();\n }\n currentTool = tool;\n setStatus('Tool: ' + tool, 'success');\n document.querySelectorAll('.toolbar .btn').forEach(b => b.style.background = '');\n const btn = document.getElementById('tool-' + tool);\n if (btn) btn.style.background = tool === 'zone' ? '#2e7d32' : '#e94560';\n\n // If zone tool selected, open the zone config modal\n if (tool === 'zone') {\n openZoneModal();\n }\n }\n\n // ==================== Zone Drawing Functions ====================\n\n function openZoneModal() {\n document.getElementById('zone-name-input').value = '';\n document.getElementById('zone-type-select').value = 'yard';\n document.getElementById('zone-desc-input').value = '';\n document.getElementById('add-zone-modal').classList.add('active');\n }\n\n function startZoneDrawing() {\n const name = document.getElementById('zone-name-input').value.trim();\n const type = document.getElementById('zone-type-select').value;\n const description = document.getElementById('zone-desc-input').value.trim();\n\n if (!name) {\n alert('Please enter a zone name');\n return;\n }\n\n pendingZoneConfig = { name, type, description };\n zoneDrawingMode = true;\n currentZonePoints = [];\n closeModal('add-zone-modal');\n setStatus('Zone drawing mode - click to add points, double-click to finish', 'warning');\n render();\n }\n\n function cancelZoneDrawing() {\n zoneDrawingMode = false;\n currentZonePoints = [];\n pendingZoneConfig = null;\n closeModal('add-zone-modal');\n setTool('select');\n setStatus('Zone drawing cancelled', 'success');\n render();\n }\n\n function finishZoneDrawing() {\n if (currentZonePoints.length < 3) {\n alert('A zone needs at least 3 points');\n return;\n }\n\n if (!pendingZoneConfig) {\n cancelZoneDrawing();\n return;\n }\n\n // Create the zone\n const zone = {\n id: 'zone_' + Date.now(),\n name: pendingZoneConfig.name,\n type: pendingZoneConfig.type,\n description: pendingZoneConfig.description || undefined,\n polygon: currentZonePoints.map(pt => ({ x: pt.x, y: pt.y })),\n };\n\n if (!topology.drawnZones) topology.drawnZones = [];\n topology.drawnZones.push(zone);\n\n // Reset state\n zoneDrawingMode = false;\n currentZonePoints = [];\n pendingZoneConfig = null;\n\n setTool('select');\n updateUI();\n render();\n setStatus('Zone \"' + zone.name + '\" created with ' + zone.polygon.length + ' points', 'success');\n }\n\n function selectZone(id) {\n selectedItem = { type: 'zone', id };\n showZoneProperties(id);\n render();\n }\n\n function showZoneProperties(id) {\n const zone = (topology.drawnZones || []).find(z => z.id === id);\n if (!zone) return;\n\n const panel = document.getElementById('properties-panel');\n panel.innerHTML = '<h3>Zone Properties</h3>' +\n '<div class=\"form-group\"><label>Name</label><input type=\"text\" value=\"' + zone.name + '\" onchange=\"updateZoneName(\\'' + id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Type</label><select onchange=\"updateZoneType(\\'' + id + '\\', this.value)\">' +\n ['yard','driveway','street','patio','walkway','parking','garden','pool','garage','entrance','custom'].map(t =>\n '<option value=\"' + t + '\"' + (zone.type === t ? ' selected' : '') + '>' + t.charAt(0).toUpperCase() + t.slice(1) + '</option>'\n ).join('') + '</select></div>' +\n '<div class=\"form-group\"><label>Description</label><input type=\"text\" value=\"' + (zone.description || '') + '\" onchange=\"updateZoneDesc(\\'' + id + '\\', this.value)\"></div>' +\n '<div class=\"form-group\"><label>Points: ' + zone.polygon.length + '</label></div>' +\n '<button class=\"btn btn-primary\" onclick=\"deleteZone(\\'' + id + '\\')\" style=\"background: #dc2626; width: 100%;\">Delete Zone</button>';\n }\n\n function updateZoneName(id, value) { const z = (topology.drawnZones || []).find(z => z.id === id); if (z) { z.name = value; updateUI(); render(); } }\n function updateZoneType(id, value) { const z = (topology.drawnZones || []).find(z => z.id === id); if (z) { z.type = value; updateUI(); render(); } }\n function updateZoneDesc(id, value) { const z = (topology.drawnZones || []).find(z => z.id === id); if (z) { z.description = value || undefined; } }\n function deleteZone(id) {\n if (!confirm('Delete this zone?')) return;\n topology.drawnZones = (topology.drawnZones || []).filter(z => z.id !== id);\n selectedItem = null;\n document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select an item to edit.</p>';\n updateUI();\n render();\n setStatus('Zone deleted', 'success');\n }\n\n function useBlankCanvas() {\n blankCanvasMode = true;\n floorPlanImage = null;\n topology.floorPlan = { type: 'blank', width: canvas.width, height: canvas.height };\n render();\n setStatus('Blank canvas ready - use Draw Wall or Draw Room tools', 'success');\n }\n\n function clearDrawings() {\n if (!confirm('Clear all drawings (walls and rooms)?')) return;\n topology.drawings = [];\n render();\n setStatus('Drawings cleared', 'success');\n }\n\n function clearAllTopology() {\n if (!confirm('DELETE ALL TOPOLOGY DATA?\\n\\nThis will remove:\\n- All cameras\\n- All connections\\n- All landmarks\\n- All zones\\n- All drawings\\n\\nThis cannot be undone.')) return;\n\n topology.cameras = [];\n topology.connections = [];\n topology.landmarks = [];\n topology.globalZones = [];\n topology.drawnZones = [];\n topology.drawings = [];\n topology.relationships = [];\n\n selectedItem = null;\n document.getElementById('properties-panel').innerHTML = '<h3>Properties</h3><p style=\"color: #666;\">Select an item to edit.</p>';\n updateCameraSelects();\n updateUI();\n render();\n setStatus('All topology data cleared', 'warning');\n }\n\n function closeModal(id) { document.getElementById(id).classList.remove('active'); }\n function setStatus(text, type) { document.getElementById('status-text').textContent = text; const dot = document.getElementById('status-dot'); dot.className = 'status-dot'; if (type === 'warning') dot.classList.add('warning'); if (type === 'error') dot.classList.add('error'); }\n\n let dragging = null;\n let rotatingCamera = null;\n\n canvas.addEventListener('mousedown', (e) => {\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n // Handle zone drawing mode separately\n if (zoneDrawingMode) {\n currentZonePoints.push({ x, y });\n render();\n setStatus('Point ' + currentZonePoints.length + ' added. ' + (currentZonePoints.length < 3 ? 'Need at least 3 points.' : 'Double-click or Enter to finish.'), 'warning');\n return;\n }\n\n if (currentTool === 'select') {\n // Check for rotation handle on selected camera first\n if (selectedItem?.type === 'camera') {\n const camera = topology.cameras.find(c => c.deviceId === selectedItem.id);\n if (camera?._handlePos) {\n const dist = Math.hypot(x - camera._handlePos.x, y - camera._handlePos.y);\n if (dist < 15) {\n rotatingCamera = camera;\n setStatus('Drag to rotate camera direction', 'warning');\n return;\n }\n }\n }\n\n // Check cameras\n for (const camera of topology.cameras) {\n if (camera.floorPlanPosition) {\n const dist = Math.hypot(x - camera.floorPlanPosition.x, y - camera.floorPlanPosition.y);\n if (dist < 25) { selectCamera(camera.deviceId); dragging = { type: 'camera', item: camera }; return; }\n }\n }\n // Check landmarks\n for (const landmark of (topology.landmarks || [])) {\n if (landmark.position) {\n const dist = Math.hypot(x - landmark.position.x, y - landmark.position.y);\n if (dist < 20) { selectLandmark(landmark.id); dragging = { type: 'landmark', item: landmark }; return; }\n }\n }\n // Check zones (click inside polygon)\n for (const zone of (topology.drawnZones || [])) {\n if (zone.polygon && isPointInPolygon({ x, y }, zone.polygon)) {\n selectZone(zone.id);\n return;\n }\n }\n } else if (currentTool === 'wall') {\n isDrawing = true;\n drawStart = { x, y };\n currentDrawing = { type: 'wall', x1: x, y1: y, x2: x, y2: y };\n } else if (currentTool === 'room') {\n isDrawing = true;\n drawStart = { x, y };\n currentDrawing = { type: 'room', x: x, y: y, width: 0, height: 0 };\n } else if (currentTool === 'camera') {\n openAddCameraModal();\n topology._pendingCameraPos = { x, y };\n } else if (currentTool === 'landmark') {\n openAddLandmarkModal();\n topology._pendingLandmarkPos = { x, y };\n }\n });\n\n // Double-click to finish zone drawing\n canvas.addEventListener('dblclick', (e) => {\n if (zoneDrawingMode && currentZonePoints.length >= 3) {\n finishZoneDrawing();\n }\n });\n\n // Point-in-polygon test (ray casting algorithm)\n function isPointInPolygon(point, polygon) {\n let inside = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i].x, yi = polygon[i].y;\n const xj = polygon[j].x, yj = polygon[j].y;\n if (((yi > point.y) !== (yj > point.y)) &&\n (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi)) {\n inside = !inside;\n }\n }\n return inside;\n }\n\n canvas.addEventListener('mousemove', (e) => {\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n // Handle camera rotation\n if (rotatingCamera) {\n const pos = rotatingCamera.floorPlanPosition;\n const angle = Math.atan2(y - pos.y, x - pos.x);\n // Convert to our direction system (0 = up/north, 90 = right/east)\n const direction = (angle * 180 / Math.PI) + 90;\n if (!rotatingCamera.fov) {\n rotatingCamera.fov = { mode: 'simple', angle: 90, direction: 0, range: 80 };\n }\n rotatingCamera.fov.direction = ((direction % 360) + 360) % 360; // Normalize 0-360\n render();\n return;\n }\n\n if (dragging) {\n if (dragging.type === 'camera') {\n dragging.item.floorPlanPosition.x = x;\n dragging.item.floorPlanPosition.y = y;\n } else if (dragging.type === 'landmark') {\n dragging.item.position.x = x;\n dragging.item.position.y = y;\n }\n render();\n } else if (isDrawing && currentDrawing) {\n if (currentDrawing.type === 'wall') {\n currentDrawing.x2 = x;\n currentDrawing.y2 = y;\n } else if (currentDrawing.type === 'room') {\n currentDrawing.width = x - drawStart.x;\n currentDrawing.height = y - drawStart.y;\n }\n render();\n }\n });\n\n canvas.addEventListener('mouseup', (e) => {\n // Clear camera rotation\n if (rotatingCamera) {\n setStatus('Camera direction updated', 'success');\n rotatingCamera = null;\n return;\n }\n\n if (isDrawing && currentDrawing) {\n if (!topology.drawings) topology.drawings = [];\n // Normalize room coordinates if drawn backwards\n if (currentDrawing.type === 'room') {\n if (currentDrawing.width < 0) {\n currentDrawing.x += currentDrawing.width;\n currentDrawing.width = Math.abs(currentDrawing.width);\n }\n if (currentDrawing.height < 0) {\n currentDrawing.y += currentDrawing.height;\n currentDrawing.height = Math.abs(currentDrawing.height);\n }\n // Only add if room is big enough\n if (currentDrawing.width > 20 && currentDrawing.height > 20) {\n const label = prompt('Room name (optional):');\n if (label) currentDrawing.label = label;\n topology.drawings.push(currentDrawing);\n }\n } else if (currentDrawing.type === 'wall') {\n // Only add if wall is long enough\n const len = Math.hypot(currentDrawing.x2 - currentDrawing.x1, currentDrawing.y2 - currentDrawing.y1);\n if (len > 20) {\n topology.drawings.push(currentDrawing);\n }\n }\n isDrawing = false;\n currentDrawing = null;\n render();\n }\n dragging = null;\n });\n\n window.addEventListener('resize', () => { resizeCanvas(); render(); });\n\n // Keyboard handler for zone drawing\n document.addEventListener('keydown', (e) => {\n if (zoneDrawingMode) {\n if (e.key === 'Enter' && currentZonePoints.length >= 3) {\n finishZoneDrawing();\n } else if (e.key === 'Escape') {\n cancelZoneDrawing();\n } else if (e.key === 'Backspace' && currentZonePoints.length > 0) {\n currentZonePoints.pop();\n render();\n setStatus('Last point removed. ' + currentZonePoints.length + ' points remaining.', 'warning');\n }\n }\n });\n init();\n <\/script>\n</body>\n</html>"},3885(e,t,n){"use strict";e.exports=n(9844)()},3891(e){function t(e){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}t.keys=()=>[],t.resolve=t,t.id=3891,e.exports=t},3936(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=n(4756),o=i(n(9278)),s=i(n(5753)),a=i(n(6968)),c=(0,s.default)("mqttjs:tls");t.default=(e,t)=>{t.port=t.port||8883,t.host=t.hostname||t.host||"localhost",0===o.default.isIP(t.host)&&(t.servername=t.host),t.rejectUnauthorized=!1!==t.rejectUnauthorized,delete t.path,c("port %d host %s rejectUnauthorized %b",t.port,t.host,t.rejectUnauthorized);const n=function(e){const{host:t,port:n,socksProxy:i,...o}=e;if(void 0!==i){const s=(0,a.default)(t,n,i,{timeout:e.socksTimeout});return(0,r.connect)({...o,socket:s})}return(0,r.connect)(e)}(t);function i(i){t.rejectUnauthorized&&e.emit("error",i),n.end()}return n.on("secureConnect",()=>{t.rejectUnauthorized&&!n.authorized?n.emit("error",new Error("TLS not authorized")):n.removeListener("error",i)}),n.on("error",i),n}},4134(e){"use strict";class t extends Error{constructor(e){if(!Array.isArray(e))throw new TypeError("Expected input to be an Array, got "+typeof e);let t="";for(let n=0;n<e.length;n++)t+=` ${e[n].stack}\n`;super(t),this.name="AggregateError",this.errors=e}}e.exports={AggregateError:t,ArrayIsArray:e=>Array.isArray(e),ArrayPrototypeIncludes:(e,t)=>e.includes(t),ArrayPrototypeIndexOf:(e,t)=>e.indexOf(t),ArrayPrototypeJoin:(e,t)=>e.join(t),ArrayPrototypeMap:(e,t)=>e.map(t),ArrayPrototypePop:(e,t)=>e.pop(t),ArrayPrototypePush:(e,t)=>e.push(t),ArrayPrototypeSlice:(e,t,n)=>e.slice(t,n),Error,FunctionPrototypeCall:(e,t,...n)=>e.call(t,...n),FunctionPrototypeSymbolHasInstance:(e,t)=>Function.prototype[Symbol.hasInstance].call(e,t),MathFloor:Math.floor,Number,NumberIsInteger:Number.isInteger,NumberIsNaN:Number.isNaN,NumberMAX_SAFE_INTEGER:Number.MAX_SAFE_INTEGER,NumberMIN_SAFE_INTEGER:Number.MIN_SAFE_INTEGER,NumberParseInt:Number.parseInt,ObjectDefineProperties:(e,t)=>Object.defineProperties(e,t),ObjectDefineProperty:(e,t,n)=>Object.defineProperty(e,t,n),ObjectGetOwnPropertyDescriptor:(e,t)=>Object.getOwnPropertyDescriptor(e,t),ObjectKeys:e=>Object.keys(e),ObjectSetPrototypeOf:(e,t)=>Object.setPrototypeOf(e,t),Promise,PromisePrototypeCatch:(e,t)=>e.catch(t),PromisePrototypeThen:(e,t,n)=>e.then(t,n),PromiseReject:e=>Promise.reject(e),PromiseResolve:e=>Promise.resolve(e),ReflectApply:Reflect.apply,RegExpPrototypeTest:(e,t)=>e.test(t),SafeSet:Set,String,StringPrototypeSlice:(e,t,n)=>e.slice(t,n),StringPrototypeToLowerCase:e=>e.toLowerCase(),StringPrototypeToUpperCase:e=>e.toUpperCase(),StringPrototypeTrim:e=>e.trim(),Symbol,SymbolFor:Symbol.for,SymbolAsyncIterator:Symbol.asyncIterator,SymbolHasInstance:Symbol.hasInstance,SymbolIterator:Symbol.iterator,SymbolDispose:Symbol.dispose||Symbol("Symbol.dispose"),SymbolAsyncDispose:Symbol.asyncDispose||Symbol("Symbol.asyncDispose"),TypedArrayPrototypeSet:(e,t,n)=>e.set(t,n),Boolean,Uint8Array}},4147(e,t,n){"use strict";const{SymbolDispose:i}=n(4134),{AbortError:r,codes:o}=n(6371),{isNodeStream:s,isWebStream:a,kControllerErrorFunction:c}=n(6115),l=n(6238),{ERR_INVALID_ARG_TYPE:d}=o;let u;e.exports.addAbortSignal=function(t,n){if(((e,t)=>{if("object"!=typeof e||!("aborted"in e))throw new d(t,"AbortSignal",e)})(t,"signal"),!s(n)&&!a(n))throw new d("stream",["ReadableStream","WritableStream","Stream"],n);return e.exports.addAbortSignalNoValidate(t,n)},e.exports.addAbortSignalNoValidate=function(e,t){if("object"!=typeof e||!("aborted"in e))return t;const o=s(t)?()=>{t.destroy(new r(void 0,{cause:e.reason}))}:()=>{t[c](new r(void 0,{cause:e.reason}))};if(e.aborted)o();else{u=u||n(7760).addAbortListener;const r=u(e,o);l(t,r[i])}return t}},4152(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.TypedEventEmitter=void 0;const r=i(n(4434)),o=n(4723);class s{}t.TypedEventEmitter=s,(0,o.applyMixin)(s,r.default)},4192(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ScryptedMimeTypes=t.ScryptedInterface=t.MediaPlayerState=t.SecuritySystemObstruction=t.SecuritySystemMode=t.AirQuality=t.AirPurifierMode=t.AirPurifierStatus=t.ChargeState=t.LockState=t.PanTiltZoomMovement=t.ThermostatMode=t.TemperatureUnit=t.FanMode=t.HumidityMode=t.ScryptedDeviceType=t.ScryptedInterfaceDescriptors=t.ScryptedInterfaceMethod=t.ScryptedInterfaceProperty=t.DeviceBase=t.TYPES_VERSION=void 0,t.TYPES_VERSION="0.5.51";var n,i,r,o,s,a,c,l,d,u,p,h,f,g,m,y,b,v;t.DeviceBase=class{},function(e){e.id="id",e.info="info",e.interfaces="interfaces",e.mixins="mixins",e.name="name",e.nativeId="nativeId",e.pluginId="pluginId",e.providedInterfaces="providedInterfaces",e.providedName="providedName",e.providedRoom="providedRoom",e.providedType="providedType",e.providerId="providerId",e.room="room",e.type="type",e.scryptedRuntimeArguments="scryptedRuntimeArguments",e.on="on",e.brightness="brightness",e.colorTemperature="colorTemperature",e.rgb="rgb",e.hsv="hsv",e.buttons="buttons",e.sensors="sensors",e.running="running",e.paused="paused",e.docked="docked",e.temperatureSetting="temperatureSetting",e.temperature="temperature",e.temperatureUnit="temperatureUnit",e.humidity="humidity",e.resolution="resolution",e.audioVolumes="audioVolumes",e.recordingActive="recordingActive",e.ptzCapabilities="ptzCapabilities",e.lockState="lockState",e.entryOpen="entryOpen",e.batteryLevel="batteryLevel",e.chargeState="chargeState",e.online="online",e.fromMimeType="fromMimeType",e.toMimeType="toMimeType",e.converters="converters",e.binaryState="binaryState",e.tampered="tampered",e.sleeping="sleeping",e.powerDetected="powerDetected",e.audioDetected="audioDetected",e.motionDetected="motionDetected",e.ambientLight="ambientLight",e.occupied="occupied",e.flooded="flooded",e.ultraviolet="ultraviolet",e.luminance="luminance",e.position="position",e.securitySystemState="securitySystemState",e.pm10Density="pm10Density",e.pm25Density="pm25Density",e.vocDensity="vocDensity",e.noxDensity="noxDensity",e.co2ppm="co2ppm",e.airQuality="airQuality",e.airPurifierState="airPurifierState",e.filterChangeIndication="filterChangeIndication",e.filterLifeLevel="filterLifeLevel",e.humiditySetting="humiditySetting",e.fan="fan",e.applicationInfo="applicationInfo",e.chatCompletionCapabilities="chatCompletionCapabilities",e.systemDevice="systemDevice"}(n||(t.ScryptedInterfaceProperty=n={})),function(e){e.listen="listen",e.probe="probe",e.setMixins="setMixins",e.setName="setName",e.setRoom="setRoom",e.setType="setType",e.getPluginJson="getPluginJson",e.turnOff="turnOff",e.turnOn="turnOn",e.setBrightness="setBrightness",e.getTemperatureMaxK="getTemperatureMaxK",e.getTemperatureMinK="getTemperatureMinK",e.setColorTemperature="setColorTemperature",e.setRgb="setRgb",e.setHsv="setHsv",e.pressButton="pressButton",e.sendNotification="sendNotification",e.start="start",e.stop="stop",e.pause="pause",e.resume="resume",e.dock="dock",e.setTemperature="setTemperature",e.setTemperatureUnit="setTemperatureUnit",e.getPictureOptions="getPictureOptions",e.takePicture="takePicture",e.getAudioStream="getAudioStream",e.setAudioVolumes="setAudioVolumes",e.startDisplay="startDisplay",e.stopDisplay="stopDisplay",e.getVideoStream="getVideoStream",e.getVideoStreamOptions="getVideoStreamOptions",e.getPrivacyMasks="getPrivacyMasks",e.setPrivacyMasks="setPrivacyMasks",e.getVideoTextOverlays="getVideoTextOverlays",e.setVideoTextOverlay="setVideoTextOverlay",e.getRecordingStream="getRecordingStream",e.getRecordingStreamCurrentTime="getRecordingStreamCurrentTime",e.getRecordingStreamOptions="getRecordingStreamOptions",e.getRecordingStreamThumbnail="getRecordingStreamThumbnail",e.deleteRecordingStream="deleteRecordingStream",e.setRecordingActive="setRecordingActive",e.ptzCommand="ptzCommand",e.getRecordedEvents="getRecordedEvents",e.getVideoClip="getVideoClip",e.getVideoClips="getVideoClips",e.getVideoClipThumbnail="getVideoClipThumbnail",e.removeVideoClips="removeVideoClips",e.setVideoStreamOptions="setVideoStreamOptions",e.startIntercom="startIntercom",e.stopIntercom="stopIntercom",e.lock="lock",e.unlock="unlock",e.addPassword="addPassword",e.getPasswords="getPasswords",e.removePassword="removePassword",e.activate="activate",e.deactivate="deactivate",e.isReversible="isReversible",e.closeEntry="closeEntry",e.openEntry="openEntry",e.getDevice="getDevice",e.releaseDevice="releaseDevice",e.adoptDevice="adoptDevice",e.discoverDevices="discoverDevices",e.createDevice="createDevice",e.getCreateDeviceSettings="getCreateDeviceSettings",e.reboot="reboot",e.getRefreshFrequency="getRefreshFrequency",e.refresh="refresh",e.getMediaStatus="getMediaStatus",e.load="load",e.seek="seek",e.skipNext="skipNext",e.skipPrevious="skipPrevious",e.convert="convert",e.convertMedia="convertMedia",e.getSettings="getSettings",e.putSetting="putSetting",e.armSecuritySystem="armSecuritySystem",e.disarmSecuritySystem="disarmSecuritySystem",e.setAirPurifierState="setAirPurifierState",e.getReadmeMarkdown="getReadmeMarkdown",e.getOauthUrl="getOauthUrl",e.onOauthCallback="onOauthCallback",e.canMixin="canMixin",e.getMixin="getMixin",e.releaseMixin="releaseMixin",e.onRequest="onRequest",e.onConnection="onConnection",e.onPush="onPush",e.run="run",e.eval="eval",e.loadScripts="loadScripts",e.saveScript="saveScript",e.forkInterface="forkInterface",e.getDetectionInput="getDetectionInput",e.getObjectTypes="getObjectTypes",e.detectObjects="detectObjects",e.generateObjectDetections="generateObjectDetections",e.getDetectionModel="getDetectionModel",e.setHumidity="setHumidity",e.setFan="setFan",e.startRTCSignalingSession="startRTCSignalingSession",e.createRTCSignalingSession="createRTCSignalingSession",e.getScryptedUserAccessControl="getScryptedUserAccessControl",e.generateVideoFrames="generateVideoFrames",e.connectStream="connectStream",e.getTTYSettings="getTTYSettings",e.getChatCompletion="getChatCompletion",e.streamChatCompletion="streamChatCompletion",e.getTextEmbedding="getTextEmbedding",e.getImageEmbedding="getImageEmbedding",e.callLLMTool="callLLMTool",e.getLLMTools="getLLMTools"}(i||(t.ScryptedInterfaceMethod=i={})),t.ScryptedInterfaceDescriptors={ScryptedDevice:{name:"ScryptedDevice",methods:["listen","probe","setMixins","setName","setRoom","setType"],properties:["id","info","interfaces","mixins","name","nativeId","pluginId","providedInterfaces","providedName","providedRoom","providedType","providerId","room","type"]},ScryptedPlugin:{name:"ScryptedPlugin",methods:["getPluginJson"],properties:[]},ScryptedPluginRuntime:{name:"ScryptedPluginRuntime",methods:[],properties:["scryptedRuntimeArguments"]},OnOff:{name:"OnOff",methods:["turnOff","turnOn"],properties:["on"]},Brightness:{name:"Brightness",methods:["setBrightness"],properties:["brightness"]},ColorSettingTemperature:{name:"ColorSettingTemperature",methods:["getTemperatureMaxK","getTemperatureMinK","setColorTemperature"],properties:["colorTemperature"]},ColorSettingRgb:{name:"ColorSettingRgb",methods:["setRgb"],properties:["rgb"]},ColorSettingHsv:{name:"ColorSettingHsv",methods:["setHsv"],properties:["hsv"]},Buttons:{name:"Buttons",methods:[],properties:["buttons"]},PressButtons:{name:"PressButtons",methods:["pressButton"],properties:[]},Sensors:{name:"Sensors",methods:[],properties:["sensors"]},Notifier:{name:"Notifier",methods:["sendNotification"],properties:[]},StartStop:{name:"StartStop",methods:["start","stop"],properties:["running"]},Pause:{name:"Pause",methods:["pause","resume"],properties:["paused"]},Dock:{name:"Dock",methods:["dock"],properties:["docked"]},TemperatureSetting:{name:"TemperatureSetting",methods:["setTemperature"],properties:["temperatureSetting"]},Thermometer:{name:"Thermometer",methods:["setTemperatureUnit"],properties:["temperature","temperatureUnit"]},HumiditySensor:{name:"HumiditySensor",methods:[],properties:["humidity"]},Camera:{name:"Camera",methods:["getPictureOptions","takePicture"],properties:[]},Resolution:{name:"Resolution",methods:[],properties:["resolution"]},Microphone:{name:"Microphone",methods:["getAudioStream"],properties:[]},AudioVolumeControl:{name:"AudioVolumeControl",methods:["setAudioVolumes"],properties:["audioVolumes"]},Display:{name:"Display",methods:["startDisplay","stopDisplay"],properties:[]},VideoCamera:{name:"VideoCamera",methods:["getVideoStream","getVideoStreamOptions"],properties:[]},VideoCameraMask:{name:"VideoCameraMask",methods:["getPrivacyMasks","setPrivacyMasks"],properties:[]},VideoTextOverlays:{name:"VideoTextOverlays",methods:["getVideoTextOverlays","setVideoTextOverlay"],properties:[]},VideoRecorder:{name:"VideoRecorder",methods:["getRecordingStream","getRecordingStreamCurrentTime","getRecordingStreamOptions","getRecordingStreamThumbnail"],properties:["recordingActive"]},VideoRecorderManagement:{name:"VideoRecorderManagement",methods:["deleteRecordingStream","setRecordingActive"],properties:[]},PanTiltZoom:{name:"PanTiltZoom",methods:["ptzCommand"],properties:["ptzCapabilities"]},EventRecorder:{name:"EventRecorder",methods:["getRecordedEvents"],properties:[]},VideoClips:{name:"VideoClips",methods:["getVideoClip","getVideoClips","getVideoClipThumbnail","removeVideoClips"],properties:[]},VideoCameraConfiguration:{name:"VideoCameraConfiguration",methods:["setVideoStreamOptions"],properties:[]},Intercom:{name:"Intercom",methods:["startIntercom","stopIntercom"],properties:[]},Lock:{name:"Lock",methods:["lock","unlock"],properties:["lockState"]},PasswordStore:{name:"PasswordStore",methods:["addPassword","getPasswords","removePassword"],properties:[]},Scene:{name:"Scene",methods:["activate","deactivate","isReversible"],properties:[]},Entry:{name:"Entry",methods:["closeEntry","openEntry"],properties:[]},EntrySensor:{name:"EntrySensor",methods:[],properties:["entryOpen"]},DeviceProvider:{name:"DeviceProvider",methods:["getDevice","releaseDevice"],properties:[]},DeviceDiscovery:{name:"DeviceDiscovery",methods:["adoptDevice","discoverDevices"],properties:[]},DeviceCreator:{name:"DeviceCreator",methods:["createDevice","getCreateDeviceSettings"],properties:[]},Battery:{name:"Battery",methods:[],properties:["batteryLevel"]},Charger:{name:"Charger",methods:[],properties:["chargeState"]},Reboot:{name:"Reboot",methods:["reboot"],properties:[]},Refresh:{name:"Refresh",methods:["getRefreshFrequency","refresh"],properties:[]},MediaPlayer:{name:"MediaPlayer",methods:["getMediaStatus","load","seek","skipNext","skipPrevious"],properties:[]},Online:{name:"Online",methods:[],properties:["online"]},BufferConverter:{name:"BufferConverter",methods:["convert"],properties:["fromMimeType","toMimeType"]},MediaConverter:{name:"MediaConverter",methods:["convertMedia"],properties:["converters"]},Settings:{name:"Settings",methods:["getSettings","putSetting"],properties:[]},BinarySensor:{name:"BinarySensor",methods:[],properties:["binaryState"]},TamperSensor:{name:"TamperSensor",methods:[],properties:["tampered"]},Sleep:{name:"Sleep",methods:[],properties:["sleeping"]},PowerSensor:{name:"PowerSensor",methods:[],properties:["powerDetected"]},AudioSensor:{name:"AudioSensor",methods:[],properties:["audioDetected"]},MotionSensor:{name:"MotionSensor",methods:[],properties:["motionDetected"]},AmbientLightSensor:{name:"AmbientLightSensor",methods:[],properties:["ambientLight"]},OccupancySensor:{name:"OccupancySensor",methods:[],properties:["occupied"]},FloodSensor:{name:"FloodSensor",methods:[],properties:["flooded"]},UltravioletSensor:{name:"UltravioletSensor",methods:[],properties:["ultraviolet"]},LuminanceSensor:{name:"LuminanceSensor",methods:[],properties:["luminance"]},PositionSensor:{name:"PositionSensor",methods:[],properties:["position"]},SecuritySystem:{name:"SecuritySystem",methods:["armSecuritySystem","disarmSecuritySystem"],properties:["securitySystemState"]},PM10Sensor:{name:"PM10Sensor",methods:[],properties:["pm10Density"]},PM25Sensor:{name:"PM25Sensor",methods:[],properties:["pm25Density"]},VOCSensor:{name:"VOCSensor",methods:[],properties:["vocDensity"]},NOXSensor:{name:"NOXSensor",methods:[],properties:["noxDensity"]},CO2Sensor:{name:"CO2Sensor",methods:[],properties:["co2ppm"]},AirQualitySensor:{name:"AirQualitySensor",methods:[],properties:["airQuality"]},AirPurifier:{name:"AirPurifier",methods:["setAirPurifierState"],properties:["airPurifierState"]},FilterMaintenance:{name:"FilterMaintenance",methods:[],properties:["filterChangeIndication","filterLifeLevel"]},Readme:{name:"Readme",methods:["getReadmeMarkdown"],properties:[]},OauthClient:{name:"OauthClient",methods:["getOauthUrl","onOauthCallback"],properties:[]},MixinProvider:{name:"MixinProvider",methods:["canMixin","getMixin","releaseMixin"],properties:[]},HttpRequestHandler:{name:"HttpRequestHandler",methods:["onRequest"],properties:[]},EngineIOHandler:{name:"EngineIOHandler",methods:["onConnection"],properties:[]},PushHandler:{name:"PushHandler",methods:["onPush"],properties:[]},Program:{name:"Program",methods:["run"],properties:[]},Scriptable:{name:"Scriptable",methods:["eval","loadScripts","saveScript"],properties:[]},ClusterForkInterface:{name:"ClusterForkInterface",methods:["forkInterface"],properties:[]},ObjectDetector:{name:"ObjectDetector",methods:["getDetectionInput","getObjectTypes"],properties:[]},ObjectDetection:{name:"ObjectDetection",methods:["detectObjects","generateObjectDetections","getDetectionModel"],properties:[]},ObjectDetectionPreview:{name:"ObjectDetectionPreview",methods:[],properties:[]},ObjectDetectionGenerator:{name:"ObjectDetectionGenerator",methods:[],properties:[]},HumiditySetting:{name:"HumiditySetting",methods:["setHumidity"],properties:["humiditySetting"]},Fan:{name:"Fan",methods:["setFan"],properties:["fan"]},RTCSignalingChannel:{name:"RTCSignalingChannel",methods:["startRTCSignalingSession"],properties:[]},RTCSignalingClient:{name:"RTCSignalingClient",methods:["createRTCSignalingSession"],properties:[]},LauncherApplication:{name:"LauncherApplication",methods:[],properties:["applicationInfo"]},ScryptedUser:{name:"ScryptedUser",methods:["getScryptedUserAccessControl"],properties:[]},VideoFrameGenerator:{name:"VideoFrameGenerator",methods:["generateVideoFrames"],properties:[]},StreamService:{name:"StreamService",methods:["connectStream"],properties:[]},TTY:{name:"TTY",methods:[],properties:[]},TTYSettings:{name:"TTYSettings",methods:["getTTYSettings"],properties:[]},ChatCompletion:{name:"ChatCompletion",methods:["getChatCompletion","streamChatCompletion"],properties:["chatCompletionCapabilities"]},TextEmbedding:{name:"TextEmbedding",methods:["getTextEmbedding"],properties:[]},ImageEmbedding:{name:"ImageEmbedding",methods:["getImageEmbedding"],properties:[]},LLMTools:{name:"LLMTools",methods:["callLLMTool","getLLMTools"],properties:[]},ScryptedSystemDevice:{name:"ScryptedSystemDevice",methods:[],properties:["systemDevice"]},ScryptedDeviceCreator:{name:"ScryptedDeviceCreator",methods:[],properties:[]},ScryptedSettings:{name:"ScryptedSettings",methods:[],properties:[]}},function(e){e.Builtin="Builtin",e.Internal="Internal",e.Camera="Camera",e.Fan="Fan",e.Light="Light",e.Switch="Switch",e.Outlet="Outlet",e.Sensor="Sensor",e.Scene="Scene",e.Program="Program",e.Automation="Automation",e.Vacuum="Vacuum",e.Notifier="Notifier",e.Thermostat="Thermostat",e.Lock="Lock",e.PasswordControl="PasswordControl",e.Display="Display",e.SmartDisplay="SmartDisplay",e.Speaker="Speaker",e.SmartSpeaker="SmartSpeaker",e.RemoteDesktop="RemoteDesktop",e.Event="Event",e.Entry="Entry",e.Garage="Garage",e.DeviceProvider="DeviceProvider",e.DataSource="DataSource",e.API="API",e.Buttons="Buttons",e.Doorbell="Doorbell",e.Irrigation="Irrigation",e.Valve="Valve",e.Person="Person",e.SecuritySystem="SecuritySystem",e.WindowCovering="WindowCovering",e.Siren="Siren",e.AirPurifier="AirPurifier",e.Internet="Internet",e.Network="Network",e.Bridge="Bridge",e.LLM="LLM",e.Unknown="Unknown"}(r||(t.ScryptedDeviceType=r={})),function(e){e.Humidify="Humidify",e.Dehumidify="Dehumidify",e.Auto="Auto",e.Off="Off"}(o||(t.HumidityMode=o={})),function(e){e.Auto="Auto",e.Manual="Manual"}(s||(t.FanMode=s={})),function(e){e.C="C",e.F="F"}(a||(t.TemperatureUnit=a={})),function(e){e.Off="Off",e.Cool="Cool",e.Heat="Heat",e.HeatCool="HeatCool",e.Auto="Auto",e.FanOnly="FanOnly",e.Purifier="Purifier",e.Eco="Eco",e.Dry="Dry",e.On="On"}(c||(t.ThermostatMode=c={})),function(e){e.Absolute="Absolute",e.Relative="Relative",e.Continuous="Continuous",e.Preset="Preset",e.Home="Home"}(l||(t.PanTiltZoomMovement=l={})),function(e){e.Locked="Locked",e.Unlocked="Unlocked",e.Jammed="Jammed"}(d||(t.LockState=d={})),function(e){e.Trickle="trickle",e.Charging="charging",e.NotCharging="not-charging"}(u||(t.ChargeState=u={})),function(e){e.Inactive="Inactive",e.Idle="Idle",e.Active="Active",e.ActiveNightMode="ActiveNightMode"}(p||(t.AirPurifierStatus=p={})),function(e){e.Manual="Manual",e.Automatic="Automatic"}(h||(t.AirPurifierMode=h={})),function(e){e.Unknown="Unknown",e.Excellent="Excellent",e.Good="Good",e.Fair="Fair",e.Inferior="Inferior",e.Poor="Poor"}(f||(t.AirQuality=f={})),function(e){e.Disarmed="Disarmed",e.HomeArmed="HomeArmed",e.AwayArmed="AwayArmed",e.NightArmed="NightArmed"}(g||(t.SecuritySystemMode=g={})),function(e){e.Sensor="Sensor",e.Occupied="Occupied",e.Time="Time",e.Error="Error"}(m||(t.SecuritySystemObstruction=m={})),function(e){e.Idle="Idle",e.Playing="Playing",e.Paused="Paused",e.Buffering="Buffering"}(y||(t.MediaPlayerState=y={})),function(e){e.ScryptedDevice="ScryptedDevice",e.ScryptedPlugin="ScryptedPlugin",e.ScryptedPluginRuntime="ScryptedPluginRuntime",e.OnOff="OnOff",e.Brightness="Brightness",e.ColorSettingTemperature="ColorSettingTemperature",e.ColorSettingRgb="ColorSettingRgb",e.ColorSettingHsv="ColorSettingHsv",e.Buttons="Buttons",e.PressButtons="PressButtons",e.Sensors="Sensors",e.Notifier="Notifier",e.StartStop="StartStop",e.Pause="Pause",e.Dock="Dock",e.TemperatureSetting="TemperatureSetting",e.Thermometer="Thermometer",e.HumiditySensor="HumiditySensor",e.Camera="Camera",e.Resolution="Resolution",e.Microphone="Microphone",e.AudioVolumeControl="AudioVolumeControl",e.Display="Display",e.VideoCamera="VideoCamera",e.VideoCameraMask="VideoCameraMask",e.VideoTextOverlays="VideoTextOverlays",e.VideoRecorder="VideoRecorder",e.VideoRecorderManagement="VideoRecorderManagement",e.PanTiltZoom="PanTiltZoom",e.EventRecorder="EventRecorder",e.VideoClips="VideoClips",e.VideoCameraConfiguration="VideoCameraConfiguration",e.Intercom="Intercom",e.Lock="Lock",e.PasswordStore="PasswordStore",e.Scene="Scene",e.Entry="Entry",e.EntrySensor="EntrySensor",e.DeviceProvider="DeviceProvider",e.DeviceDiscovery="DeviceDiscovery",e.DeviceCreator="DeviceCreator",e.Battery="Battery",e.Charger="Charger",e.Reboot="Reboot",e.Refresh="Refresh",e.MediaPlayer="MediaPlayer",e.Online="Online",e.BufferConverter="BufferConverter",e.MediaConverter="MediaConverter",e.Settings="Settings",e.BinarySensor="BinarySensor",e.TamperSensor="TamperSensor",e.Sleep="Sleep",e.PowerSensor="PowerSensor",e.AudioSensor="AudioSensor",e.MotionSensor="MotionSensor",e.AmbientLightSensor="AmbientLightSensor",e.OccupancySensor="OccupancySensor",e.FloodSensor="FloodSensor",e.UltravioletSensor="UltravioletSensor",e.LuminanceSensor="LuminanceSensor",e.PositionSensor="PositionSensor",e.SecuritySystem="SecuritySystem",e.PM10Sensor="PM10Sensor",e.PM25Sensor="PM25Sensor",e.VOCSensor="VOCSensor",e.NOXSensor="NOXSensor",e.CO2Sensor="CO2Sensor",e.AirQualitySensor="AirQualitySensor",e.AirPurifier="AirPurifier",e.FilterMaintenance="FilterMaintenance",e.Readme="Readme",e.OauthClient="OauthClient",e.MixinProvider="MixinProvider",e.HttpRequestHandler="HttpRequestHandler",e.EngineIOHandler="EngineIOHandler",e.PushHandler="PushHandler",e.Program="Program",e.Scriptable="Scriptable",e.ClusterForkInterface="ClusterForkInterface",e.ObjectDetector="ObjectDetector",e.ObjectDetection="ObjectDetection",e.ObjectDetectionPreview="ObjectDetectionPreview",e.ObjectDetectionGenerator="ObjectDetectionGenerator",e.HumiditySetting="HumiditySetting",e.Fan="Fan",e.RTCSignalingChannel="RTCSignalingChannel",e.RTCSignalingClient="RTCSignalingClient",e.LauncherApplication="LauncherApplication",e.ScryptedUser="ScryptedUser",e.VideoFrameGenerator="VideoFrameGenerator",e.StreamService="StreamService",e.TTY="TTY",e.TTYSettings="TTYSettings",e.ChatCompletion="ChatCompletion",e.TextEmbedding="TextEmbedding",e.ImageEmbedding="ImageEmbedding",e.LLMTools="LLMTools",e.ScryptedSystemDevice="ScryptedSystemDevice",e.ScryptedDeviceCreator="ScryptedDeviceCreator",e.ScryptedSettings="ScryptedSettings"}(b||(t.ScryptedInterface=b={})),function(e){e.Url="text/x-uri",e.InsecureLocalUrl="text/x-insecure-local-uri",e.LocalUrl="text/x-local-uri",e.ServerId="text/x-server-id",e.PushEndpoint="text/x-push-endpoint",e.SchemePrefix="x-scrypted/x-scrypted-scheme-",e.MediaStreamUrl="text/x-media-url",e.MediaObject="x-scrypted/x-scrypted-media-object",e.RequestMediaObject="x-scrypted/x-scrypted-request-media-object",e.RequestMediaStream="x-scrypted/x-scrypted-request-stream",e.MediaStreamFeedback="x-scrypted/x-media-stream-feedback",e.FFmpegInput="x-scrypted/x-ffmpeg-input",e.FFmpegTranscodeStream="x-scrypted/x-ffmpeg-transcode-stream",e.RTCSignalingChannel="x-scrypted/x-scrypted-rtc-signaling-channel",e.RTCSignalingSession="x-scrypted/x-scrypted-rtc-signaling-session",e.RTCConnectionManagement="x-scrypted/x-scrypted-rtc-connection-management",e.Image="x-scrypted/x-scrypted-image"}(v||(t.ScryptedMimeTypes=v={}))},4259(e,t,n){"use strict";const{ArrayIsArray:i,ObjectSetPrototypeOf:r}=n(4134),{EventEmitter:o}=n(4434);function s(e){o.call(this,e)}function a(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?i(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}r(s.prototype,o.prototype),r(s,o),s.prototype.pipe=function(e,t){const n=this;function i(t){e.writable&&!1===e.write(t)&&n.pause&&n.pause()}function r(){n.readable&&n.resume&&n.resume()}n.on("data",i),e.on("drain",r),e._isStdio||t&&!1===t.end||(n.on("end",c),n.on("close",l));let s=!1;function c(){s||(s=!0,e.end())}function l(){s||(s=!0,"function"==typeof e.destroy&&e.destroy())}function d(e){u(),0===o.listenerCount(this,"error")&&this.emit("error",e)}function u(){n.removeListener("data",i),e.removeListener("drain",r),n.removeListener("end",c),n.removeListener("close",l),n.removeListener("error",d),e.removeListener("error",d),n.removeListener("end",u),n.removeListener("close",u),e.removeListener("close",u)}return a(n,"error",d),a(e,"error",d),n.on("end",u),n.on("close",u),e.on("close",u),e.emit("pipe",n),e},e.exports={Stream:s,prependListener:a}},4264(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.default=(e,t,n)=>{e.log("handling pubrel packet");const i="undefined"!=typeof n?n:e.noop,{messageId:r}=t,o={cmd:"pubcomp",messageId:r};e.incomingStore.get(t,(t,n)=>{t?e._sendPacket(o,i):(e.emit("message",n.topic,n.payload,n),e.handleMessage(n,t=>{if(t)return i(t);e.incomingStore.del(n,e.noop),e._sendPacket(o,i)}))})}},4386(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.AlertManager=void 0;const a=s(n(7562)),c=n(4997),{systemManager:l,mediaManager:d}=a.default;t.AlertManager=class{rules=[];recentAlerts=[];cooldowns=new Map;console;storage;maxAlerts=100;constructor(e,t){this.console=e,this.storage=t,this.loadRules()}async checkAndAlert(e,t,n){const i=this.rules.find(t=>t.type===e&&t.enabled);if(!i)return null;if(i.objectClasses&&i.objectClasses.length>0&&!i.objectClasses.includes(t.className))return null;if(i.cameraIds&&i.cameraIds.length>0&&n.cameraId&&!i.cameraIds.includes(n.cameraId))return null;const r=`${i.id}:${t.globalId}`,o=this.cooldowns.get(r)||0;if(i.cooldown>0&&Date.now()-o<i.cooldown)return null;if(!this.evaluateConditions(i.conditions,t))return null;const s={...n,objectClass:t.className,objectLabel:n.objectLabel||t.label},a=(0,c.createAlert)(e,t.globalId,s,i.severity,i.id);return this.recentAlerts.unshift(a),this.recentAlerts.length>this.maxAlerts&&this.recentAlerts.pop(),this.cooldowns.set(r,Date.now()),await this.sendNotifications(a,i),this.console.log(`Alert generated: [${a.severity}] ${a.message}`),a}async sendNotifications(e,t){const n=t.notifiers.length>0?t.notifiers:this.getDefaultNotifiers();let i;const r=e.details.toCameraId||e.details.cameraId;if(r)try{const e=l.getDeviceById(r);e&&e.interfaces?.includes(a.ScryptedInterface.Camera)&&(i=await e.takePicture())}catch(e){this.console.warn(`Failed to get thumbnail from camera ${r}:`,e)}for(const t of n)try{const n=l.getDeviceById(t);if(!n){this.console.warn(`Notifier not found: ${t}`);continue}await n.sendNotification(this.getNotificationTitle(e),{body:e.message,data:{type:e.type,severity:e.severity,trackedObjectId:e.trackedObjectId,timestamp:e.timestamp}},i),this.console.log(`Notification sent to ${t}${i?" with thumbnail":""}`)}catch(e){this.console.error(`Failed to send notification to ${t}:`,e)}}getNotificationTitle(e){const t="critical"===e.severity?"🚨 ":"warning"===e.severity?"⚠️ ":"",n=e.details.objectClass?e.details.objectClass.charAt(0).toUpperCase()+e.details.objectClass.slice(1):"Object";switch(e.type){case"property_entry":return`${t}${n} Arrived`;case"property_exit":return`${t}${n} Left`;case"movement":return`${t}${n} → ${e.details.toCameraName||"area"}`;case"unusual_path":return`${t}Unusual Route`;case"dwell_time":return`${t}${n} Lingering`;case"restricted_zone":return`${t}Restricted Zone!`;case"lost_tracking":return`${t}${n} Lost`;case"reappearance":return`${t}${n} Reappeared`;default:return`${t}Spatial Alert`}}getDefaultNotifiers(){try{const e=this.storage.getItem("defaultNotifiers");if(e)try{const t=JSON.parse(e);if(Array.isArray(t))return t}catch{return e.includes(",")?e.split(",").map(e=>e.trim()).filter(Boolean):[e]}const t=this.storage.getItem("defaultNotifier");return t?[t]:[]}catch{return[]}}evaluateConditions(e,t){for(const n of e){const e=this.getFieldValue(n.field,t);switch(n.operator){case"equals":if(e!==n.value)return!1;break;case"not_equals":if(e===n.value)return!1;break;case"contains":if(!String(e).includes(String(n.value)))return!1;break;case"greater_than":if(Number(e)<=Number(n.value))return!1;break;case"less_than":if(Number(e)>=Number(n.value))return!1}}return!0}getFieldValue(e,t){const n=e.split(".");let i=t;for(const e of n){if(null==i)return;i=i[e]}return i}getRecentAlerts(e=50){return this.recentAlerts.slice(0,e)}acknowledgeAlert(e){const t=this.recentAlerts.find(t=>t.id===e);return!!t&&(t.acknowledged=!0,!0)}getAlertsForObject(e){return this.recentAlerts.filter(t=>t.trackedObjectId===e)}setRules(e){this.rules=e,this.saveRules()}getRules(){return this.rules}upsertRule(e){const t=this.rules.findIndex(t=>t.id===e.id);t>=0?this.rules[t]=e:this.rules.push(e),this.saveRules()}deleteRule(e){const t=this.rules.findIndex(t=>t.id===e);return t>=0&&(this.rules.splice(t,1),this.saveRules(),!0)}setRuleEnabled(e,t){const n=this.rules.find(t=>t.id===e);return!!n&&(n.enabled=t,this.saveRules(),!0)}loadRules(){try{const e=this.storage.getItem("alertRules");this.rules=e?JSON.parse(e):(0,c.createDefaultRules)()}catch(e){this.console.error("Failed to load alert rules:",e),this.rules=(0,c.createDefaultRules)()}}saveRules(){try{this.storage.setItem("alertRules",JSON.stringify(this.rules))}catch(e){this.console.error("Failed to save alert rules:",e)}}clearCooldowns(){this.cooldowns.clear()}clearHistory(){this.recentAlerts=[]}}},4422(e){e.exports=global.process},4434(e){"use strict";e.exports=require("events")},4478(e,t,n){"use strict";const i=n(2203);if(i&&"disable"===process.env.READABLE_STREAM){const t=i.promises;e.exports._uint8ArrayToBuffer=i._uint8ArrayToBuffer,e.exports._isUint8Array=i._isUint8Array,e.exports.isDisturbed=i.isDisturbed,e.exports.isErrored=i.isErrored,e.exports.isReadable=i.isReadable,e.exports.Readable=i.Readable,e.exports.Writable=i.Writable,e.exports.Duplex=i.Duplex,e.exports.Transform=i.Transform,e.exports.PassThrough=i.PassThrough,e.exports.addAbortSignal=i.addAbortSignal,e.exports.finished=i.finished,e.exports.destroy=i.destroy,e.exports.pipeline=i.pipeline,e.exports.compose=i.compose,Object.defineProperty(i,"promises",{configurable:!0,enumerable:!0,get:()=>t}),e.exports.Stream=i.Stream}else{const t=n(5506),i=n(3095),r=t.Readable.destroy;e.exports=t.Readable,e.exports._uint8ArrayToBuffer=t._uint8ArrayToBuffer,e.exports._isUint8Array=t._isUint8Array,e.exports.isDisturbed=t.isDisturbed,e.exports.isErrored=t.isErrored,e.exports.isReadable=t.isReadable,e.exports.Readable=t.Readable,e.exports.Writable=t.Writable,e.exports.Duplex=t.Duplex,e.exports.Transform=t.Transform,e.exports.PassThrough=t.PassThrough,e.exports.addAbortSignal=t.addAbortSignal,e.exports.finished=t.finished,e.exports.destroy=t.destroy,e.exports.destroy=r,e.exports.pipeline=t.pipeline,e.exports.compose=t.compose,Object.defineProperty(t,"promises",{configurable:!0,enumerable:!0,get:()=>i}),e.exports.Stream=t.Stream}e.exports.default=e.exports},4723(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.MQTTJS_VERSION=t.nextTick=t.ErrorWithSubackPacket=t.ErrorWithReasonCode=void 0,t.applyMixin=function(e,t,n=!1){const i=[t];for(;;){const e=i[0],t=Object.getPrototypeOf(e);if(!t?.prototype)break;i.unshift(t)}for(const t of i)for(const i of Object.getOwnPropertyNames(t.prototype))(n||"constructor"!==i)&&Object.defineProperty(e.prototype,i,Object.getOwnPropertyDescriptor(t.prototype,i)??Object.create(null))};class i extends Error{code;constructor(e,t){super(e),this.code=t,Object.setPrototypeOf(this,i.prototype),Object.getPrototypeOf(this).name="ErrorWithReasonCode"}}t.ErrorWithReasonCode=i;class r extends Error{packet;constructor(e,t){super(e),this.packet=t,Object.setPrototypeOf(this,r.prototype),Object.getPrototypeOf(this).name="ErrorWithSubackPacket"}}t.ErrorWithSubackPacket=r,t.nextTick="function"==typeof process?.nextTick?process.nextTick:e=>{setTimeout(e,0)},t.MQTTJS_VERSION=n(2860).version},4756(e){"use strict";e.exports=require("tls")},4759(e){"use strict";const t=Symbol("kDone"),n=Symbol("kRun");e.exports=class{constructor(e){this[t]=()=>{this.pending--,this[n]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[n]()}[n](){if(this.pending!==this.concurrency&&this.jobs.length){const e=this.jobs.shift();this.pending++,e(this[t])}}}},4829(e,t,n){"use strict";const i=n(4478).Duplex,r=n(2017),o=n(7813);function s(e){if(!(this instanceof s))return new s(e);if("function"==typeof e){this._callback=e;const t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)}),e=null}o._init.call(this,e),i.call(this)}r(s,i),Object.assign(s.prototype,o.prototype),s.prototype._new=function(e){return new s(e)},s.prototype._write=function(e,t,n){this._appendBuffer(e),"function"==typeof n&&n()},s.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)},s.prototype.end=function(e){i.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)},s.prototype._destroy=function(e,t){this._bufs.length=0,this.length=0,t(e)},s.prototype._isBufferList=function(e){return e instanceof s||e instanceof o||s.isBufferList(e)},s.isBufferList=o.isBufferList,e.exports=s,e.exports.BufferListStream=s,e.exports.BufferList=o},4959(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=[0,16,128,131,135,144,145,151,153];t.default=(e,t,i)=>{e.log("handlePublish: packet %o",t),i="undefined"!=typeof i?i:e.noop;let r=t.topic.toString();const o=t.payload,{qos:s}=t,{messageId:a}=t,{options:c}=e;if(5===e.options.protocolVersion){let n;if(t.properties&&(n=t.properties.topicAlias),"undefined"!=typeof n)if(0===r.length){if(!(n>0&&n<=65535))return e.log("handlePublish :: topic alias out of range. alias: %d",n),void e.emit("error",new Error("Received Topic Alias is out of range"));{const t=e.topicAliasRecv.getTopicByAlias(n);if(!t)return e.log("handlePublish :: unregistered topic alias. alias: %d",n),void e.emit("error",new Error("Received unregistered Topic Alias"));r=t,e.log("handlePublish :: topic complemented by alias. topic: %s - alias: %d",r,n)}}else{if(!e.topicAliasRecv.put(r,n))return e.log("handlePublish :: topic alias out of range. alias: %d",n),void e.emit("error",new Error("Received Topic Alias is out of range"));e.log("handlePublish :: registered topic: %s - alias: %d",r,n)}}switch(e.log("handlePublish: qos %d",s),s){case 2:c.customHandleAcks(r,o,t,(r,o)=>("number"==typeof r&&(o=r,r=null),r?e.emit("error",r):-1===n.indexOf(o)?e.emit("error",new Error("Wrong reason code for pubrec")):void(o?e._sendPacket({cmd:"pubrec",messageId:a,reasonCode:o},i):e.incomingStore.put(t,()=>{e._sendPacket({cmd:"pubrec",messageId:a},i)}))));break;case 1:c.customHandleAcks(r,o,t,(s,c)=>("number"==typeof s&&(c=s,s=null),s?e.emit("error",s):-1===n.indexOf(c)?e.emit("error",new Error("Wrong reason code for puback")):(c||e.emit("message",r,o,t),void e.handleMessage(t,t=>{if(t)return i&&i(t);e._sendPacket({cmd:"puback",messageId:a,reasonCode:c},i)}))));break;case 0:e.emit("message",r,o,t),e.handleMessage(t,i);break;default:e.log("handlePublish: unknown QoS. Doing nothing.")}}},4966(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.LRUCache=void 0;const n="object"==typeof performance&&performance&&"function"==typeof performance.now?performance:Date,i=new Set,r="object"==typeof process&&process?process:{},o=(e,t,n,i)=>{"function"==typeof r.emitWarning?r.emitWarning(e,t,n,i):console.error(`[${n}] ${t}: ${e}`)};let s=globalThis.AbortController,a=globalThis.AbortSignal;if("undefined"==typeof s){a=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(e,t){this._onabort.push(t)}},s=class{constructor(){t()}signal=new a;abort(e){if(!this.signal.aborted){this.signal.reason=e,this.signal.aborted=!0;for(const t of this.signal._onabort)t(e);this.signal.onabort?.(e)}}};let e="1"!==r.env?.LRU_CACHE_IGNORE_AC_WARNING;const t=()=>{e&&(e=!1,o("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}Symbol("type");const c=e=>e&&e===Math.floor(e)&&e>0&&isFinite(e),l=e=>c(e)?e<=Math.pow(2,8)?Uint8Array:e<=Math.pow(2,16)?Uint16Array:e<=Math.pow(2,32)?Uint32Array:e<=Number.MAX_SAFE_INTEGER?d:null:null;class d extends Array{constructor(e){super(e),this.fill(0)}}class u{heap;length;static#e=!1;static create(e){const t=l(e);if(!t)return[];u.#e=!0;const n=new u(e,t);return u.#e=!1,n}constructor(e,t){if(!u.#e)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new t(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}}class p{#t;#n;#i;#r;#o;#s;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#a;#c;#l;#d;#u;#p;#h;#f;#g;#m;#y;#b;#v;#S;#_;#w;#k;static unsafeExposeInternals(e){return{starts:e.#v,ttls:e.#S,sizes:e.#b,keyMap:e.#l,keyList:e.#d,valList:e.#u,next:e.#p,prev:e.#h,get head(){return e.#f},get tail(){return e.#g},free:e.#m,isBackgroundFetch:t=>e.#I(t),backgroundFetch:(t,n,i,r)=>e.#x(t,n,i,r),moveToTail:t=>e.#C(t),indexes:t=>e.#E(t),rindexes:t=>e.#T(t),isStale:t=>e.#O(t)}}get max(){return this.#t}get maxSize(){return this.#n}get calculatedSize(){return this.#c}get size(){return this.#a}get fetchMethod(){return this.#o}get memoMethod(){return this.#s}get dispose(){return this.#i}get disposeAfter(){return this.#r}constructor(e){const{max:t=0,ttl:n,ttlResolution:r=1,ttlAutopurge:s,updateAgeOnGet:a,updateAgeOnHas:d,allowStale:h,dispose:f,disposeAfter:g,noDisposeOnSet:m,noUpdateTTL:y,maxSize:b=0,maxEntrySize:v=0,sizeCalculation:S,fetchMethod:_,memoMethod:w,noDeleteOnFetchRejection:k,noDeleteOnStaleGet:I,allowStaleOnFetchRejection:x,allowStaleOnFetchAbort:C,ignoreFetchAbort:E}=e;if(0!==t&&!c(t))throw new TypeError("max option must be a nonnegative integer");const T=t?l(t):Array;if(!T)throw new Error("invalid max value: "+t);if(this.#t=t,this.#n=b,this.maxEntrySize=v||this.#n,this.sizeCalculation=S,this.sizeCalculation){if(!this.#n&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if("function"!=typeof this.sizeCalculation)throw new TypeError("sizeCalculation set to non-function")}if(void 0!==w&&"function"!=typeof w)throw new TypeError("memoMethod must be a function if defined");if(this.#s=w,void 0!==_&&"function"!=typeof _)throw new TypeError("fetchMethod must be a function if specified");if(this.#o=_,this.#w=!!_,this.#l=new Map,this.#d=new Array(t).fill(void 0),this.#u=new Array(t).fill(void 0),this.#p=new T(t),this.#h=new T(t),this.#f=0,this.#g=0,this.#m=u.create(t),this.#a=0,this.#c=0,"function"==typeof f&&(this.#i=f),"function"==typeof g?(this.#r=g,this.#y=[]):(this.#r=void 0,this.#y=void 0),this.#_=!!this.#i,this.#k=!!this.#r,this.noDisposeOnSet=!!m,this.noUpdateTTL=!!y,this.noDeleteOnFetchRejection=!!k,this.allowStaleOnFetchRejection=!!x,this.allowStaleOnFetchAbort=!!C,this.ignoreFetchAbort=!!E,0!==this.maxEntrySize){if(0!==this.#n&&!c(this.#n))throw new TypeError("maxSize must be a positive integer if specified");if(!c(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#P()}if(this.allowStale=!!h,this.noDeleteOnStaleGet=!!I,this.updateAgeOnGet=!!a,this.updateAgeOnHas=!!d,this.ttlResolution=c(r)||0===r?r:1,this.ttlAutopurge=!!s,this.ttl=n||0,this.ttl){if(!c(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#A()}if(0===this.#t&&0===this.ttl&&0===this.#n)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#t&&!this.#n){const e="LRU_CACHE_UNBOUNDED";if((e=>!i.has(e))(e)){i.add(e);o("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",e,p)}}}getRemainingTTL(e){return this.#l.has(e)?1/0:0}#A(){const e=new d(this.#t),t=new d(this.#t);this.#S=e,this.#v=t,this.#R=(i,r,o=n.now())=>{if(t[i]=0!==r?o:0,e[i]=r,0!==r&&this.ttlAutopurge){const e=setTimeout(()=>{this.#O(i)&&this.#M(this.#d[i],"expire")},r+1);e.unref&&e.unref()}},this.#L=i=>{t[i]=0!==e[i]?n.now():0},this.#N=(n,o)=>{if(e[o]){const s=e[o],a=t[o];if(!s||!a)return;n.ttl=s,n.start=a,n.now=i||r();const c=n.now-a;n.remainingTTL=s-c}};let i=0;const r=()=>{const e=n.now();if(this.ttlResolution>0){i=e;const t=setTimeout(()=>i=0,this.ttlResolution);t.unref&&t.unref()}return e};this.getRemainingTTL=n=>{const o=this.#l.get(n);if(void 0===o)return 0;const s=e[o],a=t[o];if(!s||!a)return 1/0;return s-((i||r())-a)},this.#O=n=>{const o=t[n],s=e[n];return!!s&&!!o&&(i||r())-o>s}}#L=()=>{};#N=()=>{};#R=()=>{};#O=()=>!1;#P(){const e=new d(this.#t);this.#c=0,this.#b=e,this.#D=t=>{this.#c-=e[t],e[t]=0},this.#B=(e,t,n,i)=>{if(this.#I(t))return 0;if(!c(n)){if(!i)throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");if("function"!=typeof i)throw new TypeError("sizeCalculation must be a function");if(n=i(t,e),!c(n))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}return n},this.#j=(t,n,i)=>{if(e[t]=n,this.#n){const n=this.#n-e[t];for(;this.#c>n;)this.#$(!0)}this.#c+=e[t],i&&(i.entrySize=n,i.totalCalculatedSize=this.#c)}}#D=e=>{};#j=(e,t,n)=>{};#B=(e,t,n,i)=>{if(n||i)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#E({allowStale:e=this.allowStale}={}){if(this.#a)for(let t=this.#g;this.#F(t)&&(!e&&this.#O(t)||(yield t),t!==this.#f);)t=this.#h[t]}*#T({allowStale:e=this.allowStale}={}){if(this.#a)for(let t=this.#f;this.#F(t)&&(!e&&this.#O(t)||(yield t),t!==this.#g);)t=this.#p[t]}#F(e){return void 0!==e&&this.#l.get(this.#d[e])===e}*entries(){for(const e of this.#E())void 0===this.#u[e]||void 0===this.#d[e]||this.#I(this.#u[e])||(yield[this.#d[e],this.#u[e]])}*rentries(){for(const e of this.#T())void 0===this.#u[e]||void 0===this.#d[e]||this.#I(this.#u[e])||(yield[this.#d[e],this.#u[e]])}*keys(){for(const e of this.#E()){const t=this.#d[e];void 0===t||this.#I(this.#u[e])||(yield t)}}*rkeys(){for(const e of this.#T()){const t=this.#d[e];void 0===t||this.#I(this.#u[e])||(yield t)}}*values(){for(const e of this.#E()){void 0===this.#u[e]||this.#I(this.#u[e])||(yield this.#u[e])}}*rvalues(){for(const e of this.#T()){void 0===this.#u[e]||this.#I(this.#u[e])||(yield this.#u[e])}}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(e,t={}){for(const n of this.#E()){const i=this.#u[n],r=this.#I(i)?i.__staleWhileFetching:i;if(void 0!==r&&e(r,this.#d[n],this))return this.get(this.#d[n],t)}}forEach(e,t=this){for(const n of this.#E()){const i=this.#u[n],r=this.#I(i)?i.__staleWhileFetching:i;void 0!==r&&e.call(t,r,this.#d[n],this)}}rforEach(e,t=this){for(const n of this.#T()){const i=this.#u[n],r=this.#I(i)?i.__staleWhileFetching:i;void 0!==r&&e.call(t,r,this.#d[n],this)}}purgeStale(){let e=!1;for(const t of this.#T({allowStale:!0}))this.#O(t)&&(this.#M(this.#d[t],"expire"),e=!0);return e}info(e){const t=this.#l.get(e);if(void 0===t)return;const i=this.#u[t],r=this.#I(i)?i.__staleWhileFetching:i;if(void 0===r)return;const o={value:r};if(this.#S&&this.#v){const e=this.#S[t],i=this.#v[t];if(e&&i){const t=e-(n.now()-i);o.ttl=t,o.start=Date.now()}}return this.#b&&(o.size=this.#b[t]),o}dump(){const e=[];for(const t of this.#E({allowStale:!0})){const i=this.#d[t],r=this.#u[t],o=this.#I(r)?r.__staleWhileFetching:r;if(void 0===o||void 0===i)continue;const s={value:o};if(this.#S&&this.#v){s.ttl=this.#S[t];const e=n.now()-this.#v[t];s.start=Math.floor(Date.now()-e)}this.#b&&(s.size=this.#b[t]),e.unshift([i,s])}return e}load(e){this.clear();for(const[t,i]of e){if(i.start){const e=Date.now()-i.start;i.start=n.now()-e}this.set(t,i.value,i)}}set(e,t,n={}){if(void 0===t)return this.delete(e),this;const{ttl:i=this.ttl,start:r,noDisposeOnSet:o=this.noDisposeOnSet,sizeCalculation:s=this.sizeCalculation,status:a}=n;let{noUpdateTTL:c=this.noUpdateTTL}=n;const l=this.#B(e,t,n.size||0,s);if(this.maxEntrySize&&l>this.maxEntrySize)return a&&(a.set="miss",a.maxEntrySizeExceeded=!0),this.#M(e,"set"),this;let d=0===this.#a?void 0:this.#l.get(e);if(void 0===d)d=0===this.#a?this.#g:0!==this.#m.length?this.#m.pop():this.#a===this.#t?this.#$(!1):this.#a,this.#d[d]=e,this.#u[d]=t,this.#l.set(e,d),this.#p[this.#g]=d,this.#h[d]=this.#g,this.#g=d,this.#a++,this.#j(d,l,a),a&&(a.set="add"),c=!1;else{this.#C(d);const n=this.#u[d];if(t!==n){if(this.#w&&this.#I(n)){n.__abortController.abort(new Error("replaced"));const{__staleWhileFetching:t}=n;void 0===t||o||(this.#_&&this.#i?.(t,e,"set"),this.#k&&this.#y?.push([t,e,"set"]))}else o||(this.#_&&this.#i?.(n,e,"set"),this.#k&&this.#y?.push([n,e,"set"]));if(this.#D(d),this.#j(d,l,a),this.#u[d]=t,a){a.set="replace";const e=n&&this.#I(n)?n.__staleWhileFetching:n;void 0!==e&&(a.oldValue=e)}}else a&&(a.set="update")}if(0===i||this.#S||this.#A(),this.#S&&(c||this.#R(d,i,r),a&&this.#N(a,d)),!o&&this.#k&&this.#y){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}return this}pop(){try{for(;this.#a;){const e=this.#u[this.#f];if(this.#$(!0),this.#I(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(void 0!==e)return e}}finally{if(this.#k&&this.#y){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}}}#$(e){const t=this.#f,n=this.#d[t],i=this.#u[t];return this.#w&&this.#I(i)?i.__abortController.abort(new Error("evicted")):(this.#_||this.#k)&&(this.#_&&this.#i?.(i,n,"evict"),this.#k&&this.#y?.push([i,n,"evict"])),this.#D(t),e&&(this.#d[t]=void 0,this.#u[t]=void 0,this.#m.push(t)),1===this.#a?(this.#f=this.#g=0,this.#m.length=0):this.#f=this.#p[t],this.#l.delete(n),this.#a--,t}has(e,t={}){const{updateAgeOnHas:n=this.updateAgeOnHas,status:i}=t,r=this.#l.get(e);if(void 0!==r){const e=this.#u[r];if(this.#I(e)&&void 0===e.__staleWhileFetching)return!1;if(!this.#O(r))return n&&this.#L(r),i&&(i.has="hit",this.#N(i,r)),!0;i&&(i.has="stale",this.#N(i,r))}else i&&(i.has="miss");return!1}peek(e,t={}){const{allowStale:n=this.allowStale}=t,i=this.#l.get(e);if(void 0===i||!n&&this.#O(i))return;const r=this.#u[i];return this.#I(r)?r.__staleWhileFetching:r}#x(e,t,n,i){const r=void 0===t?void 0:this.#u[t];if(this.#I(r))return r;const o=new s,{signal:a}=n;a?.addEventListener("abort",()=>o.abort(a.reason),{signal:o.signal});const c={signal:o.signal,options:n,context:i},l=(i,r=!1)=>{const{aborted:s}=o.signal,a=n.ignoreFetchAbort&&void 0!==i;if(n.status&&(s&&!r?(n.status.fetchAborted=!0,n.status.fetchError=o.signal.reason,a&&(n.status.fetchAbortIgnored=!0)):n.status.fetchResolved=!0),s&&!a&&!r)return d(o.signal.reason);const l=u;return this.#u[t]===u&&(void 0===i?l.__staleWhileFetching?this.#u[t]=l.__staleWhileFetching:this.#M(e,"fetch"):(n.status&&(n.status.fetchUpdated=!0),this.set(e,i,c.options))),i},d=i=>{const{aborted:r}=o.signal,s=r&&n.allowStaleOnFetchAbort,a=s||n.allowStaleOnFetchRejection,c=a||n.noDeleteOnFetchRejection,l=u;if(this.#u[t]===u){!c||void 0===l.__staleWhileFetching?this.#M(e,"fetch"):s||(this.#u[t]=l.__staleWhileFetching)}if(a)return n.status&&void 0!==l.__staleWhileFetching&&(n.status.returnedStale=!0),l.__staleWhileFetching;if(l.__returned===l)throw i};n.status&&(n.status.fetchDispatched=!0);const u=new Promise((t,i)=>{const s=this.#o?.(e,r,c);s&&s instanceof Promise&&s.then(e=>t(void 0===e?void 0:e),i),o.signal.addEventListener("abort",()=>{n.ignoreFetchAbort&&!n.allowStaleOnFetchAbort||(t(void 0),n.allowStaleOnFetchAbort&&(t=e=>l(e,!0)))})}).then(l,e=>(n.status&&(n.status.fetchRejected=!0,n.status.fetchError=e),d(e))),p=Object.assign(u,{__abortController:o,__staleWhileFetching:r,__returned:void 0});return void 0===t?(this.set(e,p,{...c.options,status:void 0}),t=this.#l.get(e)):this.#u[t]=p,p}#I(e){if(!this.#w)return!1;const t=e;return!!t&&t instanceof Promise&&t.hasOwnProperty("__staleWhileFetching")&&t.__abortController instanceof s}async fetch(e,t={}){const{allowStale:n=this.allowStale,updateAgeOnGet:i=this.updateAgeOnGet,noDeleteOnStaleGet:r=this.noDeleteOnStaleGet,ttl:o=this.ttl,noDisposeOnSet:s=this.noDisposeOnSet,size:a=0,sizeCalculation:c=this.sizeCalculation,noUpdateTTL:l=this.noUpdateTTL,noDeleteOnFetchRejection:d=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:u=this.allowStaleOnFetchRejection,ignoreFetchAbort:p=this.ignoreFetchAbort,allowStaleOnFetchAbort:h=this.allowStaleOnFetchAbort,context:f,forceRefresh:g=!1,status:m,signal:y}=t;if(!this.#w)return m&&(m.fetch="get"),this.get(e,{allowStale:n,updateAgeOnGet:i,noDeleteOnStaleGet:r,status:m});const b={allowStale:n,updateAgeOnGet:i,noDeleteOnStaleGet:r,ttl:o,noDisposeOnSet:s,size:a,sizeCalculation:c,noUpdateTTL:l,noDeleteOnFetchRejection:d,allowStaleOnFetchRejection:u,allowStaleOnFetchAbort:h,ignoreFetchAbort:p,status:m,signal:y};let v=this.#l.get(e);if(void 0===v){m&&(m.fetch="miss");const t=this.#x(e,v,b,f);return t.__returned=t}{const t=this.#u[v];if(this.#I(t)){const e=n&&void 0!==t.__staleWhileFetching;return m&&(m.fetch="inflight",e&&(m.returnedStale=!0)),e?t.__staleWhileFetching:t.__returned=t}const r=this.#O(v);if(!g&&!r)return m&&(m.fetch="hit"),this.#C(v),i&&this.#L(v),m&&this.#N(m,v),t;const o=this.#x(e,v,b,f),s=void 0!==o.__staleWhileFetching&&n;return m&&(m.fetch=r?"stale":"refresh",s&&r&&(m.returnedStale=!0)),s?o.__staleWhileFetching:o.__returned=o}}async forceFetch(e,t={}){const n=await this.fetch(e,t);if(void 0===n)throw new Error("fetch() returned undefined");return n}memo(e,t={}){const n=this.#s;if(!n)throw new Error("no memoMethod provided to constructor");const{context:i,forceRefresh:r,...o}=t,s=this.get(e,o);if(!r&&void 0!==s)return s;const a=n(e,s,{options:o,context:i});return this.set(e,a,o),a}get(e,t={}){const{allowStale:n=this.allowStale,updateAgeOnGet:i=this.updateAgeOnGet,noDeleteOnStaleGet:r=this.noDeleteOnStaleGet,status:o}=t,s=this.#l.get(e);if(void 0!==s){const t=this.#u[s],a=this.#I(t);return o&&this.#N(o,s),this.#O(s)?(o&&(o.get="stale"),a?(o&&n&&void 0!==t.__staleWhileFetching&&(o.returnedStale=!0),n?t.__staleWhileFetching:void 0):(r||this.#M(e,"expire"),o&&n&&(o.returnedStale=!0),n?t:void 0)):(o&&(o.get="hit"),a?t.__staleWhileFetching:(this.#C(s),i&&this.#L(s),t))}o&&(o.get="miss")}#U(e,t){this.#h[t]=e,this.#p[e]=t}#C(e){e!==this.#g&&(e===this.#f?this.#f=this.#p[e]:this.#U(this.#h[e],this.#p[e]),this.#U(this.#g,e),this.#g=e)}delete(e){return this.#M(e,"delete")}#M(e,t){let n=!1;if(0!==this.#a){const i=this.#l.get(e);if(void 0!==i)if(n=!0,1===this.#a)this.#z(t);else{this.#D(i);const n=this.#u[i];if(this.#I(n)?n.__abortController.abort(new Error("deleted")):(this.#_||this.#k)&&(this.#_&&this.#i?.(n,e,t),this.#k&&this.#y?.push([n,e,t])),this.#l.delete(e),this.#d[i]=void 0,this.#u[i]=void 0,i===this.#g)this.#g=this.#h[i];else if(i===this.#f)this.#f=this.#p[i];else{const e=this.#h[i];this.#p[e]=this.#p[i];const t=this.#p[i];this.#h[t]=this.#h[i]}this.#a--,this.#m.push(i)}}if(this.#k&&this.#y?.length){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}return n}clear(){return this.#z("delete")}#z(e){for(const t of this.#T({allowStale:!0})){const n=this.#u[t];if(this.#I(n))n.__abortController.abort(new Error("deleted"));else{const i=this.#d[t];this.#_&&this.#i?.(n,i,e),this.#k&&this.#y?.push([n,i,e])}}if(this.#l.clear(),this.#u.fill(void 0),this.#d.fill(void 0),this.#S&&this.#v&&(this.#S.fill(0),this.#v.fill(0)),this.#b&&this.#b.fill(0),this.#f=0,this.#g=0,this.#m.length=0,this.#c=0,this.#a=0,this.#k&&this.#y){const e=this.#y;let t;for(;t=e?.shift();)this.#r?.(...t)}}}t.LRUCache=p},4988(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const n=new WeakMap,i=new WeakMap;function r(e){const t=n.get(e);return console.assert(null!=t,"'this' is expected an Event object, but got",e),t}function o(e){null==e.passiveListener?e.event.cancelable&&(e.canceled=!0,"function"==typeof e.event.preventDefault&&e.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",e.passiveListener)}function s(e,t){n.set(this,{eventTarget:e,event:t,eventPhase:2,currentTarget:e,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:t.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});const i=Object.keys(t);for(let e=0;e<i.length;++e){const t=i[e];t in this||Object.defineProperty(this,t,a(t))}}function a(e){return{get(){return r(this).event[e]},set(t){r(this).event[e]=t},configurable:!0,enumerable:!0}}function c(e){return{value(){const t=r(this).event;return t[e].apply(t,arguments)},configurable:!0,enumerable:!0}}function l(e){if(null==e||e===Object.prototype)return s;let t=i.get(e);return null==t&&(t=function(e,t){const n=Object.keys(t);if(0===n.length)return e;function i(t,n){e.call(this,t,n)}i.prototype=Object.create(e.prototype,{constructor:{value:i,configurable:!0,writable:!0}});for(let r=0;r<n.length;++r){const o=n[r];if(!(o in e.prototype)){const e="function"==typeof Object.getOwnPropertyDescriptor(t,o).value;Object.defineProperty(i.prototype,o,e?c(o):a(o))}}return i}(l(Object.getPrototypeOf(e)),e),i.set(e,t)),t}function d(e){return r(e).immediateStopped}function u(e,t){r(e).passiveListener=t}s.prototype={get type(){return r(this).event.type},get target(){return r(this).eventTarget},get currentTarget(){return r(this).currentTarget},composedPath(){const e=r(this).currentTarget;return null==e?[]:[e]},get NONE(){return 0},get CAPTURING_PHASE(){return 1},get AT_TARGET(){return 2},get BUBBLING_PHASE(){return 3},get eventPhase(){return r(this).eventPhase},stopPropagation(){const e=r(this);e.stopped=!0,"function"==typeof e.event.stopPropagation&&e.event.stopPropagation()},stopImmediatePropagation(){const e=r(this);e.stopped=!0,e.immediateStopped=!0,"function"==typeof e.event.stopImmediatePropagation&&e.event.stopImmediatePropagation()},get bubbles(){return Boolean(r(this).event.bubbles)},get cancelable(){return Boolean(r(this).event.cancelable)},preventDefault(){o(r(this))},get defaultPrevented(){return r(this).canceled},get composed(){return Boolean(r(this).event.composed)},get timeStamp(){return r(this).timeStamp},get srcElement(){return r(this).eventTarget},get cancelBubble(){return r(this).stopped},set cancelBubble(e){if(!e)return;const t=r(this);t.stopped=!0,"boolean"==typeof t.event.cancelBubble&&(t.event.cancelBubble=!0)},get returnValue(){return!r(this).canceled},set returnValue(e){e||o(r(this))},initEvent(){}},Object.defineProperty(s.prototype,"constructor",{value:s,configurable:!0,writable:!0}),"undefined"!=typeof window&&"undefined"!=typeof window.Event&&(Object.setPrototypeOf(s.prototype,window.Event.prototype),i.set(window.Event.prototype,s));const p=new WeakMap;function h(e){return null!==e&&"object"==typeof e}function f(e){const t=p.get(e);if(null==t)throw new TypeError("'this' is expected an EventTarget object, but got another value.");return t}function g(e,t){Object.defineProperty(e,`on${t}`,function(e){return{get(){let t=f(this).get(e);for(;null!=t;){if(3===t.listenerType)return t.listener;t=t.next}return null},set(t){"function"==typeof t||h(t)||(t=null);const n=f(this);let i=null,r=n.get(e);for(;null!=r;)3===r.listenerType?null!==i?i.next=r.next:null!==r.next?n.set(e,r.next):n.delete(e):i=r,r=r.next;if(null!==t){const r={listener:t,listenerType:3,passive:!1,once:!1,next:null};null===i?n.set(e,r):i.next=r}},configurable:!0,enumerable:!0}}(t))}function m(e){function t(){y.call(this)}t.prototype=Object.create(y.prototype,{constructor:{value:t,configurable:!0,writable:!0}});for(let n=0;n<e.length;++n)g(t.prototype,e[n]);return t}function y(){if(!(this instanceof y)){if(1===arguments.length&&Array.isArray(arguments[0]))return m(arguments[0]);if(arguments.length>0){const e=new Array(arguments.length);for(let t=0;t<arguments.length;++t)e[t]=arguments[t];return m(e)}throw new TypeError("Cannot call a class as a function")}p.set(this,new Map)}y.prototype={addEventListener(e,t,n){if(null==t)return;if("function"!=typeof t&&!h(t))throw new TypeError("'listener' should be a function or an object.");const i=f(this),r=h(n),o=(r?Boolean(n.capture):Boolean(n))?1:2,s={listener:t,listenerType:o,passive:r&&Boolean(n.passive),once:r&&Boolean(n.once),next:null};let a=i.get(e);if(void 0===a)return void i.set(e,s);let c=null;for(;null!=a;){if(a.listener===t&&a.listenerType===o)return;c=a,a=a.next}c.next=s},removeEventListener(e,t,n){if(null==t)return;const i=f(this),r=(h(n)?Boolean(n.capture):Boolean(n))?1:2;let o=null,s=i.get(e);for(;null!=s;){if(s.listener===t&&s.listenerType===r)return void(null!==o?o.next=s.next:null!==s.next?i.set(e,s.next):i.delete(e));o=s,s=s.next}},dispatchEvent(e){if(null==e||"string"!=typeof e.type)throw new TypeError('"event.type" should be a string.');const t=f(this),n=e.type;let i=t.get(n);if(null==i)return!0;const o=function(e,t){return new(l(Object.getPrototypeOf(t)))(e,t)}(this,e);let s=null;for(;null!=i;){if(i.once?null!==s?s.next=i.next:null!==i.next?t.set(n,i.next):t.delete(n):s=i,u(o,i.passive?i.listener:null),"function"==typeof i.listener)try{i.listener.call(this,o)}catch(e){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(e)}else 3!==i.listenerType&&"function"==typeof i.listener.handleEvent&&i.listener.handleEvent(o);if(d(o))break;i=i.next}return u(o,null),function(e,t){r(e).eventPhase=t}(o,0),function(e,t){r(e).currentTarget=t}(o,null),!o.defaultPrevented}},Object.defineProperty(y.prototype,"constructor",{value:y,configurable:!0,writable:!0}),"undefined"!=typeof window&&"undefined"!=typeof window.EventTarget&&Object.setPrototypeOf(y.prototype,window.EventTarget.prototype),t.defineEventAttribute=g,t.EventTarget=y,t.default=y,e.exports=y,e.exports.EventTarget=e.exports.default=y,e.exports.defineEventAttribute=g},4997(e,t){"use strict";function n(e,t){const n=e=>e?e.charAt(0).toUpperCase()+e.slice(1):"Object",i=t.objectLabel?`${n(t.objectClass||"")} (${t.objectLabel})`:n(t.objectClass||"");switch(e){case"property_entry":return t.objectLabel&&t.objectLabel!==t.objectClass?t.objectLabel:t.involvedLandmarks&&t.involvedLandmarks.length>0?`${i} entered property near ${t.involvedLandmarks[0]}`:`${i} entered property at ${t.cameraName||"entrance"}`;case"property_exit":return t.objectLabel&&t.objectLabel!==t.objectClass?t.objectLabel:t.involvedLandmarks&&t.involvedLandmarks.length>0?`${i} left property via ${t.involvedLandmarks[0]}`:`${i} left property`;case"movement":if(t.objectLabel&&t.objectLabel!==t.objectClass){if(t.fromCameraId&&t.fromCameraId!==t.toCameraId&&t.transitTime){const e=Math.round(t.transitTime/1e3),n=e>0?` (${e}s)`:"",i=t.pathDescription?` via ${t.pathDescription}`:"";return`${t.objectLabel}${i}${n}`}return t.objectLabel}if(t.fromCameraId&&t.fromCameraId!==t.toCameraId){const e=t.transitTime?Math.round(t.transitTime/1e3):0,n=e>0?` (${e}s transit)`:"";let r=`${i} moving from ${t.fromCameraName||"unknown"} towards ${t.toCameraName||"unknown"}`;return t.involvedLandmarks&&t.involvedLandmarks.length>0&&(r+=` near ${t.involvedLandmarks.join(", ")}`),`${r}${n}`}return t.involvedLandmarks&&t.involvedLandmarks.length>0?`${i} detected near ${t.involvedLandmarks[0]}`:`${i} detected at ${t.cameraName||"camera"}`;case"unusual_path":return`${i} took unusual path: ${t.actualPath||"unknown"}`;case"dwell_time":return`${i} has been present for ${Math.round((t.dwellTime||0)/6e4)} minutes in ${t.zoneName||t.cameraName||"area"}`;case"restricted_zone":return`${i} entered restricted zone: ${t.zoneName}`;case"lost_tracking":return`Lost tracking of ${i} near ${t.cameraName||"unknown location"}`;case"reappearance":return`${i} reappeared on ${t.cameraName}`;case"zone_entry":return`${i} entered ${t.zoneName}`;case"zone_exit":return`${i} exited ${t.zoneName}`;default:return`Tracking event: ${e}`}}Object.defineProperty(t,"__esModule",{value:!0}),t.createDefaultRules=function(){return[{id:"property-entry",name:"Property Entry",enabled:!0,type:"property_entry",conditions:[],severity:"info",notifiers:[],cooldown:6e4},{id:"property-exit",name:"Property Exit",enabled:!0,type:"property_exit",conditions:[],severity:"info",notifiers:[],cooldown:6e4},{id:"movement",name:"Movement Between Cameras",enabled:!0,type:"movement",conditions:[],severity:"info",notifiers:[],cooldown:1e4},{id:"unusual-path",name:"Unusual Path Detected",enabled:!0,type:"unusual_path",conditions:[],severity:"warning",notifiers:[],cooldown:6e5},{id:"dwell-time",name:"Extended Dwell Time",enabled:!0,type:"dwell_time",conditions:[{field:"totalDwellTime",operator:"greater_than",value:3e5}],severity:"warning",notifiers:[],cooldown:6e5},{id:"restricted-zone",name:"Restricted Zone Entry",enabled:!0,type:"restricted_zone",conditions:[],severity:"critical",notifiers:[],cooldown:0},{id:"lost-tracking",name:"Lost Object Tracking",enabled:!1,type:"lost_tracking",conditions:[],severity:"info",notifiers:[],cooldown:3e5}]},t.generateAlertMessage=n,t.createAlert=function(e,t,i,r="info",o){return{id:`${Date.now()}-${Math.random().toString(36).slice(2,9)}`,type:e,severity:r,timestamp:Date.now(),trackedObjectId:t,message:n(e,i),details:i,acknowledged:!1,ruleId:o}}},5228(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(4723),r=n(1021);t.default=(e,t)=>{const{options:n}=e,o=n.protocolVersion,s=5===o?t.reasonCode:t.returnCode;if(5!==o){const t=new i.ErrorWithReasonCode(`Protocol error: Auth packets are only supported in MQTT 5. Your version:${o}`,s);return void e.emit("error",t)}e.handleAuth(t,(t,n)=>{if(t)e.emit("error",t);else if(24===s)e.reconnecting=!1,e._sendPacket(n);else{const t=new i.ErrorWithReasonCode(`Connection refused: ${r.ReasonCodes[s]}`,s);e.emit("error",t)}})}},5291(e,t,n){"use strict";const{MathFloor:i,NumberIsInteger:r}=n(4134),{validateInteger:o}=n(277),{ERR_INVALID_ARG_VALUE:s}=n(6371).codes;let a=16384,c=16;function l(e){return e?c:a}e.exports={getHighWaterMark:function(e,t,n,o){const a=function(e,t,n){return null!=e.highWaterMark?e.highWaterMark:t?e[n]:null}(t,o,n);if(null!=a){if(!r(a)||a<0){throw new s(o?`options.${n}`:"options.highWaterMark",a)}return i(a)}return l(e.objectMode)},getDefaultHighWaterMark:l,setDefaultHighWaterMark:function(e,t){o(t,"value",0),e?c=t:a=t}}},5389(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TrackingState=void 0;const i=n(441);t.TrackingState=class{objects=new Map;objectsByCamera=new Map;changeCallbacks=[];storage;console;constructor(e,t){this.storage=e,this.console=t,this.loadPersistedState()}createObject(e,t,n){const r=(0,i.createTrackedObject)(e,t,n);return this.upsertObject(r),r}upsertObject(e){const t=this.objects.get(e.globalId);if(t)for(const n of t.activeOnCameras)this.objectsByCamera.get(n)?.delete(e.globalId);for(const t of e.activeOnCameras)this.objectsByCamera.has(t)||this.objectsByCamera.set(t,new Set),this.objectsByCamera.get(t).add(e.globalId);this.objects.set(e.globalId,e),this.notifyChange(),this.persistState()}addSighting(e,t){const n=this.objects.get(e);return!!n&&((0,i.addSighting)(n,t),this.objectsByCamera.has(t.cameraId)||this.objectsByCamera.set(t.cameraId,new Set),this.objectsByCamera.get(t.cameraId).add(e),this.notifyChange(),this.persistState(),!0)}addJourney(e,t){const n=this.objects.get(e);return!!n&&((0,i.addJourneySegment)(n,t),this.objectsByCamera.get(t.fromCameraId)?.delete(e),this.objectsByCamera.has(t.toCameraId)||this.objectsByCamera.set(t.toCameraId,new Set),this.objectsByCamera.get(t.toCameraId).add(e),this.notifyChange(),this.persistState(),!0)}getObject(e){return this.objects.get(e)}getActiveObjects(){return Array.from(this.objects.values()).filter(e=>"active"===e.state||"pending"===e.state)}getObjectsOnCamera(e){const t=this.objectsByCamera.get(e)||new Set;return Array.from(t).map(e=>this.objects.get(e)).filter(e=>!!e&&"active"===e.state)}getAllObjects(){return Array.from(this.objects.values())}getActiveCount(){return this.getActiveObjects().length}getJourney(e){return this.objects.get(e)?.journey}markExited(e,t,n){const i=this.objects.get(e);if(i){i.state="exited",i.hasExited=!0,i.exitCamera=t,i.exitCameraName=n,i.activeOnCameras=[];for(const[t,n]of this.objectsByCamera.entries())n.delete(e);this.notifyChange(),this.persistState()}}markLost(e){const t=this.objects.get(e);if(t){t.state="lost",t.activeOnCameras=[];for(const[t,n]of this.objectsByCamera.entries())n.delete(e);this.notifyChange(),this.persistState()}}markPending(e){const t=this.objects.get(e);t&&"active"===t.state&&(t.state="pending",this.notifyChange())}reactivate(e){const t=this.objects.get(e);t&&"pending"===t.state&&(t.state="active",this.notifyChange())}onStateChange(e){this.changeCallbacks.push(e)}offStateChange(e){const t=this.changeCallbacks.indexOf(e);-1!==t&&this.changeCallbacks.splice(t,1)}notifyChange(){const e=this.getAllObjects();for(const t of this.changeCallbacks)try{t(e)}catch(e){this.console.error("State change callback error:",e)}}persistState(){try{const e=Date.now(),t=Array.from(this.objects.values()).filter(t=>"active"===t.state||"pending"===t.state||e-t.lastSeen<36e5);this.storage.setItem("tracked-objects",JSON.stringify(t))}catch(e){this.console.error("Failed to persist tracking state:",e)}}loadPersistedState(){try{const e=this.storage.getItem("tracked-objects");if(e){const t=JSON.parse(e),n=Date.now();for(const e of t){"active"===e.state&&n-e.lastSeen>3e5&&(e.state="lost",e.activeOnCameras=[]),this.objects.set(e.globalId,e);for(const t of e.activeOnCameras)this.objectsByCamera.has(t)||this.objectsByCamera.set(t,new Set),this.objectsByCamera.get(t).add(e.globalId)}this.console.log(`Loaded ${t.length} persisted tracked objects`)}}catch(e){this.console.error("Failed to load persisted tracking state:",e)}}cleanup(e=864e5){const t=Date.now();let n=0;for(const[i,r]of this.objects.entries())t-r.lastSeen>e&&"active"!==r.state&&(this.objects.delete(i),n++);n>0&&(this.console.log(`Cleaned up ${n} old tracked objects`),this.persistState())}generateId(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}}},5399(e,t,n){const i=e.exports,{Buffer:r}=n(181);i.types={0:"reserved",1:"connect",2:"connack",3:"publish",4:"puback",5:"pubrec",6:"pubrel",7:"pubcomp",8:"subscribe",9:"suback",10:"unsubscribe",11:"unsuback",12:"pingreq",13:"pingresp",14:"disconnect",15:"auth"},i.requiredHeaderFlags={1:0,2:0,4:0,5:0,6:2,7:0,8:2,9:0,10:2,11:0,12:0,13:0,14:0,15:0},i.requiredHeaderFlagsErrors={};for(const e in i.requiredHeaderFlags){const t=i.requiredHeaderFlags[e];i.requiredHeaderFlagsErrors[e]="Invalid header flag bits, must be 0x"+t.toString(16)+" for "+i.types[e]+" packet"}i.codes={};for(const e in i.types){const t=i.types[e];i.codes[t]=e}i.CMD_SHIFT=4,i.CMD_MASK=240,i.DUP_MASK=8,i.QOS_MASK=3,i.QOS_SHIFT=1,i.RETAIN_MASK=1,i.VARBYTEINT_MASK=127,i.VARBYTEINT_FIN_MASK=128,i.VARBYTEINT_MAX=268435455,i.SESSIONPRESENT_MASK=1,i.SESSIONPRESENT_HEADER=r.from([i.SESSIONPRESENT_MASK]),i.CONNACK_HEADER=r.from([i.codes.connack<<i.CMD_SHIFT]),i.USERNAME_MASK=128,i.PASSWORD_MASK=64,i.WILL_RETAIN_MASK=32,i.WILL_QOS_MASK=24,i.WILL_QOS_SHIFT=3,i.WILL_FLAG_MASK=4,i.CLEAN_SESSION_MASK=2,i.CONNECT_HEADER=r.from([i.codes.connect<<i.CMD_SHIFT]),i.properties={sessionExpiryInterval:17,willDelayInterval:24,receiveMaximum:33,maximumPacketSize:39,topicAliasMaximum:34,requestResponseInformation:25,requestProblemInformation:23,userProperties:38,authenticationMethod:21,authenticationData:22,payloadFormatIndicator:1,messageExpiryInterval:2,contentType:3,responseTopic:8,correlationData:9,maximumQoS:36,retainAvailable:37,assignedClientIdentifier:18,reasonString:31,wildcardSubscriptionAvailable:40,subscriptionIdentifiersAvailable:41,sharedSubscriptionAvailable:42,serverKeepAlive:19,responseInformation:26,serverReference:28,topicAlias:35,subscriptionIdentifier:11},i.propertiesCodes={};for(const e in i.properties){const t=i.properties[e];i.propertiesCodes[t]=e}function o(e){return[0,1,2].map(t=>[0,1].map(n=>[0,1].map(o=>{const s=r.alloc(1);return s.writeUInt8(i.codes[e]<<i.CMD_SHIFT|(n?i.DUP_MASK:0)|t<<i.QOS_SHIFT|o,0,!0),s})))}i.propertiesTypes={sessionExpiryInterval:"int32",willDelayInterval:"int32",receiveMaximum:"int16",maximumPacketSize:"int32",topicAliasMaximum:"int16",requestResponseInformation:"byte",requestProblemInformation:"byte",userProperties:"pair",authenticationMethod:"string",authenticationData:"binary",payloadFormatIndicator:"byte",messageExpiryInterval:"int32",contentType:"string",responseTopic:"string",correlationData:"binary",maximumQoS:"int8",retainAvailable:"byte",assignedClientIdentifier:"string",reasonString:"string",wildcardSubscriptionAvailable:"byte",subscriptionIdentifiersAvailable:"byte",sharedSubscriptionAvailable:"byte",serverKeepAlive:"int16",responseInformation:"string",serverReference:"string",topicAlias:"int16",subscriptionIdentifier:"var"},i.PUBLISH_HEADER=o("publish"),i.SUBSCRIBE_HEADER=o("subscribe"),i.SUBSCRIBE_OPTIONS_QOS_MASK=3,i.SUBSCRIBE_OPTIONS_NL_MASK=1,i.SUBSCRIBE_OPTIONS_NL_SHIFT=2,i.SUBSCRIBE_OPTIONS_RAP_MASK=1,i.SUBSCRIBE_OPTIONS_RAP_SHIFT=3,i.SUBSCRIBE_OPTIONS_RH_MASK=3,i.SUBSCRIBE_OPTIONS_RH_SHIFT=4,i.SUBSCRIBE_OPTIONS_RH=[0,16,32],i.SUBSCRIBE_OPTIONS_NL=4,i.SUBSCRIBE_OPTIONS_RAP=8,i.SUBSCRIBE_OPTIONS_QOS=[0,1,2],i.UNSUBSCRIBE_HEADER=o("unsubscribe"),i.ACKS={unsuback:o("unsuback"),puback:o("puback"),pubcomp:o("pubcomp"),pubrel:o("pubrel"),pubrec:o("pubrec")},i.SUBACK_HEADER=r.from([i.codes.suback<<i.CMD_SHIFT]),i.VERSION3=r.from([3]),i.VERSION4=r.from([4]),i.VERSION5=r.from([5]),i.VERSION131=r.from([131]),i.VERSION132=r.from([132]),i.QOS=[0,1,2].map(e=>r.from([e])),i.EMPTY={pingreq:r.from([i.codes.pingreq<<4,0]),pingresp:r.from([i.codes.pingresp<<4,0]),disconnect:r.from([i.codes.disconnect<<4,0])},i.MQTT5_PUBACK_PUBREC_CODES={0:"Success",16:"No matching subscribers",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",144:"Topic Name invalid",145:"Packet identifier in use",151:"Quota exceeded",153:"Payload format invalid"},i.MQTT5_PUBREL_PUBCOMP_CODES={0:"Success",146:"Packet Identifier not found"},i.MQTT5_SUBACK_CODES={0:"Granted QoS 0",1:"Granted QoS 1",2:"Granted QoS 2",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",143:"Topic Filter invalid",145:"Packet Identifier in use",151:"Quota exceeded",158:"Shared Subscriptions not supported",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"},i.MQTT5_UNSUBACK_CODES={0:"Success",17:"No subscription existed",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",143:"Topic Filter invalid",145:"Packet Identifier in use"},i.MQTT5_DISCONNECT_CODES={0:"Normal disconnection",4:"Disconnect with Will Message",128:"Unspecified error",129:"Malformed Packet",130:"Protocol Error",131:"Implementation specific error",135:"Not authorized",137:"Server busy",139:"Server shutting down",141:"Keep Alive timeout",142:"Session taken over",143:"Topic Filter invalid",144:"Topic Name invalid",147:"Receive Maximum exceeded",148:"Topic Alias invalid",149:"Packet too large",150:"Message rate too high",151:"Quota exceeded",152:"Administrative action",153:"Payload format invalid",154:"Retain not supported",155:"QoS not supported",156:"Use another server",157:"Server moved",158:"Shared Subscriptions not supported",159:"Connection rate exceeded",160:"Maximum connect time",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"},i.MQTT5_AUTH_CODES={0:"Success",24:"Continue authentication",25:"Re-authenticate"}},5438(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SOCKS5_NO_ACCEPTABLE_AUTH=t.SOCKS5_CUSTOM_AUTH_END=t.SOCKS5_CUSTOM_AUTH_START=t.SOCKS_INCOMING_PACKET_SIZES=t.SocksClientState=t.Socks5Response=t.Socks5HostType=t.Socks5Auth=t.Socks4Response=t.SocksCommand=t.ERRORS=t.DEFAULT_TIMEOUT=void 0;t.DEFAULT_TIMEOUT=3e4;t.ERRORS={InvalidSocksCommand:"An invalid SOCKS command was provided. Valid options are connect, bind, and associate.",InvalidSocksCommandForOperation:"An invalid SOCKS command was provided. Only a subset of commands are supported for this operation.",InvalidSocksCommandChain:"An invalid SOCKS command was provided. Chaining currently only supports the connect command.",InvalidSocksClientOptionsDestination:"An invalid destination host was provided.",InvalidSocksClientOptionsExistingSocket:"An invalid existing socket was provided. This should be an instance of stream.Duplex.",InvalidSocksClientOptionsProxy:"Invalid SOCKS proxy details were provided.",InvalidSocksClientOptionsTimeout:"An invalid timeout value was provided. Please enter a value above 0 (in ms).",InvalidSocksClientOptionsProxiesLength:"At least two socks proxies must be provided for chaining.",InvalidSocksClientOptionsCustomAuthRange:"Custom auth must be a value between 0x80 and 0xFE.",InvalidSocksClientOptionsCustomAuthOptions:"When a custom_auth_method is provided, custom_auth_request_handler, custom_auth_response_size, and custom_auth_response_handler must also be provided and valid.",NegotiationError:"Negotiation error",SocketClosed:"Socket closed",ProxyConnectionTimedOut:"Proxy connection timed out",InternalError:"SocksClient internal error (this should not happen)",InvalidSocks4HandshakeResponse:"Received invalid Socks4 handshake response",Socks4ProxyRejectedConnection:"Socks4 Proxy rejected connection",InvalidSocks4IncomingConnectionResponse:"Socks4 invalid incoming connection response",Socks4ProxyRejectedIncomingBoundConnection:"Socks4 Proxy rejected incoming bound connection",InvalidSocks5InitialHandshakeResponse:"Received invalid Socks5 initial handshake response",InvalidSocks5IntiailHandshakeSocksVersion:"Received invalid Socks5 initial handshake (invalid socks version)",InvalidSocks5InitialHandshakeNoAcceptedAuthType:"Received invalid Socks5 initial handshake (no accepted authentication type)",InvalidSocks5InitialHandshakeUnknownAuthType:"Received invalid Socks5 initial handshake (unknown authentication type)",Socks5AuthenticationFailed:"Socks5 Authentication failed",InvalidSocks5FinalHandshake:"Received invalid Socks5 final handshake response",InvalidSocks5FinalHandshakeRejected:"Socks5 proxy rejected connection",InvalidSocks5IncomingConnectionResponse:"Received invalid Socks5 incoming connection response",Socks5ProxyRejectedIncomingBoundConnection:"Socks5 Proxy rejected incoming bound connection"};var n,i,r;t.SOCKS_INCOMING_PACKET_SIZES={Socks5InitialHandshakeResponse:2,Socks5UserPassAuthenticationResponse:2,Socks5ResponseHeader:5,Socks5ResponseIPv4:10,Socks5ResponseIPv6:22,Socks5ResponseHostname:e=>e+7,Socks4Response:8},function(e){e[e.connect=1]="connect",e[e.bind=2]="bind",e[e.associate=3]="associate"}(n||(t.SocksCommand=n={})),function(e){e[e.Granted=90]="Granted",e[e.Failed=91]="Failed",e[e.Rejected=92]="Rejected",e[e.RejectedIdent=93]="RejectedIdent"}(i||(t.Socks4Response=i={})),function(e){e[e.NoAuth=0]="NoAuth",e[e.GSSApi=1]="GSSApi",e[e.UserPass=2]="UserPass"}(r||(t.Socks5Auth=r={}));t.SOCKS5_CUSTOM_AUTH_START=128;t.SOCKS5_CUSTOM_AUTH_END=254;var o,s,a;t.SOCKS5_NO_ACCEPTABLE_AUTH=255,function(e){e[e.Granted=0]="Granted",e[e.Failure=1]="Failure",e[e.NotAllowed=2]="NotAllowed",e[e.NetworkUnreachable=3]="NetworkUnreachable",e[e.HostUnreachable=4]="HostUnreachable",e[e.ConnectionRefused=5]="ConnectionRefused",e[e.TTLExpired=6]="TTLExpired",e[e.CommandNotSupported=7]="CommandNotSupported",e[e.AddressNotSupported=8]="AddressNotSupported"}(o||(t.Socks5Response=o={})),function(e){e[e.IPv4=1]="IPv4",e[e.Hostname=3]="Hostname",e[e.IPv6=4]="IPv6"}(s||(t.Socks5HostType=s={})),function(e){e[e.Created=0]="Created",e[e.Connecting=1]="Connecting",e[e.Connected=2]="Connected",e[e.SentInitialHandshake=3]="SentInitialHandshake",e[e.ReceivedInitialHandshakeResponse=4]="ReceivedInitialHandshakeResponse",e[e.SentAuthentication=5]="SentAuthentication",e[e.ReceivedAuthenticationResponse=6]="ReceivedAuthenticationResponse",e[e.SentFinalHandshake=7]="SentFinalHandshake",e[e.ReceivedFinalResponse=8]="ReceivedFinalResponse",e[e.BoundWaitingForConnection=9]="BoundWaitingForConnection",e[e.Established=10]="Established",e[e.Disconnected=11]="Disconnected",e[e.Error=99]="Error"}(a||(t.SocksClientState=a={}))},5471(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.GlobalTrackerSensor=void 0;const i=n(7562),r=n(441);class o extends i.ScryptedDeviceBase{trackingState;plugin;constructor(e,t,n){super(t),this.plugin=e,this.trackingState=n,n.onStateChange(()=>this.updateOccupancy()),this.updateOccupancy()}updateOccupancy(){const e=this.trackingState.getActiveCount();this.occupied=e>0}async getSettings(){const e=this.trackingState.getActiveObjects(),t=this.trackingState.getAllObjects(),n=[];if(n.push({key:"activeCount",title:"Currently Active",type:"string",readonly:!0,value:`${e.length} object${1!==e.length?"s":""}`,group:"Status"}),n.push({key:"totalTracked",title:"Total Tracked (24h)",type:"string",readonly:!0,value:`${t.length} object${1!==t.length?"s":""}`,group:"Status"}),e.length>0){n.push({key:"activeObjectsHeader",title:"Active Objects",type:"html",value:'<h4 style="margin: 0;">Currently Tracked</h4>',group:"Active Objects"});for(const t of e.slice(0,10)){const e=(0,r.calculateDwellTime)(t),i=Math.round(e/6e4);n.push({key:`active-${t.globalId}`,title:`${t.className}${t.label?` (${t.label})`:""}`,type:"string",readonly:!0,value:`Cameras: ${t.activeOnCameras.join(", ")} | Time: ${i}m`,group:"Active Objects"})}e.length>10&&n.push({key:"moreActive",title:"More",type:"string",readonly:!0,value:`...and ${e.length-10} more`,group:"Active Objects"})}const i=t.filter(e=>"exited"===e.state).sort((e,t)=>t.lastSeen-e.lastSeen).slice(0,5);if(i.length>0){n.push({key:"recentExitsHeader",title:"Recent Exits",type:"html",value:'<h4 style="margin: 0;">Recently Exited</h4>',group:"Recent Activity"});for(const e of i){const t=new Date(e.lastSeen).toLocaleTimeString(),i=(0,r.getJourneySummary)(e);n.push({key:`exit-${e.globalId}`,title:`${e.className} at ${t}`,type:"string",readonly:!0,value:i||"No journey recorded",group:"Recent Activity"})}}return n}async putSetting(e,t){}async getReadmeMarkdown(){const e=this.trackingState.getActiveObjects(),t=this.trackingState.getAllObjects(),n=e.filter(e=>"person"===e.className).length,i=e.filter(e=>["car","vehicle","truck"].includes(e.className)).length,r=e.filter(e=>"animal"===e.className).length;let o="";return n>0&&(o+=`- People: ${n}\n`),i>0&&(o+=`- Vehicles: ${i}\n`),r>0&&(o+=`- Animals: ${r}\n`),`\n# Global Object Tracker\n\nThis sensor tracks the presence of objects across all connected cameras in your property.\n\n## Current Status\n\n**Occupied**: ${this.occupied?"Yes":"No"}\n\n**Active Objects**: ${e.length}\n${o||"- None currently"}\n\n**Total Tracked (24h)**: ${t.length}\n\n## How It Works\n\nThe Global Tracker combines detection events from all configured cameras to maintain a unified view of objects on your property. When an object moves from one camera's view to another, the system correlates these sightings to track the object's journey.\n\n## States\n\n- **Active**: Object is currently visible on camera\n- **Pending**: Object left camera view, waiting for correlation\n- **Exited**: Object left the property\n- **Lost**: Object disappeared without exiting (timeout)\n\n## Integration\n\nThis sensor can be used in automations:\n- Trigger actions when property becomes occupied/unoccupied\n- Create presence-based automations\n- Monitor overall property activity\n`}}t.GlobalTrackerSensor=o},5506(e,t,n){"use strict";const{Buffer:i}=n(181),{ObjectDefineProperty:r,ObjectKeys:o,ReflectApply:s}=n(4134),{promisify:{custom:a}}=n(7760),{streamReturningOperators:c,promiseReturningOperators:l}=n(823),{codes:{ERR_ILLEGAL_CONSTRUCTOR:d}}=n(6371),u=n(7830),{setDefaultHighWaterMark:p,getDefaultHighWaterMark:h}=n(5291),{pipeline:f}=n(7758),{destroyer:g}=n(5896),m=n(6238),y=n(3095),b=n(6115),v=e.exports=n(4259).Stream;v.isDestroyed=b.isDestroyed,v.isDisturbed=b.isDisturbed,v.isErrored=b.isErrored,v.isReadable=b.isReadable,v.isWritable=b.isWritable,v.Readable=n(7576);for(const _ of o(c)){const w=c[_];function k(...e){if(new.target)throw d();return v.Readable.from(s(w,this,e))}r(k,"name",{__proto__:null,value:w.name}),r(k,"length",{__proto__:null,value:w.length}),r(v.Readable.prototype,_,{__proto__:null,value:k,enumerable:!1,configurable:!0,writable:!0})}for(const I of o(l)){const x=l[I];function C(...e){if(new.target)throw d();return s(x,this,e)}r(C,"name",{__proto__:null,value:x.name}),r(C,"length",{__proto__:null,value:x.length}),r(v.Readable.prototype,I,{__proto__:null,value:C,enumerable:!1,configurable:!0,writable:!0})}v.Writable=n(8584),v.Duplex=n(3370),v.Transform=n(7382),v.PassThrough=n(6524),v.pipeline=f;const{addAbortSignal:S}=n(4147);v.addAbortSignal=S,v.finished=m,v.destroy=g,v.compose=u,v.setDefaultHighWaterMark=p,v.getDefaultHighWaterMark=h,r(v,"promises",{__proto__:null,configurable:!0,enumerable:!0,get:()=>y}),r(f,a,{__proto__:null,enumerable:!0,get:()=>y.pipeline}),r(m,a,{__proto__:null,enumerable:!0,get:()=>y.finished}),v.Stream=v,v._isUint8Array=function(e){return e instanceof Uint8Array},v._uint8ArrayToBuffer=function(e){return i.from(e.buffer,e.byteOffset,e.byteLength)}},5670(e,t,n){"use strict";const i=n(181),r=n(4478),o=n(2635);let s,a,c;t.A=(e,t)=>{if(t.hostname=t.hostname||t.host,!t.hostname)throw new Error("Could not determine host. Specify host manually.");const n="MQIsdp"===t.protocolId&&3===t.protocolVersion?"mqttv3.1":"mqtt";!function(e){e.hostname||(e.hostname="localhost"),e.path||(e.path="/"),e.wsOptions||(e.wsOptions={})}(t);const l=function(e,t){const n="wxs"===e.protocol?"wss":"ws";let i=`${n}://${e.hostname}${e.path}`;return e.port&&80!==e.port&&443!==e.port&&(i=`${n}://${e.hostname}:${e.port}${e.path}`),"function"==typeof e.transformWsUrl&&(i=e.transformWsUrl(i,e,t)),i}(t,e);s=wx.connectSocket({url:l,protocols:[n]}),a=function(){const e=new r.Transform;return e._write=(e,t,n)=>{s.send({data:e.buffer,success(){n()},fail(e){n(new Error(e))}})},e._flush=e=>{s.close({success(){e()}})},e}(),c=new o.BufferedDuplex(t,a,s),c._destroy=(e,t)=>{s.close({success(){t&&t(e)}})};const d=c.destroy;return c.destroy=(e,t)=>(c.destroy=d,setTimeout(()=>{s.close({fail(){c._destroy(e,t)}})},0),c),s.onOpen(()=>{c.socketReady()}),s.onMessage(e=>{let{data:t}=e;t=t instanceof ArrayBuffer?i.Buffer.from(t):i.Buffer.from(t,"utf8"),a.push(t)}),s.onClose(()=>{c.emit("close"),c.end(),c.destroy()}),s.onError(e=>{const t=new Error(e.errMsg);c.destroy(t)}),c}},5692(e){"use strict";e.exports=require("https")},5753(e,t,n){"undefined"==typeof process||"renderer"===process.type||!0===process.browser||process.__nwjs?e.exports=n(7833):e.exports=n(6033)},5861(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||i(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),r(n(7631),t)},5880(e,t,n){"use strict";const{isUtf8:i}=n(181),{hasBlob:r}=n(2614);function o(e){const t=e.length;let n=0;for(;n<t;)if(128&e[n])if(192==(224&e[n])){if(n+1===t||128!=(192&e[n+1])||192==(254&e[n]))return!1;n+=2}else if(224==(240&e[n])){if(n+2>=t||128!=(192&e[n+1])||128!=(192&e[n+2])||224===e[n]&&128==(224&e[n+1])||237===e[n]&&160==(224&e[n+1]))return!1;n+=3}else{if(240!=(248&e[n]))return!1;if(n+3>=t||128!=(192&e[n+1])||128!=(192&e[n+2])||128!=(192&e[n+3])||240===e[n]&&128==(240&e[n+1])||244===e[n]&&e[n+1]>143||e[n]>244)return!1;n+=4}else n++;return!0}if(e.exports={isBlob:function(e){return r&&"object"==typeof e&&"function"==typeof e.arrayBuffer&&"string"==typeof e.type&&"function"==typeof e.stream&&("Blob"===e[Symbol.toStringTag]||"File"===e[Symbol.toStringTag])},isValidStatusCode:function(e){return e>=1e3&&e<=1014&&1004!==e&&1005!==e&&1006!==e||e>=3e3&&e<=4999},isValidUTF8:o,tokenChars:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0]},i)e.exports.isValidUTF8=function(e){return e.length<24?o(e):i(e)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{const t=n(Object(function(){var e=new Error("Cannot find module 'utf-8-validate'");throw e.code="MODULE_NOT_FOUND",e}()));e.exports.isValidUTF8=function(e){return e.length<32?o(e):t(e)}}catch(e){}},5884(e){"use strict";e.exports=(e,t=process.argv)=>{const n=e.startsWith("-")?"":1===e.length?"-":"--",i=t.indexOf(n+e),r=t.indexOf("--");return-1!==i&&(-1===r||i<r)}},5896(e,t,n){"use strict";const i=n(4422),{aggregateTwoErrors:r,codes:{ERR_MULTIPLE_CALLBACK:o},AbortError:s}=n(6371),{Symbol:a}=n(4134),{kIsDestroyed:c,isDestroyed:l,isFinished:d,isServerRequest:u}=n(6115),p=a("kDestroy"),h=a("kConstruct");function f(e,t,n){e&&(e.stack,t&&!t.errored&&(t.errored=e),n&&!n.errored&&(n.errored=e))}function g(e,t,n){let r=!1;function o(t){if(r)return;r=!0;const o=e._readableState,s=e._writableState;f(t,s,o),s&&(s.closed=!0),o&&(o.closed=!0),"function"==typeof n&&n(t),t?i.nextTick(m,e,t):i.nextTick(y,e)}try{e._destroy(t||null,o)}catch(t){o(t)}}function m(e,t){b(e,t),y(e)}function y(e){const t=e._readableState,n=e._writableState;n&&(n.closeEmitted=!0),t&&(t.closeEmitted=!0),(null!=n&&n.emitClose||null!=t&&t.emitClose)&&e.emit("close")}function b(e,t){const n=e._readableState,i=e._writableState;null!=i&&i.errorEmitted||null!=n&&n.errorEmitted||(i&&(i.errorEmitted=!0),n&&(n.errorEmitted=!0),e.emit("error",t))}function v(e,t,n){const r=e._readableState,o=e._writableState;if(null!=o&&o.destroyed||null!=r&&r.destroyed)return this;null!=r&&r.autoDestroy||null!=o&&o.autoDestroy?e.destroy(t):t&&(t.stack,o&&!o.errored&&(o.errored=t),r&&!r.errored&&(r.errored=t),n?i.nextTick(b,e,t):b(e,t))}function S(e){let t=!1;function n(n){if(t)return void v(e,null!=n?n:new o);t=!0;const r=e._readableState,s=e._writableState,a=s||r;r&&(r.constructed=!0),s&&(s.constructed=!0),a.destroyed?e.emit(p,n):n?v(e,n,!0):i.nextTick(_,e)}try{e._construct(e=>{i.nextTick(n,e)})}catch(e){i.nextTick(n,e)}}function _(e){e.emit(h)}function w(e){return(null==e?void 0:e.setHeader)&&"function"==typeof e.abort}function k(e){e.emit("close")}function I(e,t){e.emit("error",t),i.nextTick(k,e)}e.exports={construct:function(e,t){if("function"!=typeof e._construct)return;const n=e._readableState,r=e._writableState;n&&(n.constructed=!1),r&&(r.constructed=!1),e.once(h,t),e.listenerCount(h)>1||i.nextTick(S,e)},destroyer:function(e,t){e&&!l(e)&&(t||d(e)||(t=new s),u(e)?(e.socket=null,e.destroy(t)):w(e)?e.abort():w(e.req)?e.req.abort():"function"==typeof e.destroy?e.destroy(t):"function"==typeof e.close?e.close():t?i.nextTick(I,e,t):i.nextTick(k,e),e.destroyed||(e[c]=!0))},destroy:function(e,t){const n=this._readableState,i=this._writableState,o=i||n;return null!=i&&i.destroyed||null!=n&&n.destroyed?("function"==typeof t&&t(),this):(f(e,i,n),i&&(i.destroyed=!0),n&&(n.destroyed=!0),o.constructed?g(this,e,t):this.once(p,function(n){g(this,r(n,e),t)}),this)},undestroy:function(){const e=this._readableState,t=this._writableState;e&&(e.constructed=!0,e.closed=!1,e.closeEmitted=!1,e.destroyed=!1,e.errored=null,e.errorEmitted=!1,e.reading=!1,e.ended=!1===e.readable,e.endEmitted=!1===e.readable),t&&(t.constructed=!0,t.destroyed=!1,t.closed=!1,t.closeEmitted=!1,t.errored=null,t.errorEmitted=!1,t.finalCalled=!1,t.prefinished=!1,t.ended=!1===t.writable,t.ending=!1===t.writable,t.finished=!1===t.writable)},errorOrDestroy:v}},5926(e,t,n){"use strict";const{tokenChars:i}=n(5880);function r(e,t,n){void 0===e[t]?e[t]=[n]:e[t].push(n)}e.exports={format:function(e){return Object.keys(e).map(t=>{let n=e[t];return Array.isArray(n)||(n=[n]),n.map(e=>[t].concat(Object.keys(e).map(t=>{let n=e[t];return Array.isArray(n)||(n=[n]),n.map(e=>!0===e?t:`${t}=${e}`).join("; ")})).join("; ")).join(", ")}).join(", ")},parse:function(e){const t=Object.create(null);let n,o,s=Object.create(null),a=!1,c=!1,l=!1,d=-1,u=-1,p=-1,h=0;for(;h<e.length;h++)if(u=e.charCodeAt(h),void 0===n)if(-1===p&&1===i[u])-1===d&&(d=h);else if(0===h||32!==u&&9!==u){if(59!==u&&44!==u)throw new SyntaxError(`Unexpected character at index ${h}`);{if(-1===d)throw new SyntaxError(`Unexpected character at index ${h}`);-1===p&&(p=h);const i=e.slice(d,p);44===u?(r(t,i,s),s=Object.create(null)):n=i,d=p=-1}}else-1===p&&-1!==d&&(p=h);else if(void 0===o)if(-1===p&&1===i[u])-1===d&&(d=h);else if(32===u||9===u)-1===p&&-1!==d&&(p=h);else if(59===u||44===u){if(-1===d)throw new SyntaxError(`Unexpected character at index ${h}`);-1===p&&(p=h),r(s,e.slice(d,p),!0),44===u&&(r(t,n,s),s=Object.create(null),n=void 0),d=p=-1}else{if(61!==u||-1===d||-1!==p)throw new SyntaxError(`Unexpected character at index ${h}`);o=e.slice(d,h),d=p=-1}else if(c){if(1!==i[u])throw new SyntaxError(`Unexpected character at index ${h}`);-1===d?d=h:a||(a=!0),c=!1}else if(l)if(1===i[u])-1===d&&(d=h);else if(34===u&&-1!==d)l=!1,p=h;else{if(92!==u)throw new SyntaxError(`Unexpected character at index ${h}`);c=!0}else if(34===u&&61===e.charCodeAt(h-1))l=!0;else if(-1===p&&1===i[u])-1===d&&(d=h);else if(-1===d||32!==u&&9!==u){if(59!==u&&44!==u)throw new SyntaxError(`Unexpected character at index ${h}`);{if(-1===d)throw new SyntaxError(`Unexpected character at index ${h}`);-1===p&&(p=h);let i=e.slice(d,p);a&&(i=i.replace(/\\/g,""),a=!1),r(s,o,i),44===u&&(r(t,n,s),s=Object.create(null),n=void 0),o=void 0,d=p=-1}}else-1===p&&(p=h);if(-1===d||l||32===u||9===u)throw new SyntaxError("Unexpected end of input");-1===p&&(p=h);const f=e.slice(d,p);return void 0===n?r(t,f,s):(void 0===o?r(s,f,!0):r(s,o,a?f.replace(/\\/g,""):f),r(t,n,s)),t}}},6033(e,t,n){const i=n(2018),r=n(9023);t.init=function(e){e.inspectOpts={};const n=Object.keys(t.inspectOpts);for(let i=0;i<n.length;i++)e.inspectOpts[n[i]]=t.inspectOpts[n[i]]},t.log=function(...e){return process.stderr.write(r.formatWithOptions(t.inspectOpts,...e)+"\n")},t.formatArgs=function(n){const{namespace:i,useColors:r}=this;if(r){const t=this.color,r="[3"+(t<8?t:"8;5;"+t),o=` ${r};1m${i} [0m`;n[0]=o+n[0].split("\n").join("\n"+o),n.push(r+"m+"+e.exports.humanize(this.diff)+"[0m")}else n[0]=function(){if(t.inspectOpts.hideDate)return"";return(new Date).toISOString()+" "}()+i+" "+n[0]},t.save=function(e){e?process.env.DEBUG=e:delete process.env.DEBUG},t.load=function(){return process.env.DEBUG},t.useColors=function(){return"colors"in t.inspectOpts?Boolean(t.inspectOpts.colors):i.isatty(process.stderr.fd)},t.destroy=r.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."),t.colors=[6,2,3,4,5,1];try{const e=n(7687);e&&(e.stderr||e).level>=2&&(t.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch(e){}t.inspectOpts=Object.keys(process.env).filter(e=>/^debug_/i.test(e)).reduce((e,t)=>{const n=t.substring(6).toLowerCase().replace(/_([a-z])/g,(e,t)=>t.toUpperCase());let i=process.env[t];return i=!!/^(yes|on|true|enabled)$/i.test(i)||!/^(no|off|false|disabled)$/i.test(i)&&("null"===i?null:Number(i)),e[n]=i,e},{}),e.exports=n(736)(t);const{formatters:o}=e.exports;o.o=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts).split("\n").map(e=>e.trim()).join(" ")},o.O=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts)}},6115(e,t,n){"use strict";const{SymbolAsyncIterator:i,SymbolIterator:r,SymbolFor:o}=n(4134),s=o("nodejs.stream.destroyed"),a=o("nodejs.stream.errored"),c=o("nodejs.stream.readable"),l=o("nodejs.stream.writable"),d=o("nodejs.stream.disturbed"),u=o("nodejs.webstream.isClosedPromise"),p=o("nodejs.webstream.controllerErrorFunction");function h(e,t=!1){var n;return!(!e||"function"!=typeof e.pipe||"function"!=typeof e.on||t&&("function"!=typeof e.pause||"function"!=typeof e.resume)||e._writableState&&!1===(null===(n=e._readableState)||void 0===n?void 0:n.readable)||e._writableState&&!e._readableState)}function f(e){var t;return!(!e||"function"!=typeof e.write||"function"!=typeof e.on||e._readableState&&!1===(null===(t=e._writableState)||void 0===t?void 0:t.writable))}function g(e){return e&&(e._readableState||e._writableState||"function"==typeof e.write&&"function"==typeof e.on||"function"==typeof e.pipe&&"function"==typeof e.on)}function m(e){return!(!e||g(e)||"function"!=typeof e.pipeThrough||"function"!=typeof e.getReader||"function"!=typeof e.cancel)}function y(e){return!(!e||g(e)||"function"!=typeof e.getWriter||"function"!=typeof e.abort)}function b(e){return!(!e||g(e)||"object"!=typeof e.readable||"object"!=typeof e.writable)}function v(e){if(!g(e))return null;const t=e._writableState,n=e._readableState,i=t||n;return!!(e.destroyed||e[s]||null!=i&&i.destroyed)}function S(e){if(!f(e))return null;if(!0===e.writableEnded)return!0;const t=e._writableState;return(null==t||!t.errored)&&("boolean"!=typeof(null==t?void 0:t.ended)?null:t.ended)}function _(e,t){if(!h(e))return null;const n=e._readableState;return(null==n||!n.errored)&&("boolean"!=typeof(null==n?void 0:n.endEmitted)?null:!!(n.endEmitted||!1===t&&!0===n.ended&&0===n.length))}function w(e){return e&&null!=e[c]?e[c]:"boolean"!=typeof(null==e?void 0:e.readable)?null:!v(e)&&(h(e)&&e.readable&&!_(e))}function k(e){return e&&null!=e[l]?e[l]:"boolean"!=typeof(null==e?void 0:e.writable)?null:!v(e)&&(f(e)&&e.writable&&!S(e))}function I(e){return"boolean"==typeof e._closed&&"boolean"==typeof e._defaultKeepAlive&&"boolean"==typeof e._removedConnection&&"boolean"==typeof e._removedContLen}function x(e){return"boolean"==typeof e._sent100&&I(e)}e.exports={isDestroyed:v,kIsDestroyed:s,isDisturbed:function(e){var t;return!(!e||!(null!==(t=e[d])&&void 0!==t?t:e.readableDidRead||e.readableAborted))},kIsDisturbed:d,isErrored:function(e){var t,n,i,r,o,s,c,l,d,u;return!(!e||!(null!==(t=null!==(n=null!==(i=null!==(r=null!==(o=null!==(s=e[a])&&void 0!==s?s:e.readableErrored)&&void 0!==o?o:e.writableErrored)&&void 0!==r?r:null===(c=e._readableState)||void 0===c?void 0:c.errorEmitted)&&void 0!==i?i:null===(l=e._writableState)||void 0===l?void 0:l.errorEmitted)&&void 0!==n?n:null===(d=e._readableState)||void 0===d?void 0:d.errored)&&void 0!==t?t:null===(u=e._writableState)||void 0===u?void 0:u.errored))},kIsErrored:a,isReadable:w,kIsReadable:c,kIsClosedPromise:u,kControllerErrorFunction:p,kIsWritable:l,isClosed:function(e){if(!g(e))return null;if("boolean"==typeof e.closed)return e.closed;const t=e._writableState,n=e._readableState;return"boolean"==typeof(null==t?void 0:t.closed)||"boolean"==typeof(null==n?void 0:n.closed)?(null==t?void 0:t.closed)||(null==n?void 0:n.closed):"boolean"==typeof e._closed&&I(e)?e._closed:null},isDuplexNodeStream:function(e){return!(!e||"function"!=typeof e.pipe||!e._readableState||"function"!=typeof e.on||"function"!=typeof e.write)},isFinished:function(e,t){return g(e)?!!v(e)||(!1===(null==t?void 0:t.readable)||!w(e))&&(!1===(null==t?void 0:t.writable)||!k(e)):null},isIterable:function(e,t){return null!=e&&(!0===t?"function"==typeof e[i]:!1===t?"function"==typeof e[r]:"function"==typeof e[i]||"function"==typeof e[r])},isReadableNodeStream:h,isReadableStream:m,isReadableEnded:function(e){if(!h(e))return null;if(!0===e.readableEnded)return!0;const t=e._readableState;return!(!t||t.errored)&&("boolean"!=typeof(null==t?void 0:t.ended)?null:t.ended)},isReadableFinished:_,isReadableErrored:function(e){var t,n;return g(e)?e.readableErrored?e.readableErrored:null!==(t=null===(n=e._readableState)||void 0===n?void 0:n.errored)&&void 0!==t?t:null:null},isNodeStream:g,isWebStream:function(e){return m(e)||y(e)||b(e)},isWritable:k,isWritableNodeStream:f,isWritableStream:y,isWritableEnded:S,isWritableFinished:function(e,t){if(!f(e))return null;if(!0===e.writableFinished)return!0;const n=e._writableState;return(null==n||!n.errored)&&("boolean"!=typeof(null==n?void 0:n.finished)?null:!!(n.finished||!1===t&&!0===n.ended&&0===n.length))},isWritableErrored:function(e){var t,n;return g(e)?e.writableErrored?e.writableErrored:null!==(t=null===(n=e._writableState)||void 0===n?void 0:n.errored)&&void 0!==t?t:null:null},isServerRequest:function(e){var t;return"boolean"==typeof e._consuming&&"boolean"==typeof e._dumped&&void 0===(null===(t=e.req)||void 0===t?void 0:t.upgradeOrConnect)},isServerResponse:x,willEmitClose:function(e){if(!g(e))return null;const t=e._writableState,n=e._readableState,i=t||n;return!i&&x(e)||!!(i&&i.autoDestroy&&i.emitClose&&!1===i.closed)},isTransformStream:b}},6117(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.StorageSettings=void 0;const a=s(n(7562)),{systemManager:c}=a.default;t.StorageSettings=class{constructor(e,t){this.device=e,this.settings=t,this.values={},this.hasValue={};for(const e of Object.keys(t)){const n=t[e],i=()=>this.getItem(e);let r;r="clippath"!==n.type?i:()=>{try{return JSON.parse(i())}catch(e){}},Object.defineProperty(this.values,e,{get:r,set:t=>this.putSetting(e,t),enumerable:!0}),Object.defineProperty(this.hasValue,e,{get:()=>null!=this.device.storage.getItem(e),enumerable:!0})}}get keys(){const e={};for(const t of Object.keys(this.settings))e[t]=t;return e}async getSettings(){const e=await(this.options?.onGet?.()),t=[];for(const[n,i]of Object.entries(this.settings)){let r=Object.assign({},i);e?.[n]&&(r=Object.assign(r,e[n])),r.onGet&&(r=Object.assign(r,await r.onGet())),r.hide||await(this.options?.hide?.[n]?.())||(r.key=n,r.value=this.getItemInternal(n,r,!0),"function"==typeof r.deviceFilter&&(r.deviceFilter=r.deviceFilter.toString()),t.push(r),delete r.onPut,delete r.onGet,delete r.mapPut,delete r.mapGet)}return t}async putSetting(e,t){const n=this.settings[e];let i;return n&&(i=this.getItemInternal(e,n)),this.putSettingInternal(n,i,e,t)}putSettingInternal(e,t,n,i){e?.noStore||(e?.mapPut&&(i=e.mapPut(t,i)),null==i?this.device.storage.removeItem(n):"object"==typeof i?this.device.storage.setItem(n,JSON.stringify(i)):this.device.storage.setItem(n,i?.toString())),e?.onPut?.(t,i),e?.hide||this.device.onDeviceEvent(a.ScryptedInterface.Settings,void 0)}getItemInternal(e,t,n){if(!t)return this.device.storage.getItem(e);const i=function(e,t,n,i){if(null==e)return n();const r=t.multiple?"array":t.type;if("boolean"===r)return"true"===e||"false"!==e&&(n()||!1);if("number"===r){const t=parseFloat(e);return isNaN(t)?n()||0:t}if("integer"===r){const t=parseInt(e);return isNaN(t)?n()||0:t}if("array"===r){if(!e)return n()||[];try{return JSON.parse(e)}catch(e){return n()||[]}}if("device"===r)return i?e:c.getDeviceById(e)||c.getDeviceById(n());if(e&&t.json)try{return JSON.parse(e)}catch(e){return n()}return e||n()}(this.device.storage.getItem(e),t,()=>null!=t.persistedDefaultValue?(this.putSettingInternal(t,void 0,e,t.persistedDefaultValue),t.persistedDefaultValue):t.defaultValue,n);return t.mapGet?t.mapGet(i):i}getItem(e){return this.getItemInternal(e,this.settings[e])}}},6172(e,t,n){const{Buffer:i}=n(181),r={},o=i.isBuffer(i.from([1,2]).subarray(0,1));function s(e){const t=i.allocUnsafe(2);return t.writeUInt8(e>>8,0),t.writeUInt8(255&e,1),t}e.exports={cache:r,generateCache:function(){for(let e=0;e<65536;e++)r[e]=s(e)},generateNumber:s,genBufVariableByteInt:function(e){let t=0,n=0;const r=i.allocUnsafe(4);do{t=e%128|0,(e=e/128|0)>0&&(t|=128),r.writeUInt8(t,n++)}while(e>0&&n<4);return e>0&&(n=0),o?r.subarray(0,n):r.slice(0,n)},generate4ByteBuffer:function(e){const t=i.allocUnsafe(4);return t.writeUInt32BE(e,0),t}}},6238(e,t,n){"use strict";const i=n(4422),{AbortError:r,codes:o}=n(6371),{ERR_INVALID_ARG_TYPE:s,ERR_STREAM_PREMATURE_CLOSE:a}=o,{kEmptyObject:c,once:l}=n(7760),{validateAbortSignal:d,validateFunction:u,validateObject:p,validateBoolean:h}=n(277),{Promise:f,PromisePrototypeThen:g,SymbolDispose:m}=n(4134),{isClosed:y,isReadable:b,isReadableNodeStream:v,isReadableStream:S,isReadableFinished:_,isReadableErrored:w,isWritable:k,isWritableNodeStream:I,isWritableStream:x,isWritableFinished:C,isWritableErrored:E,isNodeStream:T,willEmitClose:O,kIsClosedPromise:P}=n(6115);let A;const R=()=>{};function M(e,t,o){var h,f;if(2===arguments.length?(o=t,t=c):null==t?t=c:p(t,"options"),u(o,"callback"),d(t.signal,"options.signal"),o=l(o),S(e)||x(e))return function(e,t,o){let s=!1,a=R;if(t.signal)if(a=()=>{s=!0,o.call(e,new r(void 0,{cause:t.signal.reason}))},t.signal.aborted)i.nextTick(a);else{A=A||n(7760).addAbortListener;const i=A(t.signal,a),r=o;o=l((...t)=>{i[m](),r.apply(e,t)})}const c=(...t)=>{s||i.nextTick(()=>o.apply(e,t))};return g(e[P].promise,c,c),R}(e,t,o);if(!T(e))throw new s("stream",["ReadableStream","WritableStream","Stream"],e);const M=null!==(h=t.readable)&&void 0!==h?h:v(e),L=null!==(f=t.writable)&&void 0!==f?f:I(e),N=e._writableState,D=e._readableState,B=()=>{e.writable||F()};let j=O(e)&&v(e)===M&&I(e)===L,$=C(e,!1);const F=()=>{$=!0,e.destroyed&&(j=!1),(!j||e.readable&&!M)&&(M&&!U||o.call(e))};let U=_(e,!1);const z=()=>{U=!0,e.destroyed&&(j=!1),(!j||e.writable&&!L)&&(L&&!$||o.call(e))},V=t=>{o.call(e,t)};let W=y(e);const H=()=>{W=!0;const t=E(e)||w(e);return t&&"boolean"!=typeof t?o.call(e,t):M&&!U&&v(e,!0)&&!_(e,!1)?o.call(e,new a):!L||$||C(e,!1)?void o.call(e):o.call(e,new a)},q=()=>{W=!0;const t=E(e)||w(e);if(t&&"boolean"!=typeof t)return o.call(e,t);o.call(e)},G=()=>{e.req.on("finish",F)};!function(e){return e.setHeader&&"function"==typeof e.abort}(e)?L&&!N&&(e.on("end",B),e.on("close",B)):(e.on("complete",F),j||e.on("abort",H),e.req?G():e.on("request",G)),j||"boolean"!=typeof e.aborted||e.on("aborted",H),e.on("end",z),e.on("finish",F),!1!==t.error&&e.on("error",V),e.on("close",H),W?i.nextTick(H):null!=N&&N.errorEmitted||null!=D&&D.errorEmitted?j||i.nextTick(q):(M||j&&!b(e)||!$&&!1!==k(e))&&(L||j&&!k(e)||!U&&!1!==b(e))?D&&e.req&&e.aborted&&i.nextTick(q):i.nextTick(q);const K=()=>{o=R,e.removeListener("aborted",H),e.removeListener("complete",F),e.removeListener("abort",H),e.removeListener("request",G),e.req&&e.req.removeListener("finish",F),e.removeListener("end",B),e.removeListener("close",B),e.removeListener("finish",F),e.removeListener("end",z),e.removeListener("error",V),e.removeListener("close",H)};if(t.signal&&!W){const s=()=>{const n=o;K(),n.call(e,new r(void 0,{cause:t.signal.reason}))};if(t.signal.aborted)i.nextTick(s);else{A=A||n(7760).addAbortListener;const i=A(t.signal,s),r=o;o=l((...t)=>{i[m](),r.apply(e,t)})}}return K}e.exports=M,e.exports.finished=function(e,t){var n;let i=!1;return null===t&&(t=c),null!==(n=t)&&void 0!==n&&n.cleanup&&(h(t.cleanup,"cleanup"),i=t.cleanup),new f((n,r)=>{const o=M(e,t,e=>{i&&o(),e?r(e):n()})})}},6286(e,t,n){"use strict";const{Writable:i}=n(2203),r=n(2971),{BINARY_TYPES:o,EMPTY_BUFFER:s,kStatusCode:a,kWebSocket:c}=n(2614),{concat:l,toArrayBuffer:d,unmask:u}=n(3338),{isValidStatusCode:p,isValidUTF8:h}=n(5880),f=Buffer[Symbol.species];e.exports=class extends i{constructor(e={}){super(),this._allowSynchronousEvents=void 0===e.allowSynchronousEvents||e.allowSynchronousEvents,this._binaryType=e.binaryType||o[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxPayload=0|e.maxPayload,this._skipUTF8Validation=!!e.skipUTF8Validation,this[c]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=0}_write(e,t,n){if(8===this._opcode&&0==this._state)return n();this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(n)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){const t=this._buffers[0];return this._buffers[0]=new f(t.buffer,t.byteOffset+e,t.length-e),new f(t.buffer,t.byteOffset,e)}const t=Buffer.allocUnsafe(e);do{const n=this._buffers[0],i=t.length-e;e>=n.length?t.set(this._buffers.shift(),i):(t.set(new Uint8Array(n.buffer,n.byteOffset,e),i),this._buffers[0]=new f(n.buffer,n.byteOffset+e,n.length-e)),e-=n.length}while(e>0);return t}startLoop(e){this._loop=!0;do{switch(this._state){case 0:this.getInfo(e);break;case 1:this.getPayloadLength16(e);break;case 2:this.getPayloadLength64(e);break;case 3:this.getMask();break;case 4:this.getData(e);break;case 5:case 6:return void(this._loop=!1)}}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2)return void(this._loop=!1);const t=this.consume(2);if(48&t[0]){return void e(this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3"))}const n=!(64&~t[0]);if(n&&!this._extensions[r.extensionName]){return void e(this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1"))}if(this._fin=!(128&~t[0]),this._opcode=15&t[0],this._payloadLength=127&t[1],0===this._opcode){if(n){return void e(this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1"))}if(!this._fragmented){return void e(this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE"))}this._opcode=this._fragmented}else if(1===this._opcode||2===this._opcode){if(this._fragmented){return void e(this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE"))}this._compressed=n}else{if(!(this._opcode>7&&this._opcode<11)){return void e(this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE"))}if(!this._fin){return void e(this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN"))}if(n){return void e(this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1"))}if(this._payloadLength>125||8===this._opcode&&1===this._payloadLength){return void e(this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"))}}if(this._fin||this._fragmented||(this._fragmented=this._opcode),this._masked=!(128&~t[1]),this._isServer){if(!this._masked){return void e(this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK"))}}else if(this._masked){return void e(this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK"))}126===this._payloadLength?this._state=1:127===this._payloadLength?this._state=2:this.haveLength(e)}getPayloadLength16(e){this._bufferedBytes<2?this._loop=!1:(this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e))}getPayloadLength64(e){if(this._bufferedBytes<8)return void(this._loop=!1);const t=this.consume(8),n=t.readUInt32BE(0);if(n>Math.pow(2,21)-1){return void e(this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"))}this._payloadLength=n*Math.pow(2,32)+t.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){return void e(this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"))}this._masked?this._state=3:this._state=4}getMask(){this._bufferedBytes<4?this._loop=!1:(this._mask=this.consume(4),this._state=4)}getData(e){let t=s;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength)return void(this._loop=!1);t=this.consume(this._payloadLength),this._masked&&0!==(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])&&u(t,this._mask)}if(this._opcode>7)this.controlMessage(t,e);else{if(this._compressed)return this._state=5,void this.decompress(t,e);t.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(t)),this.dataMessage(e)}}decompress(e,t){this._extensions[r.extensionName].decompress(e,this._fin,(e,n)=>{if(e)return t(e);if(n.length){if(this._messageLength+=n.length,this._messageLength>this._maxPayload&&this._maxPayload>0){const e=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");return void t(e)}this._fragments.push(n)}this.dataMessage(t),0===this._state&&this.startLoop(t)})}dataMessage(e){if(!this._fin)return void(this._state=0);const t=this._messageLength,n=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],2===this._opcode){let i;i="nodebuffer"===this._binaryType?l(n,t):"arraybuffer"===this._binaryType?d(l(n,t)):"blob"===this._binaryType?new Blob(n):n,this._allowSynchronousEvents?(this.emit("message",i,!0),this._state=0):(this._state=6,setImmediate(()=>{this.emit("message",i,!0),this._state=0,this.startLoop(e)}))}else{const i=l(n,t);if(!this._skipUTF8Validation&&!h(i)){const t=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");return void e(t)}5===this._state||this._allowSynchronousEvents?(this.emit("message",i,!1),this._state=0):(this._state=6,setImmediate(()=>{this.emit("message",i,!1),this._state=0,this.startLoop(e)}))}}controlMessage(e,t){if(8!==this._opcode)this._allowSynchronousEvents?(this.emit(9===this._opcode?"ping":"pong",e),this._state=0):(this._state=6,setImmediate(()=>{this.emit(9===this._opcode?"ping":"pong",e),this._state=0,this.startLoop(t)}));else{if(0===e.length)this._loop=!1,this.emit("conclude",1005,s),this.end();else{const n=e.readUInt16BE(0);if(!p(n)){const e=this.createError(RangeError,`invalid status code ${n}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");return void t(e)}const i=new f(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!h(i)){const e=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");return void t(e)}this._loop=!1,this.emit("conclude",n,i),this.end()}this._state=0}}createError(e,t,n,i,r){this._loop=!1,this._errored=!0;const o=new e(n?`Invalid WebSocket frame: ${t}`:t);return Error.captureStackTrace(o,this.createError),o.code=r,o[a]=i,o}}},6329(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.Address6=void 0;const s=o(n(837)),a=o(n(9576)),c=o(n(8914)),l=o(n(465)),d=n(2839),u=n(321),p=n(2437),h=n(837);function f(e){if(!e)throw new Error("Assertion failed.")}function g(e){return e=(e=e.replace(/^(0{1,})([1-9]+)$/,'<span class="parse-error">$1</span>$2')).replace(/^(0{1,})(0)$/,'<span class="parse-error">$1</span>$2')}function m(e){return parseInt(e,16).toString(16).padStart(4,"0")}function y(e){return 255&e}class b{constructor(e,t){this.addressMinusSuffix="",this.parsedSubnet="",this.subnet="/128",this.subnetMask=128,this.v4=!1,this.zone="",this.isInSubnet=s.isInSubnet,this.isCorrect=s.isCorrect(c.BITS),this.groups=void 0===t?c.GROUPS:t,this.address=e;const n=c.RE_SUBNET_STRING.exec(e);if(n){if(this.parsedSubnet=n[0].replace("/",""),this.subnetMask=parseInt(this.parsedSubnet,10),this.subnet=`/${this.subnetMask}`,Number.isNaN(this.subnetMask)||this.subnetMask<0||this.subnetMask>c.BITS)throw new p.AddressError("Invalid subnet mask.");e=e.replace(c.RE_SUBNET_STRING,"")}else if(/\//.test(e))throw new p.AddressError("Invalid subnet mask.");const i=c.RE_ZONE_STRING.exec(e);i&&(this.zone=i[0],e=e.replace(c.RE_ZONE_STRING,"")),this.addressMinusSuffix=e,this.parsedAddress=this.parse(this.addressMinusSuffix)}static isValid(e){try{return new b(e),!0}catch(e){return!1}}static fromBigInt(e){const t=e.toString(16).padStart(32,"0"),n=[];let i;for(i=0;i<c.GROUPS;i++)n.push(t.slice(4*i,4*(i+1)));return new b(n.join(":"))}static fromURL(e){let t,n,i=null;if(-1!==e.indexOf("[")&&-1!==e.indexOf("]:")){if(n=c.RE_URL_WITH_PORT.exec(e),null===n)return{error:"failed to parse address with port",address:null,port:null};t=n[1],i=n[2]}else if(-1!==e.indexOf("/")){if(e=e.replace(/^[a-z0-9]+:\/\//,""),n=c.RE_URL.exec(e),null===n)return{error:"failed to parse address from URL",address:null,port:null};t=n[1]}else t=e;return i?(i=parseInt(i,10),(i<0||i>65536)&&(i=null)):i=null,{address:new b(t),port:i}}static fromAddress4(e){const t=new d.Address4(e),n=c.BITS-(a.BITS-t.subnetMask);return new b(`::ffff:${t.correctForm()}/${n}`)}static fromArpa(e){let t=e.replace(/(\.ip6\.arpa)?\.$/,"");if(63!==t.length)throw new p.AddressError("Invalid 'ip6.arpa' form.");const n=t.split(".").reverse();for(let e=7;e>0;e--){const t=4*e;n.splice(t,0,":")}return t=n.join(""),new b(t)}microsoftTranscription(){return`${this.correctForm().replace(/:/g,"-")}.ipv6-literal.net`}mask(e=this.subnetMask){return this.getBitsBase2(0,e)}possibleSubnets(e=128){const t=c.BITS-this.subnetMask-Math.abs(e-c.BITS);return t<0?"0":function(e){const t=/(\d+)(\d{3})/;for(;t.test(e);)e=e.replace(t,"$1,$2");return e}((BigInt("2")**BigInt(t)).toString(10))}_startAddress(){return BigInt(`0b${this.mask()+"0".repeat(c.BITS-this.subnetMask)}`)}startAddress(){return b.fromBigInt(this._startAddress())}startAddressExclusive(){const e=BigInt("1");return b.fromBigInt(this._startAddress()+e)}_endAddress(){return BigInt(`0b${this.mask()+"1".repeat(c.BITS-this.subnetMask)}`)}endAddress(){return b.fromBigInt(this._endAddress())}endAddressExclusive(){const e=BigInt("1");return b.fromBigInt(this._endAddress()-e)}getScope(){let e=c.SCOPES[parseInt(this.getBits(12,16).toString(10),10)];return"Global unicast"===this.getType()&&"Link local"!==e&&(e="Global"),e||"Unknown"}getType(){for(const e of Object.keys(c.TYPES))if(this.isInSubnet(new b(e)))return c.TYPES[e];return"Global unicast"}getBits(e,t){return BigInt(`0b${this.getBitsBase2(e,t)}`)}getBitsBase2(e,t){return this.binaryZeroPad().slice(e,t)}getBitsBase16(e,t){const n=t-e;if(n%4!=0)throw new Error("Length of bits to retrieve must be divisible by four");return this.getBits(e,t).toString(16).padStart(n/4,"0")}getBitsPastSubnet(){return this.getBitsBase2(this.subnetMask,c.BITS)}reverseForm(e){e||(e={});const t=Math.floor(this.subnetMask/4),n=this.canonicalForm().replace(/:/g,"").split("").slice(0,t).reverse().join(".");return t>0?e.omitSuffix?n:`${n}.ip6.arpa.`:e.omitSuffix?"":"ip6.arpa."}correctForm(){let e,t=[],n=0;const i=[];for(e=0;e<this.parsedAddress.length;e++){const t=parseInt(this.parsedAddress[e],16);0===t&&n++,0!==t&&n>0&&(n>1&&i.push([e-n,e-1]),n=0)}n>1&&i.push([this.parsedAddress.length-n,this.parsedAddress.length-1]);const r=i.map(e=>e[1]-e[0]+1);if(i.length>0){const e=r.indexOf(Math.max(...r));t=function(e,t){const n=[],i=[];let r;for(r=0;r<e.length;r++)r<t[0]?n.push(e[r]):r>t[1]&&i.push(e[r]);return n.concat(["compact"]).concat(i)}(this.parsedAddress,i[e])}else t=this.parsedAddress;for(e=0;e<t.length;e++)"compact"!==t[e]&&(t[e]=parseInt(t[e],16).toString(16));let o=t.join(":");return o=o.replace(/^compact$/,"::"),o=o.replace(/(^compact)|(compact$)/,":"),o=o.replace(/compact/,""),o}binaryZeroPad(){return this.bigInt().toString(2).padStart(c.BITS,"0")}parse4in6(e){const t=e.split(":"),n=t.slice(-1)[0].match(a.RE_ADDRESS);if(n){this.parsedAddress4=n[0],this.address4=new d.Address4(this.parsedAddress4);for(let t=0;t<this.address4.groups;t++)if(/^0[0-9]+/.test(this.address4.parsedAddress[t]))throw new p.AddressError("IPv4 addresses can't have leading zeroes.",e.replace(a.RE_ADDRESS,this.address4.parsedAddress.map(g).join(".")));this.v4=!0,t[t.length-1]=this.address4.toGroup6(),e=t.join(":")}return e}parse(e){const t=(e=this.parse4in6(e)).match(c.RE_BAD_CHARACTERS);if(t)throw new p.AddressError(`Bad character${t.length>1?"s":""} detected in address: ${t.join("")}`,e.replace(c.RE_BAD_CHARACTERS,'<span class="parse-error">$1</span>'));const n=e.match(c.RE_BAD_ADDRESS);if(n)throw new p.AddressError(`Address failed regex: ${n.join("")}`,e.replace(c.RE_BAD_ADDRESS,'<span class="parse-error">$1</span>'));let i=[];const r=e.split("::");if(2===r.length){let e=r[0].split(":"),t=r[1].split(":");1===e.length&&""===e[0]&&(e=[]),1===t.length&&""===t[0]&&(t=[]);const n=this.groups-(e.length+t.length);if(!n)throw new p.AddressError("Error parsing groups");this.elidedGroups=n,this.elisionBegin=e.length,this.elisionEnd=e.length+this.elidedGroups,i=i.concat(e);for(let e=0;e<n;e++)i.push("0");i=i.concat(t)}else{if(1!==r.length)throw new p.AddressError("Too many :: groups found");i=e.split(":"),this.elidedGroups=0}if(i=i.map(e=>parseInt(e,16).toString(16)),i.length!==this.groups)throw new p.AddressError("Incorrect number of groups found");return i}canonicalForm(){return this.parsedAddress.map(m).join(":")}decimal(){return this.parsedAddress.map(e=>parseInt(e,16).toString(10).padStart(5,"0")).join(":")}bigInt(){return BigInt(`0x${this.parsedAddress.map(m).join("")}`)}to4(){const e=this.binaryZeroPad().split("");return d.Address4.fromHex(BigInt(`0b${e.slice(96,128).join("")}`).toString(16))}to4in6(){const e=this.to4(),t=new b(this.parsedAddress.slice(0,6).join(":"),6).correctForm();let n="";return/:$/.test(t)||(n=":"),t+n+e.address}inspectTeredo(){const e=this.getBitsBase16(0,32),t=(this.getBits(80,96)^BigInt("0xffff")).toString(),n=d.Address4.fromHex(this.getBitsBase16(32,64)),i=this.getBits(96,128),r=d.Address4.fromHex((i^BigInt("0xffffffff")).toString(16)),o=this.getBitsBase2(64,80),s=(0,h.testBit)(o,15),a=(0,h.testBit)(o,14),c=(0,h.testBit)(o,8),l=(0,h.testBit)(o,9),u=BigInt(`0b${o.slice(2,6)+o.slice(8,16)}`).toString(10);return{prefix:`${e.slice(0,4)}:${e.slice(4,8)}`,server4:n.address,client4:r.address,flags:o,coneNat:s,microsoft:{reserved:a,universalLocal:l,groupIndividual:c,nonce:u},udpPort:t}}inspect6to4(){const e=this.getBitsBase16(0,16),t=d.Address4.fromHex(this.getBitsBase16(16,48));return{prefix:e.slice(0,4),gateway:t.address}}to6to4(){if(!this.is4())return null;const e=["2002",this.getBitsBase16(96,112),this.getBitsBase16(112,128),"","/16"].join(":");return new b(e)}toByteArray(){const e=this.bigInt().toString(16),t=`${"0".repeat(e.length%2)}${e}`,n=[];for(let e=0,i=t.length;e<i;e+=2)n.push(parseInt(t.substring(e,e+2),16));return n}toUnsignedByteArray(){return this.toByteArray().map(y)}static fromByteArray(e){return this.fromUnsignedByteArray(e.map(y))}static fromUnsignedByteArray(e){const t=BigInt("256");let n=BigInt("0"),i=BigInt("1");for(let r=e.length-1;r>=0;r--)n+=i*BigInt(e[r].toString(10)),i*=t;return b.fromBigInt(n)}isCanonical(){return this.addressMinusSuffix===this.canonicalForm()}isLinkLocal(){return"1111111010000000000000000000000000000000000000000000000000000000"===this.getBitsBase2(0,64)}isMulticast(){return"Multicast"===this.getType()}is4(){return this.v4}isTeredo(){return this.isInSubnet(new b("2001::/32"))}is6to4(){return this.isInSubnet(new b("2002::/16"))}isLoopback(){return"Loopback"===this.getType()}href(e){return e=void 0===e?"":`:${e}`,`http://[${this.correctForm()}]${e}/`}link(e){e||(e={}),void 0===e.className&&(e.className=""),void 0===e.prefix&&(e.prefix="/#address="),void 0===e.v4&&(e.v4=!1);let t=this.correctForm;e.v4&&(t=this.to4in6);const n=t.call(this);return e.className?`<a href="${e.prefix}${n}" class="${e.className}">${n}</a>`:`<a href="${e.prefix}${n}">${n}</a>`}group(){if(0===this.elidedGroups)return l.simpleGroup(this.address).join(":");f("number"==typeof this.elidedGroups),f("number"==typeof this.elisionBegin);const e=[],[t,n]=this.address.split("::");t.length?e.push(...l.simpleGroup(t)):e.push("");const i=["hover-group"];for(let e=this.elisionBegin;e<this.elisionBegin+this.elidedGroups;e++)i.push(`group-${e}`);return e.push(`<span class="${i.join(" ")}"></span>`),n.length?e.push(...l.simpleGroup(n,this.elisionEnd)):e.push(""),this.is4()&&(f(this.address4 instanceof d.Address4),e.pop(),e.push(this.address4.groupForV6())),e.join(":")}regularExpressionString(e=!1){let t=[];const n=new b(this.correctForm());if(0===n.elidedGroups)t.push((0,u.simpleRegularExpression)(n.parsedAddress));else if(n.elidedGroups===c.GROUPS)t.push((0,u.possibleElisions)(c.GROUPS));else{const e=n.address.split("::");e[0].length&&t.push((0,u.simpleRegularExpression)(e[0].split(":"))),f("number"==typeof n.elidedGroups),t.push((0,u.possibleElisions)(n.elidedGroups,0!==e[0].length,0!==e[1].length)),e[1].length&&t.push((0,u.simpleRegularExpression)(e[1].split(":"))),t=[t.join(":")]}return e||(t=["(?=^|",u.ADDRESS_BOUNDARY,"|[^\\w\\:])(",...t,")(?=[^\\w\\:]|",u.ADDRESS_BOUNDARY,"|$)"]),t.join("")}regularExpression(e=!1){return new RegExp(this.regularExpressionString(e),"i")}}t.Address6=b},6371(e,t,n){"use strict";const{format:i,inspect:r}=n(9231),{AggregateError:o}=n(4134),s=globalThis.AggregateError||o,a=Symbol("kIsNodeError"),c=["string","function","number","object","Function","Object","boolean","bigint","symbol"],l=/^([A-Z][a-z0-9]*)+$/,d={};function u(e,t){if(!e)throw new d.ERR_INTERNAL_ASSERTION(t)}function p(e){let t="",n=e.length;const i="-"===e[0]?1:0;for(;n>=i+4;n-=3)t=`_${e.slice(n-3,n)}${t}`;return`${e.slice(0,n)}${t}`}function h(e,t,n){n||(n=Error);class r extends n{constructor(...n){super(function(e,t,n){if("function"==typeof t)return u(t.length<=n.length,`Code: ${e}; The provided arguments length (${n.length}) does not match the required ones (${t.length}).`),t(...n);const r=(t.match(/%[dfijoOs]/g)||[]).length;return u(r===n.length,`Code: ${e}; The provided arguments length (${n.length}) does not match the required ones (${r}).`),0===n.length?t:i(t,...n)}(e,t,n))}toString(){return`${this.name} [${e}]: ${this.message}`}}Object.defineProperties(r.prototype,{name:{value:n.name,writable:!0,enumerable:!1,configurable:!0},toString:{value(){return`${this.name} [${e}]: ${this.message}`},writable:!0,enumerable:!1,configurable:!0}}),r.prototype.code=e,r.prototype[a]=!0,d[e]=r}function f(e){const t="__node_internal_"+e.name;return Object.defineProperty(e,"name",{value:t}),e}class g extends Error{constructor(e="The operation was aborted",t=void 0){if(void 0!==t&&"object"!=typeof t)throw new d.ERR_INVALID_ARG_TYPE("options","Object",t);super(e,t),this.code="ABORT_ERR",this.name="AbortError"}}h("ERR_ASSERTION","%s",Error),h("ERR_INVALID_ARG_TYPE",(e,t,n)=>{u("string"==typeof e,"'name' must be a string"),Array.isArray(t)||(t=[t]);let i="The ";e.endsWith(" argument")?i+=`${e} `:i+=`"${e}" ${e.includes(".")?"property":"argument"} `,i+="must be ";const o=[],s=[],a=[];for(const e of t)u("string"==typeof e,"All expected entries have to be of type string"),c.includes(e)?o.push(e.toLowerCase()):l.test(e)?s.push(e):(u("object"!==e,'The value "object" should be written as "Object"'),a.push(e));if(s.length>0){const e=o.indexOf("object");-1!==e&&(o.splice(o,e,1),s.push("Object"))}if(o.length>0){switch(o.length){case 1:i+=`of type ${o[0]}`;break;case 2:i+=`one of type ${o[0]} or ${o[1]}`;break;default:{const e=o.pop();i+=`one of type ${o.join(", ")}, or ${e}`}}(s.length>0||a.length>0)&&(i+=" or ")}if(s.length>0){switch(s.length){case 1:i+=`an instance of ${s[0]}`;break;case 2:i+=`an instance of ${s[0]} or ${s[1]}`;break;default:{const e=s.pop();i+=`an instance of ${s.join(", ")}, or ${e}`}}a.length>0&&(i+=" or ")}switch(a.length){case 0:break;case 1:a[0].toLowerCase()!==a[0]&&(i+="an "),i+=`${a[0]}`;break;case 2:i+=`one of ${a[0]} or ${a[1]}`;break;default:{const e=a.pop();i+=`one of ${a.join(", ")}, or ${e}`}}if(null==n)i+=`. Received ${n}`;else if("function"==typeof n&&n.name)i+=`. Received function ${n.name}`;else if("object"==typeof n){var d;if(null!==(d=n.constructor)&&void 0!==d&&d.name)i+=`. Received an instance of ${n.constructor.name}`;else{i+=`. Received ${r(n,{depth:-1})}`}}else{let e=r(n,{colors:!1});e.length>25&&(e=`${e.slice(0,25)}...`),i+=`. Received type ${typeof n} (${e})`}return i},TypeError),h("ERR_INVALID_ARG_VALUE",(e,t,n="is invalid")=>{let i=r(t);i.length>128&&(i=i.slice(0,128)+"...");return`The ${e.includes(".")?"property":"argument"} '${e}' ${n}. Received ${i}`},TypeError),h("ERR_INVALID_RETURN_VALUE",(e,t,n)=>{var i;return`Expected ${e} to be returned from the "${t}" function but got ${null!=n&&null!==(i=n.constructor)&&void 0!==i&&i.name?`instance of ${n.constructor.name}`:"type "+typeof n}.`},TypeError),h("ERR_MISSING_ARGS",(...e)=>{let t;u(e.length>0,"At least one arg needs to be specified");const n=e.length;switch(e=(Array.isArray(e)?e:[e]).map(e=>`"${e}"`).join(" or "),n){case 1:t+=`The ${e[0]} argument`;break;case 2:t+=`The ${e[0]} and ${e[1]} arguments`;break;default:{const n=e.pop();t+=`The ${e.join(", ")}, and ${n} arguments`}}return`${t} must be specified`},TypeError),h("ERR_OUT_OF_RANGE",(e,t,n)=>{let i;if(u(t,'Missing "range" argument'),Number.isInteger(n)&&Math.abs(n)>2**32)i=p(String(n));else if("bigint"==typeof n){i=String(n);const e=BigInt(2)**BigInt(32);(n>e||n<-e)&&(i=p(i)),i+="n"}else i=r(n);return`The value of "${e}" is out of range. It must be ${t}. Received ${i}`},RangeError),h("ERR_MULTIPLE_CALLBACK","Callback called multiple times",Error),h("ERR_METHOD_NOT_IMPLEMENTED","The %s method is not implemented",Error),h("ERR_STREAM_ALREADY_FINISHED","Cannot call %s after a stream was finished",Error),h("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable",Error),h("ERR_STREAM_DESTROYED","Cannot call %s after a stream was destroyed",Error),h("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),h("ERR_STREAM_PREMATURE_CLOSE","Premature close",Error),h("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF",Error),h("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event",Error),h("ERR_STREAM_WRITE_AFTER_END","write after end",Error),h("ERR_UNKNOWN_ENCODING","Unknown encoding: %s",TypeError),e.exports={AbortError:g,aggregateTwoErrors:f(function(e,t){if(e&&t&&e!==t){if(Array.isArray(t.errors))return t.errors.push(e),t;const n=new s([t,e],t.message);return n.code=t.code,n}return e||t}),hideStackFrames:f,codes:d}},6524(e,t,n){"use strict";const{ObjectSetPrototypeOf:i}=n(4134);e.exports=o;const r=n(7382);function o(e){if(!(this instanceof o))return new o(e);r.call(this,e)}i(o.prototype,r.prototype),i(o,r),o.prototype._transform=function(e,t,n){n(null,e)}},6532(e,t,n){"use strict";const i=n(4422),{PromisePrototypeThen:r,SymbolAsyncIterator:o,SymbolIterator:s}=n(4134),{Buffer:a}=n(181),{ERR_INVALID_ARG_TYPE:c,ERR_STREAM_NULL_VALUES:l}=n(6371).codes;e.exports=function(e,t,n){let d,u;if("string"==typeof t||t instanceof a)return new e({objectMode:!0,...n,read(){this.push(t),this.push(null)}});if(t&&t[o])u=!0,d=t[o]();else{if(!t||!t[s])throw new c("iterable",["Iterable"],t);u=!1,d=t[s]()}const p=new e({objectMode:!0,highWaterMark:1,...n});let h=!1;return p._read=function(){h||(h=!0,async function(){for(;;){try{const{value:e,done:t}=u?await d.next():d.next();if(t)p.push(null);else{const t=e&&"function"==typeof e.then?await e:e;if(null===t)throw h=!1,new l;if(p.push(t))continue;h=!1}}catch(e){p.destroy(e)}break}}())},p._destroy=function(e,t){r(async function(e){const t=null!=e,n="function"==typeof d.throw;if(t&&n){const{value:t,done:n}=await d.throw(e);if(await t,n)return}if("function"==typeof d.return){const{value:e}=await d.return();await e}}(e),()=>i.nextTick(t,e),n=>i.nextTick(t,n||e))},p}},6584(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=n(4988);class r extends i.EventTarget{constructor(){throw super(),new TypeError("AbortSignal cannot be constructed directly")}get aborted(){const e=o.get(this);if("boolean"!=typeof e)throw new TypeError("Expected 'this' to be an 'AbortSignal' object, but got "+(null===this?"null":typeof this));return e}}i.defineEventAttribute(r.prototype,"abort");const o=new WeakMap;Object.defineProperties(r.prototype,{aborted:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag&&Object.defineProperty(r.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortSignal"});class s{constructor(){a.set(this,function(){const e=Object.create(r.prototype);return i.EventTarget.call(e),o.set(e,!1),e}())}get signal(){return c(this)}abort(){var e;e=c(this),!1===o.get(e)&&(o.set(e,!0),e.dispatchEvent({type:"abort"}))}}const a=new WeakMap;function c(e){const t=a.get(e);if(null==t)throw new TypeError("Expected 'this' to be an 'AbortController' object, but got "+(null===e?"null":typeof e));return t}Object.defineProperties(s.prototype,{signal:{enumerable:!0},abort:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag&&Object.defineProperty(s.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortController"}),t.AbortController=s,t.AbortSignal=r,t.default=s,e.exports=s,e.exports.AbortController=e.exports.default=s,e.exports.AbortSignal=r},6585(e){var t=1e3,n=60*t,i=60*n,r=24*i,o=7*r,s=365.25*r;function a(e,t,n,i){var r=t>=1.5*n;return Math.round(e/n)+" "+i+(r?"s":"")}e.exports=function(e,c){c=c||{};var l=typeof e;if("string"===l&&e.length>0)return function(e){if((e=String(e)).length>100)return;var a=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!a)return;var c=parseFloat(a[1]);switch((a[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return c*s;case"weeks":case"week":case"w":return c*o;case"days":case"day":case"d":return c*r;case"hours":case"hour":case"hrs":case"hr":case"h":return c*i;case"minutes":case"minute":case"mins":case"min":case"m":return c*n;case"seconds":case"second":case"secs":case"sec":case"s":return c*t;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return c;default:return}}(e);if("number"===l&&isFinite(e))return c.long?function(e){var o=Math.abs(e);if(o>=r)return a(e,o,r,"day");if(o>=i)return a(e,o,i,"hour");if(o>=n)return a(e,o,n,"minute");if(o>=t)return a(e,o,t,"second");return e+" ms"}(e):function(e){var o=Math.abs(e);if(o>=r)return Math.round(e/r)+"d";if(o>=i)return Math.round(e/i)+"h";if(o>=n)return Math.round(e/n)+"m";if(o>=t)return Math.round(e/t)+"s";return e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},6687(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.SpatialReasoningEngine=void 0,t.mediaObjectToBase64=c,t.buildImageContent=l,t.isVisionFormatError=d;const r=i(n(7562)),o=n(1554),{systemManager:s,mediaManager:a}=r.default;async function c(e){try{const t=e?.mimeType||"image/jpeg";let n;console.log(`[Image] Converting MediaObject, mimeType=${t}`);try{n=await a.convertMediaObjectToBuffer(e,t)}catch(t){console.warn("[Image] Direct conversion failed, trying with explicit JPEG:",t);try{const t=e;if("function"!=typeof t.getData)return console.warn("[Image] No getData method available"),null;{const e=await t.getData();if(!(e&&Buffer.isBuffer(e)&&e.length>1e3))return console.warn("[Image] getData returned invalid data"),null;console.log(`[Image] Got raw data: ${e.length} bytes`),n=e}}catch(e){return console.warn("[Image] Alternate data fetch failed:",e),null}}const i=Buffer.isBuffer(n),r=i?n.length:0;if(console.log(`[Image] Buffer: isBuffer=${i}, length=${r}`),!i||0===r)return console.warn("[Image] Did not receive a valid Buffer"),null;if(r<1e3)return console.warn(`[Image] Buffer too small: ${r} bytes`),null;const o=n.toString("base64");return console.log(`[Image] Converted to base64: ${o.length} chars`),{base64:o,mediaType:"image/jpeg"}}catch(e){return console.warn("[Image] Failed to convert MediaObject to base64:",e),null}}function l(e,t="unknown"){return{type:"image_url",image_url:{url:`data:${e.mediaType};base64,${e.base64}`}}}function d(e){const t=String(e);return t.includes("content.str")||t.includes("should be a valid string")||t.includes("Invalid content type")||t.includes("does not support vision")||t.includes("invalid base64")||t.includes("Invalid base64")||t.includes(".image.source")||t.includes(".image_url")||t.includes("image_url")&&t.includes("not supported")||t.includes("400")&&t.includes("content")}t.SpatialReasoningEngine=class{config;console;topology=null;llmDevice=null;contextChunks=[];topologyContextCache=null;contextCacheTime=0;landmarkSuggestions=new Map;constructor(e,t){this.config=e,this.console=t}updateTopology(e){this.topology=e,this.rebuildContextChunks(),this.topologyContextCache=null,this.contextCacheTime=0}rebuildContextChunks(){if(this.topology){this.contextChunks=[],this.topology.property&&this.contextChunks.push({id:"property",type:"property",content:this.buildPropertyContext(),metadata:{...this.topology.property}});for(const e of this.topology.cameras)this.contextChunks.push({id:`camera_${e.deviceId}`,type:"camera",content:this.buildCameraContext(e),metadata:{deviceId:e.deviceId,name:e.name,isEntryPoint:e.isEntryPoint,isExitPoint:e.isExitPoint}});for(const e of this.topology.landmarks||[])this.contextChunks.push({id:`landmark_${e.id}`,type:"landmark",content:this.buildLandmarkContext(e),metadata:{id:e.id,name:e.name,type:e.type,isEntryPoint:e.isEntryPoint,isExitPoint:e.isExitPoint}});for(const e of this.topology.connections)this.contextChunks.push({id:`connection_${e.id}`,type:"connection",content:this.buildConnectionContext(e),metadata:{id:e.id,fromCameraId:e.fromCameraId,toCameraId:e.toCameraId}});this.console.log(`Built ${this.contextChunks.length} context chunks for spatial reasoning`)}}buildPropertyContext(){if(!this.topology?.property)return"";const e=this.topology.property,t=[];return e.propertyType&&t.push(`Property type: ${e.propertyType}`),e.description&&t.push(e.description),e.frontFacing&&t.push(`Front faces ${e.frontFacing}`),e.features?.length&&t.push(`Features: ${e.features.join(", ")}`),t.join(". ")}buildCameraContext(e){const t=[`Camera: ${e.name}`];if(e.context?.mountLocation&&t.push(`Mounted at: ${e.context.mountLocation}`),e.context?.coverageDescription&&t.push(`Coverage: ${e.context.coverageDescription}`),e.context?.mountHeight&&t.push(`Height: ${e.context.mountHeight} feet`),e.isEntryPoint&&t.push("Watches property entry point"),e.isExitPoint&&t.push("Watches property exit point"),this.topology&&e.context?.visibleLandmarks?.length){const n=e.context.visibleLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);n.length&&t.push(`Can see: ${n.join(", ")}`)}return t.join(". ")}buildLandmarkContext(e){const t=[`${e.name} (${e.type})`];if(e.description&&t.push(e.description),e.isEntryPoint&&t.push("Property entry point"),e.isExitPoint&&t.push("Property exit point"),this.topology&&e.adjacentTo?.length){const n=e.adjacentTo.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);n.length&&t.push(`Adjacent to: ${n.join(", ")}`)}return t.join(". ")}buildConnectionContext(e){if(!this.topology)return"";const t=(0,o.findCamera)(this.topology,e.fromCameraId),n=(0,o.findCamera)(this.topology,e.toCameraId);if(!t||!n)return"";const i=[`Path from ${t.name} to ${n.name}`];e.name&&i.push(`Called: ${e.name}`);const r=Math.round(e.transitTime.typical/1e3);if(i.push(`Typical transit: ${r} seconds`),e.bidirectional&&i.push("Bidirectional path"),e.pathLandmarks?.length){const t=e.pathLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);t.length&&i.push(`Passes: ${t.join(" → ")}`)}return i.join(". ")}getTopologyContext(){const e=Date.now();return this.topologyContextCache&&e-this.contextCacheTime<this.config.contextCacheTtl?this.topologyContextCache:this.topology?(this.topologyContextCache=(0,o.generateTopologyDescription)(this.topology),this.contextCacheTime=e,this.topologyContextCache):""}retrieveRelevantContext(e,t){const n=[],i=this.contextChunks.find(e=>"property"===e.type);i&&n.push(i);const r=this.contextChunks.find(t=>t.id===`camera_${e}`),s=this.contextChunks.find(e=>e.id===`camera_${t}`);r&&n.push(r),s&&n.push(s);const a=this.contextChunks.find(n=>"connection"===n.type&&(n.metadata.fromCameraId===e&&n.metadata.toCameraId===t||n.metadata.fromCameraId===t&&n.metadata.toCameraId===e));if(a&&n.push(a),this.topology){const i=(0,o.getLandmarksVisibleFromCamera)(this.topology,e),r=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),s=new Set([...i.map(e=>e.id),...r.map(e=>e.id)]);for(const e of s){const t=this.contextChunks.find(t=>t.id===`landmark_${e}`);t&&n.push(t)}}return n}llmSearched=!1;llmProvider=null;llmProviderType="unknown";async findLlmDevice(){if(this.llmDevice)return this.llmDevice;if(this.llmSearched)return null;this.llmSearched=!0;try{for(const e of Object.keys(s.getSystemState())){const t=s.getDeviceById(e);if(t&&t.interfaces?.includes("ChatCompletion")){const e=t.name?.toLowerCase()||"",n=t.pluginId?.toLowerCase()||"";let i="Unknown",r="unknown";return e.includes("openai")||e.includes("gpt")?(i="OpenAI",r="openai"):e.includes("anthropic")||e.includes("claude")?(i="Anthropic",r="anthropic"):e.includes("ollama")?(i="Ollama",r="openai"):e.includes("gemini")||e.includes("google")?(i="Google",r="openai"):e.includes("llama")?(i="llama.cpp",r="openai"):(n.includes("@scrypted/llm")||n.includes("llm"))&&(i="Scrypted LLM",r="unknown"),this.llmDevice=t,this.llmProvider=`${i} (${t.name})`,this.llmProviderType=r,this.console.log(`[LLM] Connected to ${i}: ${t.name}`),this.console.log(`[LLM] Plugin: ${n||"N/A"}`),this.console.log(`[LLM] Image format: ${r}`),this.console.log(`[LLM] Interfaces: ${t.interfaces?.join(", ")}`),this.llmDevice}}this.console.warn("[LLM] No ChatCompletion device found. Install @scrypted/llm for enhanced descriptions."),this.console.warn("[LLM] Falling back to rule-based descriptions using topology data.")}catch(e){this.console.error("[LLM] Error searching for LLM device:",e)}return null}getLlmProvider(){return this.llmProvider}getLlmProviderType(){return this.llmProviderType}isLlmAvailable(){return null!==this.llmDevice}async generateEntryDescription(e,t,n){if(!this.topology)return{description:`${this.capitalizeFirst(e.className)} entered property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const i=(0,o.findCamera)(this.topology,t);if(!i)return{description:`${this.capitalizeFirst(e.className)} entered property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const r=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),s=this.capitalizeFirst(e.className),a=this.describeLocation(i,r,"to"),c=r.find(e=>"street"===e.type),l=r.find(e=>"neighbor"===e.type);let d="";c?d=` from ${c.name}`:l&&(d=` from ${l.name}`);const u=`${s} arrived at ${a}${d}`;if(this.console.log(`[Entry] enableLlm=${this.config.enableLlm}, hasMediaObject=${!!n}`),this.config.enableLlm&&n){this.console.log("[Entry] Attempting LLM description for entry event");const t=await this.getLlmEntryExitDescription(e,i,r,"entry",n);if(t)return this.console.log(`[Entry] LLM returned: ${t.substring(0,50)}...`),{description:t,involvedLandmarks:r,confidence:.9,usedLlm:!0};this.console.warn("[Entry] LLM returned null, falling back to basic")}else this.console.log(`[Entry] Skipping LLM (enableLlm=${this.config.enableLlm}, mediaObject=${!!n})`);return{description:u,involvedLandmarks:r,confidence:.8,usedLlm:!1}}async generateExitDescription(e,t,n){if(!this.topology)return{description:`${this.capitalizeFirst(e.className)} left property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const i=(0,o.findCamera)(this.topology,t);if(!i)return{description:`${this.capitalizeFirst(e.className)} left property`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const r=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),s=this.capitalizeFirst(e.className),a=this.describeLocation(i,r,"from"),c=r.find(e=>e.isExitPoint),l=r.find(e=>"street"===e.type);let d="";l?d=` towards ${l.name}`:c&&(d=` via ${c.name}`);const u=Math.round((e.lastSeen-e.firstSeen)/1e3);let p="";u>60?p=` after ${Math.round(u/60)}m on property`:u>10&&(p=` after ${u}s`);let h="";if(e.journey.length>0&&this.topology){const t=[];if(e.entryCamera){const n=(0,o.getLandmarksVisibleFromCamera)(this.topology,e.entryCamera),i=n.find(e=>e.isEntryPoint||"access"===e.type)||n[0];i&&t.push(i.name)}for(const n of e.journey){const e=(0,o.getLandmarksVisibleFromCamera)(this.topology,n.toCameraId).find(e=>!t.includes(e.name)&&("access"===e.type||"zone"===e.type||"structure"===e.type));e&&!t.includes(e.name)&&t.push(e.name)}t.length>1&&(h=` — visited ${t.join(" → ")}`)}const f=`${s} left ${a}${d}${p}${h}`;if(this.console.log(`[Exit] enableLlm=${this.config.enableLlm}, hasMediaObject=${!!n}`),this.config.enableLlm&&n){this.console.log("[Exit] Attempting LLM description for exit event");const t=await this.getLlmEntryExitDescription(e,i,r,"exit",n,h);if(t)return this.console.log(`[Exit] LLM returned: ${t.substring(0,50)}...`),{description:t,involvedLandmarks:r,confidence:.9,usedLlm:!0};this.console.warn("[Exit] LLM returned null, falling back to basic")}else this.console.log(`[Exit] Skipping LLM (enableLlm=${this.config.enableLlm}, mediaObject=${!!n})`);return{description:f,involvedLandmarks:r,confidence:.8,usedLlm:!1}}async generateMovementDescription(e,t,n,i,r){if(!this.topology)return{description:`${e.className} moving between cameras`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const s=(0,o.findCamera)(this.topology,t),a=(0,o.findCamera)(this.topology,n);if(!s||!a)return{description:`${e.className} moving between cameras`,involvedLandmarks:[],confidence:.5,usedLlm:!1};const c=(0,o.getLandmarksVisibleFromCamera)(this.topology,t),l=(0,o.getLandmarksVisibleFromCamera)(this.topology,n),d=[...new Set([...c,...l])];let u=this.buildBasicDescription(e,s,a,i,c,l);if(this.config.enableLlm&&r){const t=await this.getLlmEnhancedDescription(e,s,a,i,c,l,r);if(t)return{description:t,involvedLandmarks:d,pathDescription:this.buildPathDescription(s,a),confidence:.9,usedLlm:!0}}return{description:u,involvedLandmarks:d,pathDescription:this.buildPathDescription(s,a),confidence:.7,usedLlm:!1}}buildBasicDescription(e,t,n,i,r,s){const a=this.capitalizeFirst(e.className),c=Math.round(i/1e3),l=this.topology?(0,o.findConnection)(this.topology,t.deviceId,n.deviceId):null;let d=this.describeLocation(t,r,"from"),u=this.describeLocation(n,s,"to"),p="";if(l?.name)p=` via ${l.name}`;else if(l?.pathLandmarks?.length&&this.topology){const e=l.pathLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);e.length>0&&(p=` past ${e.join(" and ")}`)}let h="";if(e.journey.length>0){const t=Math.round((Date.now()-e.firstSeen)/1e3);t>60&&(h=` (${Math.round(t/60)}m on property)`)}return`${a} ${this.getMovementVerb(e.className,c)} ${d} heading ${u}${p}${h}`}describeLocation(e,t,n){const i=t.find(e=>"from"===n&&e.isExitPoint||"to"===n&&e.isEntryPoint);if(i)return`the ${i.name}`;const r=t.find(e=>"access"===e.type);if(r)return`the ${r.name}`;const o=t.find(e=>"zone"===e.type);if(o)return`the ${o.name}`;if(t.length>0)return`near ${t[0].name}`;if(e.context?.coverageDescription){return`the ${e.context.coverageDescription.split(".")[0].toLowerCase()}`}return"property"}getMovementVerb(e,t){return"car"===e||"vehicle"===e||"truck"===e?t<10?"driving from":"moved from":t<5?"walking from":t<30?"moved from":"traveled from"}buildPathDescription(e,t){if(!this.topology)return;const n=(0,o.findConnection)(this.topology,e.deviceId,t.deviceId);if(n){if(n.pathLandmarks?.length){const e=n.pathLandmarks.map(e=>(0,o.findLandmark)(this.topology,e)?.name).filter(Boolean);if(e.length)return`Via ${e.join(" → ")}`}return n.name||void 0}}async getLlmEnhancedDescription(e,t,n,i,r,o,s){const a=await this.findLlmDevice();if(!a||!a.getChatCompletion)return null;try{const d=await c(s),u=this.retrieveRelevantContext(t.deviceId,n.deviceId).map(e=>e.content).join("\n\n"),p=this.buildLlmPrompt(e,t,n,i,r,o,u);let h;h=d?[{type:"text",text:p},l(d,this.llmProviderType)]:p;const f=await a.getChatCompletion({messages:[{role:"user",content:h}],max_tokens:150,temperature:.7}),g=f?.choices?.[0]?.message?.content;return g&&"string"==typeof g?g.trim():null}catch(e){return this.console.warn("LLM description generation failed:",e),null}}async getLlmEntryExitDescription(e,t,n,i,r,o){this.console.log(`[LLM] getLlmEntryExitDescription called for ${i} event`);const s=await this.findLlmDevice();if(!s)return this.console.warn(`[LLM] No LLM device found for ${i} description`),null;if(!s.getChatCompletion)return this.console.warn("[LLM] LLM device has no getChatCompletion method"),null;this.console.log(`[LLM] Using LLM device: ${this.llmProvider}`);try{const a=await c(r);this.console.log(`[LLM] Image converted: ${a?"success":"failed"}, type: ${a?.mediaType}`);const u=n.map(e=>e.name).join(", ")||"none identified",p=Math.round((e.lastSeen-e.firstSeen)/1e3),h="entry"===i?`You are a security camera system. Analyze this image and describe who/what just arrived.\n\nCONTEXT:\n- Camera: ${t.name}\n- Object type: ${e.className}\n- Nearby landmarks: ${u}\n\nINSTRUCTIONS:\nLook at the image and generate a single, natural sentence describing:\n1. Physical description (if person: gender, clothing, items carried; if vehicle: color, type, make)\n2. What they appear to be doing (arriving, approaching, etc.)\n3. Relevant landmark context (driveway, front door, mailbox, etc.)\n\nExamples of good descriptions:\n- "Man in gray hoodie approaching the front door"\n- "Woman in scrubs arriving with shopping bags"\n- "White delivery van pulling into the driveway"\n- "UPS driver carrying package towards the porch"\n- "Teenager on bicycle coming up the driveway"\n\nGenerate ONLY the description, nothing else:`:`You are a security camera system. Analyze this image and describe who/what is leaving.\n\nCONTEXT:\n- Camera: ${t.name}\n- Object type: ${e.className}\n- Time on property: ${p>60?Math.round(p/60)+" minutes":p+" seconds"}\n- Nearby landmarks: ${u}\n${o?`- Journey: ${o}`:""}\n\nINSTRUCTIONS:\nLook at the image and generate a single, natural sentence describing:\n1. Physical description (if person: gender, clothing, items carried; if vehicle: color, type)\n2. What they did (if determinable from context)\n3. Direction they're leaving towards\n\nExamples of good descriptions:\n- "Man in black hoodie leaving after checking the mailbox"\n- "Woman in business attire heading to car in driveway"\n- "Red sedan backing out of the driveway"\n- "Delivery driver returning to FedEx truck after leaving package"\n- "Landscaper with leaf blower heading to work truck"\n\nGenerate ONLY the description, nothing else:`;let f,g=!1;if(a)try{this.console.log(`[LLM] Attempting multimodal ${i} call with image...`);const e=[{type:"text",text:h},l(a,this.llmProviderType)];f=await s.getChatCompletion({messages:[{role:"user",content:e}],max_tokens:100,temperature:.7}),g=!0}catch(e){d(e)?this.console.warn(`[LLM] Vision format not supported, falling back to text-only: ${e.message||e}`):this.console.warn(`[LLM] Multimodal call failed, trying text-only: ${e.message||e}`)}f||(this.console.log(`[LLM] Calling text-only getChatCompletion for ${i}...`),f=await s.getChatCompletion({messages:[{role:"user",content:h}],max_tokens:100,temperature:.7}));const m=f?.choices?.[0]?.message?.content;return m&&"string"==typeof m?(this.console.log(`[LLM] Got ${i} description (vision=${g}): ${m.trim().substring(0,50)}...`),m.trim()):(this.console.warn(`[LLM] No content in response for ${i}`),null)}catch(e){return this.console.warn(`[LLM] ${i} description generation failed:`,e),null}}buildLlmPrompt(e,t,n,i,r,o,s){const a=Math.round(i/1e3);return`You are a security camera system describing movement on a property.\n\nPROPERTY CONTEXT:\n${s}\n\nCURRENT EVENT:\n- Object type: ${e.className}\n- Moving from: ${t.name}${r.length?` (near ${r.map(e=>e.name).join(", ")})`:""}\n- Moving to: ${n.name}${o.length?` (near ${o.map(e=>e.name).join(", ")})`:""}\n- Transit time: ${a} seconds\n\nINSTRUCTIONS:\nGenerate a single, concise sentence describing this movement. Include:\n1. Description of the ${e.className} (if person: gender, clothing; if vehicle: color, type)\n2. Where they came from (using landmark names if available)\n3. Where they're heading (using landmark names if available)\n\nExamples of good descriptions:\n- "Man in blue jacket walking from the driveway towards the front door"\n- "Black SUV pulling into the driveway from the street"\n- "Woman with dog walking from the backyard towards the side gate"\n- "Delivery person approaching the front porch from the mailbox"\n\nGenerate ONLY the description, nothing else:`}async suggestLandmark(e,t,n,i){if(!this.config.enableLandmarkLearning)return null;const r=await this.findLlmDevice();if(!r||!r.getChatCompletion)return null;try{const o=await c(t),s=`Analyze this security camera image. A ${n} was detected.\n\nLooking at the surroundings and environment, identify any notable landmarks or features visible that could help describe this location. Consider:\n- Structures (house, garage, shed, porch)\n- Features (mailbox, tree, pool, garden)\n- Access points (driveway, walkway, gate, door)\n- Boundaries (fence, wall, hedge)\n\nIf you can identify a clear landmark feature, respond with ONLY a JSON object:\n{"name": "Landmark Name", "type": "structure|feature|boundary|access|vehicle|neighbor|zone|street", "description": "Brief description"}\n\nIf no clear landmark is identifiable, respond with: {"name": null}`;let a;a=o?[{type:"text",text:s},l(o,this.llmProviderType)]:s;const d=await r.getChatCompletion({messages:[{role:"user",content:a}],max_tokens:100,temperature:.3}),u=d?.choices?.[0]?.message?.content;if(u&&"string"==typeof u)try{const t=JSON.parse(u.trim());if(t.name&&t.type){const n=`suggest_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,r={id:n,landmark:{id:`landmark_${Date.now()}`,name:t.name,type:t.type,position:i,description:t.description,aiSuggested:!0,aiConfidence:.7,visibleFromCameras:[e]},detectedByCameras:[e],timestamp:Date.now(),detectionCount:1,status:"pending"},o=this.findSimilarSuggestion(t.name,i);if(o){const t=this.landmarkSuggestions.get(o);return t.detectionCount++,t.landmark.aiConfidence=Math.min(.95,t.landmark.aiConfidence+.05),t.detectedByCameras.includes(e)||t.detectedByCameras.push(e),t}return this.landmarkSuggestions.set(n,r),r}}catch(e){}return null}catch(e){return this.console.warn("Landmark suggestion failed:",e),null}}findSimilarSuggestion(e,t){const n=e.toLowerCase();for(const[e,i]of this.landmarkSuggestions){if("pending"!==i.status)continue;const r=i.landmark.name.toLowerCase(),o=Math.sqrt(Math.pow(i.landmark.position.x-t.x,2)+Math.pow(i.landmark.position.y-t.y,2));if((r.includes(n)||n.includes(r))&&o<100)return e}return null}getPendingSuggestions(){return Array.from(this.landmarkSuggestions.values()).filter(e=>"pending"===e.status&&e.landmark.aiConfidence>=this.config.landmarkConfidenceThreshold).sort((e,t)=>t.detectionCount-e.detectionCount)}acceptSuggestion(e){const t=this.landmarkSuggestions.get(e);if(!t)return null;t.status="accepted";const n={...t.landmark};return n.aiSuggested=!1,this.landmarkSuggestions.delete(e),n}rejectSuggestion(e){const t=this.landmarkSuggestions.get(e);return!!t&&(t.status="rejected",this.landmarkSuggestions.delete(e),!0)}capitalizeFirst(e){return e?e.charAt(0).toUpperCase()+e.slice(1):"Object"}getLandmarkTemplates(){return o.LANDMARK_TEMPLATES}}},6698(e){"function"==typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}},6706(e,t,n){const i=n(4422),r=n(181),{isReadable:o,isWritable:s,isIterable:a,isNodeStream:c,isReadableNodeStream:l,isWritableNodeStream:d,isDuplexNodeStream:u,isReadableStream:p,isWritableStream:h}=n(6115),f=n(6238),{AbortError:g,codes:{ERR_INVALID_ARG_TYPE:m,ERR_INVALID_RETURN_VALUE:y}}=n(6371),{destroyer:b}=n(5896),v=n(3370),S=n(7576),_=n(8584),{createDeferredPromise:w}=n(7760),k=n(6532),I=globalThis.Blob||r.Blob,x="undefined"!=typeof I?function(e){return e instanceof I}:function(e){return!1},C=globalThis.AbortController||n(6584).AbortController,{FunctionPrototypeCall:E}=n(4134);class T extends v{constructor(e){super(e),!1===(null==e?void 0:e.readable)&&(this._readableState.readable=!1,this._readableState.ended=!0,this._readableState.endEmitted=!0),!1===(null==e?void 0:e.writable)&&(this._writableState.writable=!1,this._writableState.ending=!0,this._writableState.ended=!0,this._writableState.finished=!0)}}function O(e){const t=e.readable&&"function"!=typeof e.readable.read?S.wrap(e.readable):e.readable,n=e.writable;let i,r,a,c,l,d=!!o(t),u=!!s(n);function p(e){const t=c;c=null,t?t(e):e&&l.destroy(e)}return l=new T({readableObjectMode:!(null==t||!t.readableObjectMode),writableObjectMode:!(null==n||!n.writableObjectMode),readable:d,writable:u}),u&&(f(n,e=>{u=!1,e&&b(t,e),p(e)}),l._write=function(e,t,r){n.write(e,t)?r():i=r},l._final=function(e){n.end(),r=e},n.on("drain",function(){if(i){const e=i;i=null,e()}}),n.on("finish",function(){if(r){const e=r;r=null,e()}})),d&&(f(t,e=>{d=!1,e&&b(t,e),p(e)}),t.on("readable",function(){if(a){const e=a;a=null,e()}}),t.on("end",function(){l.push(null)}),l._read=function(){for(;;){const e=t.read();if(null===e)return void(a=l._read);if(!l.push(e))return}}),l._destroy=function(e,o){e||null===c||(e=new g),a=null,i=null,r=null,null===c?o(e):(c=o,b(n,e),b(t,e))},l}e.exports=function e(t,n){if(u(t))return t;if(l(t))return O({readable:t});if(d(t))return O({writable:t});if(c(t))return O({writable:!1,readable:!1});if(p(t))return O({readable:S.fromWeb(t)});if(h(t))return O({writable:_.fromWeb(t)});if("function"==typeof t){const{value:e,write:r,final:o,destroy:s}=function(e){let{promise:t,resolve:n}=w();const r=new C,o=r.signal,s=e(async function*(){for(;;){const e=t;t=null;const{chunk:r,done:s,cb:a}=await e;if(i.nextTick(a),s)return;if(o.aborted)throw new g(void 0,{cause:o.reason});({promise:t,resolve:n}=w()),yield r}}(),{signal:o});return{value:s,write(e,t,i){const r=n;n=null,r({chunk:e,done:!1,cb:i})},final(e){const t=n;n=null,t({done:!0,cb:e})},destroy(e,t){r.abort(),t(e)}}}(t);if(a(e))return k(T,e,{objectMode:!0,write:r,final:o,destroy:s});const c=null==e?void 0:e.then;if("function"==typeof c){let t;const n=E(c,e,e=>{if(null!=e)throw new y("nully","body",e)},e=>{b(t,e)});return t=new T({objectMode:!0,readable:!1,write:r,final(e){o(async()=>{try{await n,i.nextTick(e,null)}catch(t){i.nextTick(e,t)}})},destroy:s})}throw new y("Iterable, AsyncIterable or AsyncFunction",n,e)}if(x(t))return e(t.arrayBuffer());if(a(t))return k(T,t,{objectMode:!0,writable:!1});if(p(null==t?void 0:t.readable)&&h(null==t?void 0:t.writable))return T.fromWeb(t);if("object"==typeof(null==t?void 0:t.writable)||"object"==typeof(null==t?void 0:t.readable)){return O({readable:null!=t&&t.readable?l(null==t?void 0:t.readable)?null==t?void 0:t.readable:e(t.readable):void 0,writable:null!=t&&t.writable?d(null==t?void 0:t.writable)?null==t?void 0:t.writable:e(t.writable):void 0})}const r=null==t?void 0:t.then;if("function"==typeof r){let e;return E(r,t,t=>{null!=t&&e.push(t),e.push(null)},t=>{b(e,t)}),e=new T({objectMode:!0,writable:!1,read(){}})}throw new m(n,["Blob","ReadableStream","WritableStream","Stream","Iterable","AsyncIterable","Function","{ readable, writable } pair","Promise"],t)}},6751(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ObjectCorrelator=void 0;const i=n(1554),r=n(441);t.ObjectCorrelator=class{topology;config;constructor(e,t){this.topology=e,this.config=t}async findBestMatch(e,t){const n=[];for(const i of t){const t=await this.evaluateCandidate(i,e);t.confidence>=this.config.correlationThreshold&&n.push(t)}if(0===n.length){const n=t.filter(t=>t.className===e.detection.className);if(1===n.length){const t=await this.evaluateCandidate(n[0],e);if(t.confidence>=.3&&t.factors.timing>0)return t}return null}return n.sort((e,t)=>t.confidence-e.confidence),n[0]}async evaluateCandidate(e,t){const n={timing:this.evaluateTimingFactor(e,t),visual:await this.evaluateVisualFactor(e,t),spatial:this.evaluateSpatialFactor(e,t),class:this.evaluateClassFactor(e,t)};if(0===n.class)return{trackedObject:e,newSighting:t,confidence:0,factors:n};if(0===n.timing)return{trackedObject:e,newSighting:t,confidence:0,factors:n};return{trackedObject:e,newSighting:t,confidence:.3*n.timing+.35*n.visual+.25*n.spatial+.1*n.class,factors:n}}evaluateTimingFactor(e,t){const n=(0,r.getLastSighting)(e);if(!n)return 0;if(n.cameraId===t.cameraId)return 1;const o=t.timestamp-n.timestamp,s=(0,i.findConnection)(this.topology,n.cameraId,t.cameraId);if(!s){return o>0&&o<3e5?o<6e4?.9:o<12e4?.7:Math.max(.4,.7-(o-12e4)/18e4*.3):.3}const{min:a,typical:c,max:l}=s.transitTime;if(o<.5*a||o>2*l)return 0;if(o<a||o>l)return o<a?o/a*.3:l/o*.3;const d=Math.abs(o-c),u=(l-a)/2;return 0===u?1:Math.max(.5,1-d/u*.5)}async evaluateVisualFactor(e,t){if(!this.config.useVisualMatching)return.5;if(!e.visualDescriptor||!t.embedding)return.5;try{return(this.cosineSimilarity(e.visualDescriptor,t.embedding)+1)/2}catch(e){return.5}}evaluateSpatialFactor(e,t){const n=(0,r.getLastSighting)(e);if(!n)return.5;if(n.cameraId===t.cameraId)return 1;const o=(0,i.findConnection)(this.topology,n.cameraId,t.cameraId);if(!o)return.5;let s=0;if(n.position&&o.exitZone.length>0){this.isPointNearZone(n.position,o.exitZone,.2)&&(s+=.5)}else s+=.25;if(t.position&&o.entryZone.length>0){this.isPointNearZone(t.position,o.entryZone,.2)&&(s+=.5)}else s+=.25;return s}evaluateClassFactor(e,t){if(e.className===t.detection.className)return 1;return({car:["vehicle","truck","suv"],vehicle:["car","truck","suv"],truck:["vehicle","car"],person:["human"],human:["person"]}[e.className]||[]).includes(t.detection.className)?.8:0}cosineSimilarity(e,t){try{const n=this.decodeEmbedding(e),i=this.decodeEmbedding(t);if(n.length!==i.length||0===n.length)return 0;let r=0,o=0,s=0;for(let e=0;e<n.length;e++)r+=n[e]*i[e],o+=n[e]*n[e],s+=i[e]*i[e];return o=Math.sqrt(o),s=Math.sqrt(s),0===o||0===s?0:r/(o*s)}catch(e){return 0}}decodeEmbedding(e){try{const t=Buffer.from(e,"base64"),n=[];for(let e=0;e<t.length;e+=4)n.push(t.readFloatLE(e));return n}catch(e){return[]}}isPointNearZone(e,t,n){if(t.length<3)return!1;const i=100*e.x,r=100*e.y;let o=!1;for(let e=0,n=t.length-1;e<t.length;n=e++){const s=t[e][0],a=t[e][1],c=t[n][0],l=t[n][1];a>r!=l>r&&i<(c-s)*(r-a)/(l-a)+s&&(o=!o)}if(o)return!0;for(const e of t){const t=Math.abs(i-e[0])/100,o=Math.abs(r-e[1])/100;if(t<n&&o<n)return!0}return!1}}},6887(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isReactNativeBrowser=t.isWebWorker=void 0;const n=()=>Boolean("object"==typeof self&&self?.constructor?.name?.includes("WorkerGlobalScope")&&"undefined"==typeof Deno),i=()=>"undefined"!=typeof navigator&&"ReactNative"===navigator.product,r=(()=>{if("undefined"!=typeof window){if("undefined"!=typeof navigator&&navigator.userAgent?.toLowerCase().indexOf(" electron/")>-1&&process?.versions){return!Object.prototype.hasOwnProperty.call(process.versions,"electron")}return"undefined"!=typeof window.document}return!1})()||n()||i();t.isWebWorker=n(),t.isReactNativeBrowser=i(),t.default=r},6912(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const r=i(n(4959)),o=i(n(5228)),s=i(n(495)),a=i(n(1021)),c=i(n(4264));t.default=(e,t,n)=>{const{options:i}=e;if(5===i.protocolVersion&&i.properties&&i.properties.maximumPacketSize&&i.properties.maximumPacketSize<t.length)return e.emit("error",new Error(`exceeding packets size ${t.cmd}`)),e.end({reasonCode:149,properties:{reasonString:"Maximum packet size was exceeded"}}),e;switch(e.log("_handlePacket :: emitting packetreceive"),e.emit("packetreceive",t),t.cmd){case"publish":(0,r.default)(e,t,n);break;case"puback":case"pubrec":case"pubcomp":case"suback":case"unsuback":e.reschedulePing(),(0,a.default)(e,t),n();break;case"pubrel":e.reschedulePing(),(0,c.default)(e,t,n);break;case"connack":(0,s.default)(e,t),n();break;case"auth":e.reschedulePing(),(0,o.default)(e,t),n();break;case"pingresp":e.log("_handlePacket :: received pingresp"),e.reschedulePing(!0),n();break;case"disconnect":e.emit("disconnect",t),n();break;default:e.log("_handlePacket :: unknown command"),n()}}},6928(e){"use strict";e.exports=require("path")},6968(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,n,i){f("SOCKS connection to %s:%d via %s",e,t,n);const r=new g;return async function(e,t,n,i,r={}){const o=r.lookup??(0,p.promisify)(u.lookup),[s,a]=function(e){const t=new URL(e);if(t.pathname||t.hash||t.search)throw m(new Error("bad SOCKS URL"));const[n,i]=function(e){switch(e){case"socks5h:":return[5,!0];case"socks4a:":return[4,!0];case"socks5:":return[5,!1];case"socks4:":return[4,!1];default:return[void 0,!1]}}(t.protocol);if(!n)throw m(new Error("bad SOCKS URL: invalid protocol"));const r=parseInt(t.port,10);if(Number.isNaN(r))throw m(new Error("bad SOCKS URL: invalid port"));const o={host:t.hostname,port:r,type:n};return[o,i]}(n);a||(f("resolving %s locally",e),e=(await o(e,{family:4===s.type?4:0})).address);f("establishing SOCKS%d connection to %s:%d via %s:%d",s.type,e,t,s.host,s.port);const c=new d.SocksClient({command:"connect",destination:{host:e,port:t},proxy:{...s},timeout:r.timeout});c.connect(),c.on("established",({socket:e})=>i._start(e)),c.on("error",e=>{f("SOCKS failed: %s",e),i.destroy(m(e))})}(e,t,n,r,i).catch(e=>{f("SOCKS failed: %s",e),r.destroy(e)}),r};const c=a(n(5753)),l=n(2203),d=n(5861),u=s(n(2250)),p=n(9023),h=a(n(2613)),f=(0,c.default)("mqttjs:socks");class g extends l.Duplex{_flowing=!1;_socket;constructor(){super({autoDestroy:!1}),this.cork()}_start(e){f("proxy stream started"),(0,h.default)(!this._socket),this.destroyed?e.destroy(this.errored):(this._socket=e,this._flowing||e.pause(),e.on("data",this._onData),e.on("end",this._onEnd),e.on("error",this._onError),e.on("close",this._onClose),e.emit("connect"),this.uncork())}_write(e,t,n){(0,h.default)(this._socket),this._socket.write(e,n)}_read(e){this._flowing=!0,this._socket?.resume?.()}_destroy(e,t){this._socket?.destroy?.(e),t(e)}_onData=e=>{(0,h.default)(this._socket),this._flowing=this.push(e),this._flowing||this._socket.pause()};_onEnd=()=>{f("proxy stream received EOF"),this.push(null)};_onClose=()=>{f("proxy stream closed"),this.destroy()};_onError=e=>{f("proxy stream died with error %s",e),this.destroy(e)}}function m(e){try{return void 0===e.code&&(e.code="SOCKS"),e}catch{return e}}},6982(e){"use strict";e.exports=require("crypto")},7016(e){"use strict";e.exports=require("url")},7130(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ipToBuffer=t.int32ToIpv4=t.ipv4ToInt32=t.validateSocksClientChainOptions=t.validateSocksClientOptions=void 0;const i=n(3763),r=n(5438),o=n(2203),s=n(9424),a=n(9278);function c(e,t){if(void 0!==e.custom_auth_method){if(e.custom_auth_method<r.SOCKS5_CUSTOM_AUTH_START||e.custom_auth_method>r.SOCKS5_CUSTOM_AUTH_END)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthRange,t);if(void 0===e.custom_auth_request_handler||"function"!=typeof e.custom_auth_request_handler)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthOptions,t);if(void 0===e.custom_auth_response_size)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthOptions,t);if(void 0===e.custom_auth_response_handler||"function"!=typeof e.custom_auth_response_handler)throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsCustomAuthOptions,t)}}function l(e){return e&&"string"==typeof e.host&&Buffer.byteLength(e.host)<256&&"number"==typeof e.port&&e.port>=0&&e.port<=65535}function d(e){return e&&("string"==typeof e.host||"string"==typeof e.ipaddress)&&"number"==typeof e.port&&e.port>=0&&e.port<=65535&&(4===e.type||5===e.type)}function u(e){return"number"==typeof e&&e>0}t.validateSocksClientOptions=function(e,t=["connect","bind","associate"]){if(!r.SocksCommand[e.command])throw new i.SocksClientError(r.ERRORS.InvalidSocksCommand,e);if(-1===t.indexOf(e.command))throw new i.SocksClientError(r.ERRORS.InvalidSocksCommandForOperation,e);if(!l(e.destination))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsDestination,e);if(!d(e.proxy))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsProxy,e);if(c(e.proxy,e),e.timeout&&!u(e.timeout))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsTimeout,e);if(e.existing_socket&&!(e.existing_socket instanceof o.Duplex))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsExistingSocket,e)},t.validateSocksClientChainOptions=function(e){if("connect"!==e.command)throw new i.SocksClientError(r.ERRORS.InvalidSocksCommandChain,e);if(!l(e.destination))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsDestination,e);if(!(e.proxies&&Array.isArray(e.proxies)&&e.proxies.length>=2))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsProxiesLength,e);if(e.proxies.forEach(t=>{if(!d(t))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsProxy,e);c(t,e)}),e.timeout&&!u(e.timeout))throw new i.SocksClientError(r.ERRORS.InvalidSocksClientOptionsTimeout,e)},t.ipv4ToInt32=function(e){return new s.Address4(e).toArray().reduce((e,t)=>(e<<8)+t,0)>>>0},t.int32ToIpv4=function(e){return[e>>>24&255,e>>>16&255,e>>>8&255,255&e].join(".")},t.ipToBuffer=function(e){if(a.isIPv4(e)){const t=new s.Address4(e);return Buffer.from(t.toArray())}if(a.isIPv6(e)){const t=new s.Address6(e);return Buffer.from(t.canonicalForm().split(":").map(e=>e.padStart(4,"0")).join(""),"hex")}throw new Error("Invalid IP address format")}},7136(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.TrackingEngine=void 0;const a=s(n(7562)),c=n(1554),l=n(441),d=n(397),u=n(6751),p=n(6687),{systemManager:h}=a.default;t.TrackingEngine=class{topology;state;alertManager;config;console;correlator;spatialReasoning;listeners=new Map;pendingTimers=new Map;lostCheckInterval=null;objectLastAlertTime=new Map;onTopologyChange;lastLlmCallTime=0;llmDebounceTimer=null;observedTransits=new Map;connectionSuggestions=new Map;MIN_OBSERVATIONS_FOR_SUGGESTION=3;trainingSession=null;trainingConfig=d.DEFAULT_TRAINING_CONFIG;onTrainingStatusUpdate;snapshotCache=new Map;constructor(e,t,n,i,r){this.topology=e,this.state=t,this.alertManager=n,this.config=i,this.console=r,this.correlator=new u.ObjectCorrelator(e,i);const o={enableLlm:i.useLlmDescriptions,enableLandmarkLearning:i.enableLandmarkLearning??!0,landmarkConfidenceThreshold:i.landmarkConfidenceThreshold??.7,contextCacheTtl:6e4};this.spatialReasoning=new p.SpatialReasoningEngine(o,r),this.spatialReasoning.updateTopology(e)}setTopologyChangeCallback(e){this.onTopologyChange=e}async startTracking(){this.console.log("Starting tracking engine..."),await this.stopTracking();for(const e of this.topology.cameras)try{const t=h.getDeviceById(e.deviceId);if(!t){this.console.warn(`Camera not found: ${e.deviceId} (${e.name})`);continue}if(!t.interfaces?.includes(a.ScryptedInterface.ObjectDetector)){this.console.warn(`Camera ${e.name} does not support object detection`);continue}const n=t.listen(a.ScryptedInterface.ObjectDetector,(t,n,i)=>{this.handleDetection(e.deviceId,e.name,i)});this.listeners.set(e.deviceId,n),this.console.log(`Listening to camera: ${e.name}`)}catch(t){this.console.error(`Failed to subscribe to camera ${e.name}:`,t)}this.lostCheckInterval=setInterval(()=>{this.checkForLostObjects()},3e4),this.console.log(`Tracking engine started with ${this.listeners.size} cameras`)}async stopTracking(){for(const[e,t]of this.listeners.entries())try{t.removeListener()}catch(t){this.console.error(`Failed to remove listener for ${e}:`,t)}this.listeners.clear();for(const e of this.pendingTimers.values())clearTimeout(e);this.pendingTimers.clear(),this.lostCheckInterval&&(clearInterval(this.lostCheckInterval),this.lostCheckInterval=null),this.console.log("Tracking engine stopped")}async handleDetection(e,t,n){if(!n.detections||0===n.detections.length)return;const i=(0,c.findCamera)(this.topology,e);if(!i)return;const r=n.timestamp||Date.now();for(const o of n.detections){if(o.score<.5)continue;if(this.isTrainingActive()&&"person"===o.className&&this.recordTrainerDetection(e,o,o.score),i.trackClasses.length>0&&!i.trackClasses.includes(o.className))continue;const s={detection:o,cameraId:e,cameraName:t,timestamp:r,confidence:o.score,embedding:o.embedding,detectionId:n.detectionId,position:o.boundingBox?{x:(o.boundingBox[0]+o.boundingBox[2]/2)/100,y:(o.boundingBox[1]+o.boundingBox[3]/2)/100}:void 0};await this.processSighting(s,i.isEntryPoint,i.isExitPoint)}}passesLoiteringThreshold(e){return e.lastSeen-e.firstSeen>=this.config.loiteringThreshold}isInAlertCooldown(e){const t=this.objectLastAlertTime.get(e);return!!t&&Date.now()-t<this.config.objectAlertCooldown}recordAlertTime(e){this.objectLastAlertTime.set(e,Date.now())}isLlmCallAllowed(){const e=this.config.llmDebounceInterval||0;if(e<=0)return!0;return Date.now()-this.lastLlmCallTime>=e}recordLlmCall(){this.lastLlmCallTime=Date.now()}async getSpatialDescription(e,t,n,i,r){const o=this.config.llmFallbackEnabled??!0,s=this.config.llmFallbackTimeout??3e3;try{if(!this.isLlmCallAllowed())return this.console.log("LLM rate-limited, using basic notification"),null;let c,l;if(this.config.useLlmDescriptions){const e=h.getDeviceById(r);e?.interfaces?.includes(a.ScryptedInterface.Camera)&&(c=await e.takePicture())}if(this.recordLlmCall(),o&&c){const r=new Promise((e,t)=>{setTimeout(()=>t(new Error("LLM timeout")),s)}),o=this.spatialReasoning.generateMovementDescription(e,t,n,i,c);try{l=await Promise.race([o,r])}catch(e){return this.console.log("LLM timed out, using basic notification"),null}}else l=await this.spatialReasoning.generateMovementDescription(e,t,n,i,c);return this.config.enableLandmarkLearning&&c&&this.tryLearnLandmark(r,c,e.className),l}catch(e){return this.console.warn("Spatial reasoning failed:",e),null}}async tryLearnLandmark(e,t,n){try{const i={x:50,y:50},r=await this.spatialReasoning.suggestLandmark(e,t,n,i);r&&this.console.log(`AI suggested landmark: ${r.landmark.name} (${r.landmark.type}, confidence: ${r.landmark.aiConfidence?.toFixed(2)})`)}catch(e){}}async processSighting(e,t,n){const i=await this.correlateDetection(e);if(i){const t=i.trackedObject,r=(0,l.getLastSighting)(t);if(r&&r.cameraId!==e.cameraId){const n=e.timestamp-r.timestamp;if(this.config.useLlmDescriptions&&this.captureAndCacheSnapshot(t.globalId,e.cameraId).catch(e=>{this.console.warn(`[Transition Snapshot] Failed to update snapshot: ${e}`)}),this.state.addJourney(t.globalId,{fromCameraId:r.cameraId,fromCameraName:r.cameraName,toCameraId:e.cameraId,toCameraName:e.cameraName,exitTime:r.timestamp,entryTime:e.timestamp,transitDuration:n,correlationConfidence:i.confidence}),this.recordObservedTransit(r.cameraId,e.cameraId,n),this.console.log(`Object ${t.globalId.slice(0,8)} transited: ${r.cameraName} → ${e.cameraName} (confidence: ${(100*i.confidence).toFixed(0)}%)`),this.passesLoiteringThreshold(t)&&!this.isInAlertCooldown(t.globalId)){const i=await this.getSpatialDescription(t,r.cameraId,e.cameraId,n,e.cameraId);await this.alertManager.checkAndAlert("movement",t,{fromCameraId:r.cameraId,fromCameraName:r.cameraName,toCameraId:e.cameraId,toCameraName:e.cameraName,transitTime:n,objectClass:e.detection.className,objectLabel:i?.description||e.detection.label,detectionId:e.detectionId,pathDescription:i?.pathDescription,involvedLandmarks:i?.involvedLandmarks?.map(e=>e.name),usedLlm:i?.usedLlm}),this.recordAlertTime(t.globalId)}}this.state.addSighting(t.globalId,e);const o=this.pendingTimers.get(t.globalId);o&&(clearTimeout(o),this.pendingTimers.delete(t.globalId)),this.state.reactivate(t.globalId),n&&this.isLeavingFrame(e)&&this.handlePotentialExit(t,e)}else{const n=this.state.generateId();this.state.createObject(n,e,t);this.console.log(`New ${e.detection.className} detected on ${e.cameraName} (ID: ${n.slice(0,8)})`),this.scheduleLoiteringAlert(n,e,t)}}scheduleLoiteringAlert(e,t,n){this.config.useLlmDescriptions&&this.captureAndCacheSnapshot(e,t.cameraId).catch(e=>{this.console.warn(`[Snapshot] Failed to cache initial snapshot: ${e}`)}),setTimeout(async()=>{const i=this.state.getObject(e);if(!i||"active"!==i.state)return;if(this.isInAlertCooldown(e))return;let r=this.snapshotCache.get(e);this.console.log(`[Entry Alert] Using cached snapshot: ${!!r}`),this.console.log(`[Entry Alert] Calling generateEntryDescription with mediaObject=${!!r}`);const o=await this.spatialReasoning.generateEntryDescription(i,t.cameraId,r);this.console.log(`[Entry Alert] Got description: "${o.description.substring(0,60)}...", usedLlm=${o.usedLlm}`),n?await this.alertManager.checkAndAlert("property_entry",i,{cameraId:t.cameraId,cameraName:t.cameraName,objectClass:t.detection.className,objectLabel:o.description,detectionId:t.detectionId,involvedLandmarks:o.involvedLandmarks?.map(e=>e.name),usedLlm:o.usedLlm}):await this.alertManager.checkAndAlert("movement",i,{cameraId:t.cameraId,cameraName:t.cameraName,toCameraId:t.cameraId,toCameraName:t.cameraName,objectClass:t.detection.className,objectLabel:o.description,detectionId:t.detectionId,involvedLandmarks:o.involvedLandmarks?.map(e=>e.name),usedLlm:o.usedLlm}),this.recordAlertTime(e)},this.config.loiteringThreshold)}async captureAndCacheSnapshot(e,t){try{const n=h.getDeviceById(t);if(n?.interfaces?.includes(a.ScryptedInterface.Camera)){const i=await n.takePicture();i&&(this.snapshotCache.set(e,i),this.console.log(`[Snapshot] Cached snapshot for ${e.slice(0,8)} from ${t}`))}}catch(e){this.console.warn(`[Snapshot] Failed to capture snapshot: ${e}`)}}async correlateDetection(e){const t=this.state.getActiveObjects();if(0===t.length)return null;for(const n of t){const t=(0,l.getLastSighting)(n);if(t&&t.cameraId===e.cameraId&&t.detection.id===e.detection.id)return{trackedObject:n,newSighting:e,confidence:1,factors:{timing:1,visual:1,spatial:1,class:1}}}return await this.correlator.findBestMatch(e,t)}isLeavingFrame(e){if(!e.position)return!1;const t=.1;return e.position.x<t||e.position.x>.9||e.position.y<t||e.position.y>.9}handlePotentialExit(e,t){this.state.markPending(e.globalId),this.config.useLlmDescriptions&&this.captureAndCacheSnapshot(e.globalId,t.cameraId).catch(e=>{this.console.warn(`[Exit Snapshot] Failed to update snapshot: ${e}`)});const n=setTimeout(async()=>{const n=this.state.getObject(e.globalId);if(n&&"pending"===n.state){this.state.markExited(e.globalId,t.cameraId,t.cameraName);let i=this.snapshotCache.get(e.globalId);this.console.log(`[Exit Alert] Using cached snapshot: ${!!i}`),this.console.log(`[Exit Alert] Calling generateExitDescription with mediaObject=${!!i}`);const r=await this.spatialReasoning.generateExitDescription(n,t.cameraId,i);this.console.log(`[Exit Alert] Object ${e.globalId.slice(0,8)} exited: "${r.description.substring(0,60)}...", usedLlm=${r.usedLlm}`),await this.alertManager.checkAndAlert("property_exit",n,{cameraId:t.cameraId,cameraName:t.cameraName,objectClass:n.className,objectLabel:r.description,involvedLandmarks:r.involvedLandmarks?.map(e=>e.name),usedLlm:r.usedLlm}),this.snapshotCache.delete(e.globalId)}this.pendingTimers.delete(e.globalId)},this.config.correlationWindow);this.pendingTimers.set(e.globalId,n)}checkForLostObjects(){const e=Date.now(),t=this.state.getActiveObjects();for(const n of t){const t=e-n.lastSeen;t>this.config.lostTimeout&&(this.state.markLost(n.globalId),this.console.log(`Object ${n.globalId.slice(0,8)} marked as lost (not seen for ${Math.round(t/1e3)}s)`),this.snapshotCache.delete(n.globalId),this.alertManager.checkAndAlert("lost_tracking",n,{objectClass:n.className,objectLabel:n.label}))}}updateTopology(e){this.topology=e,this.correlator=new u.ObjectCorrelator(e,this.config),this.spatialReasoning.updateTopology(e)}getPendingLandmarkSuggestions(){return this.spatialReasoning.getPendingSuggestions()}acceptLandmarkSuggestion(e){const t=this.spatialReasoning.acceptSuggestion(e);return t&&this.topology&&(this.topology.landmarks||(this.topology.landmarks=[]),this.topology.landmarks.push(t),this.onTopologyChange&&this.onTopologyChange(this.topology)),t}rejectLandmarkSuggestion(e){return this.spatialReasoning.rejectSuggestion(e)}getLandmarkTemplates(){return this.spatialReasoning.getLandmarkTemplates()}getSpatialReasoningEngine(){return this.spatialReasoning}getTopology(){return this.topology}getTrackedObjects(){return this.state.getAllObjects()}getTrackedObject(e){return this.state.getObject(e)}recordObservedTransit(e,t,n){if(!this.config.enableTransitTimeLearning)return;const i=`${e}->${t}`,r={fromCameraId:e,toCameraId:t,transitTime:n,timestamp:Date.now()};this.observedTransits.has(i)||this.observedTransits.set(i,[]);const o=this.observedTransits.get(i);o.push(r),o.length>100&&o.shift();const s=(0,c.findConnection)(this.topology,e,t);s?this.maybeUpdateConnectionTransitTime(s,o):this.config.enableConnectionSuggestions&&this.maybeCreateConnectionSuggestion(e,t,o)}maybeUpdateConnectionTransitTime(e,t){if(t.length<5)return;const n=t.map(e=>e.transitTime).sort((e,t)=>e-t),i=n[Math.floor(.1*n.length)],r=n[Math.floor(.5*n.length)],o=n[Math.floor(.9*n.length)],s=e.transitTime.typical;Math.abs(r-s)/s>.2&&t.length>=10&&(this.console.log(`Updating transit time for ${e.name}: ${Math.round(s/1e3)}s → ${Math.round(r/1e3)}s (based on ${t.length} observations)`),e.transitTime={min:i,typical:r,max:o},this.onTopologyChange&&this.onTopologyChange(this.topology))}maybeCreateConnectionSuggestion(e,t,n){if(n.length<this.MIN_OBSERVATIONS_FOR_SUGGESTION)return;const i=(0,c.findCamera)(this.topology,e),r=(0,c.findCamera)(this.topology,t);if(!i||!r)return;const o=`${e}->${t}`,s=n.map(e=>e.transitTime).sort((e,t)=>e-t),a=s[Math.floor(.1*s.length)]||s[0],l=s[Math.floor(.5*s.length)]||s[0],d=s[Math.floor(.9*s.length)]||s[s.length-1],u=s.reduce((e,t)=>e+t,0)/s.length,p=s.reduce((e,t)=>e+Math.pow(t-u,2),0)/s.length,h=Math.sqrt(p)/u,f=.6*Math.min(n.length/10,1)+.4*Math.max(0,1-h),g={id:`suggest_${o}`,fromCameraId:e,fromCameraName:i.name,toCameraId:t,toCameraName:r.name,observedTransits:n.slice(-10),suggestedTransitTime:{min:a,typical:l,max:d},confidence:f,timestamp:Date.now()};this.connectionSuggestions.set(o,g),n.length===this.MIN_OBSERVATIONS_FOR_SUGGESTION&&this.console.log(`New connection suggested: ${i.name} → ${r.name} (typical: ${Math.round(l/1e3)}s, confidence: ${Math.round(100*f)}%)`)}getConnectionSuggestions(){return Array.from(this.connectionSuggestions.values()).filter(e=>e.confidence>=.5).sort((e,t)=>t.confidence-e.confidence)}acceptConnectionSuggestion(e){const t=e.replace("suggest_",""),n=this.connectionSuggestions.get(t);if(!n)return null;const i=(0,c.findCamera)(this.topology,n.fromCameraId),r=(0,c.findCamera)(this.topology,n.toCameraId);if(!i||!r)return null;const o={id:`conn-${Date.now()}`,fromCameraId:n.fromCameraId,toCameraId:n.toCameraId,name:`${i.name} to ${r.name}`,exitZone:[],entryZone:[],transitTime:n.suggestedTransitTime,bidirectional:!0};return this.topology.connections.push(o),this.connectionSuggestions.delete(t),this.onTopologyChange&&this.onTopologyChange(this.topology),this.console.log(`Connection accepted: ${o.name}`),o}rejectConnectionSuggestion(e){const t=e.replace("suggest_","");return!!this.connectionSuggestions.has(t)&&(this.connectionSuggestions.delete(t),this.observedTransits.delete(t),!0)}getLiveTrackingState(){return{objects:this.state.getActiveObjects().map(e=>{const t=(0,l.getLastSighting)(e),n=t?(0,c.findCamera)(this.topology,t.cameraId):null;return{globalId:e.globalId,className:e.className,label:e.label,lastCameraId:t?.cameraId||"",lastCameraName:t?.cameraName||"",lastSeen:e.lastSeen,state:e.state,cameraPosition:n?.floorPlanPosition}}),timestamp:Date.now()}}getJourneyPath(e){const t=this.state.getObject(e);if(!t)return null;const n=t.journey.map(e=>{const t=(0,c.findCamera)(this.topology,e.fromCameraId),n=(0,c.findCamera)(this.topology,e.toCameraId);return{fromCamera:{id:e.fromCameraId,name:e.fromCameraName,position:t?.floorPlanPosition},toCamera:{id:e.toCameraId,name:e.toCameraName,position:n?.floorPlanPosition},transitTime:e.transitDuration,timestamp:e.entryTime}}),i=(0,l.getLastSighting)(t);let r;if(i){const e=(0,c.findCamera)(this.topology,i.cameraId);r={cameraId:i.cameraId,cameraName:i.cameraName,position:e?.floorPlanPosition}}return{segments:n,currentLocation:r}}setTrainingStatusCallback(e){this.onTrainingStatusUpdate=e}getTrainingSession(){return this.trainingSession}isTrainingActive(){return null!==this.trainingSession&&"active"===this.trainingSession.state}startTrainingSession(e,t){return this.trainingSession&&"active"===this.trainingSession.state&&this.endTrainingSession(),t&&(this.trainingConfig={...d.DEFAULT_TRAINING_CONFIG,...t}),this.trainingSession=(0,d.createTrainingSession)(e),this.trainingSession.state="active",this.console.log(`Training session started: ${this.trainingSession.id}`),this.emitTrainingStatus(),this.trainingSession}pauseTrainingSession(){return!(!this.trainingSession||"active"!==this.trainingSession.state)&&(this.trainingSession.state="paused",this.trainingSession.updatedAt=Date.now(),this.console.log("Training session paused"),this.emitTrainingStatus(),!0)}resumeTrainingSession(){return!(!this.trainingSession||"paused"!==this.trainingSession.state)&&(this.trainingSession.state="active",this.trainingSession.updatedAt=Date.now(),this.console.log("Training session resumed"),this.emitTrainingStatus(),!0)}endTrainingSession(){if(!this.trainingSession)return null;this.trainingSession.state="completed",this.trainingSession.completedAt=Date.now(),this.trainingSession.updatedAt=Date.now(),this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.console.log(`Training session completed: ${this.trainingSession.stats.camerasVisited} cameras, ${this.trainingSession.stats.transitsRecorded} transits, ${this.trainingSession.stats.landmarksMarked} landmarks`);const e=this.trainingSession;return this.emitTrainingStatus(),e}recordTrainerDetection(e,t,n){if(!this.trainingSession||"active"!==this.trainingSession.state)return;if("person"!==t.className)return;if(n<this.trainingConfig.minDetectionConfidence)return;const i=(0,c.findCamera)(this.topology,e),r=i?.name||e,o=Date.now();if(this.trainingSession.currentCameraId===e){const i=this.trainingSession.visits.find(t=>t.cameraId===e&&null===t.departedAt);i&&(i.detectionConfidence=Math.max(i.detectionConfidence,n),t.boundingBox&&(i.boundingBox=t.boundingBox))}else{if(this.trainingSession.currentCameraId&&this.trainingSession.transitStartTime){const t=o-this.trainingSession.transitStartTime,n=this.trainingSession.previousCameraId||this.trainingSession.currentCameraId,i=(0,c.findCamera)(this.topology,n),s=this.trainingSession.visits.find(e=>e.cameraId===n&&null===e.departedAt);s&&(s.departedAt=this.trainingSession.transitStartTime);const a=this.checkTrainingOverlap(n,e,o),l={id:`transit-${o}`,fromCameraId:n,toCameraId:e,startTime:this.trainingSession.transitStartTime,endTime:o,transitSeconds:Math.round(t/1e3),hasOverlap:a};this.trainingSession.transits.push(l),this.console.log(`Training transit: ${i?.name||n} → ${r} (${l.transitSeconds}s${a?", overlap detected":""})`),a&&this.trainingConfig.autoDetectOverlaps&&this.recordTrainingOverlap(n,e)}const s={cameraId:e,cameraName:r,arrivedAt:o,departedAt:null,trainerEmbedding:t.embedding,detectionConfidence:n,boundingBox:t.boundingBox,floorPlanPosition:i?.floorPlanPosition};this.trainingSession.visits.push(s),this.trainingSession.previousCameraId=this.trainingSession.currentCameraId,this.trainingSession.currentCameraId=e,this.trainingSession.transitStartTime=o,!this.trainingSession.trainerEmbedding&&t.embedding&&(this.trainingSession.trainerEmbedding=t.embedding)}this.trainingSession.updatedAt=o,this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.emitTrainingStatus()}checkTrainingOverlap(e,t,n){const i=this.trainingSession?.visits.find(t=>t.cameraId===e&&(null===t.departedAt||t.departedAt>n-5e3)),r=this.trainingSession?.visits.find(e=>e.cameraId===t&&e.arrivedAt<=n&&e.arrivedAt>=n-5e3);return!(!i||!r)}recordTrainingOverlap(e,t){if(!this.trainingSession)return;if(this.trainingSession.overlaps.find(n=>n.camera1Id===e&&n.camera2Id===t||n.camera1Id===t&&n.camera2Id===e))return;const n=(0,c.findCamera)(this.topology,e),i=(0,c.findCamera)(this.topology,t);let r={x:50,y:50};n?.floorPlanPosition&&i?.floorPlanPosition&&(r={x:(n.floorPlanPosition.x+i.floorPlanPosition.x)/2,y:(n.floorPlanPosition.y+i.floorPlanPosition.y)/2});const o={id:`overlap-${Date.now()}`,camera1Id:e,camera2Id:t,position:r,radius:30,markedAt:Date.now()};this.trainingSession.overlaps.push(o),this.console.log(`Camera overlap detected: ${n?.name} ↔ ${i?.name}`)}markTrainingLandmark(e){if(!this.trainingSession)return null;const t={...e,id:`landmark-${Date.now()}`,markedAt:Date.now()};return this.trainingSession.landmarks.push(t),this.trainingSession.updatedAt=Date.now(),this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.console.log(`Landmark marked: ${t.name} (${t.type})`),this.emitTrainingStatus(),t}markTrainingStructure(e){if(!this.trainingSession)return null;const t={...e,id:`structure-${Date.now()}`,markedAt:Date.now()};return this.trainingSession.structures.push(t),this.trainingSession.updatedAt=Date.now(),this.trainingSession.stats=(0,d.calculateTrainingStats)(this.trainingSession,this.topology.cameras.length),this.console.log(`Structure marked: ${t.name} (${t.type})`),this.emitTrainingStatus(),t}confirmCameraPosition(e,t){if(!this.trainingSession)return!1;const n=this.trainingSession.visits.find(t=>t.cameraId===e);n&&(n.floorPlanPosition=t);const i=(0,c.findCamera)(this.topology,e);return i&&(i.floorPlanPosition=t,this.onTopologyChange&&this.onTopologyChange(this.topology)),this.trainingSession.updatedAt=Date.now(),this.emitTrainingStatus(),!0}getTrainingStatus(){if(!this.trainingSession)return null;const e=this.trainingSession.currentCameraId?(0,c.findCamera)(this.topology,this.trainingSession.currentCameraId):null,t=this.trainingSession.previousCameraId?(0,c.findCamera)(this.topology,this.trainingSession.previousCameraId):null,n=[],i=new Set(this.trainingSession.visits.map(e=>e.cameraId)),r=this.topology.cameras.filter(e=>!i.has(e.deviceId));if(r.length>0){const t=(e?(0,c.findConnectionsFrom)(this.topology,e.deviceId):[]).map(e=>e.toCameraId).filter(e=>!i.has(e));if(t.length>0){const e=(0,c.findCamera)(this.topology,t[0]);e&&n.push(`Walk to ${e.name}`)}else n.push(`${r.length} cameras not yet visited`)}this.trainingSession.visits.length>=2&&0===this.trainingSession.landmarks.length&&n.push("Consider marking some landmarks"),i.size>=this.topology.cameras.length&&n.push("All cameras visited! You can end training.");return{sessionId:this.trainingSession.id,state:this.trainingSession.state,currentCamera:e?{id:e.deviceId,name:e.name,detectedAt:this.trainingSession.visits.find(t=>t.cameraId===e.deviceId&&!t.departedAt)?.arrivedAt||Date.now(),confidence:this.trainingSession.visits.find(t=>t.cameraId===e.deviceId&&!t.departedAt)?.detectionConfidence||0}:void 0,activeTransit:this.trainingSession.transitStartTime&&t?{fromCameraId:t.deviceId,fromCameraName:t.name,startTime:this.trainingSession.transitStartTime,elapsedSeconds:Math.round((Date.now()-this.trainingSession.transitStartTime)/1e3)}:void 0,stats:this.trainingSession.stats,suggestions:n}}emitTrainingStatus(){if(this.onTrainingStatusUpdate){const e=this.getTrainingStatus();e&&this.onTrainingStatusUpdate(e)}}applyTrainingToTopology(){const e={camerasAdded:0,connectionsCreated:0,connectionsUpdated:0,landmarksAdded:0,zonesCreated:0,warnings:[],success:!1};if(!this.trainingSession)return e.warnings.push("No training session to apply"),e;try{for(const t of this.trainingSession.visits){const n=(0,c.findCamera)(this.topology,t.cameraId);n&&t.floorPlanPosition&&(n.floorPlanPosition||(n.floorPlanPosition=t.floorPlanPosition,e.camerasAdded++))}for(const t of this.trainingSession.transits){const n=(0,c.findConnection)(this.topology,t.fromCameraId,t.toCameraId);if(n){const i=1e3*t.transitSeconds;n.transitTime={min:Math.min(n.transitTime.min,.7*i),typical:i,max:Math.max(n.transitTime.max,1.3*i)},e.connectionsUpdated++}else{const n=(0,c.findCamera)(this.topology,t.fromCameraId),i=(0,c.findCamera)(this.topology,t.toCameraId);if(n&&i){const r=1e3*t.transitSeconds,o={id:`conn-training-${Date.now()}-${e.connectionsCreated}`,fromCameraId:t.fromCameraId,toCameraId:t.toCameraId,name:`${n.name} to ${i.name}`,exitZone:[],entryZone:[],transitTime:{min:.7*r,typical:r,max:1.3*r},bidirectional:!0};this.topology.connections.push(o),e.connectionsCreated++}}}for(const t of this.trainingSession.landmarks){const n={mailbox:"feature",garage:"structure",shed:"structure",tree:"feature",gate:"access",door:"access",driveway:"access",pathway:"access",garden:"feature",pool:"feature",deck:"structure",patio:"structure",other:"feature"},i={id:t.id,name:t.name,type:n[t.type]||"feature",position:t.position,visibleFromCameras:t.visibleFromCameras.length>0?t.visibleFromCameras:void 0,description:t.description};this.topology.landmarks||(this.topology.landmarks=[]),this.topology.landmarks.push(i),e.landmarksAdded++}for(const t of this.trainingSession.overlaps){const n=(0,c.findCamera)(this.topology,t.camera1Id),i=(0,c.findCamera)(this.topology,t.camera2Id);if(n&&i){const r=`${n.name}/${i.name} Overlap`,o=this.topology.globalZones?.find(e=>e.name===r);if(!o){this.topology.globalZones||(this.topology.globalZones=[]);const n=[{cameraId:t.camera1Id,zone:[]},{cameraId:t.camera2Id,zone:[]}];this.topology.globalZones.push({id:`zone-overlap-${t.id}`,name:r,type:"dwell",cameraZones:n}),e.zonesCreated++}}}this.onTopologyChange&&this.onTopologyChange(this.topology),e.success=!0,this.console.log(`Training applied: ${e.connectionsCreated} connections created, ${e.connectionsUpdated} updated, ${e.landmarksAdded} landmarks added`)}catch(t){e.warnings.push(`Error applying training: ${t}`)}return e}clearTrainingSession(){this.trainingSession=null,this.emitTrainingStatus()}}},7279(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MqttPublisher=void 0;const r=i(n(9372));t.MqttPublisher=class{client=null;config;console;connected=!1;reconnectTimer=null;constructor(e,t){this.config=e,this.console=t}async connect(){if(this.client)return;const e={clientId:`scrypted-spatial-awareness-${Date.now()}`,clean:!0,connectTimeout:1e4,reconnectPeriod:5e3};this.config.username&&(e.username=this.config.username,e.password=this.config.password);try{this.client=r.default.connect(this.config.broker,e),this.client.on("connect",()=>{this.connected=!0,this.console.log(`MQTT connected to ${this.config.broker}`),this.publishDiscovery()}),this.client.on("error",e=>{this.console.error("MQTT error:",e)}),this.client.on("close",()=>{this.connected=!1,this.console.log("MQTT connection closed")}),this.client.on("offline",()=>{this.connected=!1,this.console.log("MQTT offline")})}catch(e){this.console.error("Failed to connect to MQTT:",e)}}disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.client&&(this.client.end(),this.client=null,this.connected=!1)}publishDiscovery(){if(!this.client||!this.connected)return;const e=this.config.baseTopic,t={name:"Property Occupancy",unique_id:"spatial_awareness_occupancy",state_topic:`${e}/occupancy/state`,device_class:"occupancy",payload_on:"ON",payload_off:"OFF",device:{identifiers:["spatial_awareness"],name:"Spatial Awareness",model:"Cross-Camera Tracker",manufacturer:"Scrypted"}};this.client.publish("homeassistant/binary_sensor/spatial_awareness_occupancy/config",JSON.stringify(t),{retain:!0});const n={name:"Active Tracked Objects",unique_id:"spatial_awareness_count",state_topic:`${e}/count/state`,icon:"mdi:account-multiple",device:{identifiers:["spatial_awareness"]}};this.client.publish("homeassistant/sensor/spatial_awareness_count/config",JSON.stringify(n),{retain:!0});const i={name:"People on Property",unique_id:"spatial_awareness_person_count",state_topic:`${e}/person_count/state`,icon:"mdi:account-group",device:{identifiers:["spatial_awareness"]}};this.client.publish("homeassistant/sensor/spatial_awareness_person_count/config",JSON.stringify(i),{retain:!0});const r={name:"Vehicles on Property",unique_id:"spatial_awareness_vehicle_count",state_topic:`${e}/vehicle_count/state`,icon:"mdi:car",device:{identifiers:["spatial_awareness"]}};this.client.publish("homeassistant/sensor/spatial_awareness_vehicle_count/config",JSON.stringify(r),{retain:!0}),this.console.log("MQTT discovery published")}publishState(e){if(!this.client||!this.connected)return;const t=this.config.baseTopic,n=e.filter(e=>"active"===e.state||"pending"===e.state),i=n.length>0;this.client.publish(`${t}/occupancy/state`,i?"ON":"OFF",{retain:!0}),this.client.publish(`${t}/count/state`,String(n.length),{retain:!0});const r=n.filter(e=>"person"===e.className).length;this.client.publish(`${t}/person_count/state`,String(r),{retain:!0});const o=n.filter(e=>["car","vehicle","truck"].includes(e.className)).length;this.client.publish(`${t}/vehicle_count/state`,String(o),{retain:!0});const s={timestamp:Date.now(),occupied:i,activeCount:n.length,personCount:r,vehicleCount:o,objects:n.map(e=>({id:e.globalId,class:e.className,label:e.label,cameras:e.activeOnCameras,firstSeen:e.firstSeen,lastSeen:e.lastSeen,state:e.state}))};this.client.publish(`${t}/state`,JSON.stringify(s),{retain:!0})}publishAlert(e){if(!this.client||!this.connected)return;const t=this.config.baseTopic,n={id:e.id,type:e.type,severity:e.severity,message:e.message,timestamp:e.timestamp,objectId:e.trackedObjectId,details:e.details};this.client.publish(`${t}/alerts`,JSON.stringify(n)),this.client.publish(`${t}/alerts/${e.type}`,JSON.stringify(n))}publishEntry(e,t){if(!this.client||!this.connected)return;const n=this.config.baseTopic,i={event:"entry",timestamp:Date.now(),object:{id:e.globalId,class:e.className,label:e.label},camera:t};this.client.publish(`${n}/events/entry`,JSON.stringify(i))}publishExit(e,t){if(!this.client||!this.connected)return;const n=this.config.baseTopic,i={event:"exit",timestamp:Date.now(),object:{id:e.globalId,class:e.className,label:e.label,dwellTime:e.lastSeen-e.firstSeen},camera:t};this.client.publish(`${n}/events/exit`,JSON.stringify(i))}publishTransition(e,t,n){if(!this.client||!this.connected)return;const i=this.config.baseTopic,r={event:"transition",timestamp:Date.now(),object:{id:e.globalId,class:e.className,label:e.label},from:t,to:n};this.client.publish(`${i}/events/transition`,JSON.stringify(r))}isConnected(){return this.connected}}},7382(e,t,n){"use strict";const{ObjectSetPrototypeOf:i,Symbol:r}=n(4134);e.exports=l;const{ERR_METHOD_NOT_IMPLEMENTED:o}=n(6371).codes,s=n(3370),{getHighWaterMark:a}=n(5291);i(l.prototype,s.prototype),i(l,s);const c=r("kCallback");function l(e){if(!(this instanceof l))return new l(e);const t=e?a(this,e,"readableHighWaterMark",!0):null;0===t&&(e={...e,highWaterMark:null,readableHighWaterMark:t,writableHighWaterMark:e.writableHighWaterMark||0}),s.call(this,e),this._readableState.sync=!1,this[c]=null,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",u)}function d(e){"function"!=typeof this._flush||this.destroyed?(this.push(null),e&&e()):this._flush((t,n)=>{t?e?e(t):this.destroy(t):(null!=n&&this.push(n),this.push(null),e&&e())})}function u(){this._final!==d&&d.call(this)}l.prototype._final=d,l.prototype._transform=function(e,t,n){throw new o("_transform()")},l.prototype._write=function(e,t,n){const i=this._readableState,r=this._writableState,o=i.length;this._transform(e,t,(e,t)=>{e?n(e):(null!=t&&this.push(t),r.ended||o===i.length||i.length<i.highWaterMark?n():this[c]=n)})},l.prototype._read=function(){if(this[c]){const e=this[c];this[c]=null,e()}}},7562(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||i(t,e,n)},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.sdk=t.MixinDeviceBase=t.ScryptedDeviceBase=void 0,r(n(4192),t);const s=o(n(9896)),a=n(4192);n(3339);class c extends a.DeviceBase{constructor(e){super(),this.nativeId=e}get storage(){return this._storage||(this._storage=t.sdk.deviceManager.getDeviceStorage(this.nativeId)),this._storage}get log(){return this._log||(this._log=t.sdk.deviceManager.getDeviceLogger(this.nativeId)),this._log}get console(){return this._console||(this._console=t.sdk.deviceManager.getDeviceConsole(this.nativeId)),this._console}async createMediaObject(e,n){return t.sdk.mediaManager.createMediaObject(e,n,{sourceId:this.id})}getMediaObjectConsole(e){return"string"!=typeof e.sourceId?this.console:t.sdk.deviceManager.getMixinConsole(e.sourceId,this.nativeId)}_lazyLoadDeviceState(){this._deviceState||(this.nativeId?this._deviceState=t.sdk.deviceManager.getDeviceState(this.nativeId):this._deviceState=t.sdk.deviceManager.getDeviceState())}onDeviceEvent(e,n){return t.sdk.deviceManager.onDeviceEvent(this.nativeId,e,n)}}t.ScryptedDeviceBase=c;class l extends a.DeviceBase{constructor(e){super(),this._listeners=new Set,this.mixinDevice=e.mixinDevice,this.mixinDeviceInterfaces=e.mixinDeviceInterfaces,this.mixinStorageSuffix=e.mixinStorageSuffix,this._deviceState=e.mixinDeviceState,this.nativeId=t.sdk.systemManager.getDeviceById(this.id).nativeId,this.mixinProviderNativeId=e.mixinProviderNativeId,this._deviceState.__rpcproxy_traps_all_properties&&"string"==typeof this._deviceState.id&&(this._deviceState=t.sdk.deviceManager.createDeviceState(this._deviceState.id,this._deviceState.setState))}get storage(){if(!this._storage){const e=this.mixinStorageSuffix,n=this.id+(e?":"+e:"");this._storage=t.sdk.deviceManager.getMixinStorage(n,this.mixinProviderNativeId)}return this._storage}get console(){return this._console||(t.sdk.deviceManager.getMixinConsole?this._console=t.sdk.deviceManager.getMixinConsole(this.id,this.mixinProviderNativeId):this._console=t.sdk.deviceManager.getDeviceConsole(this.mixinProviderNativeId)),this._console}async createMediaObject(e,n){return t.sdk.mediaManager.createMediaObject(e,n,{sourceId:this.id})}getMediaObjectConsole(e){return"string"!=typeof e.sourceId?this.console:t.sdk.deviceManager.getMixinConsole(e.sourceId,this.mixinProviderNativeId)}onDeviceEvent(e,n){return t.sdk.deviceManager.onMixinEvent(this.id,this,e,n)}_lazyLoadDeviceState(){}manageListener(e){this._listeners.add(e)}release(){for(const e of this._listeners)e.removeListener()}}t.MixinDeviceBase=l,function(){function e(e){return function(){return this._lazyLoadDeviceState(),this._deviceState?.[e]}}function t(e){return function(t){this._lazyLoadDeviceState(),this._deviceState?this._deviceState[e]=t:console.warn("device state is unavailable. the device must be discovered with deviceManager.onDeviceDiscovered or deviceManager.onDevicesChanged before the state can be set.")}}for(const n of Object.values(a.ScryptedInterfaceProperty))n!==a.ScryptedInterfaceProperty.nativeId&&(Object.defineProperty(c.prototype,n,{set:t(n),get:e(n)}),Object.defineProperty(l.prototype,n,{set:t(n),get:e(n)}))}(),t.sdk={};try{let e=!1;try{process.env.SCRYPTED_SDK_ES_MODULE||process.env.SCRYPTED_SDK_MODULE;const i=process.env.SCRYPTED_SDK_CJS_MODULE||process.env.SCRYPTED_SDK_MODULE;if(i)if("undefined"!=typeof require){const n=require(process.env.SCRYPTED_SDK_MODULE);Object.assign(t.sdk,n.getScryptedStatic()),e=!0}else{const r=n(3891)(i);Object.assign(t.sdk,r.getScryptedStatic()),e=!0}}catch(e){throw console.warn("failed to load sdk module",e),e}if(!e){let e;try{e=pluginRuntimeAPI}catch(e){}Object.assign(t.sdk,{log:deviceManager.getDeviceLogger(void 0),deviceManager,endpointManager,mediaManager,systemManager,pluginHostAPI,...e})}try{let e={...a.ScryptedInterfaceDescriptors};try{const t=JSON.parse(s.default.readFileSync("../sdk.json").toString()).interfaceDescriptors;t&&(e={...e,...t})}catch(e){console.warn("failed to load custom interface descriptors",e)}t.sdk.systemManager.setScryptedInterfaceDescriptors?.(a.TYPES_VERSION,e)?.catch(()=>{})}catch(e){}}catch(e){console.error("sdk initialization error, import @scrypted/types or use @scrypted/client instead",e)}t.default=t.sdk},7575(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(1725);class r{constructor(e){if(this.length=0,this._encoding="utf8",this._writeOffset=0,this._readOffset=0,r.isSmartBufferOptions(e))if(e.encoding&&(i.checkEncoding(e.encoding),this._encoding=e.encoding),e.size){if(!(i.isFiniteInteger(e.size)&&e.size>0))throw new Error(i.ERRORS.INVALID_SMARTBUFFER_SIZE);this._buff=Buffer.allocUnsafe(e.size)}else if(e.buff){if(!Buffer.isBuffer(e.buff))throw new Error(i.ERRORS.INVALID_SMARTBUFFER_BUFFER);this._buff=e.buff,this.length=e.buff.length}else this._buff=Buffer.allocUnsafe(4096);else{if("undefined"!=typeof e)throw new Error(i.ERRORS.INVALID_SMARTBUFFER_OBJECT);this._buff=Buffer.allocUnsafe(4096)}}static fromSize(e,t){return new this({size:e,encoding:t})}static fromBuffer(e,t){return new this({buff:e,encoding:t})}static fromOptions(e){return new this(e)}static isSmartBufferOptions(e){const t=e;return t&&(void 0!==t.encoding||void 0!==t.size||void 0!==t.buff)}readInt8(e){return this._readNumberValue(Buffer.prototype.readInt8,1,e)}readInt16BE(e){return this._readNumberValue(Buffer.prototype.readInt16BE,2,e)}readInt16LE(e){return this._readNumberValue(Buffer.prototype.readInt16LE,2,e)}readInt32BE(e){return this._readNumberValue(Buffer.prototype.readInt32BE,4,e)}readInt32LE(e){return this._readNumberValue(Buffer.prototype.readInt32LE,4,e)}readBigInt64BE(e){return i.bigIntAndBufferInt64Check("readBigInt64BE"),this._readNumberValue(Buffer.prototype.readBigInt64BE,8,e)}readBigInt64LE(e){return i.bigIntAndBufferInt64Check("readBigInt64LE"),this._readNumberValue(Buffer.prototype.readBigInt64LE,8,e)}writeInt8(e,t){return this._writeNumberValue(Buffer.prototype.writeInt8,1,e,t),this}insertInt8(e,t){return this._insertNumberValue(Buffer.prototype.writeInt8,1,e,t)}writeInt16BE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt16BE,2,e,t)}insertInt16BE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt16BE,2,e,t)}writeInt16LE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt16LE,2,e,t)}insertInt16LE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt16LE,2,e,t)}writeInt32BE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt32BE,4,e,t)}insertInt32BE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt32BE,4,e,t)}writeInt32LE(e,t){return this._writeNumberValue(Buffer.prototype.writeInt32LE,4,e,t)}insertInt32LE(e,t){return this._insertNumberValue(Buffer.prototype.writeInt32LE,4,e,t)}writeBigInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64BE"),this._writeNumberValue(Buffer.prototype.writeBigInt64BE,8,e,t)}insertBigInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64BE"),this._insertNumberValue(Buffer.prototype.writeBigInt64BE,8,e,t)}writeBigInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64LE"),this._writeNumberValue(Buffer.prototype.writeBigInt64LE,8,e,t)}insertBigInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigInt64LE"),this._insertNumberValue(Buffer.prototype.writeBigInt64LE,8,e,t)}readUInt8(e){return this._readNumberValue(Buffer.prototype.readUInt8,1,e)}readUInt16BE(e){return this._readNumberValue(Buffer.prototype.readUInt16BE,2,e)}readUInt16LE(e){return this._readNumberValue(Buffer.prototype.readUInt16LE,2,e)}readUInt32BE(e){return this._readNumberValue(Buffer.prototype.readUInt32BE,4,e)}readUInt32LE(e){return this._readNumberValue(Buffer.prototype.readUInt32LE,4,e)}readBigUInt64BE(e){return i.bigIntAndBufferInt64Check("readBigUInt64BE"),this._readNumberValue(Buffer.prototype.readBigUInt64BE,8,e)}readBigUInt64LE(e){return i.bigIntAndBufferInt64Check("readBigUInt64LE"),this._readNumberValue(Buffer.prototype.readBigUInt64LE,8,e)}writeUInt8(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt8,1,e,t)}insertUInt8(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt8,1,e,t)}writeUInt16BE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt16BE,2,e,t)}insertUInt16BE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt16BE,2,e,t)}writeUInt16LE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt16LE,2,e,t)}insertUInt16LE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt16LE,2,e,t)}writeUInt32BE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt32BE,4,e,t)}insertUInt32BE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt32BE,4,e,t)}writeUInt32LE(e,t){return this._writeNumberValue(Buffer.prototype.writeUInt32LE,4,e,t)}insertUInt32LE(e,t){return this._insertNumberValue(Buffer.prototype.writeUInt32LE,4,e,t)}writeBigUInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64BE"),this._writeNumberValue(Buffer.prototype.writeBigUInt64BE,8,e,t)}insertBigUInt64BE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64BE"),this._insertNumberValue(Buffer.prototype.writeBigUInt64BE,8,e,t)}writeBigUInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64LE"),this._writeNumberValue(Buffer.prototype.writeBigUInt64LE,8,e,t)}insertBigUInt64LE(e,t){return i.bigIntAndBufferInt64Check("writeBigUInt64LE"),this._insertNumberValue(Buffer.prototype.writeBigUInt64LE,8,e,t)}readFloatBE(e){return this._readNumberValue(Buffer.prototype.readFloatBE,4,e)}readFloatLE(e){return this._readNumberValue(Buffer.prototype.readFloatLE,4,e)}writeFloatBE(e,t){return this._writeNumberValue(Buffer.prototype.writeFloatBE,4,e,t)}insertFloatBE(e,t){return this._insertNumberValue(Buffer.prototype.writeFloatBE,4,e,t)}writeFloatLE(e,t){return this._writeNumberValue(Buffer.prototype.writeFloatLE,4,e,t)}insertFloatLE(e,t){return this._insertNumberValue(Buffer.prototype.writeFloatLE,4,e,t)}readDoubleBE(e){return this._readNumberValue(Buffer.prototype.readDoubleBE,8,e)}readDoubleLE(e){return this._readNumberValue(Buffer.prototype.readDoubleLE,8,e)}writeDoubleBE(e,t){return this._writeNumberValue(Buffer.prototype.writeDoubleBE,8,e,t)}insertDoubleBE(e,t){return this._insertNumberValue(Buffer.prototype.writeDoubleBE,8,e,t)}writeDoubleLE(e,t){return this._writeNumberValue(Buffer.prototype.writeDoubleLE,8,e,t)}insertDoubleLE(e,t){return this._insertNumberValue(Buffer.prototype.writeDoubleLE,8,e,t)}readString(e,t){let n;"number"==typeof e?(i.checkLengthValue(e),n=Math.min(e,this.length-this._readOffset)):(t=e,n=this.length-this._readOffset),"undefined"!=typeof t&&i.checkEncoding(t);const r=this._buff.slice(this._readOffset,this._readOffset+n).toString(t||this._encoding);return this._readOffset+=n,r}insertString(e,t,n){return i.checkOffsetValue(t),this._handleString(e,!0,t,n)}writeString(e,t,n){return this._handleString(e,!1,t,n)}readStringNT(e){"undefined"!=typeof e&&i.checkEncoding(e);let t=this.length;for(let e=this._readOffset;e<this.length;e++)if(0===this._buff[e]){t=e;break}const n=this._buff.slice(this._readOffset,t);return this._readOffset=t+1,n.toString(e||this._encoding)}insertStringNT(e,t,n){return i.checkOffsetValue(t),this.insertString(e,t,n),this.insertUInt8(0,t+e.length),this}writeStringNT(e,t,n){return this.writeString(e,t,n),this.writeUInt8(0,"number"==typeof t?t+e.length:this.writeOffset),this}readBuffer(e){"undefined"!=typeof e&&i.checkLengthValue(e);const t="number"==typeof e?e:this.length,n=Math.min(this.length,this._readOffset+t),r=this._buff.slice(this._readOffset,n);return this._readOffset=n,r}insertBuffer(e,t){return i.checkOffsetValue(t),this._handleBuffer(e,!0,t)}writeBuffer(e,t){return this._handleBuffer(e,!1,t)}readBufferNT(){let e=this.length;for(let t=this._readOffset;t<this.length;t++)if(0===this._buff[t]){e=t;break}const t=this._buff.slice(this._readOffset,e);return this._readOffset=e+1,t}insertBufferNT(e,t){return i.checkOffsetValue(t),this.insertBuffer(e,t),this.insertUInt8(0,t+e.length),this}writeBufferNT(e,t){return"undefined"!=typeof t&&i.checkOffsetValue(t),this.writeBuffer(e,t),this.writeUInt8(0,"number"==typeof t?t+e.length:this._writeOffset),this}clear(){return this._writeOffset=0,this._readOffset=0,this.length=0,this}remaining(){return this.length-this._readOffset}get readOffset(){return this._readOffset}set readOffset(e){i.checkOffsetValue(e),i.checkTargetOffset(e,this),this._readOffset=e}get writeOffset(){return this._writeOffset}set writeOffset(e){i.checkOffsetValue(e),i.checkTargetOffset(e,this),this._writeOffset=e}get encoding(){return this._encoding}set encoding(e){i.checkEncoding(e),this._encoding=e}get internalBuffer(){return this._buff}toBuffer(){return this._buff.slice(0,this.length)}toString(e){const t="string"==typeof e?e:this._encoding;return i.checkEncoding(t),this._buff.toString(t,0,this.length)}destroy(){return this.clear(),this}_handleString(e,t,n,r){let o=this._writeOffset,s=this._encoding;"number"==typeof n?o=n:"string"==typeof n&&(i.checkEncoding(n),s=n),"string"==typeof r&&(i.checkEncoding(r),s=r);const a=Buffer.byteLength(e,s);return t?this.ensureInsertable(a,o):this._ensureWriteable(a,o),this._buff.write(e,o,a,s),t?this._writeOffset+=a:"number"==typeof n?this._writeOffset=Math.max(this._writeOffset,o+a):this._writeOffset+=a,this}_handleBuffer(e,t,n){const i="number"==typeof n?n:this._writeOffset;return t?this.ensureInsertable(e.length,i):this._ensureWriteable(e.length,i),e.copy(this._buff,i),t?this._writeOffset+=e.length:"number"==typeof n?this._writeOffset=Math.max(this._writeOffset,i+e.length):this._writeOffset+=e.length,this}ensureReadable(e,t){let n=this._readOffset;if("undefined"!=typeof t&&(i.checkOffsetValue(t),n=t),n<0||n+e>this.length)throw new Error(i.ERRORS.INVALID_READ_BEYOND_BOUNDS)}ensureInsertable(e,t){i.checkOffsetValue(t),this._ensureCapacity(this.length+e),t<this.length&&this._buff.copy(this._buff,t+e,t,this._buff.length),t+e>this.length?this.length=t+e:this.length+=e}_ensureWriteable(e,t){const n="number"==typeof t?t:this._writeOffset;this._ensureCapacity(n+e),n+e>this.length&&(this.length=n+e)}_ensureCapacity(e){const t=this._buff.length;if(e>t){let n=this._buff,i=3*t/2+1;i<e&&(i=e),this._buff=Buffer.allocUnsafe(i),n.copy(this._buff,0,0,t)}}_readNumberValue(e,t,n){this.ensureReadable(t,n);const i=e.call(this._buff,"number"==typeof n?n:this._readOffset);return"undefined"==typeof n&&(this._readOffset+=t),i}_insertNumberValue(e,t,n,r){return i.checkOffsetValue(r),this.ensureInsertable(t,r),e.call(this._buff,n,r),this._writeOffset+=t,this}_writeNumberValue(e,t,n,r){if("number"==typeof r){if(r<0)throw new Error(i.ERRORS.INVALID_WRITE_BEYOND_BOUNDS);i.checkOffsetValue(r)}const o="number"==typeof r?r:this._writeOffset;return this._ensureWriteable(t,o),e.call(this._buff,n,o),"number"==typeof r?this._writeOffset=Math.max(this._writeOffset,o+t):this._writeOffset+=t,this}}t.SmartBuffer=r},7576(e,t,n){"use strict";const i=n(4422),{ArrayPrototypeIndexOf:r,NumberIsInteger:o,NumberIsNaN:s,NumberParseInt:a,ObjectDefineProperties:c,ObjectKeys:l,ObjectSetPrototypeOf:d,Promise:u,SafeSet:p,SymbolAsyncDispose:h,SymbolAsyncIterator:f,Symbol:g}=n(4134);e.exports=W,W.ReadableState=V;const{EventEmitter:m}=n(4434),{Stream:y,prependListener:b}=n(4259),{Buffer:v}=n(181),{addAbortSignal:S}=n(4147),_=n(6238);let w=n(7760).debuglog("stream",e=>{w=e});const k=n(345),I=n(5896),{getHighWaterMark:x,getDefaultHighWaterMark:C}=n(5291),{aggregateTwoErrors:E,codes:{ERR_INVALID_ARG_TYPE:T,ERR_METHOD_NOT_IMPLEMENTED:O,ERR_OUT_OF_RANGE:P,ERR_STREAM_PUSH_AFTER_EOF:A,ERR_STREAM_UNSHIFT_AFTER_END_EVENT:R},AbortError:M}=n(6371),{validateObject:L}=n(277),N=g("kPaused"),{StringDecoder:D}=n(3141),B=n(6532);d(W.prototype,y.prototype),d(W,y);const j=()=>{},{errorOrDestroy:$}=I,F=2048,U=4096;function z(e){return{enumerable:!1,get(){return 0!==(this.state&e)},set(t){t?this.state|=e:this.state&=~e}}}function V(e,t,i){"boolean"!=typeof i&&(i=t instanceof n(3370)),this.state=6192,e&&e.objectMode&&(this.state|=1),i&&e&&e.readableObjectMode&&(this.state|=1),this.highWaterMark=e?x(this,e,"readableHighWaterMark",i):C(!1),this.buffer=new k,this.length=0,this.pipes=[],this.flowing=null,this[N]=null,e&&!1===e.emitClose&&(this.state&=-2049),e&&!1===e.autoDestroy&&(this.state&=-4097),this.errored=null,this.defaultEncoding=e&&e.defaultEncoding||"utf8",this.awaitDrainWriters=null,this.decoder=null,this.encoding=null,e&&e.encoding&&(this.decoder=new D(e.encoding),this.encoding=e.encoding)}function W(e){if(!(this instanceof W))return new W(e);const t=this instanceof n(3370);this._readableState=new V(e,this,t),e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.construct&&(this._construct=e.construct),e.signal&&!t&&S(e.signal,this)),y.call(this,e),I.construct(this,()=>{this._readableState.needReadable&&J(this,this._readableState)})}function H(e,t,n,i){w("readableAddChunk",t);const r=e._readableState;let o;if(1&r.state||("string"==typeof t?(n=n||r.defaultEncoding,r.encoding!==n&&(i&&r.encoding?t=v.from(t,n).toString(r.encoding):(t=v.from(t,n),n=""))):t instanceof v?n="":y._isUint8Array(t)?(t=y._uint8ArrayToBuffer(t),n=""):null!=t&&(o=new T("chunk",["string","Buffer","Uint8Array"],t))),o)$(e,o);else if(null===t)r.state&=-9,function(e,t){if(w("onEofChunk"),t.ended)return;if(t.decoder){const e=t.decoder.end();e&&e.length&&(t.buffer.push(e),t.length+=t.objectMode?1:e.length)}t.ended=!0,t.sync?K(e):(t.needReadable=!1,t.emittedReadable=!0,Z(e))}(e,r);else if(1&r.state||t&&t.length>0)if(i)if(4&r.state)$(e,new R);else{if(r.destroyed||r.errored)return!1;q(e,r,t,!0)}else if(r.ended)$(e,new A);else{if(r.destroyed||r.errored)return!1;r.state&=-9,r.decoder&&!n?(t=r.decoder.write(t),r.objectMode||0!==t.length?q(e,r,t,!1):J(e,r)):q(e,r,t,!1)}else i||(r.state&=-9,J(e,r));return!r.ended&&(r.length<r.highWaterMark||0===r.length)}function q(e,t,n,i){t.flowing&&0===t.length&&!t.sync&&e.listenerCount("data")>0?(65536&t.state?t.awaitDrainWriters.clear():t.awaitDrainWriters=null,t.dataEmitted=!0,e.emit("data",n)):(t.length+=t.objectMode?1:n.length,i?t.buffer.unshift(n):t.buffer.push(n),64&t.state&&K(e)),J(e,t)}c(V.prototype,{objectMode:z(1),ended:z(2),endEmitted:z(4),reading:z(8),constructed:z(16),sync:z(32),needReadable:z(64),emittedReadable:z(128),readableListening:z(256),resumeScheduled:z(512),errorEmitted:z(1024),emitClose:z(F),autoDestroy:z(U),destroyed:z(8192),closed:z(16384),closeEmitted:z(32768),multiAwaitDrain:z(65536),readingMore:z(1<<17),dataEmitted:z(1<<18)}),W.prototype.destroy=I.destroy,W.prototype._undestroy=I.undestroy,W.prototype._destroy=function(e,t){t(e)},W.prototype[m.captureRejectionSymbol]=function(e){this.destroy(e)},W.prototype[h]=function(){let e;return this.destroyed||(e=this.readableEnded?null:new M,this.destroy(e)),new u((t,n)=>_(this,i=>i&&i!==e?n(i):t(null)))},W.prototype.push=function(e,t){return H(this,e,t,!1)},W.prototype.unshift=function(e,t){return H(this,e,t,!0)},W.prototype.isPaused=function(){const e=this._readableState;return!0===e[N]||!1===e.flowing},W.prototype.setEncoding=function(e){const t=new D(e);this._readableState.decoder=t,this._readableState.encoding=this._readableState.decoder.encoding;const n=this._readableState.buffer;let i="";for(const e of n)i+=t.write(e);return n.clear(),""!==i&&n.push(i),this._readableState.length=i.length,this};function G(e,t){return e<=0||0===t.length&&t.ended?0:1&t.state?1:s(e)?t.flowing&&t.length?t.buffer.first().length:t.length:e<=t.length?e:t.ended?t.length:0}function K(e){const t=e._readableState;w("emitReadable",t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(w("emitReadable",t.flowing),t.emittedReadable=!0,i.nextTick(Z,e))}function Z(e){const t=e._readableState;w("emitReadable_",t.destroyed,t.length,t.ended),t.destroyed||t.errored||!t.length&&!t.ended||(e.emit("readable"),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,te(e)}function J(e,t){!t.readingMore&&t.constructed&&(t.readingMore=!0,i.nextTick(Q,e,t))}function Q(e,t){for(;!t.reading&&!t.ended&&(t.length<t.highWaterMark||t.flowing&&0===t.length);){const n=t.length;if(w("maybeReadMore read 0"),e.read(0),n===t.length)break}t.readingMore=!1}function Y(e){const t=e._readableState;t.readableListening=e.listenerCount("readable")>0,t.resumeScheduled&&!1===t[N]?t.flowing=!0:e.listenerCount("data")>0?e.resume():t.readableListening||(t.flowing=null)}function X(e){w("readable nexttick read 0"),e.read(0)}function ee(e,t){w("resume",t.reading),t.reading||e.read(0),t.resumeScheduled=!1,e.emit("resume"),te(e),t.flowing&&!t.reading&&e.read(0)}function te(e){const t=e._readableState;for(w("flow",t.flowing);t.flowing&&null!==e.read(););}function ne(e,t){"function"!=typeof e.read&&(e=W.wrap(e,{objectMode:!0}));const n=async function*(e,t){let n,i=j;function r(t){this===e?(i(),i=j):i=t}e.on("readable",r);const o=_(e,{writable:!1},e=>{n=e?E(n,e):null,i(),i=j});try{for(;;){const t=e.destroyed?null:e.read();if(null!==t)yield t;else{if(n)throw n;if(null===n)return;await new u(r)}}}catch(e){throw n=E(n,e),n}finally{!n&&!1===(null==t?void 0:t.destroyOnReturn)||void 0!==n&&!e._readableState.autoDestroy?(e.off("readable",r),o()):I.destroyer(e,null)}}(e,t);return n.stream=e,n}function ie(e,t){if(0===t.length)return null;let n;return t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.first():t.buffer.concat(t.length),t.buffer.clear()):n=t.buffer.consume(e,t.decoder),n}function re(e){const t=e._readableState;w("endReadable",t.endEmitted),t.endEmitted||(t.ended=!0,i.nextTick(oe,t,e))}function oe(e,t){if(w("endReadableNT",e.endEmitted,e.length),!e.errored&&!e.closeEmitted&&!e.endEmitted&&0===e.length)if(e.endEmitted=!0,t.emit("end"),t.writable&&!1===t.allowHalfOpen)i.nextTick(se,t);else if(e.autoDestroy){const e=t._writableState;(!e||e.autoDestroy&&(e.finished||!1===e.writable))&&t.destroy()}}function se(e){e.writable&&!e.writableEnded&&!e.destroyed&&e.end()}let ae;function ce(){return void 0===ae&&(ae={}),ae}W.prototype.read=function(e){w("read",e),void 0===e?e=NaN:o(e)||(e=a(e,10));const t=this._readableState,n=e;if(e>t.highWaterMark&&(t.highWaterMark=function(e){if(e>1073741824)throw new P("size","<= 1GiB",e);return e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,++e}(e)),0!==e&&(t.state&=-129),0===e&&t.needReadable&&((0!==t.highWaterMark?t.length>=t.highWaterMark:t.length>0)||t.ended))return w("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?re(this):K(this),null;if(0===(e=G(e,t))&&t.ended)return 0===t.length&&re(this),null;let i,r=!!(64&t.state);if(w("need readable",r),(0===t.length||t.length-e<t.highWaterMark)&&(r=!0,w("length less than watermark",r)),t.ended||t.reading||t.destroyed||t.errored||!t.constructed)r=!1,w("reading, ended or constructing",r);else if(r){w("do read"),t.state|=40,0===t.length&&(t.state|=64);try{this._read(t.highWaterMark)}catch(e){$(this,e)}t.state&=-33,t.reading||(e=G(n,t))}return i=e>0?ie(e,t):null,null===i?(t.needReadable=t.length<=t.highWaterMark,e=0):(t.length-=e,t.multiAwaitDrain?t.awaitDrainWriters.clear():t.awaitDrainWriters=null),0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&re(this)),null===i||t.errorEmitted||t.closeEmitted||(t.dataEmitted=!0,this.emit("data",i)),i},W.prototype._read=function(e){throw new O("_read()")},W.prototype.pipe=function(e,t){const n=this,r=this._readableState;1===r.pipes.length&&(r.multiAwaitDrain||(r.multiAwaitDrain=!0,r.awaitDrainWriters=new p(r.awaitDrainWriters?[r.awaitDrainWriters]:[]))),r.pipes.push(e),w("pipe count=%d opts=%j",r.pipes.length,t);const o=(!t||!1!==t.end)&&e!==i.stdout&&e!==i.stderr?a:m;function s(t,i){w("onunpipe"),t===n&&i&&!1===i.hasUnpiped&&(i.hasUnpiped=!0,function(){w("cleanup"),e.removeListener("close",f),e.removeListener("finish",g),c&&e.removeListener("drain",c);e.removeListener("error",h),e.removeListener("unpipe",s),n.removeListener("end",a),n.removeListener("end",m),n.removeListener("data",u),l=!0,c&&r.awaitDrainWriters&&(!e._writableState||e._writableState.needDrain)&&c()}())}function a(){w("onend"),e.end()}let c;r.endEmitted?i.nextTick(o):n.once("end",o),e.on("unpipe",s);let l=!1;function d(){l||(1===r.pipes.length&&r.pipes[0]===e?(w("false write response, pause",0),r.awaitDrainWriters=e,r.multiAwaitDrain=!1):r.pipes.length>1&&r.pipes.includes(e)&&(w("false write response, pause",r.awaitDrainWriters.size),r.awaitDrainWriters.add(e)),n.pause()),c||(c=function(e,t){return function(){const n=e._readableState;n.awaitDrainWriters===t?(w("pipeOnDrain",1),n.awaitDrainWriters=null):n.multiAwaitDrain&&(w("pipeOnDrain",n.awaitDrainWriters.size),n.awaitDrainWriters.delete(t)),n.awaitDrainWriters&&0!==n.awaitDrainWriters.size||!e.listenerCount("data")||e.resume()}}(n,e),e.on("drain",c))}function u(t){w("ondata");const n=e.write(t);w("dest.write",n),!1===n&&d()}function h(t){if(w("onerror",t),m(),e.removeListener("error",h),0===e.listenerCount("error")){const n=e._writableState||e._readableState;n&&!n.errorEmitted?$(e,t):e.emit("error",t)}}function f(){e.removeListener("finish",g),m()}function g(){w("onfinish"),e.removeListener("close",f),m()}function m(){w("unpipe"),n.unpipe(e)}return n.on("data",u),b(e,"error",h),e.once("close",f),e.once("finish",g),e.emit("pipe",n),!0===e.writableNeedDrain?d():r.flowing||(w("pipe resume"),n.resume()),e},W.prototype.unpipe=function(e){const t=this._readableState;if(0===t.pipes.length)return this;if(!e){const e=t.pipes;t.pipes=[],this.pause();for(let t=0;t<e.length;t++)e[t].emit("unpipe",this,{hasUnpiped:!1});return this}const n=r(t.pipes,e);return-1===n||(t.pipes.splice(n,1),0===t.pipes.length&&this.pause(),e.emit("unpipe",this,{hasUnpiped:!1})),this},W.prototype.on=function(e,t){const n=y.prototype.on.call(this,e,t),r=this._readableState;return"data"===e?(r.readableListening=this.listenerCount("readable")>0,!1!==r.flowing&&this.resume()):"readable"===e&&(r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.flowing=!1,r.emittedReadable=!1,w("on readable",r.length,r.reading),r.length?K(this):r.reading||i.nextTick(X,this))),n},W.prototype.addListener=W.prototype.on,W.prototype.removeListener=function(e,t){const n=y.prototype.removeListener.call(this,e,t);return"readable"===e&&i.nextTick(Y,this),n},W.prototype.off=W.prototype.removeListener,W.prototype.removeAllListeners=function(e){const t=y.prototype.removeAllListeners.apply(this,arguments);return"readable"!==e&&void 0!==e||i.nextTick(Y,this),t},W.prototype.resume=function(){const e=this._readableState;return e.flowing||(w("resume"),e.flowing=!e.readableListening,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,i.nextTick(ee,e,t))}(this,e)),e[N]=!1,this},W.prototype.pause=function(){return w("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(w("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState[N]=!0,this},W.prototype.wrap=function(e){let t=!1;e.on("data",n=>{!this.push(n)&&e.pause&&(t=!0,e.pause())}),e.on("end",()=>{this.push(null)}),e.on("error",e=>{$(this,e)}),e.on("close",()=>{this.destroy()}),e.on("destroy",()=>{this.destroy()}),this._read=()=>{t&&e.resume&&(t=!1,e.resume())};const n=l(e);for(let t=1;t<n.length;t++){const i=n[t];void 0===this[i]&&"function"==typeof e[i]&&(this[i]=e[i].bind(e))}return this},W.prototype[f]=function(){return ne(this)},W.prototype.iterator=function(e){return void 0!==e&&L(e,"options"),ne(this,e)},c(W.prototype,{readable:{__proto__:null,get(){const e=this._readableState;return!(!e||!1===e.readable||e.destroyed||e.errorEmitted||e.endEmitted)},set(e){this._readableState&&(this._readableState.readable=!!e)}},readableDidRead:{__proto__:null,enumerable:!1,get:function(){return this._readableState.dataEmitted}},readableAborted:{__proto__:null,enumerable:!1,get:function(){return!(!1===this._readableState.readable||!this._readableState.destroyed&&!this._readableState.errored||this._readableState.endEmitted)}},readableHighWaterMark:{__proto__:null,enumerable:!1,get:function(){return this._readableState.highWaterMark}},readableBuffer:{__proto__:null,enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}},readableFlowing:{__proto__:null,enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}},readableLength:{__proto__:null,enumerable:!1,get(){return this._readableState.length}},readableObjectMode:{__proto__:null,enumerable:!1,get(){return!!this._readableState&&this._readableState.objectMode}},readableEncoding:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.encoding:null}},errored:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.errored:null}},closed:{__proto__:null,get(){return!!this._readableState&&this._readableState.closed}},destroyed:{__proto__:null,enumerable:!1,get(){return!!this._readableState&&this._readableState.destroyed},set(e){this._readableState&&(this._readableState.destroyed=e)}},readableEnded:{__proto__:null,enumerable:!1,get(){return!!this._readableState&&this._readableState.endEmitted}}}),c(V.prototype,{pipesCount:{__proto__:null,get(){return this.pipes.length}},paused:{__proto__:null,get(){return!1!==this[N]},set(e){this[N]=!!e}}}),W._fromList=ie,W.from=function(e,t){return B(W,e,t)},W.fromWeb=function(e,t){return ce().newStreamReadableFromReadableStream(e,t)},W.toWeb=function(e,t){return ce().newReadableStreamFromStreamReadable(e,t)},W.wrap=function(e,t){var n,i;return new W({objectMode:null===(n=null!==(i=e.readableObjectMode)&&void 0!==i?i:e.objectMode)||void 0===n||n,...t,destroy(t,n){I.destroyer(e,t),n(t)}}).wrap(e)}},7631(e,t,n){"use strict";var i=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{c(i.next(e))}catch(e){o(e)}}function a(e){try{c(i.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}c((i=i.apply(e,t||[])).next())})};Object.defineProperty(t,"__esModule",{value:!0}),t.SocksClientError=t.SocksClient=void 0;const r=n(4434),o=n(9278),s=n(7575),a=n(5438),c=n(7130),l=n(7736),d=n(3763);Object.defineProperty(t,"SocksClientError",{enumerable:!0,get:function(){return d.SocksClientError}});const u=n(9424);class p extends r.EventEmitter{constructor(e){super(),this.options=Object.assign({},e),(0,c.validateSocksClientOptions)(e),this.setState(a.SocksClientState.Created)}static createConnection(e,t){return new Promise((n,i)=>{try{(0,c.validateSocksClientOptions)(e,["connect"])}catch(e){return"function"==typeof t?(t(e),n(e)):i(e)}const r=new p(e);r.connect(e.existing_socket),r.once("established",e=>{r.removeAllListeners(),"function"==typeof t?(t(null,e),n(e)):n(e)}),r.once("error",e=>{r.removeAllListeners(),"function"==typeof t?(t(e),n(e)):i(e)})})}static createConnectionChain(e,t){return new Promise((n,r)=>i(this,void 0,void 0,function*(){try{(0,c.validateSocksClientChainOptions)(e)}catch(e){return"function"==typeof t?(t(e),n(e)):r(e)}e.randomizeChain&&(0,d.shuffleArray)(e.proxies);try{let i;for(let t=0;t<e.proxies.length;t++){const n=e.proxies[t],r=t===e.proxies.length-1?e.destination:{host:e.proxies[t+1].host||e.proxies[t+1].ipaddress,port:e.proxies[t+1].port},o=yield p.createConnection({command:"connect",proxy:n,destination:r,existing_socket:i});i=i||o.socket}"function"==typeof t?(t(null,{socket:i}),n({socket:i})):n({socket:i})}catch(e){"function"==typeof t?(t(e),n(e)):r(e)}}))}static createUDPFrame(e){const t=new s.SmartBuffer;return t.writeUInt16BE(0),t.writeUInt8(e.frameNumber||0),o.isIPv4(e.remoteHost.host)?(t.writeUInt8(a.Socks5HostType.IPv4),t.writeUInt32BE((0,c.ipv4ToInt32)(e.remoteHost.host))):o.isIPv6(e.remoteHost.host)?(t.writeUInt8(a.Socks5HostType.IPv6),t.writeBuffer((0,c.ipToBuffer)(e.remoteHost.host))):(t.writeUInt8(a.Socks5HostType.Hostname),t.writeUInt8(Buffer.byteLength(e.remoteHost.host)),t.writeString(e.remoteHost.host)),t.writeUInt16BE(e.remoteHost.port),t.writeBuffer(e.data),t.toBuffer()}static parseUDPFrame(e){const t=s.SmartBuffer.fromBuffer(e);t.readOffset=2;const n=t.readUInt8(),i=t.readUInt8();let r;r=i===a.Socks5HostType.IPv4?(0,c.int32ToIpv4)(t.readUInt32BE()):i===a.Socks5HostType.IPv6?u.Address6.fromByteArray(Array.from(t.readBuffer(16))).canonicalForm():t.readString(t.readUInt8());return{frameNumber:n,remoteHost:{host:r,port:t.readUInt16BE()},data:t.readBuffer()}}setState(e){this.state!==a.SocksClientState.Error&&(this.state=e)}connect(e){this.onDataReceived=e=>this.onDataReceivedHandler(e),this.onClose=()=>this.onCloseHandler(),this.onError=e=>this.onErrorHandler(e),this.onConnect=()=>this.onConnectHandler();const t=setTimeout(()=>this.onEstablishedTimeout(),this.options.timeout||a.DEFAULT_TIMEOUT);t.unref&&"function"==typeof t.unref&&t.unref(),this.socket=e||new o.Socket,this.socket.once("close",this.onClose),this.socket.once("error",this.onError),this.socket.once("connect",this.onConnect),this.socket.on("data",this.onDataReceived),this.setState(a.SocksClientState.Connecting),this.receiveBuffer=new l.ReceiveBuffer,e?this.socket.emit("connect"):(this.socket.connect(this.getSocketOptions()),void 0!==this.options.set_tcp_nodelay&&null!==this.options.set_tcp_nodelay&&this.socket.setNoDelay(!!this.options.set_tcp_nodelay)),this.prependOnceListener("established",e=>{setImmediate(()=>{if(this.receiveBuffer.length>0){const t=this.receiveBuffer.get(this.receiveBuffer.length);e.socket.emit("data",t)}e.socket.resume()})})}getSocketOptions(){return Object.assign(Object.assign({},this.options.socket_options),{host:this.options.proxy.host||this.options.proxy.ipaddress,port:this.options.proxy.port})}onEstablishedTimeout(){this.state!==a.SocksClientState.Established&&this.state!==a.SocksClientState.BoundWaitingForConnection&&this.closeSocket(a.ERRORS.ProxyConnectionTimedOut)}onConnectHandler(){this.setState(a.SocksClientState.Connected),4===this.options.proxy.type?this.sendSocks4InitialHandshake():this.sendSocks5InitialHandshake(),this.setState(a.SocksClientState.SentInitialHandshake)}onDataReceivedHandler(e){this.receiveBuffer.append(e),this.processData()}processData(){for(;this.state!==a.SocksClientState.Established&&this.state!==a.SocksClientState.Error&&this.receiveBuffer.length>=this.nextRequiredPacketBufferSize;)if(this.state===a.SocksClientState.SentInitialHandshake)4===this.options.proxy.type?this.handleSocks4FinalHandshakeResponse():this.handleInitialSocks5HandshakeResponse();else if(this.state===a.SocksClientState.SentAuthentication)this.handleInitialSocks5AuthenticationHandshakeResponse();else if(this.state===a.SocksClientState.SentFinalHandshake)this.handleSocks5FinalHandshakeResponse();else{if(this.state!==a.SocksClientState.BoundWaitingForConnection){this.closeSocket(a.ERRORS.InternalError);break}4===this.options.proxy.type?this.handleSocks4IncomingConnectionResponse():this.handleSocks5IncomingConnectionResponse()}}onCloseHandler(){this.closeSocket(a.ERRORS.SocketClosed)}onErrorHandler(e){this.closeSocket(e.message)}removeInternalSocketHandlers(){this.socket.pause(),this.socket.removeListener("data",this.onDataReceived),this.socket.removeListener("close",this.onClose),this.socket.removeListener("error",this.onError),this.socket.removeListener("connect",this.onConnect)}closeSocket(e){this.state!==a.SocksClientState.Error&&(this.setState(a.SocksClientState.Error),this.socket.destroy(),this.removeInternalSocketHandlers(),this.emit("error",new d.SocksClientError(e,this.options)))}sendSocks4InitialHandshake(){const e=this.options.proxy.userId||"",t=new s.SmartBuffer;t.writeUInt8(4),t.writeUInt8(a.SocksCommand[this.options.command]),t.writeUInt16BE(this.options.destination.port),o.isIPv4(this.options.destination.host)?(t.writeBuffer((0,c.ipToBuffer)(this.options.destination.host)),t.writeStringNT(e)):(t.writeUInt8(0),t.writeUInt8(0),t.writeUInt8(0),t.writeUInt8(1),t.writeStringNT(e),t.writeStringNT(this.options.destination.host)),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks4Response,this.socket.write(t.toBuffer())}handleSocks4FinalHandshakeResponse(){const e=this.receiveBuffer.get(8);if(e[1]!==a.Socks4Response.Granted)this.closeSocket(`${a.ERRORS.Socks4ProxyRejectedConnection} - (${a.Socks4Response[e[1]]})`);else if(a.SocksCommand[this.options.command]===a.SocksCommand.bind){const t=s.SmartBuffer.fromBuffer(e);t.readOffset=2;const n={port:t.readUInt16BE(),host:(0,c.int32ToIpv4)(t.readUInt32BE())};"0.0.0.0"===n.host&&(n.host=this.options.proxy.ipaddress),this.setState(a.SocksClientState.BoundWaitingForConnection),this.emit("bound",{remoteHost:n,socket:this.socket})}else this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{socket:this.socket})}handleSocks4IncomingConnectionResponse(){const e=this.receiveBuffer.get(8);if(e[1]!==a.Socks4Response.Granted)this.closeSocket(`${a.ERRORS.Socks4ProxyRejectedIncomingBoundConnection} - (${a.Socks4Response[e[1]]})`);else{const t=s.SmartBuffer.fromBuffer(e);t.readOffset=2;const n={port:t.readUInt16BE(),host:(0,c.int32ToIpv4)(t.readUInt32BE())};this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket})}}sendSocks5InitialHandshake(){const e=new s.SmartBuffer,t=[a.Socks5Auth.NoAuth];(this.options.proxy.userId||this.options.proxy.password)&&t.push(a.Socks5Auth.UserPass),void 0!==this.options.proxy.custom_auth_method&&t.push(this.options.proxy.custom_auth_method),e.writeUInt8(5),e.writeUInt8(t.length);for(const n of t)e.writeUInt8(n);this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5InitialHandshakeResponse,this.socket.write(e.toBuffer()),this.setState(a.SocksClientState.SentInitialHandshake)}handleInitialSocks5HandshakeResponse(){const e=this.receiveBuffer.get(2);5!==e[0]?this.closeSocket(a.ERRORS.InvalidSocks5IntiailHandshakeSocksVersion):e[1]===a.SOCKS5_NO_ACCEPTABLE_AUTH?this.closeSocket(a.ERRORS.InvalidSocks5InitialHandshakeNoAcceptedAuthType):e[1]===a.Socks5Auth.NoAuth?(this.socks5ChosenAuthType=a.Socks5Auth.NoAuth,this.sendSocks5CommandRequest()):e[1]===a.Socks5Auth.UserPass?(this.socks5ChosenAuthType=a.Socks5Auth.UserPass,this.sendSocks5UserPassAuthentication()):e[1]===this.options.proxy.custom_auth_method?(this.socks5ChosenAuthType=this.options.proxy.custom_auth_method,this.sendSocks5CustomAuthentication()):this.closeSocket(a.ERRORS.InvalidSocks5InitialHandshakeUnknownAuthType)}sendSocks5UserPassAuthentication(){const e=this.options.proxy.userId||"",t=this.options.proxy.password||"",n=new s.SmartBuffer;n.writeUInt8(1),n.writeUInt8(Buffer.byteLength(e)),n.writeString(e),n.writeUInt8(Buffer.byteLength(t)),n.writeString(t),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5UserPassAuthenticationResponse,this.socket.write(n.toBuffer()),this.setState(a.SocksClientState.SentAuthentication)}sendSocks5CustomAuthentication(){return i(this,void 0,void 0,function*(){this.nextRequiredPacketBufferSize=this.options.proxy.custom_auth_response_size,this.socket.write(yield this.options.proxy.custom_auth_request_handler()),this.setState(a.SocksClientState.SentAuthentication)})}handleSocks5CustomAuthHandshakeResponse(e){return i(this,void 0,void 0,function*(){return yield this.options.proxy.custom_auth_response_handler(e)})}handleSocks5AuthenticationNoAuthHandshakeResponse(e){return i(this,void 0,void 0,function*(){return 0===e[1]})}handleSocks5AuthenticationUserPassHandshakeResponse(e){return i(this,void 0,void 0,function*(){return 0===e[1]})}handleInitialSocks5AuthenticationHandshakeResponse(){return i(this,void 0,void 0,function*(){this.setState(a.SocksClientState.ReceivedAuthenticationResponse);let e=!1;this.socks5ChosenAuthType===a.Socks5Auth.NoAuth?e=yield this.handleSocks5AuthenticationNoAuthHandshakeResponse(this.receiveBuffer.get(2)):this.socks5ChosenAuthType===a.Socks5Auth.UserPass?e=yield this.handleSocks5AuthenticationUserPassHandshakeResponse(this.receiveBuffer.get(2)):this.socks5ChosenAuthType===this.options.proxy.custom_auth_method&&(e=yield this.handleSocks5CustomAuthHandshakeResponse(this.receiveBuffer.get(this.options.proxy.custom_auth_response_size))),e?this.sendSocks5CommandRequest():this.closeSocket(a.ERRORS.Socks5AuthenticationFailed)})}sendSocks5CommandRequest(){const e=new s.SmartBuffer;e.writeUInt8(5),e.writeUInt8(a.SocksCommand[this.options.command]),e.writeUInt8(0),o.isIPv4(this.options.destination.host)?(e.writeUInt8(a.Socks5HostType.IPv4),e.writeBuffer((0,c.ipToBuffer)(this.options.destination.host))):o.isIPv6(this.options.destination.host)?(e.writeUInt8(a.Socks5HostType.IPv6),e.writeBuffer((0,c.ipToBuffer)(this.options.destination.host))):(e.writeUInt8(a.Socks5HostType.Hostname),e.writeUInt8(this.options.destination.host.length),e.writeString(this.options.destination.host)),e.writeUInt16BE(this.options.destination.port),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHeader,this.socket.write(e.toBuffer()),this.setState(a.SocksClientState.SentFinalHandshake)}handleSocks5FinalHandshakeResponse(){const e=this.receiveBuffer.peek(5);if(5!==e[0]||e[1]!==a.Socks5Response.Granted)this.closeSocket(`${a.ERRORS.InvalidSocks5FinalHandshakeRejected} - ${a.Socks5Response[e[1]]}`);else{const t=e[3];let n,i;if(t===a.Socks5HostType.IPv4){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv4;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:(0,c.int32ToIpv4)(i.readUInt32BE()),port:i.readUInt16BE()},"0.0.0.0"===n.host&&(n.host=this.options.proxy.ipaddress)}else if(t===a.Socks5HostType.Hostname){const t=e[4],r=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHostname(t);if(this.receiveBuffer.length<r)return void(this.nextRequiredPacketBufferSize=r);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(r).slice(5)),n={host:i.readString(t),port:i.readUInt16BE()}}else if(t===a.Socks5HostType.IPv6){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv6;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:u.Address6.fromByteArray(Array.from(i.readBuffer(16))).canonicalForm(),port:i.readUInt16BE()}}this.setState(a.SocksClientState.ReceivedFinalResponse),a.SocksCommand[this.options.command]===a.SocksCommand.connect?(this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket})):a.SocksCommand[this.options.command]===a.SocksCommand.bind?(this.setState(a.SocksClientState.BoundWaitingForConnection),this.nextRequiredPacketBufferSize=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHeader,this.emit("bound",{remoteHost:n,socket:this.socket})):a.SocksCommand[this.options.command]===a.SocksCommand.associate&&(this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket}))}}handleSocks5IncomingConnectionResponse(){const e=this.receiveBuffer.peek(5);if(5!==e[0]||e[1]!==a.Socks5Response.Granted)this.closeSocket(`${a.ERRORS.Socks5ProxyRejectedIncomingBoundConnection} - ${a.Socks5Response[e[1]]}`);else{const t=e[3];let n,i;if(t===a.Socks5HostType.IPv4){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv4;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:(0,c.int32ToIpv4)(i.readUInt32BE()),port:i.readUInt16BE()},"0.0.0.0"===n.host&&(n.host=this.options.proxy.ipaddress)}else if(t===a.Socks5HostType.Hostname){const t=e[4],r=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseHostname(t);if(this.receiveBuffer.length<r)return void(this.nextRequiredPacketBufferSize=r);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(r).slice(5)),n={host:i.readString(t),port:i.readUInt16BE()}}else if(t===a.Socks5HostType.IPv6){const e=a.SOCKS_INCOMING_PACKET_SIZES.Socks5ResponseIPv6;if(this.receiveBuffer.length<e)return void(this.nextRequiredPacketBufferSize=e);i=s.SmartBuffer.fromBuffer(this.receiveBuffer.get(e).slice(4)),n={host:u.Address6.fromByteArray(Array.from(i.readBuffer(16))).canonicalForm(),port:i.readUInt16BE()}}this.setState(a.SocksClientState.Established),this.removeInternalSocketHandlers(),this.emit("established",{remoteHost:n,socket:this.socket})}}get socksClientOptions(){return Object.assign({},this.options)}}t.SocksClient=p},7687(e,t,n){"use strict";const i=n(857),r=n(2018),o=n(5884),{env:s}=process;let a;function c(e){return 0!==e&&{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function l(e,t){if(0===a)return 0;if(o("color=16m")||o("color=full")||o("color=truecolor"))return 3;if(o("color=256"))return 2;if(e&&!t&&void 0===a)return 0;const n=a||0;if("dumb"===s.TERM)return n;if("win32"===process.platform){const e=i.release().split(".");return Number(e[0])>=10&&Number(e[2])>=10586?Number(e[2])>=14931?3:2:1}if("CI"in s)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(e=>e in s)||"codeship"===s.CI_NAME?1:n;if("TEAMCITY_VERSION"in s)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(s.TEAMCITY_VERSION)?1:0;if("truecolor"===s.COLORTERM)return 3;if("TERM_PROGRAM"in s){const e=parseInt((s.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(s.TERM_PROGRAM){case"iTerm.app":return e>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(s.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(s.TERM)||"COLORTERM"in s?1:n}o("no-color")||o("no-colors")||o("color=false")||o("color=never")?a=0:(o("color")||o("colors")||o("color=true")||o("color=always"))&&(a=1),"FORCE_COLOR"in s&&(a="true"===s.FORCE_COLOR?1:"false"===s.FORCE_COLOR?0:0===s.FORCE_COLOR.length?1:Math.min(parseInt(s.FORCE_COLOR,10),3)),e.exports={supportsColor:function(e){return c(l(e,e&&e.isTTY))},stdout:c(l(!0,r.isatty(1))),stderr:c(l(!0,r.isatty(2)))}},7699(e,t,n){"use strict";const i=n(1060);i.createWebSocketStream=n(3719),i.Server=n(1722),i.Receiver=n(6286),i.Sender=n(914),i.WebSocket=i,i.WebSocketServer=i.Server,e.exports=i},7732(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0});const a=n(8600),c=s(n(6887)),l={set:a.setInterval,clear:a.clearInterval},d={set:(e,t)=>setInterval(e,t),clear:e=>clearInterval(e)};t.default=e=>{switch(e){case"native":return d;case"worker":return l;default:return!c.default||c.isWebWorker||c.isReactNativeBrowser?d:l}}},7736(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ReceiveBuffer=void 0;t.ReceiveBuffer=class{constructor(e=4096){this.buffer=Buffer.allocUnsafe(e),this.offset=0,this.originalSize=e}get length(){return this.offset}append(e){if(!Buffer.isBuffer(e))throw new Error("Attempted to append a non-buffer instance to ReceiveBuffer.");if(this.offset+e.length>=this.buffer.length){const t=this.buffer;this.buffer=Buffer.allocUnsafe(Math.max(this.buffer.length+this.originalSize,this.buffer.length+e.length)),t.copy(this.buffer)}return e.copy(this.buffer,this.offset),this.offset+=e.length}peek(e){if(e>this.offset)throw new Error("Attempted to read beyond the bounds of the managed internal data.");return this.buffer.slice(0,e)}get(e){if(e>this.offset)throw new Error("Attempted to read beyond the bounds of the managed internal data.");const t=Buffer.allocUnsafe(e);return this.buffer.slice(0,e).copy(t),this.buffer.copyWithin(0,e,e+this.offset-e),this.offset-=e,t}}},7758(e,t,n){const i=n(4422),{ArrayIsArray:r,Promise:o,SymbolAsyncIterator:s,SymbolDispose:a}=n(4134),c=n(6238),{once:l}=n(7760),d=n(5896),u=n(3370),{aggregateTwoErrors:p,codes:{ERR_INVALID_ARG_TYPE:h,ERR_INVALID_RETURN_VALUE:f,ERR_MISSING_ARGS:g,ERR_STREAM_DESTROYED:m,ERR_STREAM_PREMATURE_CLOSE:y},AbortError:b}=n(6371),{validateFunction:v,validateAbortSignal:S}=n(277),{isIterable:_,isReadable:w,isReadableNodeStream:k,isNodeStream:I,isTransformStream:x,isWebStream:C,isReadableStream:E,isReadableFinished:T}=n(6115),O=globalThis.AbortController||n(6584).AbortController;let P,A,R;function M(e,t,n){let i=!1;e.on("close",()=>{i=!0});return{destroy:t=>{i||(i=!0,d.destroyer(e,t||new m("pipe")))},cleanup:c(e,{readable:t,writable:n},e=>{i=!e})}}function L(e){if(_(e))return e;if(k(e))return async function*(e){A||(A=n(7576));yield*A.prototype[s].call(e)}(e);throw new h("val",["Readable","Iterable","AsyncIterable"],e)}async function N(e,t,n,{end:i}){let r,s=null;const a=e=>{if(e&&(r=e),s){const e=s;s=null,e()}},l=()=>new o((e,t)=>{r?t(r):s=()=>{r?t(r):e()}});t.on("drain",a);const d=c(t,{readable:!1},a);try{t.writableNeedDrain&&await l();for await(const n of e)t.write(n)||await l();i&&(t.end(),await l()),n()}catch(e){n(r!==e?p(r,e):e)}finally{d(),t.off("drain",a)}}async function D(e,t,n,{end:i}){x(t)&&(t=t.writable);const r=t.getWriter();try{for await(const t of e)await r.ready,r.write(t).catch(()=>{});await r.ready,i&&await r.close(),n()}catch(e){try{await r.abort(e),n(e)}catch(e){n(e)}}}function B(e,t,o){if(1===e.length&&r(e[0])&&(e=e[0]),e.length<2)throw new g("streams");const s=new O,c=s.signal,l=null==o?void 0:o.signal,d=[];function p(){F(new b)}let m,y,v;S(l,"options.signal"),R=R||n(7760).addAbortListener,l&&(m=R(l,p));const T=[];let A,B=0;function $(e){F(e,0===--B)}function F(e,n){var r;if(!e||y&&"ERR_STREAM_PREMATURE_CLOSE"!==y.code||(y=e),y||n){for(;T.length;)T.shift()(y);null===(r=m)||void 0===r||r[a](),s.abort(),n&&(y||d.forEach(e=>e()),i.nextTick(t,y,v))}}for(let W=0;W<e.length;W++){const H=e[W],q=W<e.length-1,G=W>0,K=q||!1!==(null==o?void 0:o.end),Z=W===e.length-1;if(I(H)){if(K){const{destroy:J,cleanup:Q}=M(H,q,G);T.push(J),w(H)&&Z&&d.push(Q)}function U(e){e&&"AbortError"!==e.name&&"ERR_STREAM_PREMATURE_CLOSE"!==e.code&&$(e)}H.on("error",U),w(H)&&Z&&d.push(()=>{H.removeListener("error",U)})}if(0===W)if("function"==typeof H){if(A=H({signal:c}),!_(A))throw new f("Iterable, AsyncIterable or Stream","source",A)}else A=_(H)||k(H)||x(H)?H:u.from(H);else if("function"==typeof H){var z;if(x(A))A=L(null===(z=A)||void 0===z?void 0:z.readable);else A=L(A);if(A=H(A,{signal:c}),q){if(!_(A,!0))throw new f("AsyncIterable",`transform[${W-1}]`,A)}else{var V;P||(P=n(6524));const Y=new P({objectMode:!0}),X=null===(V=A)||void 0===V?void 0:V.then;if("function"==typeof X)B++,X.call(A,e=>{v=e,null!=e&&Y.write(e),K&&Y.end(),i.nextTick($)},e=>{Y.destroy(e),i.nextTick($,e)});else if(_(A,!0))B++,N(A,Y,$,{end:K});else{if(!E(A)&&!x(A))throw new f("AsyncIterable or Promise","destination",A);{const ne=A.readable||A;B++,N(ne,Y,$,{end:K})}}A=Y;const{destroy:ee,cleanup:te}=M(A,!1,!0);T.push(ee),Z&&d.push(te)}}else if(I(H)){if(k(A)){B+=2;const ie=j(A,H,$,{end:K});w(H)&&Z&&d.push(ie)}else if(x(A)||E(A)){const re=A.readable||A;B++,N(re,H,$,{end:K})}else{if(!_(A))throw new h("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],A);B++,N(A,H,$,{end:K})}A=H}else if(C(H)){if(k(A))B++,D(L(A),H,$,{end:K});else if(E(A)||_(A))B++,D(A,H,$,{end:K});else{if(!x(A))throw new h("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],A);B++,D(A.readable,H,$,{end:K})}A=H}else A=u.from(H)}return(null!=c&&c.aborted||null!=l&&l.aborted)&&i.nextTick(p),A}function j(e,t,n,{end:r}){let o=!1;if(t.on("close",()=>{o||n(new y)}),e.pipe(t,{end:!1}),r){function s(){o=!0,t.end()}T(e)?i.nextTick(s):e.once("end",s)}else n();return c(e,{readable:!0,writable:!1},t=>{const i=e._readableState;t&&"ERR_STREAM_PREMATURE_CLOSE"===t.code&&i&&i.ended&&!i.errored&&!i.errorEmitted?e.once("end",n).once("error",n):n(t)}),c(t,{readable:!1,writable:!0},n)}e.exports={pipelineImpl:B,pipeline:function(...e){return B(e,l(function(e){return v(e[e.length-1],"streams[stream.length - 1]"),e.pop()}(e)))}}},7760(e,t,n){"use strict";const i=n(181),{format:r,inspect:o}=n(9231),{codes:{ERR_INVALID_ARG_TYPE:s}}=n(6371),{kResistStopPropagation:a,AggregateError:c,SymbolDispose:l}=n(4134),d=globalThis.AbortSignal||n(6584).AbortSignal,u=globalThis.AbortController||n(6584).AbortController,p=Object.getPrototypeOf(async function(){}).constructor,h=globalThis.Blob||i.Blob,f="undefined"!=typeof h?function(e){return e instanceof h}:function(e){return!1},g=(e,t)=>{if(void 0!==e&&(null===e||"object"!=typeof e||!("aborted"in e)))throw new s(t,"AbortSignal",e)};e.exports={AggregateError:c,kEmptyObject:Object.freeze({}),once(e){let t=!1;return function(...n){t||(t=!0,e.apply(this,n))}},createDeferredPromise:function(){let e,t;return{promise:new Promise((n,i)=>{e=n,t=i}),resolve:e,reject:t}},promisify:e=>new Promise((t,n)=>{e((e,...i)=>e?n(e):t(...i))}),debuglog:()=>function(){},format:r,inspect:o,types:{isAsyncFunction:e=>e instanceof p,isArrayBufferView:e=>ArrayBuffer.isView(e)},isBlob:f,deprecate:(e,t)=>e,addAbortListener:n(4434).addAbortListener||function(e,t){if(void 0===e)throw new s("signal","AbortSignal",e);let n;return g(e,"signal"),((e,t)=>{if("function"!=typeof e)throw new s(t,"Function",e)})(t,"listener"),e.aborted?queueMicrotask(()=>t()):(e.addEventListener("abort",t,{__proto__:null,once:!0,[a]:!0}),n=()=>{e.removeEventListener("abort",t)}),{__proto__:null,[l](){var e;null===(e=n)||void 0===e||e()}}},AbortSignalAny:d.any||function(e){if(1===e.length)return e[0];const t=new u,n=()=>t.abort();return e.forEach(e=>{g(e,"signals"),e.addEventListener("abort",n,{once:!0})}),t.signal.addEventListener("abort",()=>{e.forEach(e=>e.removeEventListener("abort",n))},{once:!0}),t.signal}},e.exports.promisify.custom=Symbol.for("nodejs.util.promisify.custom")},7813(e,t,n){"use strict";const{Buffer:i}=n(181),r=Symbol.for("BufferList");function o(e){if(!(this instanceof o))return new o(e);o._init.call(this,e)}o._init=function(e){Object.defineProperty(this,r,{value:!0}),this._bufs=[],this.length=0,e&&this.append(e)},o.prototype._new=function(e){return new o(e)},o.prototype._offset=function(e){if(0===e)return[0,0];let t=0;for(let n=0;n<this._bufs.length;n++){const i=t+this._bufs[n].length;if(e<i||n===this._bufs.length-1)return[n,e-t];t=i}},o.prototype._reverseOffset=function(e){const t=e[0];let n=e[1];for(let e=0;e<t;e++)n+=this._bufs[e].length;return n},o.prototype.getBuffers=function(){return this._bufs},o.prototype.get=function(e){if(e>this.length||e<0)return;const t=this._offset(e);return this._bufs[t[0]][t[1]]},o.prototype.slice=function(e,t){return"number"==typeof e&&e<0&&(e+=this.length),"number"==typeof t&&t<0&&(t+=this.length),this.copy(null,0,e,t)},o.prototype.copy=function(e,t,n,r){if(("number"!=typeof n||n<0)&&(n=0),("number"!=typeof r||r>this.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);const o=!!e,s=this._offset(n),a=r-n;let c=a,l=o&&t||0,d=s[1];if(0===n&&r===this.length){if(!o)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(let t=0;t<this._bufs.length;t++)this._bufs[t].copy(e,l),l+=this._bufs[t].length;return e}if(c<=this._bufs[s[0]].length-d)return o?this._bufs[s[0]].copy(e,t,d,d+c):this._bufs[s[0]].slice(d,d+c);o||(e=i.allocUnsafe(a));for(let t=s[0];t<this._bufs.length;t++){const n=this._bufs[t].length-d;if(!(c>n)){this._bufs[t].copy(e,l,d,d+c),l+=n;break}this._bufs[t].copy(e,l,d),l+=n,c-=n,d&&(d=0)}return e.length>l?e.slice(0,l):e},o.prototype.shallowSlice=function(e,t){if(e=e||0,t="number"!=typeof t?this.length:t,e<0&&(e+=this.length),t<0&&(t+=this.length),e===t)return this._new();const n=this._offset(e),i=this._offset(t),r=this._bufs.slice(n[0],i[0]+1);return 0===i[1]?r.pop():r[r.length-1]=r[r.length-1].slice(0,i[1]),0!==n[1]&&(r[0]=r[0].slice(n[1])),this._new(r)},o.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},o.prototype.consume=function(e){if(e=Math.trunc(e),Number.isNaN(e)||e<=0)return this;for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},o.prototype.duplicate=function(){const e=this._new();for(let t=0;t<this._bufs.length;t++)e.append(this._bufs[t]);return e},o.prototype.append=function(e){return this._attach(e,o.prototype._appendBuffer)},o.prototype.prepend=function(e){return this._attach(e,o.prototype._prependBuffer,!0)},o.prototype._attach=function(e,t,n){if(null==e)return this;if(e.buffer)t.call(this,i.from(e.buffer,e.byteOffset,e.byteLength));else if(Array.isArray(e)){const[i,r]=n?[e.length-1,-1]:[0,1];for(let o=i;o>=0&&o<e.length;o+=r)this._attach(e[o],t,n)}else if(this._isBufferList(e)){const[i,r]=n?[e._bufs.length-1,-1]:[0,1];for(let o=i;o>=0&&o<e._bufs.length;o+=r)this._attach(e._bufs[o],t,n)}else"number"==typeof e&&(e=e.toString()),t.call(this,i.from(e));return this},o.prototype._appendBuffer=function(e){this._bufs.push(e),this.length+=e.length},o.prototype._prependBuffer=function(e){this._bufs.unshift(e),this.length+=e.length},o.prototype.indexOf=function(e,t,n){if(void 0===n&&"string"==typeof t&&(n=t,t=void 0),"function"==typeof e||Array.isArray(e))throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.');if("number"==typeof e?e=i.from([e]):"string"==typeof e?e=i.from(e,n):this._isBufferList(e)?e=e.slice():Array.isArray(e.buffer)?e=i.from(e.buffer,e.byteOffset,e.byteLength):i.isBuffer(e)||(e=i.from(e)),t=Number(t||0),isNaN(t)&&(t=0),t<0&&(t=this.length+t),t<0&&(t=0),0===e.length)return t>this.length?this.length:t;const r=this._offset(t);let o=r[0],s=r[1];for(;o<this._bufs.length;o++){const t=this._bufs[o];for(;s<t.length;){if(t.length-s>=e.length){const n=t.indexOf(e,s);if(-1!==n)return this._reverseOffset([o,n]);s=t.length-e.length+1}else{const t=this._reverseOffset([o,s]);if(this._match(t,e))return t;s++}}s=0}return-1},o.prototype._match=function(e,t){if(this.length-e<t.length)return!1;for(let n=0;n<t.length;n++)if(this.get(e+n)!==t[n])return!1;return!0},function(){const e={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readBigInt64BE:8,readBigInt64LE:8,readBigUInt64BE:8,readBigUInt64LE:8,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1,readIntBE:null,readIntLE:null,readUIntBE:null,readUIntLE:null};for(const t in e)(function(t){o.prototype[t]=null===e[t]?function(e,n){return this.slice(e,e+n)[t](0,n)}:function(n=0){return this.slice(n,n+e[t])[t](0)}})(t)}(),o.prototype._isBufferList=function(e){return e instanceof o||o.isBufferList(e)},o.isBufferList=function(e){return null!=e&&e[r]},e.exports=o},7830(e,t,n){"use strict";const{pipeline:i}=n(7758),r=n(3370),{destroyer:o}=n(5896),{isNodeStream:s,isReadable:a,isWritable:c,isWebStream:l,isTransformStream:d,isWritableStream:u,isReadableStream:p}=n(6115),{AbortError:h,codes:{ERR_INVALID_ARG_VALUE:f,ERR_MISSING_ARGS:g}}=n(6371),m=n(6238);e.exports=function(...e){if(0===e.length)throw new g("streams");if(1===e.length)return r.from(e[0]);const t=[...e];if("function"==typeof e[0]&&(e[0]=r.from(e[0])),"function"==typeof e[e.length-1]){const t=e.length-1;e[t]=r.from(e[t])}for(let n=0;n<e.length;++n)if(s(e[n])||l(e[n])){if(n<e.length-1&&!(a(e[n])||p(e[n])||d(e[n])))throw new f(`streams[${n}]`,t[n],"must be readable");if(n>0&&!(c(e[n])||u(e[n])||d(e[n])))throw new f(`streams[${n}]`,t[n],"must be writable")}let n,y,b,v,S;const _=e[0],w=i(e,function(e){const t=v;v=null,t?t(e):e?S.destroy(e):I||k||S.destroy()}),k=!!(c(_)||u(_)||d(_)),I=!!(a(w)||p(w)||d(w));if(S=new r({writableObjectMode:!(null==_||!_.writableObjectMode),readableObjectMode:!(null==w||!w.readableObjectMode),writable:k,readable:I}),k){if(s(_))S._write=function(e,t,i){_.write(e,t)?i():n=i},S._final=function(e){_.end(),y=e},_.on("drain",function(){if(n){const e=n;n=null,e()}});else if(l(_)){const e=(d(_)?_.writable:_).getWriter();S._write=async function(t,n,i){try{await e.ready,e.write(t).catch(()=>{}),i()}catch(e){i(e)}},S._final=async function(t){try{await e.ready,e.close().catch(()=>{}),y=t}catch(e){t(e)}}}const e=d(w)?w.readable:w;m(e,()=>{if(y){const e=y;y=null,e()}})}if(I)if(s(w))w.on("readable",function(){if(b){const e=b;b=null,e()}}),w.on("end",function(){S.push(null)}),S._read=function(){for(;;){const e=w.read();if(null===e)return void(b=S._read);if(!S.push(e))return}};else if(l(w)){const e=(d(w)?w.readable:w).getReader();S._read=async function(){for(;;)try{const{value:t,done:n}=await e.read();if(!S.push(t))return;if(n)return void S.push(null)}catch{return}}}return S._destroy=function(e,t){e||null===v||(e=new h),b=null,n=null,y=null,null===v?t(e):(v=t,s(w)&&o(w,e))},S}},7833(e,t,n){t.formatArgs=function(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+e.exports.humanize(this.diff),!this.useColors)return;const n="color: "+this.color;t.splice(1,0,n,"color: inherit");let i=0,r=0;t[0].replace(/%[a-zA-Z%]/g,e=>{"%%"!==e&&(i++,"%c"===e&&(r=i))}),t.splice(r,0,n)},t.save=function(e){try{e?t.storage.setItem("debug",e):t.storage.removeItem("debug")}catch(e){}},t.load=function(){let e;try{e=t.storage.getItem("debug")||t.storage.getItem("DEBUG")}catch(e){}!e&&"undefined"!=typeof process&&"env"in process&&(e=process.env.DEBUG);return e},t.useColors=function(){if("undefined"!=typeof window&&window.process&&("renderer"===window.process.type||window.process.__nwjs))return!0;if("undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let e;return"undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&(e=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(e[1],10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)},t.storage=function(){try{return localStorage}catch(e){}}(),t.destroy=(()=>{let e=!1;return()=>{e||(e=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),t.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],t.log=console.debug||console.log||(()=>{}),e.exports=n(736)(t);const{formatters:i}=e.exports;i.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}},7927(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.SpatialAwarenessPlugin=void 0;const a=s(n(7562)),c=n(6117),l=s(n(9896)),d=s(n(6928)),u=n(1554),p=n(4997),h=n(5389),f=n(7136),g=n(4386),m=n(5471),y=n(2846),b=n(7279),v=n(3874),S=n(1711),_=n(8462),{deviceManager:w,systemManager:k,mediaManager:I}=a.default,x="tracking-zone:",C="global-tracker";class E extends a.ScryptedDeviceBase{trackingEngine=null;trackingState;alertManager;mqttPublisher=null;discoveryEngine=null;devices=new Map;storageSettings=new c.StorageSettings(this,{topology:{title:"Camera Topology",type:"string",description:"JSON configuration of camera relationships",hide:!0},floorPlanImage:{title:"Floor Plan Image",type:"string",hide:!0},correlationWindow:{title:"Correlation Window (seconds)",type:"number",defaultValue:30,description:"Maximum time to wait for an object to appear on connected camera",group:"Tracking"},correlationThreshold:{title:"Correlation Confidence Threshold",type:"number",defaultValue:.35,description:"Minimum confidence (0-1) for automatic object correlation. Lower values allow more matches.",group:"Tracking"},lostTimeout:{title:"Lost Object Timeout (seconds)",type:"number",defaultValue:300,description:"Time before marking a tracked object as lost",group:"Tracking"},useVisualMatching:{title:"Use Visual Matching",type:"boolean",defaultValue:!0,description:"Use visual embeddings for object correlation (requires compatible detectors)",group:"Tracking"},loiteringThreshold:{title:"Loitering Threshold (seconds)",type:"number",defaultValue:3,description:"Object must be visible for this duration before triggering movement alerts",group:"Tracking"},objectAlertCooldown:{title:"Per-Object Alert Cooldown (seconds)",type:"number",defaultValue:30,description:"Minimum time between alerts for the same tracked object",group:"Tracking"},useLlmDescriptions:{title:"Use LLM for Rich Descriptions",type:"boolean",defaultValue:!0,description:'Use LLM plugin (if installed) to generate descriptive alerts like "Man walking from garage towards front door"',group:"AI & Spatial Reasoning"},llmDebounceInterval:{title:"LLM Rate Limit (seconds)",type:"number",defaultValue:10,description:"Minimum time between LLM calls to prevent API overload (0 = no limit)",group:"AI & Spatial Reasoning"},llmFallbackEnabled:{title:"Fallback to Basic Notifications",type:"boolean",defaultValue:!0,description:"When LLM is rate-limited or slow, fall back to basic notifications immediately",group:"AI & Spatial Reasoning"},llmFallbackTimeout:{title:"LLM Timeout (seconds)",type:"number",defaultValue:3,description:"Maximum time to wait for LLM response before falling back to basic notification",group:"AI & Spatial Reasoning"},enableTransitTimeLearning:{title:"Learn Transit Times",type:"boolean",defaultValue:!0,description:"Automatically adjust connection transit times based on observed movement patterns",group:"AI & Spatial Reasoning"},enableConnectionSuggestions:{title:"Suggest Camera Connections",type:"boolean",defaultValue:!0,description:"Automatically suggest new camera connections based on observed movement patterns",group:"AI & Spatial Reasoning"},enableLandmarkLearning:{title:"Learn Landmarks from AI",type:"boolean",defaultValue:!0,description:"Allow AI to suggest new landmarks based on detected objects and camera context",group:"AI & Spatial Reasoning"},landmarkConfidenceThreshold:{title:"Landmark Suggestion Confidence",type:"number",defaultValue:.7,description:"Minimum AI confidence (0-1) to suggest a landmark",group:"AI & Spatial Reasoning"},discoveryIntervalHours:{title:"Auto-Discovery Interval (hours)",type:"number",defaultValue:0,description:"Automatically scan cameras to discover landmarks and connections. Set to 0 to disable. Uses vision LLM to analyze camera views.",group:"Auto-Topology Discovery"},minLandmarkConfidence:{title:"Min Landmark Confidence",type:"number",defaultValue:.6,description:"Minimum confidence (0-1) for discovered landmarks",group:"Auto-Topology Discovery"},minConnectionConfidence:{title:"Min Connection Confidence",type:"number",defaultValue:.5,description:"Minimum confidence (0-1) for suggested camera connections",group:"Auto-Topology Discovery"},autoAcceptThreshold:{title:"Auto-Accept Threshold",type:"number",defaultValue:.85,description:"Suggestions above this confidence are automatically accepted (0-1)",group:"Auto-Topology Discovery"},enableMqtt:{title:"Enable MQTT",type:"boolean",defaultValue:!1,group:"MQTT Integration"},mqttBroker:{title:"MQTT Broker URL",type:"string",placeholder:"mqtt://localhost:1883",group:"MQTT Integration"},mqttUsername:{title:"MQTT Username",type:"string",group:"MQTT Integration"},mqttPassword:{title:"MQTT Password",type:"password",group:"MQTT Integration"},mqttBaseTopic:{title:"MQTT Base Topic",type:"string",defaultValue:"scrypted/spatial-awareness",group:"MQTT Integration"},enableAlerts:{title:"Enable Alerts",type:"boolean",defaultValue:!0,group:"Alerts"},defaultNotifiers:{title:"Notifiers",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${a.ScryptedInterface.Notifier}')`,description:"Select one or more notifiers to receive alerts",group:"Alerts"},trackedCameras:{title:"Cameras to Track",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${a.ScryptedInterface.ObjectDetector}')`,group:"Cameras",description:"Select cameras with object detection to track"},alertRules:{title:"Alert Rules",type:"string",hide:!0}});constructor(e){super(e),this.trackingState=new h.TrackingState(this.storage,this.console),this.alertManager=new g.AlertManager(this.console,this.storage),process.nextTick(()=>this.initialize())}async initialize(){this.console.log("Initializing Spatial Awareness Plugin"),await w.onDeviceDiscovered({nativeId:C,name:"Global Object Tracker",type:a.ScryptedDeviceType.Sensor,interfaces:[a.ScryptedInterface.OccupancySensor,a.ScryptedInterface.Settings,a.ScryptedInterface.Readme]});const e=this.storage.getItem("topology");if(e)try{const t=JSON.parse(e);await this.startTrackingEngine(t)}catch(e){this.console.error("Failed to parse topology:",e)}const t=this.storage.getItem("alertRules");if(t)try{const e=JSON.parse(t);this.alertManager.setRules(e)}catch(e){this.console.error("Failed to parse alert rules:",e),this.alertManager.setRules((0,p.createDefaultRules)())}else this.alertManager.setRules((0,p.createDefaultRules)());this.storageSettings.values.enableMqtt&&await this.initializeMqtt(),this.console.log("Spatial Awareness Plugin initialized")}async initializeMqtt(){const e=this.storageSettings.values.mqttBroker;if(!e)return void this.console.warn("MQTT enabled but no broker URL configured");const t={broker:e,username:this.storageSettings.values.mqttUsername,password:this.storageSettings.values.mqttPassword,baseTopic:this.storageSettings.values.mqttBaseTopic||"scrypted/spatial-awareness"};this.mqttPublisher=new b.MqttPublisher(t,this.console),await this.mqttPublisher.connect(),this.trackingState.onStateChange(e=>{this.mqttPublisher?.publishState(e)}),this.console.log("MQTT publisher initialized")}async startTrackingEngine(e){this.trackingEngine&&await this.trackingEngine.stopTracking();const t={correlationWindow:1e3*(this.storageSettings.values.correlationWindow||30),correlationThreshold:this.storageSettings.values.correlationThreshold||.35,lostTimeout:1e3*(this.storageSettings.values.lostTimeout||300),useVisualMatching:this.storageSettings.values.useVisualMatching??!0,loiteringThreshold:1e3*(this.storageSettings.values.loiteringThreshold||3),objectAlertCooldown:1e3*(this.storageSettings.values.objectAlertCooldown||30),useLlmDescriptions:this.storageSettings.values.useLlmDescriptions??!0,llmDebounceInterval:1e3*(this.storageSettings.values.llmDebounceInterval||10),llmFallbackEnabled:this.storageSettings.values.llmFallbackEnabled??!0,llmFallbackTimeout:1e3*(this.storageSettings.values.llmFallbackTimeout||3),enableTransitTimeLearning:this.storageSettings.values.enableTransitTimeLearning??!0,enableConnectionSuggestions:this.storageSettings.values.enableConnectionSuggestions??!0,enableLandmarkLearning:this.storageSettings.values.enableLandmarkLearning??!0,landmarkConfidenceThreshold:this.storageSettings.values.landmarkConfidenceThreshold??.7};this.trackingEngine=new f.TrackingEngine(e,this.trackingState,this.alertManager,t,this.console),this.trackingEngine.setTopologyChangeCallback(e=>{this.storage.setItem("topology",JSON.stringify(e)),this.console.log("Topology auto-saved after change")}),await this.trackingEngine.startTracking(),this.console.log("Tracking engine started"),await this.initializeDiscoveryEngine(e)}async initializeDiscoveryEngine(e){const t={discoveryIntervalHours:this.storageSettings.values.discoveryIntervalHours??0,autoAcceptThreshold:this.storageSettings.values.autoAcceptThreshold??.85,minLandmarkConfidence:this.storageSettings.values.minLandmarkConfidence??.6,minConnectionConfidence:this.storageSettings.values.minConnectionConfidence??.5};this.discoveryEngine?(this.discoveryEngine.updateConfig(t),this.discoveryEngine.updateTopology(e)):(this.discoveryEngine=new _.TopologyDiscoveryEngine(t,this.console),this.discoveryEngine.updateTopology(e),t.discoveryIntervalHours>0&&this.discoveryEngine.startPeriodicDiscovery())}async getDevice(e){let t=this.devices.get(e);return t||(e===C?t=new m.GlobalTrackerSensor(this,e,this.trackingState):e.startsWith(x)&&(t=new y.TrackingZone(this,e,this.trackingState)),t&&this.devices.set(e,t)),t}async releaseDevice(e,t){this.devices.delete(t)}async getCreateDeviceSettings(){return[{key:"name",title:"Zone Name",description:"Name for this tracking zone",type:"string"},{key:"type",title:"Zone Type",type:"string",choices:["entry","exit","dwell","restricted"],value:"entry"},{key:"cameras",title:"Cameras",type:"device",multiple:!0,deviceFilter:`interfaces.includes('${a.ScryptedInterface.ObjectDetector}')`}]}async createDevice(e){const t=x+Date.now().toString();return await w.onDeviceDiscovered({nativeId:t,name:e.name||"Tracking Zone",type:a.ScryptedDeviceType.Sensor,interfaces:[a.ScryptedInterface.OccupancySensor,a.ScryptedInterface.MotionSensor,a.ScryptedInterface.Settings]}),this.storage.setItem(`zone:${t}`,JSON.stringify({type:e.type,cameras:e.cameras})),t}async getSettings(){const e=await this.storageSettings.getSettings(),t=[],n=n=>{e.filter(e=>e.group===n).forEach(e=>t.push(e))};t.push({key:"trainingMode",title:"Training Mode",type:"html",value:"\n <style>\n .sa-training-container {\n padding: 16px;\n background: rgba(255,255,255,0.03);\n border-radius: 4px;\n border: 1px solid rgba(255,255,255,0.08);\n }\n .sa-training-title {\n color: #4fc3f7;\n font-size: 14px;\n font-weight: 500;\n margin-bottom: 8px;\n font-family: inherit;\n }\n .sa-training-desc {\n color: rgba(255,255,255,0.6);\n margin-bottom: 12px;\n font-size: 13px;\n line-height: 1.5;\n font-family: inherit;\n }\n .sa-training-btn {\n background: #4fc3f7;\n color: #000;\n border: none;\n padding: 10px 20px;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n transition: background 0.2s;\n font-family: inherit;\n }\n .sa-training-btn:hover {\n background: #81d4fa;\n }\n .sa-training-steps {\n color: rgba(255,255,255,0.5);\n font-size: 12px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid rgba(255,255,255,0.05);\n font-family: inherit;\n }\n .sa-training-steps ol {\n margin: 6px 0 0 16px;\n padding: 0;\n }\n .sa-training-steps li {\n margin-bottom: 2px;\n }\n </style>\n <div class=\"sa-training-container\">\n <div class=\"sa-training-title\">Guided Property Training</div>\n <p class=\"sa-training-desc\">Walk your property while the system learns your camera layout, transit times, and landmarks automatically.</p>\n <button class=\"sa-training-btn\" onclick=\"(function(){var e=document.getElementById('sa-training-modal');if(e)e.remove();var m=document.createElement('div');m.id='sa-training-modal';m.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.85);z-index:2147483647;display:flex;align-items:center;justify-content:center;';var c=document.createElement('div');c.style.cssText='width:min(420px,95vw);height:92vh;max-height:900px;background:#121212;border-radius:8px;overflow:hidden;position:relative;box-shadow:0 8px 32px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.1);';var b=document.createElement('button');b.innerHTML='×';b.style.cssText='position:absolute;top:8px;right:8px;z-index:2147483647;background:rgba(255,255,255,0.1);color:white;border:none;width:32px;height:32px;border-radius:4px;font-size:18px;cursor:pointer;line-height:1;';b.onclick=function(){m.remove();};var f=document.createElement('iframe');f.src='/endpoint/@blueharford/scrypted-spatial-awareness/ui/training';f.style.cssText='width:100%;height:100%;border:none;';c.appendChild(b);c.appendChild(f);m.appendChild(c);m.onclick=function(ev){if(ev.target===m)m.remove();};document.body.appendChild(m);})()\">\n Start Training Mode\n </button>\n <div class=\"sa-training-steps\">\n <strong>How it works:</strong>\n <ol>\n <li>Start training and walk to each camera</li>\n <li>System auto-detects you and records transit times</li>\n <li>Mark landmarks as you encounter them</li>\n <li>Apply results to generate your topology</li>\n </ol>\n </div>\n </div>\n ",group:"Getting Started"});t.push({key:"topologyEditor",title:"Topology Editor",type:"html",value:"\n <style>\n .sa-open-btn {\n background: #4fc3f7;\n color: #000;\n border: none;\n padding: 10px 20px;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n transition: background 0.2s;\n font-family: inherit;\n }\n .sa-open-btn:hover {\n background: #81d4fa;\n }\n .sa-btn-container {\n padding: 16px;\n background: rgba(255,255,255,0.03);\n border-radius: 4px;\n text-align: center;\n border: 1px solid rgba(255,255,255,0.08);\n }\n .sa-btn-desc {\n color: rgba(255,255,255,0.6);\n margin-bottom: 12px;\n font-size: 13px;\n font-family: inherit;\n }\n </style>\n <div class=\"sa-btn-container\">\n <p class=\"sa-btn-desc\">Configure camera positions, connections, and transit times</p>\n <button class=\"sa-open-btn\" onclick=\"(function(){var e=document.getElementById('sa-topology-modal');if(e)e.remove();var m=document.createElement('div');m.id='sa-topology-modal';m.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.85);z-index:2147483647;display:flex;align-items:center;justify-content:center;';var c=document.createElement('div');c.style.cssText='width:95vw;height:92vh;max-width:1800px;background:#121212;border-radius:8px;overflow:hidden;position:relative;box-shadow:0 8px 32px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.1);';var b=document.createElement('button');b.innerHTML='×';b.style.cssText='position:absolute;top:8px;right:8px;z-index:2147483647;background:rgba(255,255,255,0.1);color:white;border:none;width:32px;height:32px;border-radius:4px;font-size:18px;cursor:pointer;line-height:1;';b.onclick=function(){m.remove();};var f=document.createElement('iframe');f.src='/endpoint/@blueharford/scrypted-spatial-awareness/ui/editor';f.style.cssText='width:100%;height:100%;border:none;';c.appendChild(b);c.appendChild(f);m.appendChild(c);m.onclick=function(ev){if(ev.target===m)m.remove();};document.body.appendChild(m);})()\">\n Open Topology Editor\n </button>\n </div>\n ",group:"Topology"}),n("Cameras");const i=this.trackingState.getActiveCount(),r=this.storage.getItem("topology");let o="Not configured - add cameras and configure topology";if(this.trackingEngine)o=`Active: Tracking ${i} object${1!==i?"s":""}`;else if(r)try{const e=JSON.parse(r);e.cameras&&e.cameras.length>0&&(o=`Configured (${e.cameras.length} cameras) - Starting...`,this.startTrackingEngine(e).catch(e=>{this.console.error("Failed to restart tracking engine:",e)}))}catch(e){o="Error loading topology"}t.push({key:"status",title:"Tracking Status",type:"string",readonly:!0,value:o,group:"Status"});const s=this.alertManager.getRecentAlerts(5);s.length>0&&t.push({key:"recentAlerts",title:"Recent Alerts",type:"string",readonly:!0,value:s.map(e=>`${e.type}: ${e.message}`).join("\n"),group:"Status"}),n("Tracking"),n("AI & Spatial Reasoning"),n("Auto-Topology Discovery"),n("Alerts");const a=this.alertManager.getRules(),c=this.generateAlertRulesHtml(a);return t.push({key:"alertRulesEditor",title:"Alert Rules",type:"html",value:c,group:"Alerts"}),n("MQTT Integration"),t}generateAlertRulesHtml(e){return`\n <style>\n .sa-rules-table { width:100%; border-collapse:collapse; margin-top:10px; }\n .sa-rules-table th { text-align:left; padding:10px 8px; border-bottom:2px solid #e94560; color:#e94560; font-size:13px; }\n .sa-save-rules-btn {\n background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);\n color: white;\n border: none;\n padding: 10px 20px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n margin-top: 15px;\n }\n .sa-save-rules-btn:hover { opacity: 0.9; }\n .sa-rules-container { background:#16213e; border-radius:8px; padding:15px; }\n .sa-rules-desc { color:#888; font-size:13px; margin-bottom:10px; }\n </style>\n <div class="sa-rules-container">\n <p class="sa-rules-desc">Enable or disable alert types. Movement alerts notify you when someone moves between cameras.</p>\n <table class="sa-rules-table">\n <thead>\n <tr>\n <th style="width:40px;">On</th>\n <th>Alert Type</th>\n <th>Event</th>\n <th>Severity</th>\n <th>Cooldown</th>\n </tr>\n </thead>\n <tbody>\n ${e.map(e=>`\n <tr data-rule-id="${e.id}">\n <td style="padding:8px;border-bottom:1px solid #333;">\n <input type="checkbox" ${e.enabled?"checked":""}\n onchange="(function(el){var rules=JSON.parse(localStorage.getItem('sa-temp-rules')||'[]');var r=rules.find(x=>x.id==='${e.id}');if(r)r.enabled=el.checked;localStorage.setItem('sa-temp-rules',JSON.stringify(rules));})(this)" />\n </td>\n <td style="padding:8px;border-bottom:1px solid #333;color:#fff;">${e.name}</td>\n <td style="padding:8px;border-bottom:1px solid #333;color:#888;">${e.type}</td>\n <td style="padding:8px;border-bottom:1px solid #333;">\n <span style="padding:2px 8px;border-radius:4px;font-size:12px;background:${"critical"===e.severity?"#e94560":"warning"===e.severity?"#f39c12":"#3498db"};color:white;">${e.severity}</span>\n </td>\n <td style="padding:8px;border-bottom:1px solid #333;color:#888;">${Math.round(e.cooldown/1e3)}s</td>\n </tr>\n `).join("")}\n </tbody>\n </table>\n <button class="sa-save-rules-btn" onclick="(function(){var rules=JSON.parse(localStorage.getItem('sa-temp-rules')||'[]');fetch('/endpoint/@blueharford/scrypted-spatial-awareness/api/alert-rules',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(rules)}).then(r=>r.json()).then(d=>{if(d.success)alert('Alert rules saved!');else alert('Error: '+d.error);}).catch(e=>alert('Error: '+e));})()">Save Alert Rules</button>\n <script>(function(){${`localStorage.setItem('sa-temp-rules',JSON.stringify(${JSON.stringify(e)}))`}})();<\/script>\n </div>\n `}async putSetting(e,t){if(await this.storageSettings.putSetting(e,t),"trackedCameras"===e||"correlationWindow"===e||"correlationThreshold"===e||"lostTimeout"===e||"useVisualMatching"===e||"loiteringThreshold"===e||"objectAlertCooldown"===e||"useLlmDescriptions"===e||"llmDebounceInterval"===e||"llmFallbackEnabled"===e||"llmFallbackTimeout"===e||"enableTransitTimeLearning"===e||"enableConnectionSuggestions"===e||"enableLandmarkLearning"===e||"landmarkConfidenceThreshold"===e){const e=this.storage.getItem("topology");if(e)try{const t=JSON.parse(e);await this.startTrackingEngine(t)}catch(e){this.console.error("Failed to restart tracking engine:",e)}}"enableMqtt"!==e&&"mqttBroker"!==e&&"mqttUsername"!==e&&"mqttPassword"!==e&&"mqttBaseTopic"!==e||(this.mqttPublisher&&(this.mqttPublisher.disconnect(),this.mqttPublisher=null),this.storageSettings.values.enableMqtt&&await this.initializeMqtt())}async onRequest(e,t){const n=new URL(e.url,"http://localhost").pathname;try{if(n.endsWith("/api/tracked-objects"))return this.handleTrackedObjectsRequest(e,t);if(n.match(/\/api\/journey\/[\w-]+$/)){const e=n.split("/").pop();return this.handleJourneyRequest(e,t)}if(n.endsWith("/api/topology"))return await this.handleTopologyRequest(e,t);if(n.endsWith("/api/alerts"))return this.handleAlertsRequest(e,t);if(n.endsWith("/api/alert-rules"))return this.handleAlertRulesRequest(e,t);if(n.endsWith("/api/cameras"))return this.handleCamerasRequest(t);if(n.endsWith("/api/floor-plan"))return this.handleFloorPlanRequest(e,t);if(n.endsWith("/api/landmarks"))return this.handleLandmarksRequest(e,t);if(n.match(/\/api\/landmarks\/[\w-]+$/)){const i=n.split("/").pop();return this.handleLandmarkRequest(i,e,t)}if(n.endsWith("/api/landmark-suggestions"))return this.handleLandmarkSuggestionsRequest(e,t);if(n.match(/\/api\/landmark-suggestions\/[\w-]+\/(accept|reject)$/)){const e=n.split("/"),i=e.pop(),r=e.pop();return this.handleSuggestionActionRequest(r,i,t)}if(n.endsWith("/api/landmark-templates"))return this.handleLandmarkTemplatesRequest(t);if(n.endsWith("/api/infer-relationships"))return this.handleInferRelationshipsRequest(t);if(n.endsWith("/api/connection-suggestions"))return this.handleConnectionSuggestionsRequest(e,t);if(n.match(/\/api\/connection-suggestions\/[\w->]+\/(accept|reject)$/)){const e=n.split("/"),i=e.pop(),r=e.pop();return this.handleConnectionSuggestionActionRequest(r,i,t)}if(n.endsWith("/api/live-tracking"))return this.handleLiveTrackingRequest(t);if(n.match(/\/api\/journey-path\/[\w-]+$/)){const e=n.split("/").pop();return this.handleJourneyPathRequest(e,t)}if(n.endsWith("/api/training/start"))return this.handleTrainingStartRequest(e,t);if(n.endsWith("/api/training/pause"))return this.handleTrainingPauseRequest(t);if(n.endsWith("/api/training/resume"))return this.handleTrainingResumeRequest(t);if(n.endsWith("/api/training/end"))return this.handleTrainingEndRequest(t);if(n.endsWith("/api/training/status"))return this.handleTrainingStatusRequest(t);if(n.endsWith("/api/training/landmark"))return this.handleTrainingLandmarkRequest(e,t);if(n.endsWith("/api/training/apply"))return this.handleTrainingApplyRequest(t);if(n.endsWith("/api/discovery/scan"))return this.handleDiscoveryScanRequest(t);if(n.endsWith("/api/discovery/status"))return this.handleDiscoveryStatusRequest(t);if(n.endsWith("/api/discovery/suggestions"))return this.handleDiscoverySuggestionsRequest(t);if(n.match(/\/api\/discovery\/suggestions\/[\w-]+\/(accept|reject)$/)){const e=n.split("/"),i=e.pop(),r=e.pop();return this.handleDiscoverySuggestionActionRequest(r,i,t)}if(n.match(/\/api\/discovery\/camera\/[\w-]+$/)){const e=n.split("/").pop();return this.handleDiscoveryCameraAnalysisRequest(e,t)}if(n.endsWith("/ui/editor")||n.endsWith("/ui/editor/"))return this.serveEditorUI(t);if(n.endsWith("/ui/training")||n.endsWith("/ui/training/"))return this.serveTrainingUI(t);if(n.includes("/ui/"))return this.serveStaticFile(n,t);t.send(JSON.stringify({name:"Spatial Awareness Plugin",version:"0.5.0-beta",endpoints:{api:{trackedObjects:"/api/tracked-objects",journey:"/api/journey/{globalId}",journeyPath:"/api/journey-path/{globalId}",topology:"/api/topology",alerts:"/api/alerts",floorPlan:"/api/floor-plan",liveTracking:"/api/live-tracking",connectionSuggestions:"/api/connection-suggestions",landmarkSuggestions:"/api/landmark-suggestions",training:{start:"/api/training/start",pause:"/api/training/pause",resume:"/api/training/resume",end:"/api/training/end",status:"/api/training/status",landmark:"/api/training/landmark",apply:"/api/training/apply"},discovery:{scan:"/api/discovery/scan",status:"/api/discovery/status",suggestions:"/api/discovery/suggestions",camera:"/api/discovery/camera/{cameraId}"}},ui:{editor:"/ui/editor",training:"/ui/training"}}}),{headers:{"Content-Type":"application/json"}})}catch(e){this.console.error("HTTP request error:",e),t.send(JSON.stringify({error:e.message}),{code:500,headers:{"Content-Type":"application/json"}})}}handleTrackedObjectsRequest(e,t){const n=this.trackingState.getAllObjects();t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}handleJourneyRequest(e,t){const n=this.trackingState.getObject(e);n?t.send(JSON.stringify({globalId:n.globalId,className:n.className,label:n.label,journey:n.journey,sightings:n.sightings.map(e=>({cameraId:e.cameraId,cameraName:e.cameraName,timestamp:e.timestamp})),firstSeen:n.firstSeen,lastSeen:n.lastSeen,state:n.state}),{headers:{"Content-Type":"application/json"}}):t.send(JSON.stringify({error:"Object not found"}),{code:404,headers:{"Content-Type":"application/json"}})}async handleTopologyRequest(e,t){if("GET"===e.method){const e=this.storage.getItem("topology"),n=e?JSON.parse(e):(0,u.createEmptyTopology)();t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}else if("PUT"===e.method||"POST"===e.method)try{const n=JSON.parse(e.body);this.storage.setItem("topology",JSON.stringify(n)),await this.startTrackingEngine(n),t.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid topology JSON"}),{code:400,headers:{"Content-Type":"application/json"}})}}handleAlertsRequest(e,t){const n=this.alertManager.getRecentAlerts();t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}handleAlertRulesRequest(e,t){if("GET"===e.method){const e=this.alertManager.getRules();t.send(JSON.stringify(e),{headers:{"Content-Type":"application/json"}})}else if("PUT"===e.method||"POST"===e.method)try{const n=JSON.parse(e.body);this.alertManager.setRules(n),t.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid rules JSON"}),{code:400,headers:{"Content-Type":"application/json"}})}}handleCamerasRequest(e){try{const t=[];for(const e of Object.keys(k.getSystemState()))try{const n=k.getDeviceById(e);n&&n.interfaces?.includes(a.ScryptedInterface.ObjectDetector)&&t.push({id:e,name:n.name||`Camera ${e}`})}catch(e){}e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}catch(t){this.console.error("Error getting cameras:",t),e.send(JSON.stringify([]),{headers:{"Content-Type":"application/json"}})}}async getFloorPlanPath(){const e=await I.getFilesPath();return this.console.log("Files path from mediaManager:",e),l.existsSync(e)||l.mkdirSync(e,{recursive:!0}),d.join(e,"floorplan.jpg")}async handleFloorPlanRequest(e,t){if("GET"===e.method)try{const e=await this.getFloorPlanPath();if(this.console.log("Loading floor plan from:",e,"exists:",l.existsSync(e)),l.existsSync(e)){const n=l.readFileSync(e),i="data:image/jpeg;base64,"+n.toString("base64");this.console.log("Floor plan loaded, size:",n.length),t.send(JSON.stringify({imageData:i}),{headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({imageData:null}),{headers:{"Content-Type":"application/json"}})}catch(e){this.console.error("Failed to read floor plan:",e),t.send(JSON.stringify({imageData:null}),{headers:{"Content-Type":"application/json"}})}else if("POST"===e.method)try{const n=JSON.parse(e.body),i=n.imageData.replace(/^data:image\/\w+;base64,/,""),r=Buffer.from(i,"base64"),o=await this.getFloorPlanPath();l.writeFileSync(o,r),this.console.log("Floor plan saved to:",o,"size:",r.length),t.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})}catch(e){this.console.error("Failed to save floor plan:",e),t.send(JSON.stringify({error:"Failed to save floor plan"}),{code:500,headers:{"Content-Type":"application/json"}})}}handleLandmarksRequest(e,t){const n=this.getTopology();if(n){if("GET"===e.method)t.send(JSON.stringify({landmarks:n.landmarks||[]}),{headers:{"Content-Type":"application/json"}});else if("POST"===e.method)try{const i=JSON.parse(e.body);i.id||(i.id=`landmark_${Date.now()}`),n.landmarks||(n.landmarks=[]),n.landmarks.push(i),this.storage.setItem("topology",JSON.stringify(n)),this.trackingEngine&&this.trackingEngine.updateTopology(n),t.send(JSON.stringify({success:!0,landmark:i}),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid landmark data"}),{code:400,headers:{"Content-Type":"application/json"}})}}else t.send(JSON.stringify({landmarks:[]}),{headers:{"Content-Type":"application/json"}})}handleLandmarkRequest(e,t,n){const i=this.getTopology();if(!i)return void n.send(JSON.stringify({error:"No topology configured"}),{code:404,headers:{"Content-Type":"application/json"}});const r=i.landmarks?.findIndex(t=>t.id===e)??-1;if("GET"===t.method){const e=i.landmarks?.[r];e?n.send(JSON.stringify(e),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Landmark not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("PUT"===t.method)try{const o=JSON.parse(t.body);r>=0?(i.landmarks[r]={...i.landmarks[r],...o,id:e},this.storage.setItem("topology",JSON.stringify(i)),this.trackingEngine&&this.trackingEngine.updateTopology(i),n.send(JSON.stringify({success:!0,landmark:i.landmarks[r]}),{headers:{"Content-Type":"application/json"}})):n.send(JSON.stringify({error:"Landmark not found"}),{code:404,headers:{"Content-Type":"application/json"}})}catch(e){n.send(JSON.stringify({error:"Invalid landmark data"}),{code:400,headers:{"Content-Type":"application/json"}})}else"DELETE"===t.method&&(r>=0?(i.landmarks.splice(r,1),this.storage.setItem("topology",JSON.stringify(i)),this.trackingEngine&&this.trackingEngine.updateTopology(i),n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}})):n.send(JSON.stringify({error:"Landmark not found"}),{code:404,headers:{"Content-Type":"application/json"}}))}handleLandmarkSuggestionsRequest(e,t){if(!this.trackingEngine)return void t.send(JSON.stringify({suggestions:[]}),{headers:{"Content-Type":"application/json"}});const n=this.trackingEngine.getPendingLandmarkSuggestions();t.send(JSON.stringify({suggestions:n,count:n.length}),{headers:{"Content-Type":"application/json"}})}handleSuggestionActionRequest(e,t,n){if(this.trackingEngine)if("accept"===t){const t=this.trackingEngine.acceptLandmarkSuggestion(e);t?n.send(JSON.stringify({success:!0,landmark:t}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("reject"===t){this.trackingEngine.rejectLandmarkSuggestion(e)?n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Invalid action"}),{code:400,headers:{"Content-Type":"application/json"}});else n.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}})}handleLandmarkTemplatesRequest(e){e.send(JSON.stringify({templates:u.LANDMARK_TEMPLATES}),{headers:{"Content-Type":"application/json"}})}handleInferRelationshipsRequest(e){const t=this.getTopology();if(!t)return void e.send(JSON.stringify({relationships:[]}),{headers:{"Content-Type":"application/json"}});const n=(0,u.inferRelationships)(t);e.send(JSON.stringify({relationships:n,count:n.length}),{headers:{"Content-Type":"application/json"}})}handleConnectionSuggestionsRequest(e,t){if(!this.trackingEngine)return void t.send(JSON.stringify({suggestions:[]}),{headers:{"Content-Type":"application/json"}});const n=this.trackingEngine.getConnectionSuggestions();t.send(JSON.stringify({suggestions:n,count:n.length}),{headers:{"Content-Type":"application/json"}})}handleConnectionSuggestionActionRequest(e,t,n){if(this.trackingEngine)if("accept"===t){const t=this.trackingEngine.acceptConnectionSuggestion(e);if(t){const e=this.trackingEngine.getTopology();this.storage.setItem("topology",JSON.stringify(e)),n.send(JSON.stringify({success:!0,connection:t}),{headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("reject"===t){this.trackingEngine.rejectConnectionSuggestion(e)?n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Invalid action"}),{code:400,headers:{"Content-Type":"application/json"}});else n.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}})}handleLiveTrackingRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({objects:[],timestamp:Date.now()}),{headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.getLiveTrackingState();e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}handleJourneyPathRequest(e,t){if(!this.trackingEngine)return void t.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});const n=this.trackingEngine.getJourneyPath(e);n?t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}):t.send(JSON.stringify({error:"Object not found"}),{code:404,headers:{"Content-Type":"application/json"}})}handleTrainingStartRequest(e,t){if(this.trackingEngine)try{let n,i;if(e.body){const t=JSON.parse(e.body);i=t.trainerName,n=t.config}const r=this.trackingEngine.startTrainingSession(i,n);t.send(JSON.stringify(r),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:e.message}),{code:500,headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({error:"Tracking engine not running. Configure topology first."}),{code:500,headers:{"Content-Type":"application/json"}})}handleTrainingPauseRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});this.trackingEngine.pauseTrainingSession()?e.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):e.send(JSON.stringify({error:"No active training session to pause"}),{code:400,headers:{"Content-Type":"application/json"}})}handleTrainingResumeRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});this.trackingEngine.resumeTrainingSession()?e.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):e.send(JSON.stringify({error:"No paused training session to resume"}),{code:400,headers:{"Content-Type":"application/json"}})}async handleTrainingEndRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.endTrainingSession();if(t){const n=[...new Set(t.visits.map(e=>e.cameraId))];if(this.discoveryEngine&&n.length>0){this.console.log(`[Training] Running discovery analysis on ${n.length} visited cameras...`);let e=0,t=0;for(const i of n)try{const n=await this.discoveryEngine.analyzeScene(i);n.isValid&&(e+=n.landmarks.length,t+=n.zones.length,this.console.log(`[Training] ${i}: Found ${n.landmarks.length} landmarks, ${n.zones.length} zones`))}catch(e){this.console.warn(`[Training] Failed to analyze ${i}:`,e)}const i=this.discoveryEngine.getPendingSuggestions();for(const e of i)this.applyDiscoverySuggestion(e),this.discoveryEngine.acceptSuggestion(e.id);if(i.length>0&&this.trackingEngine){const n=this.trackingEngine.getTopology();await this.storageSettings.putSetting("topology",JSON.stringify(n)),this.console.log(`[Training] Auto-applied ${i.length} discoveries (${e} landmarks, ${t} zones)`)}}e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}else e.send(JSON.stringify({error:"No training session to end"}),{code:400,headers:{"Content-Type":"application/json"}})}handleTrainingStatusRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({state:"idle",stats:null}),{headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.getTrainingStatus();t?e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}}):e.send(JSON.stringify({state:"idle",stats:null}),{headers:{"Content-Type":"application/json"}})}handleTrainingLandmarkRequest(e,t){if(this.trackingEngine)try{const n=JSON.parse(e.body),i=this.trackingEngine.markTrainingLandmark(n);i?t.send(JSON.stringify({success:!0,landmark:i}),{headers:{"Content-Type":"application/json"}}):t.send(JSON.stringify({error:"No active training session"}),{code:400,headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:"Invalid request body"}),{code:400,headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}})}handleTrainingApplyRequest(e){if(!this.trackingEngine)return void e.send(JSON.stringify({error:"Tracking engine not running"}),{code:500,headers:{"Content-Type":"application/json"}});const t=this.trackingEngine.applyTrainingToTopology();if(t.success){const e=this.trackingEngine.getTopology();this.storage.setItem("topology",JSON.stringify(e))}e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}async handleDiscoveryScanRequest(e){if(this.discoveryEngine)try{this.console.log("[Discovery] Manual scan triggered via API");const t=await this.discoveryEngine.runFullDiscovery(),n=this.discoveryEngine.getStatus(),i=this.discoveryEngine.getPendingSuggestions();e.send(JSON.stringify({success:!0,status:n,correlation:t,suggestions:i}),{headers:{"Content-Type":"application/json"}})}catch(t){this.console.error("[Discovery] Scan failed:",t),e.send(JSON.stringify({error:`Scan failed: ${t.message}`}),{code:500,headers:{"Content-Type":"application/json"}})}else e.send(JSON.stringify({error:"Discovery engine not initialized. Configure topology first."}),{code:500,headers:{"Content-Type":"application/json"}})}handleDiscoveryStatusRequest(e){if(!this.discoveryEngine)return void e.send(JSON.stringify({isRunning:!1,isScanning:!1,lastScanTime:null,nextScanTime:null,camerasAnalyzed:0,pendingSuggestions:0}),{headers:{"Content-Type":"application/json"}});const t=this.discoveryEngine.getStatus();e.send(JSON.stringify(t),{headers:{"Content-Type":"application/json"}})}handleDiscoverySuggestionsRequest(e){if(!this.discoveryEngine)return void e.send(JSON.stringify({suggestions:[]}),{headers:{"Content-Type":"application/json"}});const t=this.discoveryEngine.getPendingSuggestions();e.send(JSON.stringify({suggestions:t}),{headers:{"Content-Type":"application/json"}})}handleDiscoverySuggestionActionRequest(e,t,n){if(this.discoveryEngine)if("accept"===t){const t=this.discoveryEngine.acceptSuggestion(e);t?(this.applyDiscoverySuggestion(t),n.send(JSON.stringify({success:!0,suggestion:t}),{headers:{"Content-Type":"application/json"}})):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else if("reject"===t){this.discoveryEngine.rejectSuggestion(e)?n.send(JSON.stringify({success:!0}),{headers:{"Content-Type":"application/json"}}):n.send(JSON.stringify({error:"Suggestion not found"}),{code:404,headers:{"Content-Type":"application/json"}})}else n.send(JSON.stringify({error:"Invalid action"}),{code:400,headers:{"Content-Type":"application/json"}});else n.send(JSON.stringify({error:"Discovery engine not initialized"}),{code:500,headers:{"Content-Type":"application/json"}})}async handleDiscoveryCameraAnalysisRequest(e,t){if(this.discoveryEngine)try{const n=await this.discoveryEngine.analyzeScene(e);t.send(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}catch(e){t.send(JSON.stringify({error:`Analysis failed: ${e.message}`}),{code:500,headers:{"Content-Type":"application/json"}})}else t.send(JSON.stringify({error:"Discovery engine not initialized"}),{code:500,headers:{"Content-Type":"application/json"}})}applyDiscoverySuggestion(e){if(!this.trackingEngine)return;const t=this.trackingEngine.getTopology();let n=!1;if("landmark"===e.type&&e.landmark){let i=e.landmark.position;if(!i||0===i.x&&0===i.y){this.console.log(`[Discovery] Processing landmark "${e.landmark.name}"`),this.console.log(`[Discovery] sourceCameras: ${JSON.stringify(e.sourceCameras)}`),this.console.log(`[Discovery] visibleFromCameras: ${JSON.stringify(e.landmark.visibleFromCameras)}`),this.console.log(`[Discovery] Available cameras: ${t.cameras.map(e=>`${e.name}(${e.deviceId})`).join(", ")}`);const n=e.sourceCameras?.[0],r=e.landmark.visibleFromCameras?.[0],o=n||r,s=o?t.cameras.find(e=>e.deviceId===o||e.name===o||e.name.toLowerCase()===o.toLowerCase()):null;if(s?(this.console.log(`[Discovery] Matched camera: ${s.name} (${s.deviceId})`),this.console.log(`[Discovery] Camera position: ${JSON.stringify(s.floorPlanPosition)}`),this.console.log(`[Discovery] Camera FOV: ${JSON.stringify(s.fov)}`)):this.console.warn(`[Discovery] No camera matched for ref="${o}" (source="${n}", visible="${r}")`),s?.floorPlanPosition){const n=s.fov||{mode:"simple",angle:90,direction:0,range:80},r=n.direction||0,o=n.range||80,a=n.angle||90,c=(r-90)*Math.PI/180,l=a/2*Math.PI/180,d=e.landmark.type,u=["neighbor","boundary","street"].includes(d||""),p=e.landmark.boundingBox;let h,f;if(p&&p.length>=2){if(h=2*(p[0]+(p[2]||0)/2-.5)*l,u)f=1.5+.5*Math.random(),this.console.log(`[Discovery] Far-type landmark "${d}" placed BEYOND FOV (${(100*f).toFixed(0)}% of range)`);else{const e=p[1]+(p[3]||0)/2;f=Math.max(.4,.9-.5*e)}this.console.log(`[Discovery] Using bounding box [${p.join(",")}] for horizontal position`)}else{const e=s.deviceId,n=(t.landmarks||[]).filter(t=>t.visibleFromCameras?.includes(e)||t.visibleFromCameras?.includes(s.name)).length;h=(n%3-1)*l*.6,u?(f=1.5+.5*Math.random(),this.console.log(`[Discovery] Far-type landmark "${d}" (no bbox) placed BEYOND FOV`)):(f=.5+n%2*.3,this.console.log(`[Discovery] No bounding box, using fallback spread (existing: ${n})`))}const g=c+h,m=o*f;i={x:s.floorPlanPosition.x+Math.cos(g)*m,y:s.floorPlanPosition.y+Math.sin(g)*m},this.console.log(`[Discovery] Placing landmark "${e.landmark.name}" in ${s.name}'s FOV: dir=${r}°, angle=${(180*h/Math.PI).toFixed(1)}°, dist=${m.toFixed(0)}px`)}else{const e=t.landmarks?.length||0,n=80,r=5;i={x:200+e%r*n,y:100+Math.floor(e/r)*n}}}const r={id:`landmark_${Date.now()}`,name:e.landmark.name,type:e.landmark.type,position:i,description:e.landmark.description,visibleFromCameras:e.landmark.visibleFromCameras,aiSuggested:!0,aiConfidence:e.confidence};t.landmarks||(t.landmarks=[]),t.landmarks.push(r),n=!0,this.console.log(`[Discovery] Added landmark: ${r.name} at (${i.x}, ${i.y})`)}if("zone"===e.type&&e.zone){const i=e.zone,r=e.sourceCameras||[],o=r[0],s=o?t.cameras.find(e=>e.deviceId===o||e.name===o||e.name.toLowerCase()===o.toLowerCase()):null;this.console.log(`[Discovery] Processing zone "${i.name}" from camera ref="${o}"`),s?this.console.log(`[Discovery] Matched camera: ${s.name} (${s.deviceId})`):o&&this.console.warn(`[Discovery] No camera matched for zone source ref="${o}"`);let a=[];const c=Date.now();if(s?.floorPlanPosition){const e=s.fov||{mode:"simple",angle:90,direction:0,range:80},n=e.direction||0,o=e.range||80,c=e.angle||90,l=(n-90)*Math.PI/180,d=c/2*Math.PI/180,u=s.floorPlanPosition.x,p=s.floorPlanPosition.y,h=i.boundingBox;let f,g,m,y;if(h&&h.length>=4){const e=h[0],t=h[0]+h[2],n=h[1];m=l+2*(e-.5)*d,y=l+2*(t-.5)*d,f=o*(.9-.6*(h[1]+h[3])),g=o*(.9-.6*n),g-f<20&&(g=f+20),this.console.log(`[Discovery] Zone "${i.name}" using bbox [${h.join(",")}] → angles ${(180*m/Math.PI).toFixed(1)}° to ${(180*y/Math.PI).toFixed(1)}°`)}else{const e=(t.drawnZones||[]).filter(e=>e.linkedCameras?.includes(r[0])).length;f=.3*o+20*e,g=.8*o+20*e,m=l-.7*d,y=l+.7*d,this.console.log(`[Discovery] Zone "${i.name}" using fallback spread (existing: ${e})`)}const b=8;for(let e=0;e<=b;e++){const t=m+(y-m)*e/b;a.push({x:u+Math.cos(t)*f,y:p+Math.sin(t)*f})}for(let e=b;e>=0;e--){const t=m+(y-m)*e/b;a.push({x:u+Math.cos(t)*g,y:p+Math.sin(t)*g})}this.console.log(`[Discovery] Creating zone "${i.name}" in ${s.name}'s FOV: dir=${n}°`)}else{const e=300+120*(t.drawnZones?.length||0),n=200,i=100;a=[{x:e-i/2,y:n-i/2},{x:e+i/2,y:n-i/2},{x:e+i/2,y:n+i/2},{x:e-i/2,y:n+i/2}]}const l={id:`zone_${c}`,name:i.name,type:i.type||"custom",description:i.description,polygon:a,linkedCameras:r};t.drawnZones||(t.drawnZones=[]),t.drawnZones.push(l);const d=this.mapZoneTypeToGlobalType(i.type),u=r.map(e=>{const n=t.cameras.find(t=>t.deviceId===e||t.name===e||t.name.toLowerCase()===e.toLowerCase());return n?{cameraId:n.deviceId,zone:[[0,0],[100,0],[100,100],[0,100]]}:(this.console.warn(`[Discovery] GlobalZone: No camera matched for ref="${e}"`),null)}).filter(e=>null!==e);if(u.length>0){const e={id:`global_${c}`,name:i.name,type:d,cameraZones:u};t.globalZones||(t.globalZones=[]),t.globalZones.push(e),this.console.log(`[Discovery] Added zone: ${i.name} (${i.type}) - DrawnZone and GlobalZone created`)}else this.console.log(`[Discovery] Added zone: ${i.name} (${i.type}) - DrawnZone only (no cameras matched)`);n=!0}if("connection"===e.type&&e.connection){const i=e.connection,r=t.cameras.find(e=>e.deviceId===i.fromCameraId||e.name===i.fromCameraId||e.name.toLowerCase()===i.fromCameraId.toLowerCase()),o=t.cameras.find(e=>e.deviceId===i.toCameraId||e.name===i.toCameraId||e.name.toLowerCase()===i.toCameraId.toLowerCase());if(!r||!o)return this.console.warn(`[Discovery] Cannot create connection: camera not found. from="${i.fromCameraId}" to="${i.toCameraId}"`),void this.console.warn(`[Discovery] Available cameras: ${t.cameras.map(e=>`${e.name} (${e.deviceId})`).join(", ")}`);if(t.connections.find(e=>e.fromCameraId===r.deviceId&&e.toCameraId===o.deviceId||e.bidirectional&&e.fromCameraId===o.deviceId&&e.toCameraId===r.deviceId))return void this.console.log(`[Discovery] Connection already exists between ${r.name} and ${o.name}`);r.floorPlanPosition&&o.floorPlanPosition||this.console.warn("[Discovery] Note: One or both cameras not positioned on floor plan yet");const s={id:`conn_${Date.now()}`,fromCameraId:r.deviceId,toCameraId:o.deviceId,bidirectional:i.bidirectional,exitZone:[[0,0],[100,0],[100,100],[0,100]],entryZone:[[0,0],[100,0],[100,100],[0,100]],transitTime:{typical:1e3*i.transitSeconds,min:Math.max(1e3,500*i.transitSeconds),max:2e3*i.transitSeconds},name:i.via?`Via ${i.via}`:void 0};t.connections.push(s),n=!0,this.console.log(`[Discovery] Added connection: ${r.name} (${r.deviceId}) -> ${o.name} (${o.deviceId})`)}n&&(this.storage.setItem("topology",JSON.stringify(t)),this.trackingEngine.updateTopology(t))}mapZoneTypeToGlobalType(e){return{yard:"dwell",driveway:"entry",street:"entry",patio:"dwell",walkway:"entry",parking:"dwell",garden:"dwell",pool:"restricted",entrance:"entry",garage:"entry",deck:"dwell",custom:"dwell"}[e]||"dwell"}serveEditorUI(e){e.send(v.EDITOR_HTML,{headers:{"Content-Type":"text/html"}})}serveTrainingUI(e){e.send(S.TRAINING_HTML,{headers:{"Content-Type":"text/html"}})}serveStaticFile(e,t){t.send("Not found",{code:404})}async getReadmeMarkdown(){return"\n# Spatial Awareness Plugin\n\nThis plugin enables cross-camera object tracking across your entire NVR system.\n\n## Features\n\n- **Cross-Camera Tracking**: Correlate objects as they move between cameras\n- **Journey History**: Complete path history for each tracked object\n- **Entry/Exit Detection**: Know when objects enter or leave your property\n- **Visual Floor Plan**: Configure camera topology with a visual editor\n- **MQTT Integration**: Export tracking data to Home Assistant\n- **REST API**: Query tracked objects and journeys programmatically\n- **Smart Alerts**: Get notified about property entry/exit, unusual paths, and more\n\n## Setup\n\n1. **Add Cameras**: Select cameras with object detection in the plugin settings\n2. **Configure Topology**: Define camera relationships and transit times\n3. **Enable Integrations**: Optionally enable MQTT for Home Assistant\n4. **Create Zones**: Add tracking zones for specific area monitoring\n\n## API Endpoints\n\n- `GET /api/tracked-objects` - List all tracked objects\n- `GET /api/journey/{id}` - Get journey for specific object\n- `GET /api/topology` - Get camera topology\n- `PUT /api/topology` - Update camera topology\n- `GET /api/alerts` - Get recent alerts\n\n## Visual Editor\n\nAccess the visual topology editor at `/ui/editor` to configure camera relationships using a floor plan.\n\n## Alert Types\n\n- **Property Entry**: Object entered the property\n- **Property Exit**: Object exited the property\n- **Unusual Path**: Object took an unexpected route\n- **Dwell Time**: Object lingered too long in an area\n- **Restricted Zone**: Object entered a restricted area\n"}getTrackingState(){return this.trackingState}getAlertManager(){return this.alertManager}getTopology(){const e=this.storage.getItem("topology");return e?JSON.parse(e):null}}t.SpatialAwarenessPlugin=E,t.default=E},7969(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const i=n(4478),r={objectMode:!0},o={clean:!0};t.default=class{options;_inflights;constructor(e){this.options=e||{},this.options={...o,...e},this._inflights=new Map}put(e,t){return this._inflights.set(e.messageId,e),t&&t(),this}createStream(){const e=new i.Readable(r),t=[];let n=!1,o=0;return this._inflights.forEach((e,n)=>{t.push(e)}),e._read=()=>{!n&&o<t.length?e.push(t[o++]):e.push(null)},e.destroy=t=>{if(!n)return n=!0,setTimeout(()=>{e.emit("close")},0),e},e}del(e,t){const n=this._inflights.get(e.messageId);return n?(this._inflights.delete(e.messageId),t(null,n)):t&&t(new Error("missing packet")),this}get(e,t){const n=this._inflights.get(e.messageId);return n?t(null,n):t&&t(new Error("missing packet")),this}close(e){this.options.clean&&(this._inflights=null),e&&e()}}},8194(e,t,n){"use strict";n.d(t,{CD:()=>_});var i,r=(i=function(e,t){return i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},i(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),o=function(){function e(e,t){this.ee=1,this.u=void 0,this.p=void 0,this.K=void 0,this.N=void 0,this.rr=void 0,this.u=e,this.p=t}return e.prototype.L=function(){var e=this;if(1===e.ee&&e.rr.rr===e)e=e.N;else if(e.K)for(e=e.K;e.N;)e=e.N;else{for(var t=e.rr;t.K===e;)t=(e=t).rr;e=t}return e},e.prototype.m=function(){var e=this;if(e.N){for(e=e.N;e.K;)e=e.K;return e}for(var t=e.rr;t.N===e;)t=(e=t).rr;return e.N!==t?t:e},e.prototype.ne=function(){var e=this.rr,t=this.N,n=t.K;return e.rr===this?e.rr=t:e.K===this?e.K=t:e.N=t,t.rr=e,t.K=this,this.rr=t,this.N=n,n&&(n.rr=this),t},e.prototype.te=function(){var e=this.rr,t=this.K,n=t.N;return e.rr===this?e.rr=t:e.K===this?e.K=t:e.N=t,t.rr=e,t.N=this,this.rr=t,this.K=n,n&&(n.rr=this),t},e}(),s=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.tr=1,t}return r(t,e),t.prototype.ne=function(){var t=e.prototype.ne.call(this);return this.ie(),t.ie(),t},t.prototype.te=function(){var t=e.prototype.te.call(this);return this.ie(),t.ie(),t},t.prototype.ie=function(){this.tr=1,this.K&&(this.tr+=this.K.tr),this.N&&(this.tr+=this.N.tr)},t}(o),a=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),c=function(){function e(e){void 0===e&&(e=0),this.iteratorType=e}return e.prototype.equals=function(e){return this.o===e.o},e}(),l=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return a(t,e),t}(function(){function e(){this.M=0}return Object.defineProperty(e.prototype,"length",{get:function(){return this.M},enumerable:!1,configurable:!0}),e.prototype.size=function(){return this.M},e.prototype.empty=function(){return 0===this.M},e}());function d(){throw new RangeError("Iterator access denied!")}var u=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),p=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var i,r,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(i=o.next()).done;)s.push(i.value)}catch(e){r={error:e}}finally{try{i&&!i.done&&(n=o.return)&&n.call(o)}finally{if(r)throw r.error}}return s},h=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&i>=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};const f=function(e){function t(t,n){void 0===t&&(t=function(e,t){return e<t?-1:e>t?1:0}),void 0===n&&(n=!1);var i=e.call(this)||this;return i.W=void 0,i.$=t,n?(i.re=s,i.v=function(e,t,n){var i=this.se(e,t,n);if(i){for(var r=i.rr;r!==this.h;)r.tr+=1,r=r.rr;var o=this.fe(i);if(o){var s=o,a=s.parentNode,c=s.grandParent,l=s.curNode;a.ie(),c.ie(),l.ie()}}return this.M},i.G=function(e){for(var t=this.he(e);t!==this.h;)t.tr-=1,t=t.rr}):(i.re=o,i.v=function(e,t,n){var i=this.se(e,t,n);return i&&this.fe(i),this.M},i.G=i.he),i.h=new i.re,i}return u(t,e),t.prototype.U=function(e,t){for(var n=this.h;e;){var i=this.$(e.u,t);if(i<0)e=e.N;else{if(!(i>0))return e;n=e,e=e.K}}return n},t.prototype.X=function(e,t){for(var n=this.h;e;){this.$(e.u,t)<=0?e=e.N:(n=e,e=e.K)}return n},t.prototype.Y=function(e,t){for(var n=this.h;e;){var i=this.$(e.u,t);if(i<0)n=e,e=e.N;else{if(!(i>0))return e;e=e.K}}return n},t.prototype.Z=function(e,t){for(var n=this.h;e;){this.$(e.u,t)<0?(n=e,e=e.N):e=e.K}return n},t.prototype.ue=function(e){for(;;){var t,n=e.rr;if(n===this.h)return;if(1===e.ee)return void(e.ee=0);if(e===n.K)if(1===(t=n.N).ee)t.ee=0,n.ee=1,n===this.W?this.W=n.ne():n.ne();else{if(t.N&&1===t.N.ee)return t.ee=n.ee,n.ee=0,t.N.ee=0,void(n===this.W?this.W=n.ne():n.ne());t.K&&1===t.K.ee?(t.ee=1,t.K.ee=0,t.te()):(t.ee=1,e=n)}else if(1===(t=n.K).ee)t.ee=0,n.ee=1,n===this.W?this.W=n.te():n.te();else{if(t.K&&1===t.K.ee)return t.ee=n.ee,n.ee=0,t.K.ee=0,void(n===this.W?this.W=n.te():n.te());t.N&&1===t.N.ee?(t.ee=1,t.N.ee=0,t.ne()):(t.ee=1,e=n)}}},t.prototype.he=function(e){var t,n;if(1===this.M)return this.clear(),this.h;for(var i=e;i.K||i.N;){if(i.N)for(i=i.N;i.K;)i=i.K;else i=i.K;t=p([i.u,e.u],2),e.u=t[0],i.u=t[1],n=p([i.p,e.p],2),e.p=n[0],i.p=n[1],e=i}this.h.K===i?this.h.K=i.rr:this.h.N===i&&(this.h.N=i.rr),this.ue(i);var r=i.rr;return i===r.K?r.K=void 0:r.N=void 0,this.M-=1,this.W.ee=0,r},t.prototype.ae=function(e,t){return void 0!==e&&(!!this.ae(e.K,t)||(!!t(e)||this.ae(e.N,t)))},t.prototype.fe=function(e){for(;;){var t=e.rr;if(0===t.ee)return;var n=t.rr;if(t===n.K){if((i=n.N)&&1===i.ee){if(i.ee=t.ee=0,n===this.W)return;n.ee=1,e=n;continue}if(e===t.N){if(e.ee=0,e.K&&(e.K.rr=t),e.N&&(e.N.rr=n),t.N=e.K,n.K=e.N,e.K=t,e.N=n,n===this.W)this.W=e,this.h.rr=e;else(r=n.rr).K===n?r.K=e:r.N=e;return e.rr=n.rr,t.rr=e,n.rr=e,n.ee=1,{parentNode:t,grandParent:n,curNode:e}}t.ee=0,n===this.W?this.W=n.te():n.te(),n.ee=1}else{var i;if((i=n.K)&&1===i.ee){if(i.ee=t.ee=0,n===this.W)return;n.ee=1,e=n;continue}if(e===t.K){var r;if(e.ee=0,e.K&&(e.K.rr=n),e.N&&(e.N.rr=t),n.N=e.K,t.K=e.N,e.K=n,e.N=t,n===this.W)this.W=e,this.h.rr=e;else(r=n.rr).K===n?r.K=e:r.N=e;return e.rr=n.rr,t.rr=e,n.rr=e,n.ee=1,{parentNode:t,grandParent:n,curNode:e}}t.ee=0,n===this.W?this.W=n.ne():n.ne(),n.ee=1}return}},t.prototype.se=function(e,t,n){if(void 0===this.W)return this.M+=1,this.W=new this.re(e,t),this.W.ee=0,this.W.rr=this.h,this.h.rr=this.W,this.h.K=this.W,void(this.h.N=this.W);var i,r=this.h.K,o=this.$(r.u,e);if(0!==o){if(o>0)r.K=new this.re(e,t),r.K.rr=r,i=r.K,this.h.K=i;else{var s=this.h.N,a=this.$(s.u,e);if(0===a)return void(s.p=t);if(a<0)s.N=new this.re(e,t),s.N.rr=s,i=s.N,this.h.N=i;else{if(void 0!==n){var c=n.o;if(c!==this.h){var l=this.$(c.u,e);if(0===l)return void(c.p=t);if(l>0){var d=c.L(),u=this.$(d.u,e);if(0===u)return void(d.p=t);u<0&&(i=new this.re(e,t),void 0===d.N?(d.N=i,i.rr=d):(c.K=i,i.rr=c))}}}if(void 0===i)for(i=this.W;;){var p=this.$(i.u,e);if(p>0){if(void 0===i.K){i.K=new this.re(e,t),i.K.rr=i,i=i.K;break}i=i.K}else{if(!(p<0))return void(i.p=t);if(void 0===i.N){i.N=new this.re(e,t),i.N.rr=i,i=i.N;break}i=i.N}}}}return this.M+=1,i}r.p=t},t.prototype.g=function(e,t){for(;e;){var n=this.$(e.u,t);if(n<0)e=e.N;else{if(!(n>0))return e;e=e.K}}return e||this.h},t.prototype.clear=function(){this.M=0,this.W=void 0,this.h.rr=void 0,this.h.K=this.h.N=void 0},t.prototype.updateKeyByIterator=function(e,t){var n=e.o;if(n===this.h&&d(),1===this.M)return n.u=t,!0;if(n===this.h.K)return this.$(n.m().u,t)>0&&(n.u=t,!0);if(n===this.h.N)return this.$(n.L().u,t)<0&&(n.u=t,!0);var i=n.L().u;if(this.$(i,t)>=0)return!1;var r=n.m().u;return!(this.$(r,t)<=0)&&(n.u=t,!0)},t.prototype.eraseElementByPos=function(e){if(e<0||e>this.M-1)throw new RangeError;var t=0,n=this;return this.ae(this.W,function(i){return e===t?(n.G(i),!0):(t+=1,!1)}),this.M},t.prototype.eraseElementByKey=function(e){if(0===this.M)return!1;var t=this.g(this.W,e);return t!==this.h&&(this.G(t),!0)},t.prototype.eraseElementByIterator=function(e){var t=e.o;t===this.h&&d();var n=void 0===t.N;return 0===e.iteratorType?n&&e.next():n&&void 0!==t.K||e.next(),this.G(t),e},t.prototype.forEach=function(e){var t,n,i=0;try{for(var r=h(this),o=r.next();!o.done;o=r.next()){e(o.value,i++,this)}}catch(e){t={error:e}}finally{try{o&&!o.done&&(n=r.return)&&n.call(r)}finally{if(t)throw t.error}}},t.prototype.getElementByPos=function(e){var t,n,i;if(e<0||e>this.M-1)throw new RangeError;var r=0;try{for(var o=h(this),s=o.next();!s.done;s=o.next()){var a=s.value;if(r===e){i=a;break}r+=1}}catch(e){t={error:e}}finally{try{s&&!s.done&&(n=o.return)&&n.call(o)}finally{if(t)throw t.error}}return i},t.prototype.getHeight=function(){if(0===this.M)return 0;var e=function(t){return t?Math.max(e(t.K),e(t.N))+1:0};return e(this.W)},t}(l);var g=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}();const m=function(e){function t(t,n,i){var r=e.call(this,i)||this;return r.o=t,r.h=n,0===r.iteratorType?(r.pre=function(){return this.o===this.h.K&&d(),this.o=this.o.L(),this},r.next=function(){return this.o===this.h&&d(),this.o=this.o.m(),this}):(r.pre=function(){return this.o===this.h.N&&d(),this.o=this.o.m(),this},r.next=function(){return this.o===this.h&&d(),this.o=this.o.L(),this}),r}return g(t,e),Object.defineProperty(t.prototype,"index",{get:function(){var e=this.o,t=this.h.rr;if(e===this.h)return t?t.tr-1:0;var n=0;for(e.K&&(n+=e.K.tr);e!==t;){var i=e.rr;e===i.N&&(n+=1,i.K&&(n+=i.K.tr)),e=i}return n},enumerable:!1,configurable:!0}),t}(c);var y=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},e(t,n)};return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),b=function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(e){return function(t){return c([e,t])}}function c(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=s.trys,(r=r.length>0&&r[r.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]<r[3])){s.label=o[1];break}if(6===o[0]&&s.label<r[1]){s.label=r[1],r=o;break}if(r&&s.label<r[2]){s.label=r[2],s.ops.push(o);break}r[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],i=0}finally{n=r=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}},v=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&i>=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},S=function(e){function t(t,n,i,r){var o=e.call(this,t,n,r)||this;return o.container=i,o}return y(t,e),Object.defineProperty(t.prototype,"pointer",{get:function(){return this.o===this.h&&d(),this.o.u},enumerable:!1,configurable:!0}),t.prototype.copy=function(){return new t(this.o,this.h,this.container,this.iteratorType)},t}(m);const _=function(e){function t(t,n,i){void 0===t&&(t=[]);var r=e.call(this,n,i)||this,o=r;return t.forEach(function(e){o.insert(e)}),r}return y(t,e),t.prototype.P=function(e){return b(this,function(t){switch(t.label){case 0:return void 0===e?[2]:[5,v(this.P(e.K))];case 1:return t.sent(),[4,e.u];case 2:return t.sent(),[5,v(this.P(e.N))];case 3:return t.sent(),[2]}})},t.prototype.begin=function(){return new S(this.h.K||this.h,this.h,this)},t.prototype.end=function(){return new S(this.h,this.h,this)},t.prototype.rBegin=function(){return new S(this.h.N||this.h,this.h,this,1)},t.prototype.rEnd=function(){return new S(this.h,this.h,this,1)},t.prototype.front=function(){return this.h.K?this.h.K.u:void 0},t.prototype.back=function(){return this.h.N?this.h.N.u:void 0},t.prototype.insert=function(e,t){return this.v(e,void 0,t)},t.prototype.find=function(e){var t=this.g(this.W,e);return new S(t,this.h,this)},t.prototype.lowerBound=function(e){var t=this.U(this.W,e);return new S(t,this.h,this)},t.prototype.upperBound=function(e){var t=this.X(this.W,e);return new S(t,this.h,this)},t.prototype.reverseLowerBound=function(e){var t=this.Y(this.W,e);return new S(t,this.h,this)},t.prototype.reverseUpperBound=function(e){var t=this.Z(this.W,e);return new S(t,this.h,this)},t.prototype.union=function(e){var t=this;return e.forEach(function(e){t.insert(e)}),this.M},t.prototype[Symbol.iterator]=function(){return this.P(this.W)},t}(f)},8203(e,t,n){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.streamBuilder=t.browserStreamBuilder=void 0;const r=n(181),o=i(n(7699)),s=i(n(5753)),a=n(4478),c=i(n(6887)),l=n(2635),d=(0,s.default)("mqttjs:ws"),u=["rejectUnauthorized","ca","cert","key","pfx","passphrase"];function p(e,t){let n=`${e.protocol}://${e.hostname}:${e.port}${e.path}`;return"function"==typeof e.transformWsUrl&&(n=e.transformWsUrl(n,e,t)),n}function h(e){const t=e;return e.port||("wss"===e.protocol?t.port=443:t.port=80),e.path||(t.path="/"),e.wsOptions||(t.wsOptions={}),c.default||e.forceNativeWebSocket||"wss"!==e.protocol||u.forEach(n=>{Object.prototype.hasOwnProperty.call(e,n)&&!Object.prototype.hasOwnProperty.call(e.wsOptions,n)&&(t.wsOptions[n]=e[n])}),t}t.streamBuilder=(e,t)=>{d("streamBuilder");const n=h(t);n.hostname=n.hostname||n.host||"localhost";const i=p(n,e),r=function(e,t,n){d("createWebSocket"),d(`protocol: ${n.protocolId} ${n.protocolVersion}`);const i="MQIsdp"===n.protocolId&&3===n.protocolVersion?"mqttv3.1":"mqtt";let r;return d(`creating new Websocket for url: ${t} and protocol: ${i}`),r=n.createWebsocket?n.createWebsocket(t,[i],n):new o.default(t,[i],n.wsOptions),r}(0,i,n),s=o.default.createWebSocketStream(r,n.wsOptions);return s.url=i,r.on("close",()=>{s.destroy()}),s};t.browserStreamBuilder=(e,t)=>{let n;d("browserStreamBuilder");const i=function(e){const t=h(e);if(t.hostname||(t.hostname=t.host),!t.hostname){if("undefined"==typeof document)throw new Error("Could not determine host. Specify host manually.");const e=new URL(document.URL);t.hostname=e.hostname,t.port||(t.port=Number(e.port))}return void 0===t.objectMode&&(t.objectMode=!(!0===t.binary||void 0===t.binary)),t}(t),o=i.browserBufferSize||524288,s=t.browserBufferTimeout||1e3,c=!t.objectMode,u=function(e,t){const n="MQIsdp"===t.protocolId&&3===t.protocolVersion?"mqttv3.1":"mqtt",i=p(t,e);let r;return r=t.createWebsocket?t.createWebsocket(i,[n],t):new WebSocket(i,[n]),r.binaryType="arraybuffer",r}(e,t),f=function(e,t,n){const i=new a.Transform({objectMode:e.objectMode});return i._write=t,i._flush=n,i}(t,function e(t,n,i){if(u.bufferedAmount>o)return void setTimeout(e,s,t,n,i);c&&"string"==typeof t&&(t=r.Buffer.from(t,"utf8"));try{u.send(t)}catch(e){return i(e)}i()},function(e){u.close(),e()});t.objectMode||(f._writev=l.writev.bind(f)),f.on("close",()=>{u.close()});const g="undefined"!=typeof u.addEventListener;function m(){d("WebSocket onOpen"),n instanceof l.BufferedDuplex&&n.socketReady()}function y(e){d("WebSocket onClose",e),n.end(),n.destroy()}function b(e){d("WebSocket onError",e);const t=new Error("WebSocket error");t.event=e,n.destroy(t)}async function v(e){if(!f||!f.readable||!f.writable)return;let{data:t}=e;t=t instanceof ArrayBuffer?r.Buffer.from(t):t instanceof Blob?r.Buffer.from(await new Response(t).arrayBuffer()):r.Buffer.from(t,"utf8"),f.push(t)}return u.readyState===u.OPEN?(n=f,n.socket=u):(n=new l.BufferedDuplex(t,f,u),g?u.addEventListener("open",m):u.onopen=m),g?(u.addEventListener("close",y),u.addEventListener("error",b),u.addEventListener("message",v)):(u.onclose=y,u.onerror=b,u.onmessage=v),n}},8237(e,t,n){"use strict";const{tokenChars:i}=n(5880);e.exports={parse:function(e){const t=new Set;let n=-1,r=-1,o=0;for(;o<e.length;o++){const s=e.charCodeAt(o);if(-1===r&&1===i[s])-1===n&&(n=o);else if(0===o||32!==s&&9!==s){if(44!==s)throw new SyntaxError(`Unexpected character at index ${o}`);{if(-1===n)throw new SyntaxError(`Unexpected character at index ${o}`);-1===r&&(r=o);const i=e.slice(n,r);if(t.has(i))throw new SyntaxError(`The "${i}" subprotocol is duplicated`);t.add(i),n=r=-1}}else-1===r&&-1!==n&&(r=o)}if(-1===n||-1!==r)throw new SyntaxError("Unexpected end of input");const s=e.slice(n,o);if(t.has(s))throw new SyntaxError(`The "${s}" subprotocol is duplicated`);return t.add(s),t}}},8462(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t});Object.defineProperty(t,"__esModule",{value:!0}),t.TopologyDiscoveryEngine=void 0;const a=s(n(7562)),c=n(2881),l=n(1554),d=n(6687),{systemManager:u}=a.default,p='I have scene analyses from multiple security cameras at the same property. Help me correlate them to understand the property layout.\n\nCAMERA SCENES:\n{scenes}\n\nIdentify:\n1. Shared landmarks - Features that appear in multiple camera views\n2. Camera connections - How someone could move between camera views and estimated walking time\n3. Overall layout - Describe the property layout based on what you see\n\nIMPORTANT: For camera references, use the EXACT device ID shown in parentheses (e.g., "device_123"), NOT the camera name.\n\nRespond with ONLY valid JSON:\n{\n "sharedLandmarks": [\n {"name": "Driveway", "type": "access", "seenByCameras": ["device_123", "device_456"], "confidence": 0.8, "description": "Concrete driveway"}\n ],\n "connections": [\n {"from": "device_123", "to": "device_456", "transitSeconds": 10, "via": "driveway", "confidence": 0.7, "bidirectional": true}\n ],\n "layoutDescription": "Single-story house with front yard facing street, driveway on the left side, backyard accessible through side gate"\n}';t.TopologyDiscoveryEngine=class{config;console;topology=null;llmDevice=null;llmSearched=!1;llmProviderType="unknown";sceneCache=new Map;suggestions=new Map;status={...c.DEFAULT_DISCOVERY_STATUS};discoveryTimer=null;constructor(e,t){this.config={...c.DEFAULT_DISCOVERY_CONFIG,...e},this.console=t}updateConfig(e){this.config={...this.config,...e},this.status.isRunning&&(this.stopPeriodicDiscovery(),this.config.discoveryIntervalHours>0&&this.startPeriodicDiscovery())}updateTopology(e){this.topology=e}getStatus(){return{...this.status}}getPendingSuggestions(){return Array.from(this.suggestions.values()).filter(e=>"pending"===e.status).sort((e,t)=>t.confidence-e.confidence)}getSceneAnalysis(e){return this.sceneCache.get(e)||null}shouldShowRateLimitWarning(){return this.config.discoveryIntervalHours>0&&this.config.discoveryIntervalHours<c.RATE_LIMIT_WARNING_THRESHOLD}isEnabled(){return this.config.discoveryIntervalHours>0}async findLlmDevice(){if(this.llmDevice)return this.llmDevice;if(this.llmSearched)return null;this.llmSearched=!0;try{for(const e of Object.keys(u.getSystemState())){const t=u.getDeviceById(e);if(t&&t.interfaces?.includes("ChatCompletion")){const e=t.name?.toLowerCase()||"";return e.includes("openai")||e.includes("gpt")?this.llmProviderType="openai":e.includes("anthropic")||e.includes("claude")?this.llmProviderType="anthropic":e.includes("ollama")||e.includes("gemini")||e.includes("google")||e.includes("llama")?this.llmProviderType="openai":this.llmProviderType="unknown",this.llmDevice=t,this.console.log(`[Discovery] Connected to LLM: ${t.name}`),this.console.log(`[Discovery] Image format: ${this.llmProviderType}`),this.llmDevice}}this.console.warn("[Discovery] No ChatCompletion device found. Vision-based discovery unavailable.")}catch(e){this.console.error("[Discovery] Error finding LLM device:",e)}return null}async getCameraSnapshot(e){try{const t=u.getDeviceById(e);if(!t?.interfaces?.includes(a.ScryptedInterface.Camera))return this.console.warn(`[Discovery] Camera ${e} doesn't have Camera interface`),null;this.console.log(`[Discovery] Taking snapshot from camera: ${t.name||e}`);const n=await t.takePicture();if(!n)return this.console.warn(`[Discovery] takePicture() returned null for ${t.name}`),null;this.console.log(`[Discovery] MediaObject received: mimeType=${n.mimeType}`);const i=await(0,d.mediaObjectToBase64)(n);return i||this.console.warn(`[Discovery] Failed to convert MediaObject to base64 for ${t.name}`),i}catch(t){return this.console.warn(`[Discovery] Failed to get snapshot from camera ${e}:`,t),null}}async analyzeScene(e){const t=this.topology?(0,l.findCamera)(this.topology,e):null,n=t?.name||e,i={cameraId:e,cameraName:n,timestamp:Date.now(),landmarks:[],zones:[],edges:{top:"",left:"",right:"",bottom:""},orientation:"unknown",potentialOverlaps:[],isValid:!1},r=await this.findLlmDevice();if(!r?.getChatCompletion)return i.error="No LLM device available",i;const o=await this.getCameraSnapshot(e);if(!o)return i.error="Failed to capture camera snapshot",i;const s=[];s.push(this.llmProviderType),"openai"===this.llmProviderType?s.push("scrypted","anthropic"):"anthropic"===this.llmProviderType?s.push("scrypted","openai"):"scrypted"===this.llmProviderType?s.push("anthropic","openai"):s.push("scrypted","anthropic","openai");let a=null;for(const e of s)try{this.console.log(`[Discovery] Trying ${e} image format for ${n}...`);const t=await r.getChatCompletion({messages:[{role:"user",content:[{type:"text",text:'Analyze this security camera image and identify what you see.\n\n1. LANDMARKS - Identify fixed features visible:\n - Structures (house, garage, shed, porch, deck)\n - Features (mailbox, tree, pool, garden, fountain)\n - Access points (door, gate, driveway entrance, walkway)\n - Boundaries (fence, wall, hedge)\n\n2. ZONES - Identify area types visible:\n - What type of area is this? (front yard, backyard, driveway, street, patio, walkway)\n - Estimate what percentage of the frame each zone covers (0.0 to 1.0)\n\n3. EDGES - What\'s visible at the frame edges:\n - Top edge: (sky, roof, trees, etc.)\n - Left edge: (fence, neighbor, street, etc.)\n - Right edge: (fence, garage, etc.)\n - Bottom edge: (ground, driveway, grass, etc.)\n\n4. ORIENTATION - Estimate camera facing direction based on shadows, sun position, or landmarks\n\nRespond with ONLY valid JSON in this exact format:\n{\n "landmarks": [\n {"name": "Front Door", "type": "access", "confidence": 0.9, "description": "White front door with black frame"}\n ],\n "zones": [\n {"name": "Front Yard", "type": "yard", "coverage": 0.4, "description": "Grass lawn area"}\n ],\n "edges": {"top": "sky with clouds", "left": "fence and trees", "right": "garage wall", "bottom": "concrete walkway"},\n "orientation": "north"\n}'},(0,d.buildImageContent)(o,e)]}],max_tokens:1500,temperature:.3}),s=t?.choices?.[0]?.message?.content;if(s&&"string"==typeof s)try{let t=s.trim();t.startsWith("```")&&(t=t.replace(/```json?\n?/g,"").replace(/```$/g,"").trim());const r=JSON.parse(t);return Array.isArray(r.landmarks)&&(i.landmarks=r.landmarks.map(e=>({name:e.name||"Unknown",type:this.mapLandmarkType(e.type),confidence:"number"==typeof e.confidence?e.confidence:.7,description:e.description||"",boundingBox:e.boundingBox}))),Array.isArray(r.zones)&&(i.zones=r.zones.map(e=>({name:e.name||"Unknown",type:this.mapZoneType(e.type),coverage:"number"==typeof e.coverage?e.coverage:.5,description:e.description||"",boundingBox:e.boundingBox}))),r.edges&&"object"==typeof r.edges&&(i.edges={top:r.edges.top||"",left:r.edges.left||"",right:r.edges.right||"",bottom:r.edges.bottom||""}),r.orientation&&(i.orientation=this.mapOrientation(r.orientation)),i.isValid=!0,this.console.log(`[Discovery] Analyzed ${n}: ${i.landmarks.length} landmarks, ${i.zones.length} zones (using ${e} format)`),e!==this.llmProviderType&&(this.console.log(`[Discovery] Switching to ${e} format for future requests`),this.llmProviderType=e),i}catch(e){return this.console.warn(`[Discovery] Failed to parse LLM response for ${n}:`,e),i.error="Failed to parse LLM response",i}}catch(t){if(a=t,(0,d.isVisionFormatError)(t)){this.console.warn(`[Discovery] ${e} format failed, trying fallback...`);continue}this.console.warn(`[Discovery] Scene analysis failed for ${n}:`,t);break}if(a){const e=String(a);(0,d.isVisionFormatError)(a)?i.error="Vision/image analysis failed with all formats. Ensure you have a vision-capable model (e.g., gpt-4o, gpt-4-turbo, claude-3-sonnet) configured and the @scrypted/llm plugin supports vision.":i.error=`Analysis failed: ${e}`}return this.sceneCache.set(e,i),i}mapLandmarkType(e){return{structure:"structure",feature:"feature",boundary:"boundary",access:"access",vehicle:"vehicle",neighbor:"neighbor",zone:"zone",street:"street"}[e?.toLowerCase()]||"feature"}mapZoneType(e){return{yard:"yard",driveway:"driveway",street:"street",patio:"patio",deck:"patio",walkway:"walkway",parking:"parking",garden:"garden",pool:"pool"}[e?.toLowerCase()]||"unknown"}mapOrientation(e){const t=e?.toLowerCase();return t?.includes("north")&&t?.includes("east")?"northeast":t?.includes("north")&&t?.includes("west")?"northwest":t?.includes("south")&&t?.includes("east")?"southeast":t?.includes("south")&&t?.includes("west")?"southwest":t?.includes("north")?"north":t?.includes("south")?"south":t?.includes("east")?"east":t?.includes("west")?"west":"unknown"}resolveCameraRef(e){if(!this.topology?.cameras||!e)return null;const t=this.topology.cameras.find(t=>t.deviceId===e);if(t)return t.deviceId;const n=this.topology.cameras.find(t=>t.name===e);if(n)return n.deviceId;const i=e.toLowerCase(),r=this.topology.cameras.find(e=>e.name.toLowerCase()===i);if(r)return r.deviceId;const o=this.topology.cameras.find(e=>e.name.toLowerCase().includes(i)||i.includes(e.name.toLowerCase()));return o?o.deviceId:(this.console.warn(`[Discovery] Could not resolve camera reference: "${e}"`),null)}normalizeCameraRefs(e){return e.map(e=>this.resolveCameraRef(e)).filter(e=>null!==e)}async runFullDiscovery(){if(!this.topology?.cameras?.length)return this.console.warn("[Discovery] No cameras in topology"),null;this.status.isScanning=!0,this.status.lastError=void 0;try{this.console.log(`[Discovery] Starting full discovery scan of ${this.topology.cameras.length} cameras`);const e=[];for(const t of this.topology.cameras){const n=await this.analyzeScene(t.deviceId);n.isValid&&e.push(n),await new Promise(e=>setTimeout(e,2e3))}if(this.status.camerasAnalyzed=e.length,this.console.log(`[Discovery] Analyzed ${e.length} cameras successfully`),0===e.length)return this.console.warn("[Discovery] No cameras were successfully analyzed"),this.status.lastError="No cameras were successfully analyzed - check LLM configuration",this.status.lastScanTime=Date.now(),null;let t=null;return e.length>=2?(t=await this.correlateScenes(e),t&&this.generateSuggestionsFromCorrelation(t)):1===e.length&&this.generateSuggestionsFromAnalysis(e[0]),this.status.lastScanTime=Date.now(),this.status.pendingSuggestions=this.getPendingSuggestions().length,t}catch(e){return this.console.error("[Discovery] Full discovery failed:",e),this.status.lastError=`Discovery failed: ${e}`,null}finally{this.status.isScanning=!1}}async correlateScenes(e){const t=await this.findLlmDevice();if(!t?.getChatCompletion)return null;try{const n=e.map(e=>{const t=e.landmarks.map(e=>`${e.name} (${e.type})`).join(", "),n=e.zones.map(e=>`${e.name} (${e.type}, ${Math.round(100*e.coverage)}%)`).join(", ");return`Camera "${e.cameraName}" (${e.cameraId}):\n - Landmarks: ${t||"None identified"}\n - Zones: ${n||"None identified"}\n - Edges: Top=${e.edges.top}, Left=${e.edges.left}, Right=${e.edges.right}, Bottom=${e.edges.bottom}\n - Orientation: ${e.orientation}`}).join("\n\n"),i=p.replace("{scenes}",n),r=await t.getChatCompletion({messages:[{role:"user",content:i}],max_tokens:2e3,temperature:.4}),o=r?.choices?.[0]?.message?.content;if(o&&"string"==typeof o)try{let e=o.trim();e.startsWith("```")&&(e=e.replace(/```json?\n?/g,"").replace(/```$/g,"").trim());const t=JSON.parse(e),n={sharedLandmarks:[],suggestedConnections:[],layoutDescription:t.layoutDescription||"",timestamp:Date.now()};return Array.isArray(t.sharedLandmarks)&&(n.sharedLandmarks=t.sharedLandmarks.map(e=>{const t=Array.isArray(e.seenByCameras)?e.seenByCameras:[],n=this.normalizeCameraRefs(t);return t.length>0&&0===n.length&&this.console.warn(`[Discovery] Landmark "${e.name}" has no resolvable camera refs: ${JSON.stringify(t)}`),{name:e.name||"Unknown",type:this.mapLandmarkType(e.type),seenByCameras:n,confidence:"number"==typeof e.confidence?e.confidence:.7,description:e.description}})),Array.isArray(t.connections)&&(n.suggestedConnections=t.connections.map(e=>{const t=e.from||e.fromCameraId||"",n=e.to||e.toCameraId||"",i=this.resolveCameraRef(t),r=this.resolveCameraRef(n);return i&&r||this.console.warn(`[Discovery] Connection has unresolvable camera refs: from="${t}" to="${n}"`),{fromCameraId:i||t,toCameraId:r||n,transitSeconds:"number"==typeof e.transitSeconds?e.transitSeconds:15,via:e.via||"",confidence:"number"==typeof e.confidence?e.confidence:.6,bidirectional:!1!==e.bidirectional}})),this.console.log(`[Discovery] Correlation found ${n.sharedLandmarks.length} shared landmarks, ${n.suggestedConnections.length} connections`),n}catch(e){this.console.warn("[Discovery] Failed to parse correlation response:",e)}}catch(e){this.console.warn("[Discovery] Correlation failed:",e)}return null}generateSuggestionsFromAnalysis(e){if(e.isValid){for(const t of e.landmarks)if(t.confidence>=this.config.minLandmarkConfidence){const n={id:`landmark_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"landmark",timestamp:Date.now(),sourceCameras:[e.cameraId],confidence:t.confidence,status:"pending",landmark:{name:t.name,type:t.type,description:t.description,visibleFromCameras:[e.cameraId],boundingBox:t.boundingBox}};this.suggestions.set(n.id,n)}for(const t of e.zones)if(t.coverage>=.2){const n={id:`zone_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"zone",timestamp:Date.now(),sourceCameras:[e.cameraId],confidence:.7,status:"pending",zone:t};this.suggestions.set(n.id,n)}}}generateSuggestionsFromCorrelation(e){for(const t of e.sharedLandmarks){const e={id:`shared_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"landmark",timestamp:Date.now(),sourceCameras:t.seenByCameras,confidence:t.confidence,status:"pending",landmark:{name:t.name,type:t.type,description:t.description,visibleFromCameras:t.seenByCameras}};this.suggestions.set(e.id,e)}for(const t of e.suggestedConnections){const e={id:`conn_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:"connection",timestamp:Date.now(),sourceCameras:[t.fromCameraId,t.toCameraId],confidence:t.confidence,status:"pending",connection:t};this.suggestions.set(e.id,e)}}acceptSuggestion(e){const t=this.suggestions.get(e);return t&&"pending"===t.status?(t.status="accepted",this.status.pendingSuggestions=this.getPendingSuggestions().length,t):null}rejectSuggestion(e){const t=this.suggestions.get(e);return!(!t||"pending"!==t.status)&&(t.status="rejected",this.status.pendingSuggestions=this.getPendingSuggestions().length,!0)}startPeriodicDiscovery(){if(this.discoveryTimer&&clearInterval(this.discoveryTimer),this.config.discoveryIntervalHours<=0)return void this.console.log("[Discovery] Periodic discovery disabled (interval = 0)");this.status.isRunning=!0;const e=60*this.config.discoveryIntervalHours*60*1e3;this.console.log(`[Discovery] Starting periodic discovery every ${this.config.discoveryIntervalHours} hours`),this.status.nextScanTime=Date.now()+e,this.discoveryTimer=setInterval(async()=>{this.status.isScanning||(await this.runFullDiscovery(),this.status.nextScanTime=Date.now()+e)},e)}stopPeriodicDiscovery(){this.discoveryTimer&&(clearInterval(this.discoveryTimer),this.discoveryTimer=null),this.status.isRunning=!1,this.status.nextScanTime=null,this.console.log("[Discovery] Stopped periodic discovery")}clearCache(){this.sceneCache.clear(),this.suggestions.clear(),this.status.pendingSuggestions=0,this.status.camerasAnalyzed=0}}},8584(e,t,n){"use strict";const i=n(4422),{ArrayPrototypeSlice:r,Error:o,FunctionPrototypeSymbolHasInstance:s,ObjectDefineProperty:a,ObjectDefineProperties:c,ObjectSetPrototypeOf:l,StringPrototypeToLowerCase:d,Symbol:u,SymbolHasInstance:p}=n(4134);e.exports=L,L.WritableState=R;const{EventEmitter:h}=n(4434),f=n(4259).Stream,{Buffer:g}=n(181),m=n(5896),{addAbortSignal:y}=n(4147),{getHighWaterMark:b,getDefaultHighWaterMark:v}=n(5291),{ERR_INVALID_ARG_TYPE:S,ERR_METHOD_NOT_IMPLEMENTED:_,ERR_MULTIPLE_CALLBACK:w,ERR_STREAM_CANNOT_PIPE:k,ERR_STREAM_DESTROYED:I,ERR_STREAM_ALREADY_FINISHED:x,ERR_STREAM_NULL_VALUES:C,ERR_STREAM_WRITE_AFTER_END:E,ERR_UNKNOWN_ENCODING:T}=n(6371).codes,{errorOrDestroy:O}=m;function P(){}l(L.prototype,f.prototype),l(L,f);const A=u("kOnFinished");function R(e,t,i){"boolean"!=typeof i&&(i=t instanceof n(3370)),this.objectMode=!(!e||!e.objectMode),i&&(this.objectMode=this.objectMode||!(!e||!e.writableObjectMode)),this.highWaterMark=e?b(this,e,"writableHighWaterMark",i):v(!1),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;const r=!(!e||!1!==e.decodeStrings);this.decodeStrings=!r,this.defaultEncoding=e&&e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=j.bind(void 0,t),this.writecb=null,this.writelen=0,this.afterWriteTickInfo=null,M(this),this.pendingcb=0,this.constructed=!0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!e||!1!==e.emitClose,this.autoDestroy=!e||!1!==e.autoDestroy,this.errored=null,this.closed=!1,this.closeEmitted=!1,this[A]=[]}function M(e){e.buffered=[],e.bufferedIndex=0,e.allBuffers=!0,e.allNoop=!0}function L(e){const t=this instanceof n(3370);if(!t&&!s(L,this))return new L(e);this._writableState=new R(e,this,t),e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final),"function"==typeof e.construct&&(this._construct=e.construct),e.signal&&y(e.signal,this)),f.call(this,e),m.construct(this,()=>{const e=this._writableState;e.writing||z(this,e),H(this,e)})}function N(e,t,n,r){const o=e._writableState;if("function"==typeof n)r=n,n=o.defaultEncoding;else{if(n){if("buffer"!==n&&!g.isEncoding(n))throw new T(n)}else n=o.defaultEncoding;"function"!=typeof r&&(r=P)}if(null===t)throw new C;if(!o.objectMode)if("string"==typeof t)!1!==o.decodeStrings&&(t=g.from(t,n),n="buffer");else if(t instanceof g)n="buffer";else{if(!f._isUint8Array(t))throw new S("chunk",["string","Buffer","Uint8Array"],t);t=f._uint8ArrayToBuffer(t),n="buffer"}let s;return o.ending?s=new E:o.destroyed&&(s=new I("write")),s?(i.nextTick(r,s),O(e,s,!0),s):(o.pendingcb++,function(e,t,n,i,r){const o=t.objectMode?1:n.length;t.length+=o;const s=t.length<t.highWaterMark;s||(t.needDrain=!0);t.writing||t.corked||t.errored||!t.constructed?(t.buffered.push({chunk:n,encoding:i,callback:r}),t.allBuffers&&"buffer"!==i&&(t.allBuffers=!1),t.allNoop&&r!==P&&(t.allNoop=!1)):(t.writelen=o,t.writecb=r,t.writing=!0,t.sync=!0,e._write(n,i,t.onwrite),t.sync=!1);return s&&!t.errored&&!t.destroyed}(e,o,t,n,r))}function D(e,t,n,i,r,o,s){t.writelen=i,t.writecb=s,t.writing=!0,t.sync=!0,t.destroyed?t.onwrite(new I("write")):n?e._writev(r,t.onwrite):e._write(r,o,t.onwrite),t.sync=!1}function B(e,t,n,i){--t.pendingcb,i(n),U(t),O(e,n)}function j(e,t){const n=e._writableState,r=n.sync,o=n.writecb;"function"==typeof o?(n.writing=!1,n.writecb=null,n.length-=n.writelen,n.writelen=0,t?(t.stack,n.errored||(n.errored=t),e._readableState&&!e._readableState.errored&&(e._readableState.errored=t),r?i.nextTick(B,e,n,t,o):B(e,n,t,o)):(n.buffered.length>n.bufferedIndex&&z(e,n),r?null!==n.afterWriteTickInfo&&n.afterWriteTickInfo.cb===o?n.afterWriteTickInfo.count++:(n.afterWriteTickInfo={count:1,cb:o,stream:e,state:n},i.nextTick($,n.afterWriteTickInfo)):F(e,n,1,o))):O(e,new w)}function $({stream:e,state:t,count:n,cb:i}){return t.afterWriteTickInfo=null,F(e,t,n,i)}function F(e,t,n,i){for(!t.ending&&!e.destroyed&&0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"));n-- >0;)t.pendingcb--,i();t.destroyed&&U(t),H(e,t)}function U(e){if(e.writing)return;for(let n=e.bufferedIndex;n<e.buffered.length;++n){var t;const{chunk:i,callback:r}=e.buffered[n],o=e.objectMode?1:i.length;e.length-=o,r(null!==(t=e.errored)&&void 0!==t?t:new I("write"))}const n=e[A].splice(0);for(let t=0;t<n.length;t++){var i;n[t](null!==(i=e.errored)&&void 0!==i?i:new I("end"))}M(e)}function z(e,t){if(t.corked||t.bufferProcessing||t.destroyed||!t.constructed)return;const{buffered:n,bufferedIndex:i,objectMode:o}=t,s=n.length-i;if(!s)return;let a=i;if(t.bufferProcessing=!0,s>1&&e._writev){t.pendingcb-=s-1;const i=t.allNoop?P:e=>{for(let t=a;t<n.length;++t)n[t].callback(e)},o=t.allNoop&&0===a?n:r(n,a);o.allBuffers=t.allBuffers,D(e,t,!0,t.length,o,"",i),M(t)}else{do{const{chunk:i,encoding:r,callback:s}=n[a];n[a++]=null;D(e,t,!1,o?1:i.length,i,r,s)}while(a<n.length&&!t.writing);a===n.length?M(t):a>256?(n.splice(0,a),t.bufferedIndex=0):t.bufferedIndex=a}t.bufferProcessing=!1}function V(e){return e.ending&&!e.destroyed&&e.constructed&&0===e.length&&!e.errored&&0===e.buffered.length&&!e.finished&&!e.writing&&!e.errorEmitted&&!e.closeEmitted}function W(e,t){t.prefinished||t.finalCalled||("function"!=typeof e._final||t.destroyed?(t.prefinished=!0,e.emit("prefinish")):(t.finalCalled=!0,function(e,t){let n=!1;function r(r){if(n)O(e,null!=r?r:w());else if(n=!0,t.pendingcb--,r){const n=t[A].splice(0);for(let e=0;e<n.length;e++)n[e](r);O(e,r,t.sync)}else V(t)&&(t.prefinished=!0,e.emit("prefinish"),t.pendingcb++,i.nextTick(q,e,t))}t.sync=!0,t.pendingcb++;try{e._final(r)}catch(e){r(e)}t.sync=!1}(e,t)))}function H(e,t,n){V(t)&&(W(e,t),0===t.pendingcb&&(n?(t.pendingcb++,i.nextTick((e,t)=>{V(t)?q(e,t):t.pendingcb--},e,t)):V(t)&&(t.pendingcb++,q(e,t))))}function q(e,t){t.pendingcb--,t.finished=!0;const n=t[A].splice(0);for(let e=0;e<n.length;e++)n[e]();if(e.emit("finish"),t.autoDestroy){const t=e._readableState;(!t||t.autoDestroy&&(t.endEmitted||!1===t.readable))&&e.destroy()}}R.prototype.getBuffer=function(){return r(this.buffered,this.bufferedIndex)},a(R.prototype,"bufferedRequestCount",{__proto__:null,get(){return this.buffered.length-this.bufferedIndex}}),a(L,p,{__proto__:null,value:function(e){return!!s(this,e)||this===L&&(e&&e._writableState instanceof R)}}),L.prototype.pipe=function(){O(this,new k)},L.prototype.write=function(e,t,n){return!0===N(this,e,t,n)},L.prototype.cork=function(){this._writableState.corked++},L.prototype.uncork=function(){const e=this._writableState;e.corked&&(e.corked--,e.writing||z(this,e))},L.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=d(e)),!g.isEncoding(e))throw new T(e);return this._writableState.defaultEncoding=e,this},L.prototype._write=function(e,t,n){if(!this._writev)throw new _("_write()");this._writev([{chunk:e,encoding:t}],n)},L.prototype._writev=null,L.prototype.end=function(e,t,n){const r=this._writableState;let s;if("function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e){const n=N(this,e,t);n instanceof o&&(s=n)}return r.corked&&(r.corked=1,this.uncork()),s||(r.errored||r.ending?r.finished?s=new x("end"):r.destroyed&&(s=new I("end")):(r.ending=!0,H(this,r,!0),r.ended=!0)),"function"==typeof n&&(s||r.finished?i.nextTick(n,s):r[A].push(n)),this},c(L.prototype,{closed:{__proto__:null,get(){return!!this._writableState&&this._writableState.closed}},destroyed:{__proto__:null,get(){return!!this._writableState&&this._writableState.destroyed},set(e){this._writableState&&(this._writableState.destroyed=e)}},writable:{__proto__:null,get(){const e=this._writableState;return!(!e||!1===e.writable||e.destroyed||e.errored||e.ending||e.ended)},set(e){this._writableState&&(this._writableState.writable=!!e)}},writableFinished:{__proto__:null,get(){return!!this._writableState&&this._writableState.finished}},writableObjectMode:{__proto__:null,get(){return!!this._writableState&&this._writableState.objectMode}},writableBuffer:{__proto__:null,get(){return this._writableState&&this._writableState.getBuffer()}},writableEnded:{__proto__:null,get(){return!!this._writableState&&this._writableState.ending}},writableNeedDrain:{__proto__:null,get(){const e=this._writableState;return!!e&&(!e.destroyed&&!e.ending&&e.needDrain)}},writableHighWaterMark:{__proto__:null,get(){return this._writableState&&this._writableState.highWaterMark}},writableCorked:{__proto__:null,get(){return this._writableState?this._writableState.corked:0}},writableLength:{__proto__:null,get(){return this._writableState&&this._writableState.length}},errored:{__proto__:null,enumerable:!1,get(){return this._writableState?this._writableState.errored:null}},writableAborted:{__proto__:null,enumerable:!1,get:function(){return!(!1===this._writableState.writable||!this._writableState.destroyed&&!this._writableState.errored||this._writableState.finished)}}});const G=m.destroy;let K;function Z(){return void 0===K&&(K={}),K}L.prototype.destroy=function(e,t){const n=this._writableState;return!n.destroyed&&(n.bufferedIndex<n.buffered.length||n[A].length)&&i.nextTick(U,n),G.call(this,e,t),this},L.prototype._undestroy=m.undestroy,L.prototype._destroy=function(e,t){t(e)},L.prototype[h.captureRejectionSymbol]=function(e){this.destroy(e)},L.fromWeb=function(e,t){return Z().newStreamWritableFromWritableStream(e,t)},L.toWeb=function(e){return Z().newWritableStreamFromStreamWritable(e)}},8600(e,t,n){"use strict";n.r(t),n.d(t,{clearInterval:()=>S,clearTimeout:()=>_,setInterval:()=>w,setTimeout:()=>k});const i=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,r=536870912,o=1073741824,s=new WeakMap;var a;const c=((e,t)=>n=>{const s=t.get(n);let a=void 0===s?n.size:s<o?s+1:0;if(!n.has(a))return e(n,a);if(n.size<r){for(;n.has(a);)a=Math.floor(Math.random()*o);return e(n,a)}if(n.size>i)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;n.has(a);)a=Math.floor(Math.random()*i);return e(n,a)})((a=s,(e,t)=>(a.set(e,t),t)),s),l=((e=>{})(c),((e,t,n,i)=>r=>{const o=t(r);return t=>{const r=e(t);t.addEventListener("message",({data:e})=>{const{id:t}=e;if(null!==t&&r.has(t)){const{reject:n,resolve:i}=r.get(t);r.delete(t),void 0===e.error?i(e.result):n(new Error(e.error.message))}}),i(t)&&t.start();const s=(e,i=null,o=[])=>new Promise((s,a)=>{const c=n(r);r.set(c,{reject:a,resolve:s}),null===i?t.postMessage({id:c,method:e},o):t.postMessage({id:c,method:e,params:i},o)}),a=(e,n,i=[])=>{t.postMessage({id:null,method:e,params:n},i)};let c={};for(const[e,t]of Object.entries(o))c={...c,[e]:t({call:s,notify:a})};return{...c}}})((u=new WeakMap,e=>{if(u.has(e))return u.get(e);const t=new Map;return u.set(e,t),t}),(d=new WeakMap,e=>({...e,connect:({call:e})=>async()=>{const{port1:t,port2:n}=new MessageChannel,i=await e("connect",{port:t},[t]);return d.set(n,i),n},disconnect:({call:e})=>async t=>{const n=d.get(t);if(void 0===n)throw new Error("The given port is not connected.");await e("disconnect",{portId:n})},isSupported:({call:e})=>()=>e("isSupported")})),c,e=>"function"==typeof e.start));var d,u;const p=new Map([[0,null]]),h=new Map([[0,null]]),f=(e=>t=>n=>{"symbol"==typeof e.get(n)&&(e.set(n,null),t(n).then(()=>{e.delete(n)}))})(p),g=(e=>t=>n=>{"symbol"==typeof e.get(n)&&(e.set(n,null),t(n).then(()=>{e.delete(n)}))})(h),m=((e,t)=>n=>(i,r=0,...o)=>{const s=Symbol(),a=e(t);t.set(a,s);const c=()=>n(r,a).then(()=>{const e=t.get(a);if(void 0===e)throw new Error("The timer is in an undefined state.");e===s&&(i(...o),t.get(a)===s&&c())});return c(),a})(c,p),y=((e,t)=>n=>(i,r=0,...o)=>{const s=Symbol(),a=e(t);return t.set(a,s),n(r,a).then(()=>{const e=t.get(a);if(void 0===e)throw new Error("The timer is in an undefined state.");e===s&&(t.delete(a),i(...o))}),a})(c,h),b=l({clearInterval:({call:e})=>f(t=>e("clear",{timerId:t,timerType:"interval"})),clearTimeout:({call:e})=>g(t=>e("clear",{timerId:t,timerType:"timeout"})),setInterval:({call:e})=>m((t,n)=>e("set",{delay:t,now:performance.timeOrigin+performance.now(),timerId:n,timerType:"interval"})),setTimeout:({call:e})=>y((t,n)=>e("set",{delay:t,now:performance.timeOrigin+performance.now(),timerId:n,timerType:"timeout"}))}),v=((e,t)=>{let n=null;return()=>{if(null!==n)return n;const i=new Blob([t],{type:"application/javascript; charset=utf-8"}),r=URL.createObjectURL(i);return n=e(r),setTimeout(()=>URL.revokeObjectURL(r)),n}})(e=>{const t=new Worker(e);return b(t)},'(()=>{var e={455(e,t){!function(e){"use strict";var t=function(e){return function(t){var r=e(t);return t.add(r),r}},r=function(e){return function(t,r){return e.set(t,r),r}},n=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,o=536870912,s=2*o,a=function(e,t){return function(r){var a=t.get(r),i=void 0===a?r.size:a<s?a+1:0;if(!r.has(i))return e(r,i);if(r.size<o){for(;r.has(i);)i=Math.floor(Math.random()*s);return e(r,i)}if(r.size>n)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;r.has(i);)i=Math.floor(Math.random()*n);return e(r,i)}},i=new WeakMap,u=r(i),c=a(u,i),l=t(c);e.addUniqueNumber=l,e.generateUniqueNumber=c}(t)}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var s=t[n]={exports:{}};return e[n].call(s.exports,s,s.exports,r),s.exports}(()=>{"use strict";const e=-32603,t=-32602,n=-32601,o=(e,t)=>Object.assign(new Error(e),{status:t}),s=t=>o(\'The handler of the method called "\'.concat(t,\'" returned an unexpected result.\'),e),a=(t,r)=>async({data:{id:a,method:i,params:u}})=>{const c=r[i];try{if(void 0===c)throw(e=>o(\'The requested method called "\'.concat(e,\'" is not supported.\'),n))(i);const r=void 0===u?c():c(u);if(void 0===r)throw(t=>o(\'The handler of the method called "\'.concat(t,\'" returned no required result.\'),e))(i);const l=r instanceof Promise?await r:r;if(null===a){if(void 0!==l.result)throw s(i)}else{if(void 0===l.result)throw s(i);const{result:e,transferables:r=[]}=l;t.postMessage({id:a,result:e},r)}}catch(e){const{message:r,status:n=-32603}=e;t.postMessage({error:{code:n,message:r},id:a})}};var i=r(455);const u=new Map,c=(e,r,n)=>({...r,connect:({port:t})=>{t.start();const n=e(t,r),o=(0,i.generateUniqueNumber)(u);return u.set(o,()=>{n(),t.close(),u.delete(o)}),{result:o}},disconnect:({portId:e})=>{const r=u.get(e);if(void 0===r)throw(e=>o(\'The specified parameter called "portId" with the given value "\'.concat(e,\'" does not identify a port connected to this worker.\'),t))(e);return r(),{result:null}},isSupported:async()=>{if(await new Promise(e=>{const t=new ArrayBuffer(0),{port1:r,port2:n}=new MessageChannel;r.onmessage=({data:t})=>e(null!==t),n.postMessage(t,[t])})){const e=n();return{result:e instanceof Promise?await e:e}}return{result:!1}}}),l=(e,t,r=()=>!0)=>{const n=c(l,t,r),o=a(e,n);return e.addEventListener("message",o),()=>e.removeEventListener("message",o)},d=(e,t)=>r=>{const n=t.get(r);if(void 0===n)return Promise.resolve(!1);const[o,s]=n;return e(o),t.delete(r),s(!1),Promise.resolve(!0)},m=(e,t,r,n)=>(o,s,a)=>{const i=o+s-t.timeOrigin,u=i-t.now();return new Promise(t=>{e.set(a,[r(n,u,i,e,t,a),t])})},f=new Map,h=d(globalThis.clearTimeout,f),p=new Map,v=d(globalThis.clearTimeout,p),w=((e,t)=>{const r=(n,o,s,a)=>{const i=n-e.now();i>0?o.set(a,[t(r,i,n,o,s,a),s]):(o.delete(a),s(!0))};return r})(performance,globalThis.setTimeout),g=m(f,performance,globalThis.setTimeout,w),T=m(p,performance,globalThis.setTimeout,w);l(self,{clear:async({timerId:e,timerType:t})=>({result:await("interval"===t?h(e):v(e))}),set:async({delay:e,now:t,timerId:r,timerType:n})=>({result:await("interval"===n?g:T)(e,t,r)})})})()})();'),S=e=>v().clearInterval(e),_=e=>v().clearTimeout(e),w=(...e)=>v().setInterval(...e),k=(...e)=>v().setTimeout(...e)},8611(e){"use strict";e.exports=require("http")},8914(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RE_URL_WITH_PORT=t.RE_URL=t.RE_ZONE_STRING=t.RE_SUBNET_STRING=t.RE_BAD_ADDRESS=t.RE_BAD_CHARACTERS=t.TYPES=t.SCOPES=t.GROUPS=t.BITS=void 0,t.BITS=128,t.GROUPS=8,t.SCOPES={0:"Reserved",1:"Interface local",2:"Link local",4:"Admin local",5:"Site local",8:"Organization local",14:"Global",15:"Reserved"},t.TYPES={"ff01::1/128":"Multicast (All nodes on this interface)","ff01::2/128":"Multicast (All routers on this interface)","ff02::1/128":"Multicast (All nodes on this link)","ff02::2/128":"Multicast (All routers on this link)","ff05::2/128":"Multicast (All routers in this site)","ff02::5/128":"Multicast (OSPFv3 AllSPF routers)","ff02::6/128":"Multicast (OSPFv3 AllDR routers)","ff02::9/128":"Multicast (RIP routers)","ff02::a/128":"Multicast (EIGRP routers)","ff02::d/128":"Multicast (PIM routers)","ff02::16/128":"Multicast (MLDv2 reports)","ff01::fb/128":"Multicast (mDNSv6)","ff02::fb/128":"Multicast (mDNSv6)","ff05::fb/128":"Multicast (mDNSv6)","ff02::1:2/128":"Multicast (All DHCP servers and relay agents on this link)","ff05::1:2/128":"Multicast (All DHCP servers and relay agents in this site)","ff02::1:3/128":"Multicast (All DHCP servers on this link)","ff05::1:3/128":"Multicast (All DHCP servers in this site)","::/128":"Unspecified","::1/128":"Loopback","ff00::/8":"Multicast","fe80::/10":"Link-local unicast"},t.RE_BAD_CHARACTERS=/([^0-9a-f:/%])/gi,t.RE_BAD_ADDRESS=/([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi,t.RE_SUBNET_STRING=/\/\d{1,3}(?=%|$)/,t.RE_ZONE_STRING=/%.*$/,t.RE_URL=/^\[{0,1}([0-9a-f:]+)\]{0,1}/,t.RE_URL_WITH_PORT=/\[([0-9a-f:]+)\]:([0-9]{1,5})/},9023(e){"use strict";e.exports=require("util")},9231(e){"use strict";e.exports={format:(e,...t)=>e.replace(/%([sdifj])/g,function(...[e,n]){const i=t.shift();if("f"===n)return i.toFixed(6);if("j"===n)return JSON.stringify(i);if("s"===n&&"object"==typeof i){return`${i.constructor!==Object?i.constructor.name:""} {}`.trim()}return i.toString()}),inspect(e){switch(typeof e){case"string":if(e.includes("'")){if(!e.includes('"'))return`"${e}"`;if(!e.includes("`")&&!e.includes("${"))return`\`${e}\``}return`'${e}'`;case"number":return isNaN(e)?"NaN":Object.is(e,-0)?String(e):e;case"bigint":return`${String(e)}n`;case"boolean":case"undefined":return String(e);case"object":return"{}"}}}},9278(e){"use strict";e.exports=require("net")},9291(e,t,n){"use strict";const i=n(8194).CD,r=n(5753)("number-allocator:trace"),o=n(5753)("number-allocator:error");function s(e,t){this.low=e,this.high=t}function a(e,t){if(!(this instanceof a))return new a(e,t);this.min=e,this.max=t,this.ss=new i([],(e,t)=>e.compare(t)),r("Create"),this.clear()}s.prototype.equals=function(e){return this.low===e.low&&this.high===e.high},s.prototype.compare=function(e){return this.low<e.low&&this.high<e.low?-1:e.low<this.low&&e.high<this.low?1:0},a.prototype.firstVacant=function(){return 0===this.ss.size()?null:this.ss.front().low},a.prototype.alloc=function(){if(0===this.ss.size())return r("alloc():empty"),null;const e=this.ss.begin(),t=e.pointer.low,n=e.pointer.high,i=t;return i+1<=n?this.ss.updateKeyByIterator(e,new s(t+1,n)):this.ss.eraseElementByPos(0),r("alloc():"+i),i},a.prototype.use=function(e){const t=new s(e,e),n=this.ss.lowerBound(t);if(!n.equals(this.ss.end())){const i=n.pointer.low,o=n.pointer.high;return n.pointer.equals(t)?(this.ss.eraseElementByIterator(n),r("use():"+e),!0):!(i>e)&&(i===e?(this.ss.updateKeyByIterator(n,new s(i+1,o)),r("use():"+e),!0):o===e?(this.ss.updateKeyByIterator(n,new s(i,o-1)),r("use():"+e),!0):(this.ss.updateKeyByIterator(n,new s(e+1,o)),this.ss.insert(new s(i,e-1)),r("use():"+e),!0))}return r("use():failed"),!1},a.prototype.free=function(e){if(e<this.min||e>this.max)return void o("free():"+e+" is out of range");const t=new s(e,e),n=this.ss.upperBound(t);if(n.equals(this.ss.end())){if(n.equals(this.ss.begin()))return void this.ss.insert(t);n.pre();const i=n.pointer.high;n.pointer.high+1===e?this.ss.updateKeyByIterator(n,new s(i,e)):this.ss.insert(t)}else if(n.equals(this.ss.begin()))if(e+1===n.pointer.low){const t=n.pointer.high;this.ss.updateKeyByIterator(n,new s(e,t))}else this.ss.insert(t);else{const i=n.pointer.low,r=n.pointer.high;n.pre();const o=n.pointer.low;n.pointer.high+1===e?e+1===i?(this.ss.eraseElementByIterator(n),this.ss.updateKeyByIterator(n,new s(o,r))):this.ss.updateKeyByIterator(n,new s(o,e)):e+1===i?(this.ss.eraseElementByIterator(n.next()),this.ss.insert(new s(e,r))):this.ss.insert(t)}r("free():"+e)},a.prototype.clear=function(){r("clear()"),this.ss.clear(),this.ss.insert(new s(this.min,this.max))},a.prototype.intervalCount=function(){return this.ss.size()},a.prototype.dump=function(){console.log("length:"+this.ss.size());for(const e of this.ss)console.log(e)},e.exports=a},9372(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0});const c=s(n(1676));t.default=c,a(n(1676),t)},9424(e,t,n){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),r=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&i(t,e,n);return r(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.v6=t.AddressError=t.Address6=t.Address4=void 0;var s=n(2839);Object.defineProperty(t,"Address4",{enumerable:!0,get:function(){return s.Address4}});var a=n(6329);Object.defineProperty(t,"Address6",{enumerable:!0,get:function(){return a.Address6}});var c=n(2437);Object.defineProperty(t,"AddressError",{enumerable:!0,get:function(){return c.AddressError}});const l=o(n(465));t.v6={helpers:l}},9576(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RE_SUBNET_STRING=t.RE_ADDRESS=t.GROUPS=t.BITS=void 0,t.BITS=32,t.GROUPS=4,t.RE_ADDRESS=/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g,t.RE_SUBNET_STRING=/\/\d{1,2}$/},9777(e,t,n){"use strict";var i,r=this&&this.__createBinding||(Object.create?function(e,t,n,i){void 0===i&&(i=n);var r=Object.getOwnPropertyDescriptor(t,n);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,i,r)}:function(e,t,n,i){void 0===i&&(i=n),e[i]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||(i=function(e){return i=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},i(e)},function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=i(e),s=0;s<n.length;s++)"default"!==n[s]&&r(t,e,n[s]);return o(t,e),t}),a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const c=a(n(1278)),l=n(4478),d=a(n(3885)),u=a(n(5753)),p=s(n(128)),h=a(n(7969)),f=a(n(6912)),g=a(n(579)),m=a(n(2639)),y=n(4723),b=n(4152),v=a(n(3175)),S=s(n(6887)),_=globalThis.setImmediate||((...e)=>{const t=e.shift();(0,y.nextTick)(()=>{t(...e)})}),w={keepalive:60,reschedulePings:!0,protocolId:"MQTT",protocolVersion:4,reconnectPeriod:1e3,connectTimeout:3e4,clean:!0,resubscribe:!0,subscribeBatchSize:null,writeCache:!0,timerVariant:"auto"};class k extends b.TypedEventEmitter{static VERSION=y.MQTTJS_VERSION;connected;disconnecting;disconnected;reconnecting;incomingStore;outgoingStore;options;queueQoSZero;_reconnectCount;log;messageIdProvider;outgoing;messageIdToTopic;noop;keepaliveManager;stream;queue;streamBuilder;_resubscribeTopics;connackTimer;reconnectTimer;_storeProcessing;_packetIdsDuringStoreProcessing;_storeProcessingQueue;_firstConnection;topicAliasRecv;topicAliasSend;_deferredReconnect;connackPacket;static defaultId(){return`mqttjs_${Math.random().toString(16).substr(2,8)}`}constructor(e,t){super(),this.options=t||{};for(const e in w)"undefined"==typeof this.options[e]?this.options[e]=w[e]:this.options[e]=t[e];this.log=this.options.log||(0,u.default)("mqttjs:client"),this.noop=this._noop.bind(this),this.log("MqttClient :: version:",k.VERSION),S.isWebWorker?this.log("MqttClient :: environment","webworker"):this.log("MqttClient :: environment",S.default?"browser":"node"),this.log("MqttClient :: options.protocol",t.protocol),this.log("MqttClient :: options.protocolVersion",t.protocolVersion),this.log("MqttClient :: options.username",t.username),this.log("MqttClient :: options.keepalive",t.keepalive),this.log("MqttClient :: options.reconnectPeriod",t.reconnectPeriod),this.log("MqttClient :: options.rejectUnauthorized",t.rejectUnauthorized),this.log("MqttClient :: options.properties.topicAliasMaximum",t.properties?t.properties.topicAliasMaximum:void 0),this.options.clientId="string"==typeof t.clientId?t.clientId:k.defaultId(),this.log("MqttClient :: clientId",this.options.clientId),this.options.customHandleAcks=5===t.protocolVersion&&t.customHandleAcks?t.customHandleAcks:(...e)=>{e[3](null,0)},this.options.writeCache||(c.default.writeToStream.cacheNumbers=!1),this.streamBuilder=e,this.messageIdProvider="undefined"==typeof this.options.messageIdProvider?new g.default:this.options.messageIdProvider,this.outgoingStore=t.outgoingStore||new h.default,this.incomingStore=t.incomingStore||new h.default,this.queueQoSZero=void 0===t.queueQoSZero||t.queueQoSZero,this._resubscribeTopics={},this.messageIdToTopic={},this.keepaliveManager=null,this.connected=!1,this.disconnecting=!1,this.reconnecting=!1,this.queue=[],this.connackTimer=null,this.reconnectTimer=null,this._storeProcessing=!1,this._packetIdsDuringStoreProcessing={},this._storeProcessingQueue=[],this.outgoing={},this._firstConnection=!0,t.properties&&t.properties.topicAliasMaximum>0&&(t.properties.topicAliasMaximum>65535?this.log("MqttClient :: options.properties.topicAliasMaximum is out of range"):this.topicAliasRecv=new m.default(t.properties.topicAliasMaximum)),this.on("connect",()=>{const{queue:e}=this,t=()=>{const n=e.shift();this.log("deliver :: entry %o",n);let i=null;if(!n)return void this._resubscribe();i=n.packet,this.log("deliver :: call _sendPacket for %o",i);let r=!0;i.messageId&&0!==i.messageId&&(this.messageIdProvider.register(i.messageId)||(r=!1)),r?this._sendPacket(i,e=>{n.cb&&n.cb(e),t()}):(this.log("messageId: %d has already used. The message is skipped and removed.",i.messageId),t())};this.log("connect :: sending queued packets"),t()}),this.on("close",()=>{this.log("close :: connected set to `false`"),this.connected=!1,this.log("close :: clearing connackTimer"),clearTimeout(this.connackTimer),this._destroyKeepaliveManager(),this.topicAliasRecv&&this.topicAliasRecv.clear(),this.log("close :: calling _setupReconnect"),this._setupReconnect()}),this.options.manualConnect||(this.log("MqttClient :: setting up stream"),this.connect())}handleAuth(e,t){t()}handleMessage(e,t){t()}_nextId(){return this.messageIdProvider.allocate()}getLastMessageId(){return this.messageIdProvider.getLastAllocated()}connect(){const e=new l.Writable,t=c.default.parser(this.options);let n=null;const i=[];this.log("connect :: calling method to clear reconnect"),this._clearReconnect(),this.disconnected&&!this.reconnecting&&(this.incomingStore=this.options.incomingStore||new h.default,this.outgoingStore=this.options.outgoingStore||new h.default,this.disconnecting=!1,this.disconnected=!1),this.log("connect :: using streamBuilder provided to client to create stream"),this.stream=this.streamBuilder(this),t.on("packet",e=>{this.log("parser :: on packet push to packets array."),i.push(e)});const r=()=>{this.log("work :: getting next packet in queue");const e=i.shift();if(e)this.log("work :: packet pulled from queue"),(0,f.default)(this,e,o);else{this.log("work :: no packets in queue");const e=n;n=null,this.log("work :: done flag is %s",!!e),e&&e()}},o=()=>{if(i.length)(0,y.nextTick)(r);else{const e=n;n=null,e()}};e._write=(e,i,o)=>{n=o,this.log("writable stream :: parsing buffer"),t.parse(e),r()};this.log("connect :: pipe stream to writable stream"),this.stream.pipe(e),this.stream.on("error",e=>{this.log("streamErrorHandler :: error",e.message),e.code?(this.log("streamErrorHandler :: emitting error"),this.emit("error",e)):this.noop(e)}),this.stream.on("close",()=>{this.log("(%s)stream :: on close",this.options.clientId),this._flushVolatile(),this.log("stream: emit close to MqttClient"),this.emit("close")}),this.log("connect: sending packet `connect`");const s={cmd:"connect",protocolId:this.options.protocolId,protocolVersion:this.options.protocolVersion,clean:this.options.clean,clientId:this.options.clientId,keepalive:this.options.keepalive,username:this.options.username,password:this.options.password,properties:this.options.properties};if(this.options.will&&(s.will={...this.options.will,payload:this.options.will?.payload}),this.topicAliasRecv&&(s.properties||(s.properties={}),this.topicAliasRecv&&(s.properties.topicAliasMaximum=this.topicAliasRecv.max)),this._writePacket(s),t.on("error",this.emit.bind(this,"error")),this.options.properties){if(!this.options.properties.authenticationMethod&&this.options.properties.authenticationData)return this.end(()=>this.emit("error",new Error("Packet has no Authentication Method"))),this;if(this.options.properties.authenticationMethod&&this.options.authPacket&&"object"==typeof this.options.authPacket){const e={cmd:"auth",reasonCode:0,...this.options.authPacket};this._writePacket(e)}}return this.stream.setMaxListeners(1e3),clearTimeout(this.connackTimer),this.connackTimer=setTimeout(()=>{this.log("!!connectTimeout hit!! Calling _cleanUp with force `true`"),this.emit("error",new Error("connack timeout")),this._cleanUp(!0)},this.options.connectTimeout),this}publish(e,t,n,i){this.log("publish :: message `%s` to topic `%s`",t,e);const{options:r}=this;"function"==typeof n&&(i=n,n=null),n=n||{};n={qos:0,retain:!1,dup:!1,...n};const{qos:o,retain:s,dup:a,properties:c,cbStorePut:l}=n;if(this._checkDisconnecting(i))return this;const d=()=>{let n=0;if((1===o||2===o)&&(n=this._nextId(),null===n))return this.log("No messageId left"),!1;const d={cmd:"publish",topic:e,payload:t,qos:o,retain:s,messageId:n,dup:a};switch(5===r.protocolVersion&&(d.properties=c),this.log("publish :: qos",o),o){case 1:case 2:this.outgoing[d.messageId]={volatile:!1,cb:i||this.noop},this.log("MqttClient:publish: packet cmd: %s",d.cmd),this._sendPacket(d,void 0,l);break;default:this.log("MqttClient:publish: packet cmd: %s",d.cmd),this._sendPacket(d,i,l)}return!0};return(this._storeProcessing||this._storeProcessingQueue.length>0||!d())&&this._storeProcessingQueue.push({invoke:d,cbStorePut:n.cbStorePut,callback:i}),this}publishAsync(e,t,n){return new Promise((i,r)=>{this.publish(e,t,n,(e,t)=>{e?r(e):i(t)})})}subscribe(e,t,n){const i=this.options.protocolVersion;"function"==typeof t&&(n=t),n=n||this.noop;let r=!1,o=[];"string"==typeof e?o=e=[e]:Array.isArray(e)?o=e:"object"==typeof e&&(r=e.resubscribe,delete e.resubscribe,o=Object.keys(e));const s=p.validateTopics(o);if(null!==s)return _(n,new Error(`Invalid topic ${s}`)),this;if(this._checkDisconnecting(n))return this.log("subscribe: discconecting true"),this;const a={qos:0};5===i&&(a.nl=!1,a.rap=!1,a.rh=0),t={...a,...t};const{properties:c}=t,l=[],d=(e,n)=>{if(n=n||t,!Object.prototype.hasOwnProperty.call(this._resubscribeTopics,e)||this._resubscribeTopics[e].qos<n.qos||r){const t={topic:e,qos:n.qos};5===i&&(t.nl=n.nl,t.rap=n.rap,t.rh=n.rh,t.properties=c),this.log("subscribe: pushing topic `%s` and qos `%s` to subs list",t.topic,t.qos),l.push(t)}};if(Array.isArray(e)?e.forEach(e=>{this.log("subscribe: array topic %s",e),d(e)}):Object.keys(e).forEach(t=>{this.log("subscribe: object topic %s, %o",t,e[t]),d(t,e[t])}),!l.length)return n(null,[]),this;const u=(e,t)=>{const n={cmd:"subscribe",subscriptions:e,messageId:t};if(c&&(n.properties=c),this.options.resubscribe){this.log("subscribe :: resubscribe true");const t=[];e.forEach(e=>{if(this.options.reconnectPeriod>0){const n={qos:e.qos};5===i&&(n.nl=e.nl||!1,n.rap=e.rap||!1,n.rh=e.rh||0,n.properties=e.properties),this._resubscribeTopics[e.topic]=n,t.push(e.topic)}}),this.messageIdToTopic[n.messageId]=t}const r=new Promise((t,i)=>{this.outgoing[n.messageId]={volatile:!0,cb(n,r){if(!n){const{granted:t}=r;for(let n=0;n<t.length;n+=1)e[n].qos=t[n]}n?i(new y.ErrorWithSubackPacket(n.message,r)):t(r)}}});return this.log("subscribe :: call _sendPacket"),this._sendPacket(n),r},h=()=>{const e=this.options.subscribeBatchSize??l.length,t=[];for(let n=0;n<l.length;n+=e){const i=l.slice(n,n+e),r=this._nextId();if(null===r)return this.log("No messageId left"),!1;t.push(u(i,r))}return Promise.all(t).then(e=>{n(null,l,e.at(-1))}).catch(e=>{n(e,l,e.packet)}),!0};return(this._storeProcessing||this._storeProcessingQueue.length>0||!h())&&this._storeProcessingQueue.push({invoke:h,callback:n}),this}subscribeAsync(e,t){return new Promise((n,i)=>{this.subscribe(e,t,(e,t)=>{e?i(e):n(t)})})}unsubscribe(e,t,n){"string"==typeof e&&(e=[e]),"function"==typeof t&&(n=t),n=n||this.noop;const i=p.validateTopics(e);if(null!==i)return _(n,new Error(`Invalid topic ${i}`)),this;if(this._checkDisconnecting(n))return this;const r=()=>{const i=this._nextId();if(null===i)return this.log("No messageId left"),!1;const r={cmd:"unsubscribe",messageId:i,unsubscriptions:[]};return"string"==typeof e?r.unsubscriptions=[e]:Array.isArray(e)&&(r.unsubscriptions=e),this.options.resubscribe&&r.unsubscriptions.forEach(e=>{delete this._resubscribeTopics[e]}),"object"==typeof t&&t.properties&&(r.properties=t.properties),this.outgoing[r.messageId]={volatile:!0,cb:n},this.log("unsubscribe: call _sendPacket"),this._sendPacket(r),!0};return(this._storeProcessing||this._storeProcessingQueue.length>0||!r())&&this._storeProcessingQueue.push({invoke:r,callback:n}),this}unsubscribeAsync(e,t){return new Promise((n,i)=>{this.unsubscribe(e,t,(e,t)=>{e?i(e):n(t)})})}end(e,t,n){this.log("end :: (%s)",this.options.clientId),null!=e&&"boolean"==typeof e||(n=n||t,t=e,e=!1),"object"!=typeof t&&(n=n||t,t=null),this.log("end :: cb? %s",!!n),n&&"function"==typeof n||(n=this.noop);const i=()=>{this.log("end :: closeStores: closing incoming and outgoing stores"),this.disconnected=!0,this.incomingStore.close(e=>{this.outgoingStore.close(t=>{if(this.log("end :: closeStores: emitting end"),this.emit("end"),n){const i=e||t;this.log("end :: closeStores: invoking callback with args"),n(i)}})}),this._deferredReconnect?this._deferredReconnect():(0===this.options.reconnectPeriod||this.options.manualConnect)&&(this.disconnecting=!1)},r=()=>{this.log("end :: (%s) :: finish :: calling _cleanUp with force %s",this.options.clientId,e),this._cleanUp(e,()=>{this.log("end :: finish :: calling process.nextTick on closeStores"),(0,y.nextTick)(i)},t)};return this.disconnecting?(n(),this):(this._clearReconnect(),this.disconnecting=!0,!e&&Object.keys(this.outgoing).length>0?(this.log("end :: (%s) :: calling finish in 10ms once outgoing is empty",this.options.clientId),this.once("outgoingEmpty",setTimeout.bind(null,r,10))):(this.log("end :: (%s) :: immediately calling finish",this.options.clientId),r()),this)}endAsync(e,t){return new Promise((n,i)=>{this.end(e,t,e=>{e?i(e):n()})})}removeOutgoingMessage(e){if(this.outgoing[e]){const{cb:t}=this.outgoing[e];this._removeOutgoingAndStoreMessage(e,()=>{t(new Error("Message removed"))})}return this}reconnect(e){this.log("client reconnect");const t=()=>{e?(this.options.incomingStore=e.incomingStore,this.options.outgoingStore=e.outgoingStore):(this.options.incomingStore=null,this.options.outgoingStore=null),this.incomingStore=this.options.incomingStore||new h.default,this.outgoingStore=this.options.outgoingStore||new h.default,this.disconnecting=!1,this.disconnected=!1,this._deferredReconnect=null,this._reconnect()};return this.disconnecting&&!this.disconnected?this._deferredReconnect=t:t(),this}_flushVolatile(){this.outgoing&&(this.log("_flushVolatile :: deleting volatile messages from the queue and setting their callbacks as error function"),Object.keys(this.outgoing).forEach(e=>{this.outgoing[e].volatile&&"function"==typeof this.outgoing[e].cb&&(this.outgoing[e].cb(new Error("Connection closed")),delete this.outgoing[e])}))}_flush(){this.outgoing&&(this.log("_flush: queue exists? %b",!!this.outgoing),Object.keys(this.outgoing).forEach(e=>{"function"==typeof this.outgoing[e].cb&&(this.outgoing[e].cb(new Error("Connection closed")),delete this.outgoing[e])}))}_removeTopicAliasAndRecoverTopicName(e){let t;e.properties&&(t=e.properties.topicAlias);let n=e.topic.toString();if(this.log("_removeTopicAliasAndRecoverTopicName :: alias %d, topic %o",t,n),0===n.length){if("undefined"==typeof t)return new Error("Unregistered Topic Alias");if(n=this.topicAliasSend.getTopicByAlias(t),"undefined"==typeof n)return new Error("Unregistered Topic Alias");e.topic=n}t&&delete e.properties.topicAlias}_checkDisconnecting(e){return this.disconnecting&&(e&&e!==this.noop?e(new Error("client disconnecting")):this.emit("error",new Error("client disconnecting"))),this.disconnecting}_reconnect(){this.log("_reconnect: emitting reconnect to client"),this.emit("reconnect"),this.connected?(this.end(()=>{this.connect()}),this.log("client already connected. disconnecting first.")):(this.log("_reconnect: calling connect"),this.connect())}_setupReconnect(){!this.disconnecting&&!this.reconnectTimer&&this.options.reconnectPeriod>0?(this.reconnecting||(this.log("_setupReconnect :: emit `offline` state"),this.emit("offline"),this.log("_setupReconnect :: set `reconnecting` to `true`"),this.reconnecting=!0),this.log("_setupReconnect :: setting reconnectTimer for %d ms",this.options.reconnectPeriod),this.reconnectTimer=setInterval(()=>{this.log("reconnectTimer :: reconnect triggered!"),this._reconnect()},this.options.reconnectPeriod)):this.log("_setupReconnect :: doing nothing...")}_clearReconnect(){this.log("_clearReconnect : clearing reconnect timer"),this.reconnectTimer&&(clearInterval(this.reconnectTimer),this.reconnectTimer=null)}_cleanUp(e,t,n={}){if(t&&(this.log("_cleanUp :: done callback provided for on stream close"),this.stream.on("close",t)),this.log("_cleanUp :: forced? %s",e),e)0===this.options.reconnectPeriod&&this.options.clean&&this._flush(),this.log("_cleanUp :: (%s) :: destroying stream",this.options.clientId),this.stream.destroy();else{const e={cmd:"disconnect",...n};this.log("_cleanUp :: (%s) :: call _sendPacket with disconnect packet",this.options.clientId),this._sendPacket(e,()=>{this.log("_cleanUp :: (%s) :: destroying stream",this.options.clientId),_(()=>{this.stream.end(()=>{this.log("_cleanUp :: (%s) :: stream destroyed",this.options.clientId)})})})}this.disconnecting||this.reconnecting||(this.log("_cleanUp :: client not disconnecting/reconnecting. Clearing and resetting reconnect."),this._clearReconnect(),this._setupReconnect()),this._destroyKeepaliveManager(),t&&!this.connected&&(this.log("_cleanUp :: (%s) :: removing stream `done` callback `close` listener",this.options.clientId),this.stream.removeListener("close",t),t())}_storeAndSend(e,t,n){this.log("storeAndSend :: store packet with cmd %s to outgoingStore",e.cmd);let i,r=e;if("publish"===r.cmd&&(r=(0,d.default)(e),i=this._removeTopicAliasAndRecoverTopicName(r),i))return t&&t(i);this.outgoingStore.put(r,i=>{if(i)return t&&t(i);n(),this._writePacket(e,t)})}_applyTopicAlias(e){if(5===this.options.protocolVersion&&"publish"===e.cmd){let t;e.properties&&(t=e.properties.topicAlias);const n=e.topic.toString();if(this.topicAliasSend)if(t){if(0!==n.length&&(this.log("applyTopicAlias :: register topic: %s - alias: %d",n,t),!this.topicAliasSend.put(n,t)))return this.log("applyTopicAlias :: error out of range. topic: %s - alias: %d",n,t),new Error("Sending Topic Alias out of range")}else 0!==n.length&&(this.options.autoAssignTopicAlias?(t=this.topicAliasSend.getAliasByTopic(n),t?(e.topic="",e.properties={...e.properties,topicAlias:t},this.log("applyTopicAlias :: auto assign(use) topic: %s - alias: %d",n,t)):(t=this.topicAliasSend.getLruAlias(),this.topicAliasSend.put(n,t),e.properties={...e.properties,topicAlias:t},this.log("applyTopicAlias :: auto assign topic: %s - alias: %d",n,t))):this.options.autoUseTopicAlias&&(t=this.topicAliasSend.getAliasByTopic(n),t&&(e.topic="",e.properties={...e.properties,topicAlias:t},this.log("applyTopicAlias :: auto use topic: %s - alias: %d",n,t))));else if(t)return this.log("applyTopicAlias :: error out of range. topic: %s - alias: %d",n,t),new Error("Sending Topic Alias out of range")}}_noop(e){this.log("noop ::",e)}_writePacket(e,t){this.log("_writePacket :: packet: %O",e),this.log("_writePacket :: emitting `packetsend`"),this.emit("packetsend",e),this.log("_writePacket :: writing to stream");const n=c.default.writeToStream(e,this.stream,this.options);this.log("_writePacket :: writeToStream result %s",n),!n&&t&&t!==this.noop?(this.log("_writePacket :: handle events on `drain` once through callback."),this.stream.once("drain",t)):t&&(this.log("_writePacket :: invoking cb"),t())}_sendPacket(e,t,n,i){this.log("_sendPacket :: (%s) :: start",this.options.clientId),n=n||this.noop,t=t||this.noop;const r=this._applyTopicAlias(e);if(r)t(r);else{if(!this.connected)return"auth"===e.cmd?void this._writePacket(e,t):(this.log("_sendPacket :: client not connected. Storing packet offline."),void this._storePacket(e,t,n));if(i)this._writePacket(e,t);else{switch(e.cmd){case"publish":break;case"pubrel":return void this._storeAndSend(e,t,n);default:return void this._writePacket(e,t)}switch(e.qos){case 2:case 1:this._storeAndSend(e,t,n);break;default:this._writePacket(e,t)}this.log("_sendPacket :: (%s) :: end",this.options.clientId)}}}_storePacket(e,t,n){this.log("_storePacket :: packet: %o",e),this.log("_storePacket :: cb? %s",!!t),n=n||this.noop;let i=e;if("publish"===i.cmd){i=(0,d.default)(e);const n=this._removeTopicAliasAndRecoverTopicName(i);if(n)return t&&t(n)}const r=i.qos||0;0===r&&this.queueQoSZero||"publish"!==i.cmd?this.queue.push({packet:i,cb:t}):r>0?(t=this.outgoing[i.messageId]?this.outgoing[i.messageId].cb:null,this.outgoingStore.put(i,e=>{if(e)return t&&t(e);n()})):t&&t(new Error("No connection to broker"))}_setupKeepaliveManager(){this.log("_setupKeepaliveManager :: keepalive %d (seconds)",this.options.keepalive),!this.keepaliveManager&&this.options.keepalive&&(this.keepaliveManager=new v.default(this,this.options.timerVariant))}_destroyKeepaliveManager(){this.keepaliveManager&&(this.log("_destroyKeepaliveManager :: destroying keepalive manager"),this.keepaliveManager.destroy(),this.keepaliveManager=null)}reschedulePing(e=!1){this.keepaliveManager&&this.options.keepalive&&(e||this.options.reschedulePings)&&this._reschedulePing()}_reschedulePing(){this.log("_reschedulePing :: rescheduling ping"),this.keepaliveManager.reschedule()}sendPing(){this.log("_sendPing :: sending pingreq"),this._sendPacket({cmd:"pingreq"})}onKeepaliveTimeout(){this.emit("error",new Error("Keepalive timeout")),this.log("onKeepaliveTimeout :: calling _cleanUp with force true"),this._cleanUp(!0)}_resubscribe(){this.log("_resubscribe");const e=Object.keys(this._resubscribeTopics);if(!this._firstConnection&&(this.options.clean||this.options.protocolVersion>=4&&!this.connackPacket.sessionPresent)&&e.length>0)if(this.options.resubscribe)if(5===this.options.protocolVersion){this.log("_resubscribe: protocolVersion 5");for(let t=0;t<e.length;t++){const n={};n[e[t]]=this._resubscribeTopics[e[t]],n.resubscribe=!0,this.subscribe(n,{properties:n[e[t]].properties})}}else this._resubscribeTopics.resubscribe=!0,this.subscribe(this._resubscribeTopics);else this._resubscribeTopics={};this._firstConnection=!1}_onConnect(e){if(this.disconnected)return void this.emit("connect",e);this.connackPacket=e,this.messageIdProvider.clear(),this._setupKeepaliveManager(),this.connected=!0;const t=()=>{let n=this.outgoingStore.createStream();const i=()=>{n.destroy(),n=null,this._flushStoreProcessingQueue(),r()},r=()=>{this._storeProcessing=!1,this._packetIdsDuringStoreProcessing={}};this.once("close",i),n.on("error",e=>{r(),this._flushStoreProcessingQueue(),this.removeListener("close",i),this.emit("error",e)});const o=()=>{if(!n)return;const e=n.read(1);let t;e?(this._storeProcessing=!0,this._packetIdsDuringStoreProcessing[e.messageId]?o():this.disconnecting||this.reconnectTimer?n.destroy&&n.destroy():(t=this.outgoing[e.messageId]?this.outgoing[e.messageId].cb:null,this.outgoing[e.messageId]={volatile:!1,cb(e,n){t&&t(e,n),o()}},this._packetIdsDuringStoreProcessing[e.messageId]=!0,this.messageIdProvider.register(e.messageId)?this._sendPacket(e,void 0,void 0,!0):this.log("messageId: %d has already used.",e.messageId))):n.once("readable",o)};n.on("end",()=>{let n=!0;for(const e in this._packetIdsDuringStoreProcessing)if(!this._packetIdsDuringStoreProcessing[e]){n=!1;break}this.removeListener("close",i),n?(r(),this._invokeAllStoreProcessingQueue(),this.emit("connect",e)):t()}),o()};t()}_invokeStoreProcessingQueue(){if(!this._storeProcessing&&this._storeProcessingQueue.length>0){const e=this._storeProcessingQueue[0];if(e&&e.invoke())return this._storeProcessingQueue.shift(),!0}return!1}_invokeAllStoreProcessingQueue(){for(;this._invokeStoreProcessingQueue(););}_flushStoreProcessingQueue(){for(const e of this._storeProcessingQueue)e.cbStorePut&&e.cbStorePut(new Error("Connection closed")),e.callback&&e.callback(new Error("Connection closed"));this._storeProcessingQueue.splice(0)}_removeOutgoingAndStoreMessage(e,t){delete this.outgoing[e],this.outgoingStore.del({messageId:e},(n,i)=>{t(n,i),this.messageIdProvider.deallocate(e),this._invokeStoreProcessingQueue()})}}t.default=k},9844(e){"use strict";function t(e){return e instanceof Buffer?Buffer.from(e):new e.constructor(e.buffer.slice(),e.byteOffset,e.length)}e.exports=function(e){if((e=e||{}).circles)return function(e){const n=[],i=[],r=new Map;if(r.set(Date,e=>new Date(e)),r.set(Map,(e,t)=>new Map(s(Array.from(e),t))),r.set(Set,(e,t)=>new Set(s(Array.from(e),t))),e.constructorHandlers)for(const t of e.constructorHandlers)r.set(t[0],t[1]);let o=null;return e.proto?c:a;function s(e,s){const a=Object.keys(e),c=new Array(a.length);for(let l=0;l<a.length;l++){const d=a[l],u=e[d];if("object"!=typeof u||null===u)c[d]=u;else if(u.constructor!==Object&&(o=r.get(u.constructor)))c[d]=o(u,s);else if(ArrayBuffer.isView(u))c[d]=t(u);else{const e=n.indexOf(u);c[d]=-1!==e?i[e]:s(u)}}return c}function a(e){if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return s(e,a);if(e.constructor!==Object&&(o=r.get(e.constructor)))return o(e,a);const c={};n.push(e),i.push(c);for(const s in e){if(!1===Object.hasOwnProperty.call(e,s))continue;const l=e[s];if("object"!=typeof l||null===l)c[s]=l;else if(l.constructor!==Object&&(o=r.get(l.constructor)))c[s]=o(l,a);else if(ArrayBuffer.isView(l))c[s]=t(l);else{const e=n.indexOf(l);c[s]=-1!==e?i[e]:a(l)}}return n.pop(),i.pop(),c}function c(e){if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return s(e,c);if(e.constructor!==Object&&(o=r.get(e.constructor)))return o(e,c);const a={};n.push(e),i.push(a);for(const s in e){const l=e[s];if("object"!=typeof l||null===l)a[s]=l;else if(l.constructor!==Object&&(o=r.get(l.constructor)))a[s]=o(l,c);else if(ArrayBuffer.isView(l))a[s]=t(l);else{const e=n.indexOf(l);a[s]=-1!==e?i[e]:c(l)}}return n.pop(),i.pop(),a}}(e);const n=new Map;if(n.set(Date,e=>new Date(e)),n.set(Map,(e,t)=>new Map(r(Array.from(e),t))),n.set(Set,(e,t)=>new Set(r(Array.from(e),t))),e.constructorHandlers)for(const t of e.constructorHandlers)n.set(t[0],t[1]);let i=null;return e.proto?function e(o){if("object"!=typeof o||null===o)return o;if(Array.isArray(o))return r(o,e);if(o.constructor!==Object&&(i=n.get(o.constructor)))return i(o,e);const s={};for(const r in o){const a=o[r];"object"!=typeof a||null===a?s[r]=a:a.constructor!==Object&&(i=n.get(a.constructor))?s[r]=i(a,e):ArrayBuffer.isView(a)?s[r]=t(a):s[r]=e(a)}return s}:function e(o){if("object"!=typeof o||null===o)return o;if(Array.isArray(o))return r(o,e);if(o.constructor!==Object&&(i=n.get(o.constructor)))return i(o,e);const s={};for(const r in o){if(!1===Object.hasOwnProperty.call(o,r))continue;const a=o[r];"object"!=typeof a||null===a?s[r]=a:a.constructor!==Object&&(i=n.get(a.constructor))?s[r]=i(a,e):ArrayBuffer.isView(a)?s[r]=t(a):s[r]=e(a)}return s};function r(e,r){const o=Object.keys(e),s=new Array(o.length);for(let a=0;a<o.length;a++){const c=o[a],l=e[c];"object"!=typeof l||null===l?s[c]=l:l.constructor!==Object&&(i=n.get(l.constructor))?s[c]=i(l,r):ArrayBuffer.isView(l)?s[c]=t(l):s[c]=r(l)}return s}}},9896(e){"use strict";e.exports=require("fs")}},t={};function n(i){var r=t[i];if(void 0!==r)return r.exports;var o=t[i]={exports:{}};return e[i].call(o.exports,o,o.exports,n),o.exports}n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i=n(7927),r=exports="undefined"==typeof exports?{}:exports;for(var o in i)r[o]=i[o];i.__esModule&&Object.defineProperty(r,"__esModule",{value:!0})})();
|
|
3
3
|
//# sourceMappingURL=main.nodejs.js.map
|