@weppy/roblox-mcp 2.9.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dashboard/dist/assets/{AssetsPage-Bg2-L4ZA.js → AssetsPage-CC3FW3XG.js} +1 -1
  3. package/dashboard/dist/assets/{ChangelogDetailPage-BfKpoGXf.js → ChangelogDetailPage-B1zg2f56.js} +1 -1
  4. package/dashboard/dist/assets/{ChangelogPage-CJgsI7aS.js → ChangelogPage-CbfWdVtL.js} +1 -1
  5. package/dashboard/dist/assets/{ConfirmModal-C9EhZCHZ.js → ConfirmModal-BCviiJ3_.js} +1 -1
  6. package/dashboard/dist/assets/{ConnectionPage-DGUYptQR.js → ConnectionPage-Dskqof1W.js} +1 -1
  7. package/dashboard/dist/assets/{ControlsPage-rqArYVq2.js → ControlsPage-C_38U6b0.js} +1 -1
  8. package/dashboard/dist/assets/{CurrentPlaceScope-BMyP2w7Z.js → CurrentPlaceScope-CHEqGWYd.js} +1 -1
  9. package/dashboard/dist/assets/{GameChangeDetail-DKAKmyGF.js → GameChangeDetail-DAEU3IYH.js} +1 -1
  10. package/dashboard/dist/assets/{InfoLabel-ZfsTcz5c.js → InfoLabel-DCq3Fmko.js} +1 -1
  11. package/dashboard/dist/assets/{OverviewPage-C9OL33DV.js → OverviewPage-lOYmwxzd.js} +1 -1
  12. package/dashboard/dist/assets/{PageHeader-Cqg4GMtU.js → PageHeader-Do_AQ2vQ.js} +1 -1
  13. package/dashboard/dist/assets/{PlaytestPage-CczAQ-A8.js → PlaytestPage-CKcxZyhl.js} +1 -1
  14. package/dashboard/dist/assets/{SettingsPage-DNp4oJDT.js → SettingsPage-C0PubIFP.js} +1 -1
  15. package/dashboard/dist/assets/{StatusBadge-BSFzbkXM.js → StatusBadge-DRbLpCd0.js} +1 -1
  16. package/dashboard/dist/assets/{SyncPage-DzOONMOM.js → SyncPage-BFsgItgP.js} +1 -1
  17. package/dashboard/dist/assets/{Tabs-B8mbzhmZ.js → Tabs-CGfFE3L1.js} +1 -1
  18. package/dashboard/dist/assets/{ToolsPage-DFh7yyab.js → ToolsPage-DHhF-Y_W.js} +1 -1
  19. package/dashboard/dist/assets/{TooltipText-ZamrETeK.js → TooltipText-CfI7WgY4.js} +1 -1
  20. package/dashboard/dist/assets/{UiStudioPage-D7awEU2z.js → UiStudioPage-RAd0qXzL.js} +1 -1
  21. package/dashboard/dist/assets/{WhatsNewPage-CTZEuf65.js → WhatsNewPage-CLnx6v4u.js} +1 -1
  22. package/dashboard/dist/assets/{copy-Cey6jv67.js → copy-BIZzQcB-.js} +1 -1
  23. package/dashboard/dist/assets/index-DYezp9b1.js +606 -0
  24. package/dashboard/dist/assets/{sample-requests-CS0o0F7H.js → sample-requests-CnV4bBG4.js} +1 -1
  25. package/dashboard/dist/assets/{useLiveUptime-BGlwL1Q-.js → useLiveUptime-BYmnk4Ph.js} +1 -1
  26. package/dashboard/dist/assets/{useSettings-mbARvRgI.js → useSettings-HzhprVq7.js} +1 -1
  27. package/dashboard/dist/index.html +1 -1
  28. package/dist/index.js +1 -1
  29. package/package.json +1 -1
  30. package/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
  31. package/dashboard/dist/assets/index-B9LVK3-K.js +0 -606
package/dist/index.js CHANGED
@@ -501,7 +501,7 @@ Used by: toggle_ui_preview (optional).
501
501
  `)}catch(i){h.warn("Failed to flush change log",{error:i instanceof Error?i.message:String(i),entries:e.length})}}startChangeLogFlusher(){this.flushTimer||(this.flushTimer=setInterval(()=>{this.flushChangeLog(),this.flushHistory()},ffe),this.flushTimer&&typeof this.flushTimer=="object"&&"unref"in this.flushTimer&&this.flushTimer.unref())}async stopChangeLogFlusher(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flushChangeLog(),await this.flushHistory()}async updateSyncIndex(e,n){this.index.updateBothHashes(e,n)}relativePath(e){return St.relative(this.config.getSyncRoot(),e)}extractServiceName(e){return Zt(e)[0]??""}findTreeNode(e,n){let i=Zt(n);if(i.length<=1)return null;let r=e.children,a;for(let o=1;o<i.length;o++){if(!r||(a=r.find(s=>s.name===i[o]),!a))return null;r=a.children}return a??null}detachTreeNode(e,n){let i=this.getParentPath(n),r=this.getLeafName(n);if(!i||!r)return null;let a=this.findTreeNode(e,i),o=a?.children??e.children,s=o.findIndex(l=>l.name===r);if(s<0)return null;let[c]=o.splice(s,1);return a?a.childCount=o.length:e.childCount=o.length,c??null}insertTreeNode(e,n,i){let r=this.findTreeNode(e,n);if(r){r.children||(r.children=[]);let o=r.children.findIndex(s=>s.name===i.name);o>=0?r.children[o]=i:r.children.push(i),r.childCount=r.children.length;return}let a=e.children.findIndex(o=>o.name===i.name);a>=0?e.children[a]=i:e.children.push(i),e.childCount=e.children.length}getLeafName(e){let n=Zt(e);return n.length===0?null:n[n.length-1]??null}getParentPath(e){let n=Zt(e);return n.length<=1?null:`game.${n.slice(0,-1).join(".")}`}async copyDirectory(e,n){await this.ensureDir(n);let i=await at.readdir(e,{withFileTypes:!0});for(let r of i){let a=St.join(e,r.name),o=St.join(n,r.name);r.isDirectory()?await this.copyDirectory(a,o):await at.copyFile(a,o)}}async tryRename(e,n){try{return this.onWriteCallback?.(e),this.onWriteCallback?.(n),await at.rename(e,n),!0}catch{return!1}}};function bR(t,e){if(t===e)return!0;if(t===null||e===null||typeof t!=typeof e||typeof t!="object")return!1;if(Array.isArray(t))return!Array.isArray(e)||t.length!==e.length?!1:t.every((o,s)=>bR(o,e[s]));let n=t,i=e,r=Object.keys(n),a=Object.keys(i);return r.length!==a.length?!1:r.every(o=>Object.hasOwn(i,o)&&bR(n[o],i[o]))}function gfe(t,e){let n={},i=new Set([...Object.keys(t??{}),...Object.keys(e)]);for(let r of i){let a=t?.[r]??null,o=e[r]??null;bR(a,o)||(n[r]={before:a,after:o})}return n}yr();import Ze from"path";import{promises as Jo}from"fs";ce();var tx=class{index;placeRoot;constructor(e,n,i){this.index=n,this.placeRoot=i??e.getSyncRoot()}async buildReverseChanges(){let{modified:e,deleted:n}=await this.index.scanForFileModifications(),i=[];for(let a of e){if(this.isForwardOnlyPath(a.fsPath)){this.logForwardOnlySkip(a.fsPath,"buildReverseChanges:modified");continue}try{let o;a.fileType==="script"?o=await this.readModifiedScript(a.fsPath,a.instancePath):a.fileType==="value"?o=await this.readModifiedValue(a.fsPath,a.instancePath):o=await this.readModifiedProps(a.fsPath,a.instancePath),i.push(o)}catch(o){h.warn("Failed to read modified file for reverse sync",{path:a.fsPath,error:o instanceof Error?o.message:String(o)})}}let r=new Set;for(let a of n){if(this.isForwardOnlyPath(a.fsPath)){this.logForwardOnlySkip(a.fsPath,"buildReverseChanges:deleted");continue}if(r.has(a.instancePath))continue;r.add(a.instancePath);let o=Ze.relative(this.placeRoot,a.fsPath);i.push({type:"instanceRemoved",instancePath:a.instancePath,fsPath:o,fileType:a.fileType,content:null})}return i}async buildChangesFromPending(e){let n=[],i=new Set,r=new Set,a=new Set;for(let o of e)if(o.type==="add"||o.type==="change"){let s=Ze.dirname(o.fsPath),c=this.getFileType(o.fsPath);(c==="props"||c==="script"||c==="value")&&a.add(s)}for(let o of e)try{if(this.isForwardOnlyPath(o.fsPath)){this.logForwardOnlySkip(o.fsPath,`buildChangesFromPending:${o.type}`);continue}if(o.type==="addDir"||o.type==="unlinkDir"){let p=this.resolveInstancePathFromDirectory(o.fsPath);if(!p)continue;let f=this.getSiblingIndexForDirectory(o.fsPath),m=this.buildPendingDedupeKey(p,f);if(o.type==="unlinkDir"){if(i.has(m)||(i.add(m),this.isServiceInstance(p)))continue;let x=Ze.relative(this.placeRoot,o.fsPath),_={type:"instanceRemoved",instancePath:p,fsPath:x,fileType:"directory",content:null};f&&(_.siblingIndex=f),n.push(_);continue}if(r.has(m)||this.isServiceInstance(p)||a.has(o.fsPath)||!await this.isContainerDirectory(o.fsPath))continue;let y=Ze.relative(this.placeRoot,o.fsPath),v={type:"containerCreated",instancePath:p,fsPath:y,fileType:"directory",content:null,className:"Folder",parentPath:this.extractParentPath(p)};f&&(v.siblingIndex=f),r.add(m),n.push(v);continue}let s=this.resolveInstancePathFromFile(o.fsPath);if(!s)continue;let c=this.getSiblingIndexForFile(o.fsPath);if(o.type==="unlink"){let p=this.buildPendingDedupeKey(s,c);if(i.has(p)||(i.add(p),this.isServiceInstance(s)))continue;let f=Ze.relative(this.placeRoot,o.fsPath),m=this.getFileType(o.fsPath);if(m!=="script"&&m!=="props"&&m!=="value")continue;let g={type:"instanceRemoved",instancePath:s,fsPath:f,fileType:m,content:null};c&&(g.siblingIndex=c),n.push(g);continue}let l=this.getFileType(o.fsPath),u=!this.index.hasEntry(o.fsPath)&&!this.index.hasInstancePath(s),d;if(u&&o.type==="add"){if(this.isServiceInstance(s))continue;if(l==="script")d=await this.readNewScript(o.fsPath,s);else if(l==="value")d=await this.readNewValue(o.fsPath,s);else if(l==="props")d=await this.readNewInstance(o.fsPath,s);else continue}else if(l==="script")d=await this.readModifiedScript(o.fsPath,s);else if(l==="value")d=await this.readModifiedValue(o.fsPath,s);else if(l==="props")d=await this.readModifiedProps(o.fsPath,s);else continue;c&&(d.siblingIndex=c),n.push(d)}catch(s){h.warn("Failed to build change from pending entry",{path:o.fsPath,type:o.type,error:s instanceof Error?s.message:String(s)})}return n}resolveInstancePathFromFile(e){return this.index.resolveInstancePathFromFsPath(e)}getSiblingIndexForFile(e){let n=this.index.getExplorerRoot();if(Ze.basename(e)==="_tree.json")return;let r=Ze.relative(n,e);if(r.startsWith(".."))return;let a=r.split(Ze.sep).filter(d=>d.length>0);if(a.length<2)return;let o=a[a.length-2],s=Ze.dirname(e),c=Ze.dirname(s),l=this.index.getOriginalInstance(c,o);return l?l.siblingIndex:Vr(o).siblingIndex}isForwardOnlyPath(e){return this.index.isPathUnderClass(e,il)}logForwardOnlySkip(e,n){h.info("Skipped reverse change for forward-only path",{source:n,path:Ze.relative(this.placeRoot,e),className:this.index.getClassNameForFsPath(e)??"unknown"})}getFileType(e){return this.index.getFileTypeFromPath(e)}resolveInstancePathFromDirectory(e){let n=this.index.getExplorerRoot(),i=Ze.relative(n,e);if(i.startsWith("..")||i===""||Ze.isAbsolute(i))return null;let r=i.split(Ze.sep).filter(s=>s.length>0);if(r.length===0)return null;let a=["game"],o=n;for(let s of r){o=Ze.join(o,s);let c=Ze.dirname(o);a.push(this.index.getOriginalNameForDir(c,s))}return gt(a)}getSiblingIndexForDirectory(e){let n=Ze.basename(e),i=Ze.dirname(e),r=this.index.getOriginalInstance(i,n);return r?r.siblingIndex:Vr(n).siblingIndex}async isContainerDirectory(e){try{let n=await Jo.readdir(e,{withFileTypes:!0});for(let i of n)if(i.isFile()&&kb.some(r=>i.name.endsWith(r)))return!1;return!0}catch(n){if(n.code==="ENOENT")return!1;throw n}}buildPendingDedupeKey(e,n){return n?`${e}#${n}`:e}async readModifiedScript(e,n){let i=await Jo.readFile(e,"utf-8"),r=Ze.relative(this.placeRoot,e);return{type:"scriptSource",instancePath:n,fsPath:r,fileType:"script",content:i}}async readModifiedProps(e,n){let i=await Jo.readFile(e,"utf-8"),r=JSON.parse(i),a=Ze.relative(this.placeRoot,e);return{type:"properties",instancePath:n,fsPath:a,fileType:"props",content:r}}async readModifiedValue(e,n){let i=await Jo.readFile(e,"utf-8"),r=JSON.parse(i),a=Ze.relative(this.placeRoot,e);return{type:"valueChanged",instancePath:n,fsPath:a,fileType:"value",content:r}}async readNewScript(e,n){let i=await Jo.readFile(e,"utf-8"),r=Ze.relative(this.placeRoot,e),a=Ze.basename(e),o="ModuleScript";a.endsWith(".server.luau")?o="Script":a.endsWith(".client.luau")&&(o="LocalScript");let s=this.extractParentPath(n);return{type:"scriptCreated",instancePath:n,fsPath:r,fileType:"script",content:i,className:o,parentPath:s}}async readNewValue(e,n){let i=await Jo.readFile(e,"utf-8"),r=JSON.parse(i),a=Ze.relative(this.placeRoot,e),o=this.extractParentPath(n);return{type:"valueCreated",instancePath:n,fsPath:a,fileType:"value",content:r,className:r.className,parentPath:o}}async readNewInstance(e,n){let i=await Jo.readFile(e,"utf-8"),r=JSON.parse(i),a=Ze.relative(this.placeRoot,e),o=this.extractParentPath(n);return{type:"instanceCreated",instancePath:n,fsPath:a,fileType:"props",content:r,className:r.className,parentPath:o}}extractParentPath(e){return _t(e)}isServiceInstance(e){let n=ki(e);return n.length!==2||n[0]!=="game"?!1:HE.has(n[1])}};ce();import bfe from"path";ce();import La from"path";import{createHash as $8}from"crypto";import{promises as _R}from"fs";yr();var hfe=500,xR=class{explorerRoot;syncIndex;scanIntervalMs;previousSnapshot=new Map;pendingChanges=new Map;scanTimer=null;readyResolvers=[];isReady=!1;isPaused=!1;isScanning=!1;refreshSnapshotOnNextScan=!1;scanEpoch=0;pendingSequence=0;suppressedPaths=new Map;directionChecker=null;onForwardViolation=null;getPendingKey(e,n){return`${La.resolve(e)}\0${n}`}getPendingSlot(e){return e==="addDir"||e==="unlinkDir"?"dir":"file"}getPendingRank(e){return e==="change"?1:2}isStaleScan(e){return this.isPaused||e!==this.scanEpoch}resolveReadyWaiters(){for(let e of this.readyResolvers)e();this.readyResolvers=[]}queuePendingChange(e){let n=this.getPendingSlot(e.type),i=this.getPendingKey(e.fsPath,n),r=this.getPendingRank(e.type),a=this.pendingChanges.get(i);a&&a.rank>r||this.pendingChanges.set(i,{change:e,rank:r,sequence:++this.pendingSequence})}constructor(e,n,i=hfe){this.explorerRoot=La.resolve(e),this.syncIndex=n,this.scanIntervalMs=i}setDirectionChecker(e){this.directionChecker=e}setOnForwardViolation(e){this.onForwardViolation=e}suppressPath(e,n){let i=La.resolve(e);if(n===void 0){this.suppressedPaths.set(i,{mode:"generic"});return}if(n==="missing"){this.suppressedPaths.set(i,{mode:"missing"});return}this.suppressedPaths.set(i,{mode:"hash",hash:n})}async start(){this.scanTimer&&await this.stop("restart"),h.info("SnapshotChangeScanner: starting",{explorerRoot:this.explorerRoot,scanIntervalMs:this.scanIntervalMs}),this.isPaused=!1,this.refreshSnapshotOnNextScan=!1,this.suppressedPaths.clear(),this.scanEpoch+=1;let e=this.scanEpoch;this.previousSnapshot=await this.syncIndex.buildSnapshotSeed(),!this.isStaleScan(e)&&(this.isReady=!0,this.resolveReadyWaiters(),this.scanTimer=setInterval(()=>{this.scanSnapshotDiffs().catch(n=>{h.warn("SnapshotChangeScanner: background scan failed",{error:n instanceof Error?n.message:String(n)})})},this.scanIntervalMs),typeof this.scanTimer=="object"&&this.scanTimer&&"unref"in this.scanTimer&&this.scanTimer.unref())}async stop(e){h.info("SnapshotChangeScanner: stopping",{reason:e??"unspecified",explorerRoot:this.explorerRoot,isReady:this.isReady,isPaused:this.isPaused,pendingChanges:this.pendingChanges.size}),this.scanTimer&&(clearInterval(this.scanTimer),this.scanTimer=null),this.scanEpoch+=1,this.clearTransientState(),this.previousSnapshot=new Map,this.refreshSnapshotOnNextScan=!1,this.isPaused=!1,this.suppressedPaths.clear(),this.resolveReadyWaiters(),this.isReady=!1,this.isScanning=!1}beginFullSyncReplacement(){this.scanEpoch+=1,this.isPaused=!0,this.isReady=!1,this.refreshSnapshotOnNextScan=!1,this.suppressedPaths.clear(),this.clearTransientState()}async endFullSyncReplacement(){if(this.clearTransientState(),this.scanTimer===null){await this.start();return}let e=++this.scanEpoch;this.isReady=!1,this.finalizeResumedBaseline(e)}isActivelyScanning(){return this.scanTimer!==null&&!this.isPaused}injectPending(e){this.isPaused||(this.queuePendingChange(e),h.debug("SnapshotChangeScanner: injected pending change",{relativePath:e.relativePath,type:e.type}))}drainPendingChanges(){let e=Array.from(this.pendingChanges.values()).sort((n,i)=>n.sequence-i.sequence).map(n=>n.change);return this.pendingChanges.clear(),e}getPendingCount(){return this.pendingChanges.size}getLastDetected(){let e=null;for(let n of this.pendingChanges.values()){let i=n.change;(!e||i.detectedAt>e)&&(e=i.detectedAt)}return e}waitUntilReady(){return this.isReady?Promise.resolve():new Promise(e=>{this.readyResolvers.push(e)})}async rescan(){let e=await this.scanSnapshotDiffs(),n=await this.scanStoredModifications();return e+n}async scanSnapshotDiffs(){if(this.isPaused||this.isScanning)return 0;let e=this.scanEpoch;this.isScanning=!0;try{let n=await this.syncIndex.buildSnapshotSeed();if(this.isStaleScan(e))return 0;if(this.refreshSnapshotOnNextScan)return this.previousSnapshot=n,this.refreshSnapshotOnNextScan=!1,this.suppressedPaths.clear(),0;let i=E8(this.previousSnapshot,n),r=await this.processCandidates(i,e);if(this.isStaleScan(e))return 0;let a=this.commitPendingChanges(r);return this.previousSnapshot=n,this.suppressedPaths.clear(),a>0&&h.info("SnapshotChangeScanner: scan found pending changes",{added:a}),a}finally{this.isScanning=!1}}async scanStoredModifications(){if(this.isPaused)return 0;let e=this.scanEpoch,n=await this.scanStoredModificationsInternal(e);if(!n||this.isStaleScan(e))return 0;for(let i of n.forwardViolations)this.onForwardViolation?.(i);return this.commitPendingChanges(n.pending)}async scanStoredModificationsInternal(e){let n=await this.syncIndex.getModifiedFiles(),i={pending:[],forwardViolations:[]};for(let r of n){if(e!==this.scanEpoch)return null;let a=r.fsPath,o=La.relative(this.explorerRoot,a);if(await this.isSuppressedPath(a))continue;if(this.shouldRedirectToForwardRestore(o,a)){i.forwardViolations.push(o);continue}let s;switch(r.changeType){case"modified":s="change";break;case"added":s="add";break;case"deleted":s="unlink";break;default:continue}i.pending.push({fsPath:a,relativePath:o,type:s,detectedAt:new Date().toISOString()})}return i}async processCandidates(e,n){let i=[];for(let r of e){if(this.isStaleScan(n))return[];let a=La.join(this.explorerRoot,r.relativePath),o=new Date().toISOString();if(await this.isSuppressedPath(a)||r.kind==="file"&&yR(r.relativePath))continue;if(this.shouldRedirectToForwardRestore(r.relativePath,a)){this.onForwardViolation?.(r.relativePath);continue}if(r.kind==="dir"){i.push({fsPath:a,relativePath:r.relativePath,type:r.changeType,detectedAt:o});continue}if(r.changeType==="unlink"){i.push({fsPath:a,relativePath:r.relativePath,type:"unlink",detectedAt:o});continue}let s=this.syncIndex.getStoredFileHash(a);try{let c=await _R.readFile(a,"utf-8"),l=$8("md5").update(c,"utf-8").digest("hex");if(s&&l===s){h.debug("SnapshotChangeScanner: echo skipped",{relativePath:r.relativePath,changeType:r.changeType});continue}i.push({fsPath:a,relativePath:r.relativePath,type:r.changeType,detectedAt:o})}catch(c){if(c.code==="ENOENT"){i.push({fsPath:a,relativePath:r.relativePath,type:"unlink",detectedAt:o});continue}h.warn("SnapshotChangeScanner: failed to read candidate file",{path:r.relativePath,changeType:r.changeType,error:c instanceof Error?c.message:String(c)})}}return i}commitPendingChanges(e){let n=0;for(let i of e){let r=this.getPendingSlot(i.type),a=this.getPendingKey(i.fsPath,r),o=this.getPendingRank(i.type),s=this.pendingChanges.get(a);s&&s.rank>o||(s||n++,this.pendingChanges.set(a,{change:i,rank:o,sequence:++this.pendingSequence}))}return n}clearTransientState(){this.pendingChanges.clear()}async finalizeResumedBaseline(e){try{let n=await this.syncIndex.buildSnapshotSeed();if(e!==this.scanEpoch)return;this.previousSnapshot=n,this.refreshSnapshotOnNextScan=!1;let i=await this.scanStoredModificationsInternal(e);if(e!==this.scanEpoch)return;if(i){for(let r of i.forwardViolations)this.onForwardViolation?.(r);this.commitPendingChanges(i.pending)}this.suppressedPaths.clear(),this.isPaused=!1,this.isReady=!0,this.resolveReadyWaiters()}catch(n){if(e!==this.scanEpoch)return;h.warn("SnapshotChangeScanner: resume baseline refresh failed",{error:n instanceof Error?n.message:String(n)}),this.refreshSnapshotOnNextScan=!0,this.isPaused=!1,this.isReady=!0,this.resolveReadyWaiters()}}shouldRedirectToForwardRestore(e,n){return this.syncIndex.isPathUnderClass(n,il)?!0:this.directionChecker?this.directionChecker(e)==="forward":!1}async isSuppressedPath(e){let n=La.resolve(e);for(let[i,r]of this.suppressedPaths){if(n===i||n.startsWith(`${i}${La.sep}`))return r.mode==="generic"?!0:r.mode==="missing"?!await yfe(n):await vfe(n)===r.hash;if(i.startsWith(`${n}${La.sep}`))return r.mode==="generic"}return!1}};async function yfe(t){try{return await _R.access(t),!0}catch{return!1}}async function vfe(t){try{let e=await _R.readFile(t,"utf-8");return $8("md5").update(e,"utf-8").digest("hex")}catch{return null}}var O8=xR;var lt="snapshot-scanner",nx=class extends O8{placeId;detectorExplorerRoot;lifecycleGeneration=0;constructor(e,n,i={}){super(e,n,i.scanIntervalMs),this.placeId=i.placeId??null,this.detectorExplorerRoot=bfe.resolve(e)}async start(){let e=++this.lifecycleGeneration;h.info("Reverse detector bootstrap scheduled",{placeId:this.placeId,mode:lt,explorerRoot:this.detectorExplorerRoot}),await super.start(),e===this.lifecycleGeneration&&h.info("Reverse detector bootstrap completed",{placeId:this.placeId,mode:lt})}async stop(e){this.lifecycleGeneration+=1,h.info("Reverse detector stopping",{placeId:this.placeId,mode:lt,reason:e??"unspecified"}),await super.stop(e)}beginFullSyncReplacement(){h.info("Reverse detector paused for full sync replacement",{placeId:this.placeId,mode:lt}),super.beginFullSyncReplacement()}async endFullSyncReplacement(){h.info("Reverse detector baseline refresh scheduled",{placeId:this.placeId,mode:lt}),await super.endFullSyncReplacement()}async rescan(){h.debug("Reverse detector manual rescan requested",{placeId:this.placeId,mode:lt});let e=await super.rescan();return h.info("Reverse detector manual rescan completed",{placeId:this.placeId,mode:lt,added:e,pendingCount:this.getPendingCount()}),e}};import _l from"path";import{promises as D8}from"fs";function Yo(t,e,n,i,r=!1){if(i&&i>=1){let s=_t(e);if(s){let c=t.getEffectiveDir(s,i);if(c){let l=ct(e);if(n){let u=t.getResolvedName(e,n);if(u)l=u;else if(r)throw new Error(`Missing collision mapping for ${e}#${n}`)}return SR(t,c,l)}if(r)throw new Error(`Missing parent collision mapping for ${s}#${i}`)}}let a=t.getEffectiveDir(e,n??1);if(a){let s=t.getExplorerRoot(),c=_l.relative(s,a).split(_l.sep).filter(l=>l.length>0);return gt(["game",...c])}let o=e;if(n){let s=t.getResolvedName(e,n);if(s)o=tf(o,s);else if(r)throw new Error(`Missing collision mapping for ${e}#${n}`)}return o}function xfe(t,e){let n=ki(t),i=ki(e);if(n.length<=i.length)return!1;for(let r=0;r<i.length;r++)if(n[r]!==i[r])return!1;return!0}function N8(t,e){e=_fe(t,e);let n=new Map;for(let r=0;r<e.length;r++){let a=e[r];if(a?.type==="instanceRemoved")try{let o=Yo(t.index,a.path,a.siblingIndex,a.parentSiblingIndex,!0);n.set(r,o)}catch{continue}}if(n.size<=1)return e;let i=new Set;for(let[r,a]of n)for(let[o,s]of n)if(r!==o&&xfe(a,s)){i.add(r);break}return i.size===0?e:e.filter((r,a)=>!i.has(a))}function _fe(t,e){let n=new Map;for(let a=0;a<e.length;a++){let o=e[a];if(o?.type!=="instanceRemoved"||o.siblingIndex===void 0)continue;let s=n.get(o.path);s||(s=[],n.set(o.path,s)),s.push(a)}let i=!1;for(let a of n.values()){if(a.length<2)continue;let o=new Set;for(let s of a){let c=e[s].siblingIndex;if(o.has(c)){i=!0;break}o.add(c)}if(i)break}if(!i)return e;let r=[...e];for(let[a,o]of n){if(o.length<2)continue;let s=Xo(t.index,a,void 0,!1),c=new Set(t.index.getRegisteredSiblingIndices(a,s));if(c.size===0)continue;let l=new Set;for(let u of o){let d=e[u];if(d.type!=="instanceRemoved")continue;let p=d.siblingIndex;if(!l.has(p)&&c.has(p))l.add(p);else{let f;for(let m of c)if(!l.has(m)){f=m;break}f!==void 0&&(l.add(f),r[u]={...d,siblingIndex:f})}}}return r}function Xo(t,e,n,i=!1){if(n&&n>=1){let r=_t(e);if(r){let a=t.getEffectiveDir(r,n);if(a)return a;if(i)throw new Error(`Missing parent collision mapping for ${r}#${n}`)}}return t.resolveParentDir(e)}async function Ua(t,e,n,i,r){let a=_l.join(e,n),o=_l.join(e,i);try{(await D8.stat(a)).isDirectory()&&(r&&(r.suppressPath(a),r.suppressPath(o)),await D8.rename(a,o),t.renameHashKeysUnder(a,o),t.renameReverseNameMappingsUnder(a,o),t.renameInstanceDirMappingsUnder(a,o))}catch{return}}function SR(t,e,n){let i=_l.relative(t.getExplorerRoot(),e).split(_l.sep).filter(r=>r.length>0);return gt(["game",...i,n])}async function rx(t,e){let n=t.index.planCollisionReindexAfterBatchRemovals(e.instancePath,[...e.removedSiblingIndices],e.parentDir);for(let i of n.renames)await Ua(t.index,e.parentDir,i.from,i.to,t.fileWatcher),await Sl(t.writer,t.index,e.parentDir,i.from,i.to);t.index.applyCollisionReindexAfterBatchRemovals(e.instancePath,e.parentDir,n)}async function Sl(t,e,n,i,r){let a=SR(e,n,i),o=SR(e,n,r);await t.renameInTree(a,o,r)}import ix from"path";var j8=5*60*1e3,M8=100;function wR(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function nf(t){return typeof t=="string"&&t.length>0}function ax(t,e){let n=ix.resolve(t),i=ix.resolve(e),r=ix.relative(n,i);return r===""||!r.startsWith("..")&&!ix.isAbsolute(r)}function z8(t){if(!wR(t))return{success:!1,error:"Body must be an object"};let e=t.phase;if(e!=="start"&&e!=="chunk"&&e!=="complete")return{success:!1,error:`Invalid phase: ${String(e)}`};if(!nf(t.clientId))return{success:!1,error:"clientId is required"};switch(e){case"start":return typeof t.placeId!="number"?{success:!1,error:"placeId must be a number"}:nf(t.placeName)?typeof t.totalServices!="number"?{success:!1,error:"totalServices must be a number"}:typeof t.totalInstances!="number"?{success:!1,error:"totalInstances must be a number"}:t.previousPlaceId!==void 0&&typeof t.previousPlaceId!="number"?{success:!1,error:"previousPlaceId must be a number"}:{success:!0,data:t}:{success:!1,error:"placeName is required"};case"chunk":return nf(t.serviceName)?nf(t.serviceClassName)?Array.isArray(t.instances)?typeof t.chunkIndex!="number"?{success:!1,error:"chunkIndex must be a number"}:typeof t.totalChunks!="number"?{success:!1,error:"totalChunks must be a number"}:{success:!0,data:t}:{success:!1,error:"instances must be an array"}:{success:!1,error:"serviceClassName is required"}:{success:!1,error:"serviceName is required"};case"complete":return typeof t.instanceCount!="number"?{success:!1,error:"instanceCount must be a number"}:typeof t.scriptCount!="number"?{success:!1,error:"scriptCount must be a number"}:{success:!0,data:t}}}function L8(t){if(!wR(t))return{success:!1,error:"Body must be an object"};if(!nf(t.clientId))return{success:!1,error:"clientId is required"};if(t.placeId!==void 0&&typeof t.placeId!="number")return{success:!1,error:"placeId must be a number"};if(typeof t.timestamp!="number")return{success:!1,error:"timestamp must be a number"};if(!Array.isArray(t.changes)||t.changes.length===0)return{success:!1,error:"changes must be a non-empty array"};let e=new Set(["propertyChanged","instanceAdded","instanceRemoved","instanceRenamed","instanceMoved","scriptSourceChanged"]);for(let n=0;n<t.changes.length;n++){let i=t.changes[n];if(!wR(i)||!e.has(i.type))return{success:!1,error:`changes[${n}]: invalid type '${String(i?.type)}'`}}return{success:!0,data:t}}import xr from"path";import{promises as Qo}from"fs";yr();ce();var ox=class{constructor(e){this.ctx=e}async processChangeForPlace(e,n,i){let r=y6(n.type);if(e.directions[r]==="reverse")return h.info("Reverse enforcement: rejecting Studio change on reverse-only path",{placeId:e.placeId,changeType:n.type,dirKey:r,path:"path"in n?n.path:void 0}),(n.type==="scriptSourceChanged"||n.type==="propertyChanged")&&await this.injectLocalAsReverse(e,n),null;switch(n.type){case"propertyChanged":{let o=Yo(e.index,n.path,n.siblingIndex,n.parentSiblingIndex,!0),s=await this.checkPropertyConflictForPlace(e,o,n);if(s)return s;let c=n;if(c.attributes!==void 0||c.tags!==void 0){let l=e.index.resolvePropsPath(o),u=await this.buildPropertyChangedPropsData(l,o,n);await e.writer.writeProps(o,u)}else c.properties&&typeof c.properties=="object"&&!Array.isArray(c.properties)?await e.writer.updateProperties(o,c.properties):n.property!==void 0?await e.writer.updateProperty(o,n.property,n.value):h.warn("propertyChanged: missing both property and properties",{path:o});return null}case"instanceAdded":{let o=rl.has(n.className),s=n.path,c=n.name;{let d=Xo(e.index,n.path,n.parentSiblingIndex,!0),{resolved:p,retroactiveRename:f}=e.index.registerCollision(n.path,n.siblingIndex,d);f&&(await Ua(e.index,d,f.from,f.to,e.fileWatcher),await Sl(e.writer,e.index,d,f.from,f.to));let m=e.index.sanitizeName(n.name);if(p!==m||d!==e.index.resolveParentDir(n.path)){let g=e.index.getExplorerRoot(),y=xr.relative(g,d).split(xr.sep).filter(v=>v.length>0);s=gt(["game",...y,p]),c=p}}await e.writer.writeInstance({path:s,name:n.name,className:n.className,properties:n.properties,attributes:n.attributes,tags:n.tags,scriptSource:n.scriptSource,hasChildren:!1,childCount:0,siblingIndex:n.siblingIndex}),this.setOriginalClassMapping(e,n.path,n.className,n.siblingIndex);let l={name:c,className:n.className,childCount:0,...c!==n.name?{originalName:n.name}:{}},u=_t(s)||n.parentPath;return await e.writer.addToTree(u,l),e.instanceCount++,o&&n.scriptSource!==void 0&&e.scriptCount++,null}case"instanceRemoved":{let o=Yo(e.index,n.path,n.siblingIndex,n.parentSiblingIndex,!0),s=Xo(e.index,n.path,n.parentSiblingIndex,!0);h.info("Processing instanceRemoved",{path:o}),await e.writer.removeInstance(o),this.removeOriginalClassMapping(e,n.path,o);let c=ct(o),l=_t(o);if(l&&c&&await e.writer.removeFromTree(l,c),n.siblingIndex!==void 0){let d=`${s}\0${n.path}`,p=i.get(d);p||(p={instancePath:n.path,parentDir:s,removedSiblingIndices:new Set},i.set(d,p)),p.removedSiblingIndices.add(n.siblingIndex)}let u=_t(o);if(u)try{let d=e.index.resolveChildrenDir(u);xr.dirname(d)!==e.index.getExplorerRoot()&&(await Qo.readdir(d)).length===0&&await Qo.rmdir(d)}catch{return null}return null}case"instanceRenamed":{let o=Yo(e.index,n.oldPath,n.siblingIndex,n.parentSiblingIndex,!0),s=_t(n.oldPath)===_t(n.newPath),c=s?Xo(e.index,n.oldPath,n.parentSiblingIndex,!0):null,l=Xo(e.index,n.newPath,n.parentSiblingIndex,!0),{resolved:u,retroactiveRename:d}=e.index.registerCollision(n.newPath,n.siblingIndex,l);d&&(await Ua(e.index,l,d.from,d.to,e.fileWatcher),await Sl(e.writer,e.index,l,d.from,d.to));let p=u!==e.index.sanitizeName(n.newName)?tf(n.newPath,u):n.newPath;if(await e.writer.renameInstance(o,p,n.newName),this.renameOriginalClassMapping(e,n.oldPath,n.newPath),await e.writer.renameInTree(o,p,u,n.newName),s&&c&&n.siblingIndex!==void 0){let f=e.index.planCollisionReindexAfterRemoval(n.oldPath,n.siblingIndex,c);for(let m of f.renames)await Ua(e.index,c,m.from,m.to,e.fileWatcher),await Sl(e.writer,e.index,c,m.from,m.to);e.index.applyCollisionReindexAfterRemoval(n.oldPath,c,f)}return null}case"instanceMoved":{let o=Yo(e.index,n.oldPath,n.siblingIndex,n.parentSiblingIndex,!0),s=Xo(e.index,n.newPath,n.parentSiblingIndex,!0),{resolved:c,retroactiveRename:l}=e.index.registerCollision(n.newPath,n.siblingIndex,s);l&&(await Ua(e.index,s,l.from,l.to,e.fileWatcher),await Sl(e.writer,e.index,s,l.from,l.to));let u=ct(n.newPath)||"",d=c!==e.index.sanitizeName(u)?tf(n.newPath,c):n.newPath;return await e.writer.moveInstance(o,d),this.renameOriginalClassMapping(e,n.oldPath,n.newPath),await e.writer.moveInTree(o,d),null}case"scriptSourceChanged":{let o=Yo(e.index,n.path,n.siblingIndex,n.parentSiblingIndex,!0),s=await this.checkScriptConflictForPlace(e,o,n.source);if(s)return s;let c=await this.resolveScriptClassForPlace(e,o);return await this.cleanupStaleScriptFilesForPlace(e,o,c),await e.writer.writeScript(o,c,n.source,!1),null}}}async injectLocalAsReverse(e,n){if(e.fileWatcher)try{if(n.type==="scriptSourceChanged"){let i=await this.resolveScriptClassForPlace(e,n.path),r=e.index.resolveScriptPath(n.path,i,!1),a=xr.join(this.ctx.config.getPlaceRoot(e.placeId),"explorer"),o=xr.relative(a,r);e.fileWatcher.injectPending({fsPath:r,relativePath:o,type:"change",detectedAt:new Date().toISOString()})}else if(n.type==="propertyChanged"){let i=e.index.resolvePropsPath(n.path),r=xr.join(this.ctx.config.getPlaceRoot(e.placeId),"explorer"),a=xr.relative(r,i);e.fileWatcher.injectPending({fsPath:i,relativePath:a,type:"change",detectedAt:new Date().toISOString()})}}catch(i){h.debug("injectLocalAsReverse: could not inject",{changeType:n.type,error:i instanceof Error?i.message:String(i)})}}async resolveScriptClassForPlace(e,n){try{let i=e.index.resolvePropsPath(n),r=await Qo.readFile(i,"utf-8"),a=JSON.parse(r);if(a.className&&rl.has(a.className))return a.className}catch{return"ModuleScript"}return"ModuleScript"}async cleanupStaleScriptFilesForPlace(e,n,i){let r=Cb[i],a=xr.join(this.ctx.config.getPlaceRoot(e.placeId),"explorer");for(let[o,s]of Object.entries(Cb)){if(s===r)continue;let c=e.index.resolveScriptPath(n,o,!1);try{await Qo.unlink(c),e.index.removeHash(c),h.info("Cleaned up stale script file",{placeId:e.placeId,removed:xr.relative(a,c),currentClassName:i})}catch(l){l.code!=="ENOENT"&&h.warn("Failed to clean up stale script file",{path:c,error:l instanceof Error?l.message:String(l)})}}}async checkPropertyConflictForPlace(e,n,i){try{let r=e.index.resolvePropsPath(n),a=e.index.getFileHash(r);if(!a)return null;let o;try{o=await Qo.readFile(r,"utf-8")}catch{return null}return e.index.computeHash(o)===a?null:{fsPath:xr.relative(this.ctx.config.getPlaceRoot(e.placeId),r),instancePath:n,fileType:"props",studioContent:await this.buildStudioPropsConflictContent(r,n,i),fileContent:o}}catch{return null}}async checkScriptConflictForPlace(e,n,i){try{let r=await this.resolveScriptClassForPlace(e,n),a=e.index.resolveScriptPath(n,r,!1),o=e.index.getFileHash(a);if(!o)return null;let s;try{s=await Qo.readFile(a,"utf-8")}catch{return null}return e.index.computeHash(s)===o?null:{fsPath:xr.relative(this.ctx.config.getPlaceRoot(e.placeId),a),instancePath:n,fileType:"script",studioContent:i,fileContent:s}}catch{return null}}async applyDeferredCollisionBatchReindexForPlace(e,n){await rx(e,n)}async buildStudioPropsConflictContent(e,n,i){let r=await this.buildPropertyChangedPropsData(e,n,i);return JSON.stringify(r,null,2)}async buildPropertyChangedPropsData(e,n,i){let r=null;try{let s=await Qo.readFile(e,"utf-8");r=JSON.parse(s)}catch{r=null}let a=i.properties?{...i.properties}:{...r?.properties??{}};i.property&&(a[i.property]=i.value);let o={name:r?.name??ct(n)??"",className:i.className??r?.className??"Folder",properties:a};return i.attributes!==void 0?Object.keys(i.attributes).length>0&&(o.attributes={...i.attributes}):r?.attributes&&(o.attributes={...r.attributes}),i.tags!==void 0?i.tags.length>0&&(o.tags=[...i.tags]):r?.tags&&(o.tags=[...r.tags]),o}setOriginalClassMapping(e,n,i,r){e.index.setClassName(n,i,r)}removeOriginalClassMapping(e,n,i){n!==i&&e.index.removeClassMappingsUnderInstancePath(n)}renameOriginalClassMapping(e,n,i){n!==i&&e.index.renameClassMappingKeys(n,i)}};import U8 from"path";import{promises as sx}from"fs";yr();ce();Xn();var cx=class{constructor(e){this.ctx=e}async handlePreCheck(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({hasPreviousSync:!1,changes:[],summary:{modified:0,deleted:0,added:0,total:0}});return}let r=this.ctx.config.getPlaceRoot(i),a=U8.join(r,".sync-index.json"),o=!1;try{await sx.access(a),o=!0}catch{o=!1}if(!o){n.status(200).json({hasPreviousSync:!1,changes:[],summary:{modified:0,deleted:0,added:0,total:0}});return}let s=U8.join(r,"explorer"),c=new za(r,s);await c.loadFromDisk();let l=await c.getModifiedFiles(),u=0,d=0,p=0;for(let m of l)switch(m.changeType){case"modified":u++;break;case"deleted":d++;break;case"added":p++;break}let f=l.map(m=>({relPath:m.relPath,instancePath:m.instancePath,changeType:m.changeType,fileType:m.fileType}));n.status(200).json({hasPreviousSync:!0,changes:f,summary:{modified:u,deleted:d,added:p,total:f.length}})}async handleSyncDirections(e,n){let i=e.body,r=i.placeId??this.ctx.getDefaultRuntimePlaceId();if(r==null){n.status(400).json({error:"Missing placeId"});return}let a=this.ctx.places.get(r);if(!a){n.status(404).json({error:"Place not found",message:`No sync context for place ${r}`});return}if(i.directions&&typeof i.directions=="object"){let o=c=>c==="forward"||c==="reverse"||c==="bidirectional",s=i.directions;o(s.scripts)&&(a.directions.scripts=s.scripts),o(s.values)&&(a.directions.values=s.values),o(s.containers)&&(a.directions.containers=s.containers),o(s.data)&&(a.directions.data=s.data),o(s.services)&&(a.directions.services=s.services),h.info("Sync directions updated",{placeId:r,directions:a.directions})}if(i.applyModes&&typeof i.applyModes=="object"){let o=c=>c==="auto"||c==="manual",s=i.applyModes;o(s.scripts)&&(a.applyModes.scripts=s.scripts),o(s.values)&&(a.applyModes.values=s.values),o(s.containers)&&(a.applyModes.containers=s.containers),o(s.data)&&(a.applyModes.data=s.data),o(s.services)&&(a.applyModes.services=s.services)}this.ctx.touchRuntimePlace(r),n.status(200).json({status:"updated",directions:a.directions,applyModes:a.applyModes})}async handleForwardRestoreList(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({paths:[]});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}let a=r.forwardRestoreQueue.splice(0);this.ctx.touchRuntimePlace(i),h.info("Forward restore list drained",{placeId:i,count:a.length}),n.status(200).json({paths:a})}async handleSyncHistory(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({entries:[],total:0,hasMore:!1});return}let r=yn(e.query.limit,50,1,200),a=yn(e.query.offset,0,0),o=e.query.direction,s=e.query.type,c=this.ctx.places.get(i);c&&(await c.writer.flushHistory(),this.ctx.touchRuntimePlace(i));let l=this.ctx.config.getHistoryPath(i),d=(await Xp(l,1e4)).reverse().filter(g=>!(o&&g.direction!==o||s&&g.type!==s)),p=d.length,m={entries:d.slice(a,a+r),total:p,hasMore:a+r<p};n.status(200).json(m)}getStatusSummary(){if(this.ctx.activeFullSyncPlaceId!==null&&this.ctx.activeFullSyncPlaceId!==void 0)return{active:!0,placeId:this.ctx.activeFullSyncPlaceId};for(let[e,n]of this.ctx.places.entries())if(n.state==="syncing")return{active:!0,placeId:e};return{active:!1}}getDirectionForCategory(e){let n;if(this.ctx.activeFullSyncPlaceId!==null&&this.ctx.activeFullSyncPlaceId!==void 0&&(n=this.ctx.places.get(this.ctx.activeFullSyncPlaceId)),!n){let r=this.ctx.getDefaultRuntimePlaceId();r!=null&&(n=this.ctx.places.get(r))}if(!n)return"forward";let i=e;return n.directions[i]??"forward"}getStatusDirect(e){let n=e!=null?parseInt(e,10):this.ctx.getDefaultRuntimePlaceId();if(n==null)return{state:"idle",instanceCount:0,scriptCount:0,lastFullSync:null,lastIncrementalSync:null,syncRoot:this.ctx.config.getSyncRoot(),activeClientId:null,reverseSyncAvailable:!1,modifiedFileCount:0,applyModes:{...Bo},reverseDetectorActive:!1,reverseDetectorMode:lt,fileWatcherActive:!1};let i=this.ctx.places.get(n);if(!i)return{state:"idle",instanceCount:0,scriptCount:0,lastFullSync:null,lastIncrementalSync:null,syncRoot:this.ctx.config.getPlaceRoot(n),activeClientId:null,reverseSyncAvailable:!1,modifiedFileCount:0,applyModes:{...Bo},reverseDetectorActive:!1,reverseDetectorMode:lt,fileWatcherActive:!1};let r=i.fileWatcher?.getPendingCount()??0,a=i.fileWatcher?.isActivelyScanning()??!1,o=i.fileWatcher!==null;return{state:i.state,instanceCount:i.instanceCount,scriptCount:i.scriptCount,lastFullSync:i.lastFullSync,lastIncrementalSync:i.lastIncrementalSync,syncRoot:this.ctx.config.getPlaceRoot(n),activeClientId:i.activeClientId,reverseSyncAvailable:r>0,modifiedFileCount:r,applyModes:{...i.applyModes},reverseDetectorActive:a,reverseDetectorMode:lt,fileWatcherActive:o}}async getHistoryDirect(e,n){let i=e!=null?parseInt(e,10):this.ctx.getDefaultRuntimePlaceId();if(i==null||!Number.isFinite(i))return{entries:[],total:0,hasMore:!1};let r=this.ctx.places.get(i);r&&await r.writer.flushHistory();let a=Math.min(Math.max(n?.limit??50,1),200),o=Math.max(n?.offset??0,0),s=this.ctx.config.getHistoryPath(i),l=(await Xp(s,1e4)).reverse(),u=l.length;return{entries:l.slice(o,o+a),total:u,hasMore:o+a<u}}getDirectionsDirect(e){let n=e!=null?parseInt(e,10):this.ctx.getDefaultRuntimePlaceId();if(n==null)return{...qo};let i=this.ctx.places.get(n);return i?{...i.directions}:{...qo}}getProgressDirect(e){let n=e!=null?parseInt(e,10):this.ctx.getDefaultRuntimePlaceId();if(n==null)return{state:"idle",isSyncing:!1};let i=this.ctx.places.get(n);if(!i)return{state:"idle",isSyncing:!1};if(!i.syncProgress)return{state:i.state,isSyncing:!1,lastSync:{instanceCount:i.instanceCount,scriptCount:i.scriptCount,completedAt:i.lastFullSync}};let r=i.syncProgress,a=Date.now()-r.syncStartTime,o=r.totalInstances>0?Math.min(100,Math.round(r.processedInstances/r.totalInstances*100)):0,s;if(r.processedInstances>0&&o<100){let l=a/r.processedInstances,u=r.totalInstances-r.processedInstances;s=Math.round(l*u)}let c=a>0?Math.round(r.bytesReceived/a*1e3):0;return{state:i.state,isSyncing:!0,progressPercent:o,currentService:r.currentService,currentChunk:{index:r.currentChunkIndex,total:r.currentTotalChunks},instances:{processed:r.processedInstances,total:r.totalInstances},services:{processed:r.processedServices,total:r.totalServices},elapsedMs:a,estimatedRemainingMs:s,bytesReceived:r.bytesReceived,bytesPerSecond:c}}async readSyncedFile(e,n){let i=parseInt(e,10),r=this.ctx.places.get(i);if(!r)throw new Error(`Place ${e} is not loaded in the sync cache. Start sync for this place before reading synced files.`);let a=r.index.resolvePropsPath(n);try{return{content:await sx.readFile(a,"utf-8"),path:a}}catch(s){if(s.code!=="ENOENT")throw s}for(let s of rl){let c=r.index.resolveScriptPath(n,s,!1);try{return{content:await sx.readFile(c,"utf-8"),path:c}}catch{continue}}let o=r.index.resolveValuePath(n);try{return{content:await sx.readFile(o,"utf-8"),path:o}}catch(s){if(s.code!=="ENOENT")throw s}throw new Error(`No synced file found for instance: ${n}. Ensure the instance has been synced to disk and that the canonical instance path is correct.`)}async writeSyncedFile(e,n,i){let r=parseInt(e,10),a=this.ctx.places.get(r);if(!a)throw new Error(`Place ${e} is not loaded in the sync cache. Start sync for this place before writing synced files.`);await a.writer.writeScript(n,"Script",i,!1)}async executeViaDisk(e,n){let i=this.ctx.getDefaultRuntimePlaceId();if(i==null)throw new Error("No active sync place for disk execution. Start sync for the current place before using reverse-sync disk execution.");let r=this.ctx.places.get(i);if(!r)throw new Error(`Place ${i} is not loaded in the sync cache. Restart sync before retrying disk execution.`);switch(e){case"manage_scripts_set_source":{let a=n.scriptType||n.className||"Script";return await r.writer.writeScript(n.path,a,n.source,!1),{success:!0,path:n.path}}case"manage_properties_set":return await r.writer.writeProps(n.path,{className:n.className||"Instance",name:ct(n.path),properties:{[n.property]:n.value}}),{success:!0,path:n.path};default:throw new Error(`Disk execution is not supported for command: ${e}. This command must run through the plugin route.`)}}};import Ne from"path";import{createHash as Sfe,randomUUID as wfe}from"crypto";import{promises as On}from"fs";yr();Rb();ce();function Cfe(t){return Sfe("md5").update(t,"utf-8").digest("hex")}function F8(t){return t.pluginProcessToken?`process:${t.pluginProcessToken}`:t.pluginSessionId?`session:${t.pluginSessionId}`:t.pluginClientId?`client:${t.pluginClientId}`:null}var lx=class{constructor(e){this.ctx=e}preserveLocalFilesMap=new Map;pendingServiceTrees=new Map;async handleInitStart(e,n,i){if(n.previousPlaceId!==void 0&&n.previousPlaceId!==e&&(h.info("Place promotion detected",{from:n.previousPlaceId,to:e}),await this.ctx.config.promotePlaceRoot(n.previousPlaceId,e,n.placeName),this.ctx.places.get(n.previousPlaceId)&&this.ctx.places.delete(n.previousPlaceId),this.ctx.activeFullSyncPlaceId===n.previousPlaceId&&(this.ctx.activeFullSyncPlaceId=null),this.ctx.clearRuntimePlaceIfMatch(n.previousPlaceId)),this.ctx.activeFullSyncPlaceId!==null&&this.ctx.activeFullSyncPlaceId!==void 0&&this.ctx.activeFullSyncPlaceId!==e){i.status(409).json({error:"Conflict",message:`Place ${this.ctx.activeFullSyncPlaceId} is currently syncing. Only one place can sync at a time.`});return}let r=await this.ctx.getOrCreatePlaceContext(e,n.placeName);if(r.activeClientId&&r.activeClientId!==n.clientId&&r.activeFullSyncSessionId!==null){i.status(409).json({error:"Conflict",message:`Another client (${r.activeClientId}) is currently syncing this place`});return}if(this.ctx.activeFullSyncPlaceId=e,this.ctx.touchRuntimePlace(e),r.activeClientId=n.clientId,r.activeSyncIdentityScope=F8(n),r.placeName=n.placeName,n.directions&&typeof n.directions=="object"){let d=n.directions,p=f=>f==="forward"||f==="reverse"||f==="bidirectional";p(d.scripts)&&(r.directions.scripts=d.scripts),p(d.values)&&(r.directions.values=d.values),p(d.containers)&&(r.directions.containers=d.containers),p(d.data)&&(r.directions.data=d.data),p(d.services)&&(r.directions.services=d.services),h.info("Sync directions received",{placeId:e,directions:r.directions})}else r.directions={...qo};if(n.applyModes&&typeof n.applyModes=="object"){let d=n.applyModes,p=f=>f==="auto"||f==="manual";p(d.scripts)&&(r.applyModes.scripts=d.scripts),p(d.values)&&(r.applyModes.values=d.values),p(d.containers)&&(r.applyModes.containers=d.containers),p(d.data)&&(r.applyModes.data=d.data),p(d.services)&&(r.applyModes.services=d.services)}else r.applyModes={...Bo};r.forwardRestoreQueue=[];let a=wfe();r.activeFullSyncSessionId=a,this.pendingServiceTrees.set(a,new Map),r.syncInitRequestsInFlight=0,r.instanceCount=0,r.scriptCount=0;let o=this.ctx.config.getPlaceRoot(e),s=Ne.join(o,`explorer_tmp_${a}`);await On.mkdir(s,{recursive:!0}),r.tmpIndex=new za(o,s),r.tmpWriter=new xl(this.ctx.config,r.tmpIndex,e),r.collisionDirMap=new Map;let c=n.preserveLocalFiles;Array.isArray(c)&&c.length>0&&(this.setPreserveLocalFiles(a,c),h.info("PreserveLocalFiles set for sync",{syncId:a,fileCount:c.length}));let l={version:1,placeId:n.placeId,placeName:n.placeName,lastFullSync:null,lastIncrementalSync:null,instanceCount:0,scriptCount:0,syncMode:"mirror"},u=Ne.join(o,".sync-meta.json");await On.mkdir(Ne.dirname(u),{recursive:!0}),await this.ctx.atomicWriteFile(u,JSON.stringify(l,null,2)+`
502
502
  `),this.startTTLTimerForPlace(r,a),r.state="initializing",r.index.resetNameCounters(),r.syncProgress={syncStartTime:Date.now(),totalInstances:n.totalInstances,totalServices:n.totalServices,processedInstances:0,processedServices:0,currentService:null,currentChunkIndex:0,currentTotalChunks:0,bytesReceived:0,processedChunks:0},r.writer.appendChangeLog(`FULL_SYNC_START clientId=${n.clientId} placeId=${n.placeId}`),r.writer.setBootstrapMode(!0),r.writer.appendHistory({timestamp:new Date().toISOString(),type:"fullSyncStart",direction:"forward",source:"studio",path:`place_${n.placeId}`,details:`services:${n.totalServices} instances:${n.totalInstances}`}),h.info("Full sync started",{syncId:a,clientId:n.clientId,identityScope:r.activeSyncIdentityScope,placeId:n.placeId,placeName:n.placeName,totalServices:n.totalServices,totalInstances:n.totalInstances}),i.status(200).json({status:"started",syncId:r.activeFullSyncSessionId})}async handleInitChunk(e,n,i){let r=this.ctx.places.get(e);if(!r||!r.activeFullSyncSessionId||!r.tmpIndex||!r.tmpWriter){i.status(400).json({error:"No active sync session",message:"Call sync/init with phase=start first"});return}if(r.activeClientId&&n.clientId&&r.activeClientId!==n.clientId){i.status(409).json({error:"Conflict",message:`This sync session belongs to client ${r.activeClientId}`});return}let a=r.activeFullSyncSessionId,o=r.tmpIndex,s=r.tmpWriter;this.startTTLTimerForPlace(r,a),this.beginInitRequest(r);try{let c=this.getOrCreatePendingServiceTree(a,n),l=0,u=r.collisionDirMap;for(let p of n.instances){if(this.ctx.config.isForbiddenPath(p.path))continue;let f=o.resolveParentDir(p.path),m=u.get(f)??f,g=r.activeSyncIdentityScope??F8(n),y=this.getPreferredResolvedName(r,g,p),{resolved:v,retroactiveRename:x}=o.registerCollisionWithPreferredName(p.path,p.siblingIndex??void 0,m,y);x&&(await Ua(o,m,x.from,x.to),this.rewritePendingEffectivePaths(c,o.getExplorerRoot(),Ne.join(m,x.from),Ne.join(m,x.to)),o.updateSessionDebugMappingResolvedName(g,x.instancePath,x.siblingIndex,x.to));let _=o.resolveChildrenDir(p.path),w=Ne.join(m,v);w!==_&&u.set(_,w);let C=o.sanitizeName(p.name),O=p;if(m!==f||v!==C){let q=o.getExplorerRoot(),ye=Ne.relative(q,m).split(Ne.sep).filter(ot=>ot.length>0),_e=gt(["game",...ye,v]);O={...p,path:_e}}let L=await s.writeInstance(O);o.setClassName(p.path,p.className,p.siblingIndex),this.recordSessionDebugMapping(r,g,p,v),l++,(L.propsWritten||L.valueWritten)&&r.instanceCount++,L.scriptWritten&&r.scriptCount++,c.instances.push({effectivePath:O.path,originalPath:p.path,className:p.className})}let d=this.isLastChunk(c,n.chunkIndex,n.totalChunks);if(d){let p=this.buildServiceTree(r,c);await s.writeTree(n.serviceName,p);let f=this.pendingServiceTrees.get(a);f?.delete(n.serviceName),f&&f.size===0&&this.pendingServiceTrees.delete(a)}r.syncProgress&&(r.syncProgress.processedInstances+=l,r.syncProgress.currentService=n.serviceName,r.syncProgress.currentChunkIndex=n.chunkIndex,r.syncProgress.currentTotalChunks=n.totalChunks,r.syncProgress.processedChunks++,r.syncProgress.bytesReceived+=JSON.stringify(n).length,d&&r.syncProgress.processedServices++),h.debug("Sync chunk processed",{placeId:e,serviceName:n.serviceName,chunkIndex:n.chunkIndex,totalChunks:n.totalChunks,processed:l}),i.status(200).json({processed:l,service:n.serviceName})}finally{this.endInitRequest(r)}}async handleInitComplete(e,n,i){let r=this.ctx.places.get(e);if(!r||!r.activeFullSyncSessionId){i.status(400).json({error:"No active sync session",message:"Call sync/init with phase=start first"});return}if(r.activeClientId&&n.clientId&&r.activeClientId!==n.clientId){i.status(409).json({error:"Conflict",message:`This sync session belongs to client ${r.activeClientId}`});return}let a=r.activeFullSyncSessionId;this.startTTLTimerForPlace(r,a),this.beginInitRequest(r);let o=this.ctx.config.getPlaceRoot(e),s=Ne.join(o,"explorer"),c=Ne.join(o,`explorer_tmp_${a}`),l=r.fileWatcher,u=this.getAndClearPreserveLocalFiles(a),d=new Map,p=[];if(u.length>0){for(let f of u){let m=Ne.resolve(o,f);try{let g=await On.readFile(m,"utf-8");d.set(f,g)}catch{p.push(f)}}h.info("Backed up local files for preservation",{placeId:e,requested:u.length,backed:d.size,deleted:p.length})}l&&l.beginFullSyncReplacement();try{try{await On.rm(s,{recursive:!0,force:!0})}catch{}await On.rename(c,s),r.instanceCount=n.instanceCount,r.scriptCount=n.scriptCount,r.lastFullSync=new Date().toISOString();let f={version:1,placeId:r.placeId,placeName:r.placeName,lastFullSync:r.lastFullSync,lastIncrementalSync:r.lastIncrementalSync,instanceCount:r.instanceCount,scriptCount:r.scriptCount,syncMode:"mirror"},m=Ne.join(o,".sync-meta.json");if(await this.ctx.atomicWriteFile(m,JSON.stringify(f,null,2)+`
503
503
  `),this.clearTTLTimerForPlace(r,a),r.index.clearAllHashes(),r.index.clearClassMappings(),r.tmpIndex){let g=r.tmpIndex.getExplorerRoot(),y=r.index.getExplorerRoot();for(let[v,x]of r.tmpIndex.getAllHashes()){let _=Ne.relative(g,v),w=Ne.resolve(y,_);r.index.updateHashByValue(w,x)}for(let[v,x]of r.tmpIndex.getAllFileHashes()){let _=Ne.relative(g,v),w=Ne.resolve(y,_);r.index.updateFileHashByValue(w,x)}r.index.resetNameCounters(),r.index.mergeNameMappingsFrom(r.tmpIndex),r.index.mergeSessionDebugMappingsFrom(r.tmpIndex)}if(r.tmpIndex=null,r.tmpWriter&&(r.tmpWriter.stopChangeLogFlusher(),r.tmpWriter=null),this.pendingServiceTrees.delete(a),r.collisionDirMap=null,r.activeSyncIdentityScope=null,await r.index.saveToDisk(),r.state="syncing",r.activeFullSyncSessionId=null,r.syncProgress=null,this.ctx.touchRuntimePlace(e),this.ctx.activeFullSyncPlaceId=null,d.size>0){for(let[g,y]of d){let v=Ne.resolve(o,g);try{await On.mkdir(Ne.dirname(v),{recursive:!0}),await On.writeFile(v,y,"utf-8"),l?.suppressPath(v,Cfe(y))}catch(x){h.warn("Failed to restore preserved file",{path:g,error:x instanceof Error?x.message:String(x)})}}h.info("Restored preserved local files",{placeId:e,count:d.size})}if(p.length>0){let g=0;for(let y of p){let v=Ne.resolve(o,y);try{await On.unlink(v),r.index.removeHash(v),l?.suppressPath(v,"missing"),g++}catch(x){x.code!=="ENOENT"&&h.warn("Failed to delete preserved-as-deleted file",{path:y,error:x instanceof Error?x.message:String(x)})}}g>0&&(await r.index.saveToDisk(),h.info("Deleted locally-removed files from new sync",{placeId:e,count:g}))}try{let g=this.ctx.config.getSyncRoot();await Eb(g,o)}catch(g){h.warn("Failed to generate place sourcemap after full sync",{placeId:e,error:g instanceof Error?g.message:String(g)})}try{let g=this.ctx.config.getSyncRoot(),y={version:1,lastActivePlaceId:r.placeId,lastActivePlaceName:r.placeName??null,lastActiveAt:new Date().toISOString()},v=Ne.join(g,".project-meta.json");await this.ctx.atomicWriteFile(v,JSON.stringify(y,null,2)+`
504
- `),await al(g)}catch(g){h.warn("Failed to refresh root representative sourcemap after full sync",{placeId:e,error:g instanceof Error?g.message:String(g)})}this.ctx.startFileWatcherForPlace(r).catch(g=>{h.warn("Failed to start reverse detector after full sync",{placeId:e,error:g instanceof Error?g.message:String(g)}),r.fileWatcher=null}),r.writer.setBootstrapMode(!1),r.writer.appendChangeLog(`FULL_SYNC_COMPLETE instances=${r.instanceCount} scripts=${r.scriptCount}`),r.writer.appendHistory({timestamp:new Date().toISOString(),type:"fullSyncComplete",direction:"forward",source:"studio",path:`place_${e}`,details:`instances:${r.instanceCount} scripts:${r.scriptCount}`}),h.info("Full sync completed",{placeId:e,instanceCount:r.instanceCount,scriptCount:r.scriptCount}),i.status(200).json({status:"completed",instanceCount:r.instanceCount,scriptCount:r.scriptCount,syncRoot:this.ctx.config.getPlaceRoot(e)})}catch(f){throw l&&l.endFullSyncReplacement(),f}finally{this.endInitRequest(r)}}setPreserveLocalFiles(e,n){this.preserveLocalFilesMap.set(e,n)}getAndClearPreserveLocalFiles(e){let n=this.preserveLocalFilesMap.get(e)||[];return this.preserveLocalFilesMap.delete(e),n}clearPreserveLocalFiles(e){this.preserveLocalFilesMap.delete(e)}clearPendingServiceTrees(e){this.pendingServiceTrees.delete(e)}startTTLTimerForPlace(e,n){e.incompleteSyncTimer&&(clearTimeout(e.incompleteSyncTimer),e.incompleteSyncTimer=null);let i=setTimeout(async()=>{if(h.warn("Incomplete sync TTL expired, cleaning up",{placeId:e.placeId,syncId:n}),e.incompleteSyncTimer=null,e.activeFullSyncSessionId===n&&e.syncInitRequestsInFlight>0){h.warn("Incomplete sync TTL expired while sync init request is in flight, extending cleanup",{placeId:e.placeId,syncId:n,syncInitRequestsInFlight:e.syncInitRequestsInFlight}),this.startTTLTimerForPlace(e,n);return}let r=this.ctx.config.getPlaceRoot(e.placeId),a=Ne.join(r,`explorer_tmp_${n}`);try{await On.rm(a,{recursive:!0,force:!0})}catch(o){h.error("Failed to clean up expired temp dir",o instanceof Error?o:new Error(String(o)))}e.activeFullSyncSessionId===n&&(e.activeFullSyncSessionId=null,e.activeClientId=null,e.state="idle",e.tmpIndex=null,e.syncInitRequestsInFlight=0,this.pendingServiceTrees.delete(n),e.collisionDirMap=null,e.activeSyncIdentityScope=null,e.tmpWriter&&(e.tmpWriter.stopChangeLogFlusher(),e.tmpWriter=null),this.ctx.activeFullSyncPlaceId===e.placeId&&(this.ctx.activeFullSyncPlaceId=null),this.ctx.clearRuntimePlaceIfMatch(e.placeId))},j8);i&&typeof i=="object"&&"unref"in i&&i.unref(),e.incompleteSyncTimer=i}getOrCreatePendingServiceTree(e,n){let i=this.pendingServiceTrees.get(e);i||(i=new Map,this.pendingServiceTrees.set(e,i));let r=i.get(n.serviceName);if(r)return r;let a={serviceName:n.tree?.name??n.serviceName,serviceClassName:n.tree?.className??n.serviceClassName,zeroBasedChunkIndex:n.chunkIndex===0,instances:[]};return i.set(n.serviceName,a),a}isLastChunk(e,n,i){return i<=1?!0:e.zeroBasedChunkIndex?n>=i-1:n>=i}getPreferredResolvedName(e,n,i){let r=typeof i.sessionDebugId=="string"?i.sessionDebugId:"";if(!n||r==="")return;let a=e.index.getSessionDebugMapping(n,r);if(!a)return;let o=_t(i.path),s=ct(i.path)||i.name;if(!(a.parentPath!==o||a.originalName!==s))return a.resolvedName}recordSessionDebugMapping(e,n,i,r){let a=typeof i.sessionDebugId=="string"?i.sessionDebugId:"";!n||a===""||!e.tmpIndex||e.tmpIndex.setSessionDebugMapping({scope:n,sessionDebugId:a,instancePath:i.path,parentPath:_t(i.path),originalName:ct(i.path)||i.name,siblingIndex:Math.max(1,i.siblingIndex??1),resolvedName:r,className:i.className,updatedAt:new Date().toISOString()})}buildServiceTree(e,n){let i={name:n.serviceName,className:n.serviceClassName,childCount:0,children:[],syncedAt:new Date().toISOString()};for(let r of n.instances){let a=this.resolveEffectiveSegments(e,r.effectivePath),o=Zt(r.originalPath);this.upsertTreeNode(i,a,o,r.className)}return this.recomputeTreeChildCounts(i),i.syncedAt=new Date().toISOString(),i}resolveEffectiveSegments(e,n){return e.tmpIndex?Zt(n).map(i=>e.tmpIndex.sanitizeName(i)):Zt(n)}rewritePendingEffectivePaths(e,n,i,r){let a=Ne.relative(n,i).split(Ne.sep).filter(l=>l.length>0),o=Ne.relative(n,r).split(Ne.sep).filter(l=>l.length>0);if(a.length===0||o.length===0)return;let s=gt(["game",...a]),c=gt(["game",...o]);for(let l of e.instances){if(l.effectivePath===s){l.effectivePath=c;continue}(l.effectivePath.startsWith(`${s}.`)||l.effectivePath.startsWith(`${s}[`))&&(l.effectivePath=`${c}${l.effectivePath.slice(s.length)}`)}}upsertTreeNode(e,n,i,r){if(n.length<=1)return;let a=e.children;for(let o=1;o<n.length;o++){let s=n[o],c=i[o],l=o===n.length-1,u=a.find(d=>d.name===s);u?l&&(u.className=r,c!==void 0&&c!==s&&(u.originalName=c)):(u={name:s,className:l?r:"Folder",childCount:0,children:[]},c!==void 0&&c!==s&&(u.originalName=c),a.push(u)),u.children||(u.children=[]),a=u.children}}recomputeTreeChildCounts(e){let n=i=>{let r=i.children??[];i.children=r;for(let a of r)n(a);i.childCount=r.length};for(let i of e.children)n(i);e.childCount=e.children.length}clearTTLTimerForPlace(e,n){e.incompleteSyncTimer&&e.activeFullSyncSessionId===n&&(clearTimeout(e.incompleteSyncTimer),e.incompleteSyncTimer=null)}beginInitRequest(e){e.syncInitRequestsInFlight++}endInitRequest(e){e.syncInitRequestsInFlight=Math.max(0,e.syncInitRequestsInFlight-1)}async cleanupStaleTempDirs(){let e=this.ctx.config.getSyncRoot();try{let n=await On.readdir(e,{withFileTypes:!0});for(let i of n)if(i.isDirectory()){if(i.name.startsWith("explorer_tmp_")){let r=Ne.join(e,i.name);h.warn("Removing stale temp directory from crashed sync",{dir:i.name});try{await On.rm(r,{recursive:!0,force:!0})}catch(a){h.error(`Failed to remove stale temp dir: ${i.name}`,a instanceof Error?a:new Error(String(a)))}}if(i.name.startsWith("place_")){let r=Ne.join(e,i.name);try{let a=await On.readdir(r,{withFileTypes:!0});for(let o of a)if(o.isDirectory()&&o.name.startsWith("explorer_tmp_")){let s=Ne.join(r,o.name);h.warn("Removing stale temp directory from crashed sync",{dir:`${i.name}/${o.name}`});try{await On.rm(s,{recursive:!0,force:!0})}catch(c){h.error(`Failed to remove stale temp dir: ${i.name}/${o.name}`,c instanceof Error?c:new Error(String(c)))}}}catch{continue}}}}catch(n){if(n.code==="ENOENT")return;h.warn("Failed to scan for stale temp dirs",{error:n instanceof Error?n.message:String(n)})}}};import _r from"path";import{promises as ux}from"fs";yr();ce();var dx=class{constructor(e){this.ctx=e}async handleReversePending(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({pending:0,hasConflicts:!1,lastDetected:null});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}let a={pending:r.fileWatcher?.getPendingCount()??0,hasConflicts:!1,lastDetected:r.fileWatcher?.getLastDetected()??null,forwardRestoreNeeded:r.forwardRestoreQueue.length};this.ctx.touchRuntimePlace(i),n.status(200).json(a)}async handleReverseSyncChanges(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({changes:[],count:0});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}if(r.state!=="syncing"){n.status(400).json({error:"Not syncing",message:"Reverse sync is only available when sync is active"});return}let a=r.fileWatcher?.drainPendingChanges()??[],o=a.length>0?await r.reader.buildChangesFromPending(a):[];this.ctx.touchRuntimePlace(i),n.status(200).json({changes:o,count:o.length})}async handleReverseSyncResult(e,n){let i=e.body,r=i.placeId??this.ctx.getDefaultRuntimePlaceId();if(r==null){n.status(400).json({error:"Validation error",message:"placeId is required (in body or via active sync session)"});return}let a=i.appliedFiles??i.appliedPaths;if(!a||!Array.isArray(a)){n.status(400).json({error:"Validation error",message:"appliedFiles (or appliedPaths) must be an array of relative file paths"});return}let o=this.ctx.places.get(r);if(!o){n.status(404).json({error:"Place not found",message:`No sync context for place ${r}`});return}this.ctx.touchRuntimePlace(r);let s=this.ctx.config.getPlaceRoot(r),c=0,l=[];for(let u of a){let d=_r.resolve(s,u);if(!ax(s,d)){l.push({path:u,error:"Path is outside the place root"});continue}try{let p=await ux.readFile(d,"utf-8"),f=o.index.computeHash(p);o.index.updateHashByValue(d,f),o.index.updateFileHashByValue(d,f),c++}catch(p){let f=p.code;if(f==="ENOENT"){o.index.removeHash(d),o.index.removeHashesUnder(d);let m=this.resolveInstancePathForAppliedPath(o.index,d);if(m){let g=ct(m),y=_t(m);y&&g&&await o.writer.removeFromTree(y,g)}c++}else f==="EISDIR"?c++:l.push({path:u,error:p instanceof Error?p.message:String(p)})}}c>0&&await o.index.saveToDisk(),c>0&&o.writer.appendHistory({timestamp:new Date().toISOString(),type:"reverseApply",direction:"reverse",source:"local",path:`place_${r}`,details:`applied:${c} failed:${l.length}`}),n.status(200).json({updated:c,failed:l.length,errors:l})}async handleResolveConflict(e,n){let i=e.body;if(!i.fsPath||!i.resolution){n.status(400).json({error:"Validation error",message:"fsPath and resolution are required"});return}let{fsPath:r,resolution:a}=i,o=this.ctx.config.getSyncRoot();if(!ax(o,_r.resolve(o,r))){n.status(403).json({error:"Forbidden",message:"Path is outside the sync root"});return}if(a==="skip"){n.status(200).json({status:"skipped",fsPath:r});return}let s;if(i.placeId&&(s=this.ctx.places.get(i.placeId)),!s){let p=r.match(/^place_(\d+)(?:_[^/]+)?\//);if(p){let f=parseInt(p[1],10);s=this.ctx.places.get(f)}else s=Array.from(this.ctx.places.values())[0]}if(!s){n.status(404).json({error:"No active place context",message:"No sync session is active. Start a sync first."});return}let c=this.ctx.config.getPlaceRoot(s.placeId),l=_r.resolve(c,r);if(!ax(c,l)){n.status(403).json({error:"Forbidden",message:"Path is outside the place root"});return}let u=s.index,d=s.reader;if(a==="apply-studio"){if(typeof i.studioContent!="string"){n.status(400).json({error:"Validation error",message:"studioContent is required for apply-studio resolution"});return}await ux.mkdir(_r.dirname(l),{recursive:!0});let p=i.studioContent,f=u.computeHash(p);s.fileWatcher?.suppressPath(l,f),await ux.writeFile(l,p,"utf-8"),u.updateHashByValue(l,f),u.updateFileHashByValue(l,f),await u.saveToDisk(),n.status(200).json({status:"resolved",resolution:"apply-studio",fsPath:r});return}if(a==="apply-file"){let p=await ux.readFile(l,"utf-8"),f=u.computeHash(p);u.resolveFile(l,"apply-file",f),await u.saveToDisk();let m=d.getFileType(l),g=d.resolveInstancePathFromFile(l);n.status(200).json({status:"resolved",resolution:"apply-file",fsPath:r,instancePath:g,fileType:m,content:p});return}n.status(400).json({error:"Invalid resolution",message:`Unknown resolution: ${a}`})}async handleReverseRescan(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({added:0});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}if(!r.fileWatcher){n.status(200).json({added:0});return}let a=await r.fileWatcher.rescan();this.ctx.touchRuntimePlace(i),h.info("Reverse rescan completed",{placeId:i,added:a}),n.status(200).json({added:a})}resolveInstancePathForAppliedPath(e,n){let i=e.resolveInstancePathFromFsPath(n);if(i)return i;let r=e.getExplorerRoot(),a=_r.relative(r,n);if(a.startsWith("..")||a===""||_r.isAbsolute(a))return null;let o=a.split(_r.sep).filter(f=>f.length>0);if(o.length<2)return null;let s=_r.basename(n),c=_r.dirname(n),l=e.getOriginalInstance(c,s);if(l)return l.instancePath;let u=s.toLowerCase();if(kb.some(f=>u.endsWith(f))||u==="_tree.json")return null;let d=["game"],p=r;for(let f of o){p=_r.join(p,f);let m=_r.dirname(p);d.push(e.getOriginalNameForDir(m,f))}return gt(d)}};yr();Rb();ce();var kfe=5;function q8(t){if(!t||typeof t!="object")return;let e=t;if(Array.isArray(e.instances))for(let n of e.instances)Array.isArray(n.properties)&&n.properties.length===0&&(n.properties={}),Array.isArray(n.attributes)&&n.attributes.length===0&&(n.attributes={});if(Array.isArray(e.changes))for(let n of e.changes)Array.isArray(n.properties)&&n.properties.length===0&&(n.properties={}),Array.isArray(n.attributes)&&n.attributes.length===0&&(n.attributes={})}function Pfe(t){return t.type==="instanceAdded"||t.type==="instanceRemoved"||t.type==="instanceRenamed"||t.type==="instanceMoved"||t.type==="scriptSourceChanged"}var Wr=class{config;places;apiHandler;changeProcessor;initHandler;reverseHandler;reverseDetectorFactory;activeFullSyncPlaceId=null;activeRuntimeSyncPlaceId=null;currentConnectedPlaceId=null;currentConnectedPlaceName=null;constructor(e,n={}){this.config=new Sb(e,n),this.reverseDetectorFactory=n.reverseDetectorFactory??(i=>new nx(i.explorerRoot,i.syncIndex,{placeId:i.placeId})),this.apiHandler=new cx(this),this.changeProcessor=new ox(this),this.initHandler=new lx(this),this.reverseHandler=new dx(this),this.places=new ex({max:kfe,dispose:(i,r)=>{h.info("Disposing place context (LRU eviction)",{placeId:r}),this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),i.fileWatcher&&(h.info("Disposing place context: stopping reverse detector",{placeId:r,reason:"lru-dispose",mode:lt}),i.fileWatcher.stop("lru-dispose").catch(a=>{h.error("Error stopping reverse detector during dispose",a)}),i.fileWatcher=null),i.writer.stopChangeLogFlusher().catch(a=>{h.error("LRU dispose \uC911 changelog flush \uC2E4\uD328",a)}),i.incompleteSyncTimer&&(clearTimeout(i.incompleteSyncTimer),i.incompleteSyncTimer=null),i.index.clearAllMaps(),i.index.saveToDisk().catch(a=>{h.error("Error saving index during dispose",a)}),i.activeFullSyncSessionId&&this.initHandler.clearPendingServiceTrees(i.activeFullSyncSessionId),i.tmpWriter&&(i.tmpWriter.stopChangeLogFlusher(),i.tmpWriter=null),i.tmpIndex=null,i.collisionDirMap=null,i.activeSyncIdentityScope=null,i.syncInitRequestsInFlight=0}})}getSyncRoot(){return this.config.getSyncRoot()}async getOrCreatePlaceContext(e,n){let i=this.places.get(e);if(i&&n){let r=this.config.getPlaceRoot(e),a=await this.config.resolvePlaceRoot(e,n);a!==r&&(h.info("Place root migrated, recreating context",{placeId:e,from:r,to:a}),this.places.delete(e),i=void 0)}if(!i){let r=await this.config.resolvePlaceRoot(e,n),a=CR.join(r,"explorer");await wl.mkdir(r,{recursive:!0}),await wl.mkdir(a,{recursive:!0});let o=new za(r,a);await o.loadFromDisk();let s=new xl(this.config,o,e),c=new tx(this.config,o,r);s.startChangeLogFlusher(),i={placeId:e,placeName:"",index:o,writer:s,reader:c,fileWatcher:null,state:"idle",activeClientId:null,activeFullSyncSessionId:null,instanceCount:0,scriptCount:0,lastFullSync:null,lastIncrementalSync:null,tmpIndex:null,tmpWriter:null,incompleteSyncTimer:null,syncInitRequestsInFlight:0,changesSinceLastSave:0,directions:{...qo},applyModes:{...Bo},forwardRestoreQueue:[],syncProgress:null,collisionDirMap:null,activeSyncIdentityScope:null},this.places.set(e,i),h.info("Created new place context",{placeId:e,placeRoot:r})}return i}async handleSyncInit(e,n){try{q8(e.body);let i=z8(e.body);if(!i.success){n.status(400).json({error:"Validation error",message:i.error});return}let r=i.data,a=r.phase==="start"?r.placeId??null:r.phase==="chunk"||r.phase==="complete"?this.activeFullSyncPlaceId:null;if(a==null){n.status(400).json({error:"Missing placeId",message:"placeId is required in start phase or must be set by previous start"});return}switch(r.phase){case"start":this.setCurrentConnectedPlace(a,r.placeName),await this.initHandler.handleInitStart(a,r,n);break;case"chunk":await this.initHandler.handleInitChunk(a,r,n);break;case"complete":await this.initHandler.handleInitComplete(a,r,n);break}}catch(i){this.sendError(n,i,"handleSyncInit")}}async handleSyncUpdate(e,n){try{q8(e.body);let i=L8(e.body);if(!i.success){n.status(400).json({error:"Validation error",message:i.error});return}let r=i.data,a=r.placeId??this.getDefaultRuntimePlaceId();if(a==null){n.status(400).json({error:"Missing placeId",message:"placeId is required in body or must have an active sync session"});return}let o=await this.getOrCreatePlaceContext(a);if(this.setCurrentConnectedPlace(a,o.placeName||this.currentConnectedPlaceName),o.activeFullSyncSessionId!==null||o.state==="initializing"){n.status(409).json({error:"Conflict",message:`Full sync in progress for place ${a}`});return}o.activeClientId=r.clientId,this.touchRuntimePlace(a);let s=N8(o,r.changes);h.info("Sync update received",{placeId:a,clientId:r.clientId,changeCount:s.length,receivedCount:r.changes.length,types:s.map(m=>m.type)});let c=[],l=[],u=0,d=!1,p=new Map;for(let m of s)try{let g=await this.changeProcessor.processChangeForPlace(o,m,p);g?l.push(g):(u++,Pfe(m)&&(d=!0))}catch(g){let y="path"in m?m.path:"oldPath"in m?m.oldPath:"unknown";c.push({path:y,error:g instanceof Error?g.message:String(g)})}for(let m of p.values())try{await rx(o,m)}catch(g){c.push({path:m.instancePath,error:g instanceof Error?g.message:String(g)})}if(d)try{let m=this.config.getSyncRoot(),g=this.config.getPlaceRoot(a);await Eb(m,g),await al(m)}catch(m){h.warn("Failed to refresh sourcemaps after incremental sync update",{placeId:a,error:m instanceof Error?m.message:String(m)})}o.changesSinceLastSave+=u,o.changesSinceLastSave>=M8&&(await o.index.saveToDisk(),o.changesSinceLastSave=0),o.lastIncrementalSync=new Date().toISOString();let f={processed:u,failed:c.length,errors:c,syncedAt:o.lastIncrementalSync};l.length>0&&(f.conflicts=l),n.status(200).json(f)}catch(i){this.sendError(n,i,"handleSyncUpdate")}}getDefaultRuntimePlaceId(){return this.currentConnectedPlaceId}getDefaultRuntimePlaceName(){if(this.currentConnectedPlaceName)return this.currentConnectedPlaceName;if(this.currentConnectedPlaceId!==null&&this.currentConnectedPlaceId!==void 0){let e=this.places.get(this.currentConnectedPlaceId);if(e?.placeName)return e.placeName}return null}setCurrentConnectedPlace(e,n){if(this.currentConnectedPlaceId=e,e==null){this.currentConnectedPlaceName=null;return}if(typeof n=="string"&&n.length>0){this.currentConnectedPlaceName=n;let r=this.places.get(e);r&&(r.placeName=n);return}let i=this.places.get(e);i?.placeName&&(this.currentConnectedPlaceName=i.placeName)}clearCurrentConnectedPlaceIfMatch(e){this.currentConnectedPlaceId===e&&(this.currentConnectedPlaceId=null,this.currentConnectedPlaceName=null)}touchRuntimePlace(e){this.activeRuntimeSyncPlaceId=e}clearRuntimePlaceIfMatch(e){this.activeRuntimeSyncPlaceId===e&&(this.activeRuntimeSyncPlaceId=null)}resolveQueryPlaceId(e,n="runtime"){let i=e.query.placeId;if(i){let r=parseInt(i,10);if(!isNaN(r))return r}return n==="full"?this.activeFullSyncPlaceId:this.getDefaultRuntimePlaceId()}async handleSyncStatus(e,n){try{let i=u=>({state:"idle",instanceCount:0,scriptCount:0,lastFullSync:null,lastIncrementalSync:null,syncRoot:u,activeClientId:null,reverseSyncAvailable:!1,modifiedFileCount:0,reverseDetectorActive:!1,reverseDetectorMode:lt,fileWatcherActive:!1}),r=this.resolveQueryPlaceId(e);if(r==null){let u=i(this.config.getSyncRoot());n.status(200).json(u);return}let a=this.places.get(r);if(!a){let u=i(this.config.getPlaceRoot(r));n.status(200).json(u);return}let o=a.fileWatcher?.getPendingCount()??0,s=a.fileWatcher?.isActivelyScanning()??!1,c=a.fileWatcher!==null;this.touchRuntimePlace(r);let l={state:a.state,instanceCount:a.instanceCount,scriptCount:a.scriptCount,lastFullSync:a.lastFullSync,lastIncrementalSync:a.lastIncrementalSync,syncRoot:this.config.getPlaceRoot(r),activeClientId:a.activeClientId,reverseSyncAvailable:o>0,modifiedFileCount:o,applyModes:a.applyModes,directions:a.directions,reverseDetectorActive:s,reverseDetectorMode:lt,fileWatcherActive:c,forwardOnlyClasses:[...il]};n.status(200).json(l)}catch(i){this.sendError(n,i,"handleSyncStatus")}}async handleSyncStop(e,n){try{let i=e.body,r=i.placeId??this.getDefaultRuntimePlaceId();if(h.info("handleSyncStop requested",{placeId:r,clientId:i.clientId??null,reason:i.reason??"requested"}),r==null){n.status(200).json({status:"idle",state:"idle",placeId:null,message:"No active sync place"});return}let a=this.places.get(r);if(!a){h.info("handleSyncStop no place context",{placeId:r,clientId:i.clientId??null}),n.status(200).json({status:"idle",state:"idle",placeId:r,message:`No sync context for place ${r}`});return}if(i.clientId&&a.activeClientId&&i.clientId!==a.activeClientId&&(a.activeFullSyncSessionId!==null||a.state==="syncing"||a.state==="initializing")){h.warn("handleSyncStop rejected due to active client mismatch",{placeId:r,requestedClientId:i.clientId,activeClientId:a.activeClientId,state:a.state,activeFullSyncSessionId:a.activeFullSyncSessionId}),n.status(409).json({error:"Conflict",message:`This sync session belongs to client ${a.activeClientId}`});return}let o=a.activeFullSyncSessionId,s=a.state,c=a.fileWatcher!==null;if(o&&(this.initHandler.clearPreserveLocalFiles(o),this.initHandler.clearPendingServiceTrees(o)),a.fileWatcher&&(h.info("handleSyncStop suspending reverse detector",{placeId:r,state:a.state,activeClientId:a.activeClientId,mode:lt}),a.fileWatcher.beginFullSyncReplacement()),a.incompleteSyncTimer&&(clearTimeout(a.incompleteSyncTimer),a.incompleteSyncTimer=null),o){let l=this.config.getPlaceRoot(r),u=CR.join(l,`explorer_tmp_${o}`);await wl.rm(u,{recursive:!0,force:!0}).catch(()=>{})}a.tmpWriter&&(a.tmpWriter.stopChangeLogFlusher(),a.tmpWriter=null),a.tmpIndex=null,a.collisionDirMap=null,a.activeSyncIdentityScope=null,a.syncInitRequestsInFlight=0,a.activeFullSyncSessionId=null,a.syncProgress=null,a.state="idle",a.activeClientId=null,a.instanceCount=0,a.scriptCount=0,a.forwardRestoreQueue=[],this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),this.clearRuntimePlaceIfMatch(r),h.info("handleSyncStop responding idle",{placeId:r,previousState:s,activeFullSyncSessionId:o,hadWatcher:c}),h.info("Sync stopped",{placeId:r,reason:i.reason??"requested"}),n.status(200).json({status:"stopped",state:"idle",placeId:r})}catch(i){this.sendError(n,i,"handleSyncStop")}}async initialize(){try{await this.config.loadFromMeta(),await this.initHandler.cleanupStaleTempDirs(),h.info("SyncController initialized")}catch(e){h.error("SyncController initialization failed",e instanceof Error?e:new Error(String(e)))}}async shutdown(){try{h.info("SyncController shutdown: clearing place contexts",{placeCount:this.places.size}),this.places.clear(),h.info("SyncController shut down")}catch(e){h.error("SyncController shutdown error",e instanceof Error?e:new Error(String(e)))}}async atomicWriteFile(e,n){let i=e+".tmp."+Ife().slice(0,8);try{await wl.writeFile(i,n,"utf-8"),await wl.rename(i,e)}catch(r){throw await wl.unlink(i).catch(()=>{}),r}}async handlePreCheck(e,n){try{await this.apiHandler.handlePreCheck(e,n)}catch(i){this.sendError(n,i,"handlePreCheck")}}async handleSyncDirections(e,n){try{await this.apiHandler.handleSyncDirections(e,n)}catch(i){this.sendError(n,i,"handleSyncDirections")}}async handleForwardRestoreList(e,n){try{await this.apiHandler.handleForwardRestoreList(e,n)}catch(i){this.sendError(n,i,"handleForwardRestoreList")}}async handleReversePending(e,n){try{await this.reverseHandler.handleReversePending(e,n)}catch(i){this.sendError(n,i,"handleReversePending")}}async handleReverseSyncChanges(e,n){try{await this.reverseHandler.handleReverseSyncChanges(e,n)}catch(i){this.sendError(n,i,"handleReverseSyncChanges")}}async handleReverseSyncResult(e,n){try{await this.reverseHandler.handleReverseSyncResult(e,n)}catch(i){this.sendError(n,i,"handleReverseSyncResult")}}async handleResolveConflict(e,n){try{await this.reverseHandler.handleResolveConflict(e,n)}catch(i){this.sendError(n,i,"handleResolveConflict")}}async handleReverseRescan(e,n){try{await this.reverseHandler.handleReverseRescan(e,n)}catch(i){this.sendError(n,i,"handleReverseRescan")}}async handleSyncHistory(e,n){try{await this.apiHandler.handleSyncHistory(e,n)}catch(i){this.sendError(n,i,"handleSyncHistory")}}async startFileWatcherForPlace(e){if(e.state!=="syncing"){h.debug("Skipping reverse detector start - place not syncing",{placeId:e.placeId,state:e.state});return}if(e.fileWatcher){if(e.fileWatcher.isActivelyScanning()){h.info("startFileWatcherForPlace: reusing active reverse detector",{placeId:e.placeId,mode:lt});return}h.info("startFileWatcherForPlace: resuming paused reverse detector",{placeId:e.placeId,mode:lt}),e.fileWatcher.endFullSyncReplacement();return}let n=this.createReverseChangeDetector(e);this.configureReverseChangeDetector(e,n),e.fileWatcher=n,n.start().then(()=>{e.fileWatcher===n&&h.info("Reverse detector started for reverse sync",{placeId:e.placeId,mode:lt})}).catch(i=>{h.warn("Failed to start reverse detector",{placeId:e.placeId,mode:lt,error:i instanceof Error?i.message:String(i)}),e.fileWatcher===n&&(e.fileWatcher=null)})}createReverseChangeDetector(e){return this.reverseDetectorFactory({explorerRoot:CR.join(this.config.getPlaceRoot(e.placeId),"explorer"),syncIndex:e.index,placeId:e.placeId})}configureReverseChangeDetector(e,n){e.writer.setOnWriteCallback(i=>{n.suppressPath(i)}),n.setDirectionChecker(i=>{let r=v6(i);return e.directions[r]}),n.setOnForwardViolation(i=>{e.forwardRestoreQueue.includes(i)||(e.forwardRestoreQueue.push(i),h.info("Forward violation queued for restore",{placeId:e.placeId,relativePath:i,queueSize:e.forwardRestoreQueue.length}))})}getStatusSummary(){return this.apiHandler.getStatusSummary()}getDirectionForCategory(e){return this.apiHandler.getDirectionForCategory(e)}getStatusDirect(e){return this.apiHandler.getStatusDirect(e)}async getHistoryDirect(e,n){return this.apiHandler.getHistoryDirect(e,n)}getDirectionsDirect(e){return this.apiHandler.getDirectionsDirect(e)}getProgressDirect(e){return this.apiHandler.getProgressDirect(e)}async readSyncedFile(e,n){return this.apiHandler.readSyncedFile(e,n)}async writeSyncedFile(e,n,i){await this.apiHandler.writeSyncedFile(e,n,i)}async executeViaDisk(e,n){return this.apiHandler.executeViaDisk(e,n)}sendError(e,n,i){let r=n instanceof Error?n.message:String(n);if(r.includes("Path traversal detected")){e.status(403).json({error:"Forbidden",message:r});return}let a=n.code;if(a==="ENOSPC"||a==="EPERM"||a==="EACCES"){h.warn(`SyncController.${i} disk error`,{code:a,message:r}),e.status(500).json({error:"Disk error",message:r,code:a,operation:i});return}h.error(`SyncController.${i} failed`,n instanceof Error?n:new Error(r)),e.status(500).json({error:"Internal error",message:`${i}: ${r}`})}};import{randomUUID as Efe}from"crypto";function B8(t,e){let n=Efe(),i=n.replace(/-/g,"").substring(0,8).toUpperCase(),r=`${i.substring(0,4)}-${i.substring(4,8)}`;return{config:t,app:e,instanceId:n,sessionId:r,startTime:Date.now(),baseUrl:`http://${t.httpHost}:${t.httpPort}`,commandQueue:new Map,pendingCommands:new Map,globalPendingCommands:[],totalCommandsProcessed:0,pluginClients:new Map,pluginCommandSessionsByClientId:new Map,pluginCommandClientIdsByProcessToken:new Map,mcpInstances:new Map,cachedSelectionMap:new Map,studioRoutingMode:"recentPriority",pinnedTargetClientId:null,isClientMode:!1,clientModeHealthTimer:null,clientModeConsecutiveHealthFailures:0,clientModeUpstreamReachable:!0,clientModeUpstreamContextCaptureEnabled:!0,clientModeLastHealthSuccessAt:null,clientModeLastHealthFailureAt:null,clientModeLastHealthError:null,shuttingDown:!1,onUpstreamPermanentlyDown:null,clientModeIdleTimeoutMs:t.clientModeIdleTimeoutMs??36e5,clientModeIdleWatchdogTimer:null,shutdownFn:null,historyManager:null,analyticsManager:null,executionContextManager:null,licenseState:null,syncController:null,internalCommandExecutor:null,dashboardFolderPicker:null,assetLibraryOpenCloudServiceFactory:null,activeSyncOwnerInstanceId:null,activeProjectRoot:null,pendingDashboardSyncRootPin:null,playtestControlCommand:null,dashboardSyncRootSwitchInFlight:!1,uiStudioRecorders:new Map,aiClientName:"",pluginVersion:"",syncedSessionToken:null,serverLastCommandAt:null}}var H8=It(Pa(),1);ce();function Z8(t){let e=H8.default.json({limit:"5mb"});t.app.use((n,i,r)=>{if(n.path.startsWith("/sync/")){r();return}e(n,i,r)}),t.app.use((n,i,r)=>{i.setHeader("Access-Control-Allow-Origin","http://localhost:3002"),i.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),i.setHeader("Access-Control-Allow-Headers","Content-Type"),r()}),t.app.use((n,i,r)=>{h.debug(`${n.method} ${n.path}`,{ip:n.ip}),r()})}ya();import{randomUUID as qx}from"crypto";ya();ce();function Rfe(){let t=process.env.WEPPY_ROBLOX_MCP_VERSION?.trim();return t||null}var tt=Rfe()??"2.9.0";xi();Xn();sf();Aa();ll();ya();Aa();var Y8="studio-",Afe=/^studio-[1-9]\d*$/;function gx(t){return Afe.test(t)}function X8(t,e){let n=new Set;for(let i of t)e!==void 0&&i.clientId===e||i.targetAlias&&gx(i.targetAlias)&&n.add(i.targetAlias);return n}function $fe(t,e){let n=X8(t,e),i=1;for(;n.has(`${Y8}${i}`);)i+=1;return`${Y8}${i}`}function hx(t,e){let n=X8(t,e.clientId);return e.targetAlias&&gx(e.targetAlias)&&!n.has(e.targetAlias)||(e.targetAlias=$fe(t,e.clientId)),e.targetAlias}ll();function yx(t){for(let e of t)hx(t,e)}function vx(t){let e={clientId:t.clientId,targetAlias:t.targetAlias??t.clientId.slice(0,8),lastSeen:t.lastSeen,connectedAt:t.connectedAt,transport:"websocket",connectionState:t.commandSessionState??He.CONNECTED};return t.placeId!==void 0&&(e.placeId=t.placeId),t.placeName!==void 0&&(e.placeName=t.placeName),t.pluginVersion!==void 0&&(e.pluginVersion=t.pluginVersion),t.studioVersion!==void 0&&(e.studioVersion=t.studioVersion),t.lastRoutedAt!==void 0&&(e.lastRoutedAt=t.lastRoutedAt),t.processToken!==void 0&&(e.processToken=t.processToken),t.inFlightRequestId!==void 0&&(e.inFlightRequestId=t.inFlightRequestId),e}function AR(t){let e=vn(t);return yx(e),Kp(e.map(vx),null)}function bx(t){let e=new Set;t.aiClientName&&e.add(t.aiClientName);for(let n of t.mcpInstances.values())n.aiClientName&&e.add(n.aiClientName);return Array.from(e)}function Q8(t){let n=Date.now();for(let[i,r]of t.mcpInstances)r.lastSeen&&n-r.lastSeen>15e3&&(t.mcpInstances.delete(i),r.sessionId&&t.executionContextManager?.endSession(r.sessionId),h.debug("Removed stale MCP instance",{instanceId:i,lastSeen:r.lastSeen}))}function eq(t,e,n){let i=e.query.clientId;if(i&&t.pluginClients.has(i)){let r=t.pluginClients.get(i);r.lastSeen=Date.now()}try{let r=e.body;if(!r||!Array.isArray(r.selection)||typeof r.count!="number"){h.warn("Invalid selection update request",{body:r}),n.status(400).json({error:"Invalid request body"});return}let a=i||"unknown",o=Date.now();t.cachedSelectionMap.set(a,{selection:r.selection,count:r.count,timestamp:o,clientId:a}),h.debug("Selection cache updated",{count:r.count,clientId:a,timestamp:o}),n.json({status:"ok",timestamp:o})}catch(r){h.error("Error handling selection update",r),n.status(500).json({error:"Internal server error"})}}function tq(t,e,n){let i=parseInt(e.query.maxAge)||3e4,r=cf(t,i);r?n.json({cached:!0,...r}):n.json({cached:!1,message:"No cached selection available"})}function cf(t,e=3e4,n){if(t.cachedSelectionMap.size===0)return null;let i;if(n)i=t.cachedSelectionMap.get(n);else for(let a of t.cachedSelectionMap.values())(!i||a.timestamp>i.timestamp)&&(i=a);if(!i)return null;let r=Date.now()-i.timestamp;return e===0||r<=e?i:null}function $R(t,e){let n=t.pluginClients.get(e.clientId),i=Date.now(),r=[...t.pluginClients.values()].filter(c=>c.clientId===e.clientId||c.commandSessionState!==He.DISCONNECTED),a=n??{clientId:e.clientId,connectedAt:i,lastSeen:i,commandsProcessed:0,connectionType:"polling"},o=hx(r,a),s={clientId:e.clientId,targetAlias:o,projectName:e.projectName??n?.projectName,placeName:e.placeName??n?.placeName,placeId:e.placeId??n?.placeId,pluginVersion:e.pluginVersion??n?.pluginVersion,studioVersion:e.studioVersion??n?.studioVersion,connectedAt:n?.connectedAt||i,lastSeen:i,commandsProcessed:n?.commandsProcessed||0,connectionType:n?.connectionType||"polling",inFlightRequestId:n?.inFlightRequestId,...n?.commandSessionState?{commandSessionState:n.commandSessionState}:{},...n?.processToken?{processToken:n.processToken}:{}};return t.pluginClients.set(e.clientId,s),t.syncController&&typeof t.syncController.setCurrentConnectedPlace=="function"&&typeof e.placeId=="number"&&Number.isFinite(e.placeId)&&t.syncController.setCurrentConnectedPlace(e.placeId,e.placeName??null),t.pendingCommands.has(e.clientId)||t.pendingCommands.set(e.clientId,[]),e.pluginVersion&&(t.pluginVersion=e.pluginVersion),typeof s.placeId=="number"&&Number.isFinite(s.placeId)&&Hb(t,s.placeId,s.placeName??null),t.analyticsManager&&(e.pluginVersion&&t.analyticsManager.setPluginVersion(e.pluginVersion),t.analyticsManager.trackPluginConnected()),h.info("Plugin client registered",{clientId:e.clientId,targetAlias:o,projectName:e.projectName,placeName:e.placeName,isReconnect:!!n}),{clientInfo:s,sessionId:t.sessionId,mcpVersion:tt,mcpInstanceCount:t.mcpInstances.size+1,aiClientNames:bx(t)}}function OR(t,e){let n=t.pluginClients.get(e),i=t.pluginClients.has(e),r=n?.commandSessionState===He.CONNECTED;if(t.pluginClients.delete(e),t.pendingCommands.delete(e),i&&cl(t,e),i&&t.syncController&&typeof t.syncController.clearCurrentConnectedPlaceIfMatch=="function"&&typeof n?.placeId=="number"&&Number.isFinite(n.placeId)){let a=[...t.pluginClients.values()].filter(o=>typeof o.placeId=="number"&&Number.isFinite(o.placeId)).sort((o,s)=>s.lastSeen-o.lastSeen)[0];a?t.syncController.setCurrentConnectedPlace?.(a.placeId??null,a.placeName??null):t.syncController.clearCurrentConnectedPlaceIfMatch(n.placeId)}return r&&Jp(t,e,"disconnected",n),h.info("Plugin client unregistered",{clientId:e,existed:i}),i}function xx(t,e,n){try{let i=e.body;if(!i.clientId){n.status(400).json({error:"Missing clientId"});return}let r=$R(t,{clientId:i.clientId,projectName:i.projectName,placeName:i.placeName,placeId:i.placeId,pluginVersion:i.pluginVersion,studioVersion:i.studioVersion});n.json({status:"ok",clientId:i.clientId,targetAlias:r.clientInfo.targetAlias,serverInstanceId:t.instanceId,sessionId:r.sessionId,mcpVersion:r.mcpVersion,connectedAt:r.clientInfo.connectedAt,aiClientNames:r.aiClientNames,serverStartTime:t.startTime,mcpInstanceCount:r.mcpInstanceCount})}catch(i){h.error("Error registering plugin client",i),n.status(500).json({error:"Internal server error"})}}function _x(t,e,n){let i=e.body?.clientId;if(!i){n.status(400).json({error:"Missing clientId"});return}let r=OR(t,i);n.json({status:"ok",existed:r})}function nq(t,e,n){try{let i=e.body;if(!i.instanceId){n.status(400).json({error:"Missing instanceId"});return}let r=Date.now(),a={instanceId:i.instanceId,...typeof i.sessionId=="string"?{sessionId:i.sessionId}:{},pid:i.pid,connectedAt:r,isServer:!1,lastSeen:r};i.aiClientName&&(a.aiClientName=i.aiClientName),i.cwd&&(a.cwd=i.cwd),"projectRoot"in i&&(a.projectRoot=i.projectRoot),t.mcpInstances.set(i.instanceId,a),et(t,"mcp_status",{aiClientName:a.aiClientName??"Unknown",instanceId:i.instanceId,status:"registered"}),fl(t,{timestamp:new Date().toISOString(),type:"mcp",status:"registered",instanceId:i.instanceId,message:`MCP registered \u2014 ${a.aiClientName??i.instanceId}`,...a.aiClientName?{aiClientName:a.aiClientName}:{}}),h.info("MCP instance registered (client mode)",{instanceId:i.instanceId,pid:i.pid,cwd:i.cwd}),n.json({status:"ok",instanceId:i.instanceId,serverInstanceId:t.instanceId,sessionId:t.sessionId,mcpVersion:tt,mcpInstanceCount:t.mcpInstances.size+1})}catch(i){h.error("Error registering MCP instance",i),n.status(500).json({error:"Internal server error"})}}function rq(t,e,n){let i=e.body?.instanceId;if(!i){n.status(400).json({error:"Missing instanceId"});return}let r=t.mcpInstances.get(i),a=!!r;t.mcpInstances.delete(i),r?.sessionId&&t.executionContextManager?.endSession(r.sessionId),a&&(et(t,"mcp_status",{aiClientName:r?.aiClientName??"Unknown",instanceId:i,status:"unregistered"}),fl(t,{timestamp:new Date().toISOString(),type:"mcp",status:"unregistered",instanceId:i,message:`MCP unregistered \u2014 ${r?.aiClientName??i}`,...r?.aiClientName?{aiClientName:r.aiClientName}:{}})),h.info("MCP instance unregistered",{instanceId:i,existed:a}),n.json({status:"ok",existed:a})}function iq(t,e,n){let{instanceId:i,aiClientName:r}=e.body;if(i&&r){let a=t.mcpInstances.get(i);a&&(a.aiClientName=r)}n.json({status:"ok"})}function aq(t){let e=3e4,n=Date.now(),i=hr({appDataDir:t.config.appDataDir});for(let[a,o]of t.pluginClients)n-o.lastSeen>e&&(t.pluginClients.delete(a),t.pendingCommands.delete(a),cl(t,a));Q8(t);let r=vn(t);return yx(r),{serverInstanceId:t.instanceId,sessionId:t.sessionId,mcpVersion:tt,uptime:n-t.startTime,serverStartTime:t.startTime,serverExecutable:process.execPath,serverHost:t.config.httpHost,serverPort:t.config.httpPort,serverPid:process.pid,pluginClients:r.map(vx),studioRoutingMode:t.studioRoutingMode,pinnedTargetClientId:t.pinnedTargetClientId,mcpInstances:[{instanceId:t.instanceId,pid:process.pid,connectedAt:t.startTime,isServer:!0,cwd:process.cwd(),projectRoot:i,lastSeen:n,...t.aiClientName?{aiClientName:t.aiClientName}:{}},...Array.from(t.mcpInstances.values())],mcpInstanceCount:t.mcpInstances.size+1}}function Sx(t,e){e.json(aq(t))}function wx(t,e,n){let i=e.query.instanceId;i&&t.mcpInstances.has(i)&&(t.mcpInstances.get(i).lastSeen=Date.now()),Q8(t);let r=vn(t);yx(r);let s={...{status:"online",connectedClients:r.length,queuedCommands:e8(t),uptime:Date.now()-t.startTime,version:tt,enableContextCapture:t.executionContextManager?.isEnabled()??t.config.enableContextCapture??!0,isClientMode:t.isClientMode,shuttingDown:t.shuttingDown,pid:process.pid,sessionId:t.sessionId,nodeVersion:process.version,studioRoutingMode:t.studioRoutingMode,pinnedTargetClientId:t.pinnedTargetClientId},instanceId:t.instanceId,mcpInstanceCount:t.mcpInstances.size+1,aiClientNames:bx(t),pluginVersion:t.pluginVersion||void 0,dashboardSseClients:t.dashboardSseClients?.size??0,websocketClients:r.length,pluginClients:r.map(vx),...t.isClientMode?{upstream:{reachable:t.clientModeUpstreamReachable,consecutiveFailures:t.clientModeConsecutiveHealthFailures,lastSuccessAt:t.clientModeLastHealthSuccessAt,lastFailureAt:t.clientModeLastHealthFailureAt,lastError:t.clientModeLastHealthError,baseUrl:t.baseUrl}}:{}};n.json(s)}function oq(t,e,n,i){let r=e.ip||e.socket.remoteAddress||"";if(!(r==="127.0.0.1"||r==="::1"||r==="::ffff:127.0.0.1"||r==="localhost")){h.warn("Shutdown request rejected from non-localhost",{ip:r}),n.status(403).json({error:"Forbidden: localhost only"});return}h.info("Shutdown request received, initiating graceful shutdown",{requestedBy:r,uptime:Date.now()-t.startTime}),n.json({status:"shutting_down",message:"Server will shutdown gracefully",pid:process.pid}),setTimeout(async()=>{try{await i(),h.info("Graceful shutdown completed"),process.exit(0)}catch(o){h.error("Error during graceful shutdown",o),process.exit(1)}},100)}async function Cx(t){if(t.isClientMode)try{let e=await fetch(`${t.baseUrl}/connection-info`);if(e.ok)return await e.json()}catch(e){h.warn("Failed to fetch connection info from server",{error:e})}return aq(t)}Aa();var ut={bridgeRunTest:"manage_studio_run_test_bridge",placeInfo:"system_info_place_info",clearLogs:"manage_logs_clear",createScript:"manage_scripts_create",getLogs:"manage_logs_get",deleteScript:"manage_scripts_delete",canonical:{playStart:"manage_studio_play_start",playStop:"manage_studio_play_stop",playPause:"manage_studio_play_pause",playResume:"manage_studio_play_resume",playStatus:"manage_studio_play_status",runTest:"manage_studio_run_test"}},Dfe=new Set([ut.canonical.runTest]),Nfe=new Set([ut.canonical.playStop]),s4e=new Set([ut.canonical.playStart,ut.canonical.playStop,ut.canonical.playPause,ut.canonical.playResume,ut.canonical.playStatus]);function Gr(t){return Dfe.has(t)}function lf(t){return Nfe.has(t)}var d4e=ut.canonical.playStop,sq=[5e3,15e3];ll();var jfe=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm","manage_assets_import_rbxm","manage_assets_generate_thumbnail"]),tn=class t extends Error{code;routing;constructor(e,n,i){super(n),this.name="CommandTargetSelectionError",this.code=e,this.routing=i,Object.setPrototypeOf(this,t.prototype)}};function Mfe(t={},e){let n={},i=t.clientId,r=t.targetAlias,a=t.placeId;if(i!==void 0){if(typeof i!="string"||i.trim().length===0)throw new tn("invalid_target_selector","clientId target selector must be a non-empty string",{selectionMode:"clientId",...typeof i=="string"?{requestedClientId:i.trim()}:{}});n.requestedClientId=i.trim()}if(r!==void 0){if(typeof r!="string"||r.trim().length===0)throw new tn("invalid_target_selector","targetAlias target selector must be a non-empty string",{selectionMode:"targetAlias",...typeof r=="string"?{requestedTargetAlias:r.trim()}:{}});n.requestedTargetAlias=r.trim()}if(a!==void 0&&zfe(e,t)){if(typeof a!="number"||!Number.isFinite(a))throw new tn("invalid_target_selector","placeId target selector must be a finite number",{selectionMode:"placeId"});n.requestedPlaceId=a}return n}function Ix(t,e,n={},i){let r=Mfe(n,i),a=A6(e,t.studioRoutingMode==="pinned"?t.pinnedTargetClientId:null);if(r.requestedClientId!==void 0)return Lfe(a,r);if(r.requestedTargetAlias!==void 0)return Ufe(a,r);if(r.requestedPlaceId!==void 0)return Ffe(a,r);if(t.studioRoutingMode==="pinned"&&t.pinnedTargetClientId!==null){let s=a.find(c=>c.clientId===t.pinnedTargetClientId);if(s)return{targetClientId:s.clientId,routing:Sr("pinnedTarget",r,s)}}let o=a[0];return o?{targetClientId:o.clientId,routing:Sr("recentPriority",r,o)}:{routing:{selectionMode:"globalQueue"}}}function zfe(t,e){return!t||!jfe.has(t)?!0:e.scope==="shared"}function Lfe(t,e){let n=t.find(i=>i.clientId===e.requestedClientId);if(!n)throw new tn("target_client_not_found",`Target client not found: ${e.requestedClientId}`,Sr("clientId",e));if(e.requestedTargetAlias!==void 0&&n.targetAlias!==e.requestedTargetAlias)throw new tn("target_selector_mismatch",`Target client ${n.clientId} does not match targetAlias ${e.requestedTargetAlias}`,Sr("clientId",e,n));return cq("clientId",e,n),{targetClientId:n.clientId,routing:Sr("clientId",e,n)}}function Ufe(t,e){let n=t.find(i=>i.targetAlias!==void 0&&gx(i.targetAlias)&&i.targetAlias===e.requestedTargetAlias);if(!n)throw new tn("target_alias_not_found",`Target alias not found: ${e.requestedTargetAlias}`,Sr("targetAlias",e));return cq("targetAlias",e,n),{targetClientId:n.clientId,routing:Sr("targetAlias",e,n)}}function Ffe(t,e){let n=t.filter(r=>r.placeId===e.requestedPlaceId);if(n.length===0)throw new tn("target_place_not_found",`Target place not found: ${e.requestedPlaceId}`,Sr("placeId",e));if(n.length>1)throw new tn("target_place_ambiguous",`Target place is ambiguous: ${e.requestedPlaceId}`,Sr("placeId",e));let i=n[0];return{targetClientId:i.clientId,routing:Sr("placeId",e,i)}}function cq(t,e,n){if(e.requestedPlaceId!==void 0&&n.placeId!==e.requestedPlaceId)throw new tn("target_selector_mismatch",`Target client ${n.clientId} is not connected to placeId ${e.requestedPlaceId}`,Sr(t,e,n))}function Sr(t,e,n){let i={selectionMode:t};return e.requestedClientId!==void 0&&(i.requestedClientId=e.requestedClientId),e.requestedTargetAlias!==void 0&&(i.requestedTargetAlias=e.requestedTargetAlias),e.requestedPlaceId!==void 0&&(i.requestedPlaceId=e.requestedPlaceId),n!==void 0&&(i.actualClientId=n.clientId,n.targetAlias!==void 0&&(i.actualTargetAlias=n.targetAlias),n.placeId!==void 0&&(i.actualPlaceId=n.placeId),n.placeName!==void 0&&(i.actualPlaceName=n.placeName)),i}GE();ce();rf();var kl={query_instances:{discriminator:"action",validActions:new Set(["get","children","find_child","find_descendant","wait_for_child","class_info","search_name","search_class","search_property","search_tag","file_tree","project_structure","descendants","ancestors"]),paramAliases:{query_instances_search_name:{query:"pattern"},query_instances_search_property:{root:"rootPath"},query_instances_search_tag:{root:"rootPath"},query_instances_project_structure:{root:"rootPath"}}},mutate_instances:{discriminator:"action",validActions:new Set(["create","create_with_props","delete","clone","move","rename","pivot","create_tree","mass_create","mass_delete","mass_duplicate","smart_duplicate"]),paramAliases:{mutate_instances_clone:{path:"sourcePath"},mutate_instances_smart_duplicate:{spacing:"offset"}}},manage_properties:{discriminator:"action",validActions:new Set(["get","set","get_all","set_multiple","get_attr","set_attr","get_all_attrs","delete_attr","add_tag","remove_tag","check_tag","get_tags","get_tagged","set_calculated","set_relative","mass_set","mass_get","modify_children"]),paramAliases:{manage_properties_get_tagged:{tagName:"tag",root:"rootPath"},manage_properties_set_relative:{amount:"value"}}},manage_scripts:{discriminator:"action",validActions:new Set(["get_source","set_source","create","delete","edit_replace","edit_insert","edit_delete","search","replace","get_dependencies"]),paramAliases:{manage_scripts_edit_replace:{newLines:"newContent"},manage_scripts_edit_insert:{lines:"content"},manage_scripts_replace:{pattern:"searchPattern"}}},manage_ui:{discriminator:"action",validActions:new Set(["design_brief","create_tree","update","delete","preview","check"])},manage_lighting:{discriminator:"action",validActions:new Set(["lighting","atmosphere","sky","terrain_props","time"])},manage_selection:{discriminator:"action",validActions:new Set(["get","set","clear","cached","context","details","add","remove","watch"])},manage_camera:{discriminator:"action",validActions:new Set(["info","focus_path","focus_position","suggest","screenshot"]),paramAliases:{manage_camera_suggest:{path:"targetPath"}}},manage_tween:{discriminator:"action",validActions:new Set(["create","play","pause","cancel"])},manage_audio:{discriminator:"action",validActions:new Set(["play","stop","pause","resume","set_listener"])},manage_animation:{discriminator:"action",validActions:new Set(["load","play","stop","get_tracks"])},manage_physics:{discriminator:"action",validActions:new Set(["register_group","set_collidable","get_groups"])},manage_effects:{discriminator:"action",validActions:new Set(["emit","clear","toggle"])},manage_terrain:{discriminator:"action",validActions:new Set(["fill_block","fill_ball","fill_cylinder","fill_wedge","clear_region","clear_bounds","replace_material","colors_get","colors_set","read_voxel","read_voxels","write_voxels","generate","smooth"])},spatial_query:{discriminator:"action",validActions:new Set(["raycast","find_ground","check_placement","multi_raycast","scan_area","find_flat","find_spawn","analyze_walkable","spatial_map","find_space","bounds","snap_grid","collision"]),paramAliases:{spatial_query_spatial_map:{path:"rootPath"}}},manage_assets:{discriminator:"action",validActions:new Set(["insert","info","search","search_insert","insert_free","insert_package","export_selection_json","export_selection_rbxm","export_path_rbxm","import_rbxm","generate_thumbnail"]),paramAliases:{manage_assets_search:{maxResults:"limit"}}},manage_open_cloud_assets:{discriminator:"action",validActions:new Set(["credential_status","capabilities","upload","update","info","operation_status"])},manage_sync:{discriminator:"action",validActions:new Set(["status_current_place","history","directions","read_file","write_file","progress"])},workspace_state:{discriminator:"action",validActions:new Set(["sync","snapshot","changes","viewport","clear_history","metadata","scripts","selection_info","clear_cache"])},manage_logs:{discriminator:"action",validActions:new Set(["get","clear","errors"]),paramAliases:{manage_logs_get:{level:"type"}}},system_info:{discriminator:"action",validActions:new Set(["ping","connection","usage","place_info","services","studio_settings"])},manage_studio:{discriminator:"action",validActions:new Set(["toggle_ui_preview","play_start","play_stop","play_pause","play_resume","play_status","run_test"])}};var qfe={manage_selection_cached:"internal",manage_open_cloud_assets_credential_status:"internal",manage_open_cloud_assets_capabilities:"internal",manage_open_cloud_assets_upload:"internal",manage_open_cloud_assets_update:"internal",manage_open_cloud_assets_info:"internal",manage_open_cloud_assets_operation_status:"internal",manage_sync_status_current_place:"internal",manage_sync_history:"internal",manage_sync_directions:"internal",manage_sync_read_file:"internal",manage_sync_write_file:"internal",manage_sync_progress:"internal",system_info_connection:"internal",manage_studio_run_test:"internal"};function kx(t){return qfe[t]||"plugin"}var lq=new Set(["batch_execute","execute_luau","extended_call_method","extended_call_methods","extended_get_properties","extended_get_property","extended_set_properties","extended_set_property","manage_animation_get_tracks","manage_animation_load","manage_animation_play","manage_animation_stop","manage_assets_export_path_rbxm","manage_assets_export_selection_json","manage_assets_export_selection_rbxm","manage_assets_generate_thumbnail","manage_assets_import_rbxm","manage_assets_info","manage_assets_insert","manage_assets_insert_free","manage_assets_insert_package","manage_assets_search","manage_assets_search_insert","manage_audio_pause","manage_audio_play","manage_audio_resume","manage_audio_set_listener","manage_audio_stop","manage_camera_screenshot","manage_effects_clear","manage_effects_emit","manage_effects_toggle","manage_lighting_atmosphere","manage_lighting_lighting","manage_lighting_sky","manage_lighting_terrain_props","manage_lighting_time","manage_open_cloud_assets_capabilities","manage_open_cloud_assets_credential_status","manage_open_cloud_assets_info","manage_open_cloud_assets_operation_status","manage_open_cloud_assets_update","manage_open_cloud_assets_upload","manage_physics_get_groups","manage_physics_register_group","manage_physics_set_collidable","manage_properties_mass_get","manage_properties_mass_set","manage_properties_modify_children","manage_properties_set_calculated","manage_properties_set_relative","manage_scripts_replace","manage_selection_add","manage_selection_context","manage_selection_details","manage_selection_remove","manage_selection_watch","manage_studio_play_pause","manage_studio_play_resume","manage_studio_play_start","manage_studio_play_status","manage_studio_play_stop","manage_studio_run_test","manage_studio_toggle_ui_preview","manage_sync_directions","manage_sync_history","manage_sync_progress","manage_sync_read_file","manage_sync_status_current_place","manage_sync_write_file","manage_terrain_clear_bounds","manage_terrain_clear_region","manage_terrain_colors_get","manage_terrain_colors_set","manage_terrain_fill_ball","manage_terrain_fill_block","manage_terrain_fill_cylinder","manage_terrain_fill_wedge","manage_terrain_generate","manage_terrain_read_voxel","manage_terrain_read_voxels","manage_terrain_replace_material","manage_terrain_smooth","manage_terrain_write_voxels","manage_tween_cancel","manage_tween_create","manage_tween_pause","manage_tween_play","manage_ui_check","manage_ui_create_tree","manage_ui_delete","manage_ui_design_brief","manage_ui_preview","manage_ui_update","mutate_instances_create_tree","mutate_instances_mass_create","mutate_instances_mass_delete","mutate_instances_mass_duplicate","mutate_instances_smart_duplicate","query_instances_ancestors","query_instances_descendants","query_instances_file_tree","query_instances_project_structure","query_instances_search_property","query_instances_search_tag","spatial_query_analyze_walkable","spatial_query_bounds","spatial_query_check_placement","spatial_query_collision","spatial_query_find_flat","spatial_query_find_ground","spatial_query_find_space","spatial_query_find_spawn","spatial_query_multi_raycast","spatial_query_raycast","spatial_query_scan_area","spatial_query_snap_grid","spatial_query_spatial_map","system_info_place_info","system_info_services","system_info_studio_settings","workspace_state_changes","workspace_state_clear_cache","workspace_state_clear_history","workspace_state_metadata","workspace_state_scripts","workspace_state_selection_info","workspace_state_snapshot","workspace_state_sync","workspace_state_viewport"]),DR=new Set(["system_info_connection","system_info_ping","system_info_usage"]);function Nn(t){return lq.has(t)?"pro":"basic"}wi();Px();import{readFile as sme}from"node:fs/promises";import cme from"node:path";import{createHash as nme,randomUUID as zR}from"node:crypto";import{mkdir as mf,readFile as bq,readdir as xq,rename as _q,rm as rme,stat as ime,writeFile as $x}from"node:fs/promises";import jt from"node:path";import{extname as Vfe}from"node:path";import{stat as Wfe}from"node:fs/promises";var Gfe=20*1024*1024,yq=[{category:"image",assetType:"Image",folder:"images",extensions:[".png",".jpeg",".jpg",".bmp",".tga"],supportsContentUpdate:!1,contentTypes:{".png":"image/png",".jpeg":"image/jpeg",".jpg":"image/jpeg",".bmp":"image/bmp",".tga":"image/tga"}},{category:"decal",assetType:"Decal",folder:"decals",extensions:[".png",".jpeg",".jpg",".bmp",".tga"],supportsContentUpdate:!1,contentTypes:{".png":"image/png",".jpeg":"image/jpeg",".jpg":"image/jpeg",".bmp":"image/bmp",".tga":"image/tga"}},{category:"audio",assetType:"Audio",folder:"audio",extensions:[".mp3",".ogg",".wav",".flac"],supportsContentUpdate:!1,contentTypes:{".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".flac":"audio/flac"}},{category:"mesh",assetType:"Mesh",folder:"meshes",extensions:[".mesh"],supportsContentUpdate:!1,contentTypes:{".mesh":"application/octet-stream"}},{category:"model",assetType:"Model",folder:"models",extensions:[".fbx",".gltf",".glb",".rbxm",".rbxmx"],supportsContentUpdate:!0,contentTypes:{".fbx":"model/fbx",".gltf":"model/gltf+json",".glb":"model/gltf-binary",".rbxm":"model/x-rbxm",".rbxmx":"model/x-rbxm"}},{category:"video",assetType:"Video",folder:"videos",extensions:[".mp4",".mov"],supportsContentUpdate:!1,contentTypes:{".mp4":"video/mp4",".mov":"video/quicktime"}},{category:"animation",assetType:"Animation",folder:"animations",extensions:[".rbxm",".rbxmx"],supportsContentUpdate:!0,contentTypes:{".rbxm":"model/x-rbxm",".rbxmx":"model/x-rbxm"}}],Kfe=new Map(yq.map(t=>[t.category,t]));function pq(t){if(!t)throw new Error("Open Cloud asset upload is disabled in WEPPY Dashboard settings.")}function Ex(t,e){return t.split(e.apiKey).join("[redacted]")}function jR(t){let e=Kfe.get(t);if(!e)throw new Error(`Unsupported asset category: ${t}`);return e}function Rx(t){return jR(t)}function fq(t,e){let n=t.creatorType??e.creatorType,i=t.creatorId??e.creatorId;if(!n||!i)throw new Error("creatorType and creatorId are required for Roblox Open Cloud asset upload/update.");return{...t,creatorType:n,creatorId:i}}async function mq(t,e,n){let i=Vfe(e).toLowerCase(),r=t.contentTypes[i];if(!r)throw new Error(`Unsupported file extension ${i||"(none)"} for ${t.category}.`);if((await Wfe(e)).size>n)throw new Error(`Asset file is too large. Maximum size is ${n} bytes.`);return r}function gq(t){return typeof t.path=="string"&&t.path.startsWith("operations/")?t.path:null}function hq(t,e,n,i){let r={apiKey:t.apiKey,operationId:e};return n!==void 0&&(r.intervalMs=n),i!==void 0&&(r.timeoutMs=i),r}var Pl=class{client;credentialStore;isOpenCloudUploadEnabled;maxFileSizeBytes;constructor(e){this.client=e.client,this.credentialStore=e.credentialStore,this.isOpenCloudUploadEnabled=e.isOpenCloudUploadEnabled,this.maxFileSizeBytes=e.maxFileSizeBytes??Gfe}getCapabilities(){return yq.map(({contentTypes:e,...n})=>n)}async uploadAsset(e){pq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=fq(e,n),r=jR(i.category),a=await mq(r,i.filePath,this.maxFileSizeBytes);try{let o={apiKey:n.apiKey,assetType:r.assetType,displayName:i.displayName,description:i.description??"",creatorType:i.creatorType,creatorId:i.creatorId,filePath:i.filePath,contentType:a};i.expectedPrice!==void 0&&(o.expectedPrice=i.expectedPrice);let s=await this.client.createAsset(o);if(i.waitForOperation){let c=gq(s);return c?await this.client.pollOperation(hq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(Ex(o instanceof Error?o.message:String(o),n))}}async updateAsset(e){pq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=fq(e,n),r=jR(i.category),a;if(i.filePath){if(!r.supportsContentUpdate)throw new Error(`${r.category} assets do not support content updates.`);a=await mq(r,i.filePath,this.maxFileSizeBytes)}try{let o={apiKey:n.apiKey,assetId:i.assetId,assetType:r.assetType,creatorType:i.creatorType,creatorId:i.creatorId};i.filePath&&(o.filePath=i.filePath),a!==void 0&&(o.contentType=a),i.displayName!==void 0&&(o.displayName=i.displayName),i.description!==void 0&&(o.description=i.description),i.updateMask!==void 0&&(o.updateMask=i.updateMask),i.expectedPrice!==void 0&&(o.expectedPrice=i.expectedPrice);let s=await this.client.updateAsset(o);if(i.waitForOperation){let c=gq(s);return c?await this.client.pollOperation(hq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(Ex(o instanceof Error?o.message:String(o),n))}}async getAsset(e){let n=await this.getRequiredCredential();try{let i={apiKey:n.apiKey,assetId:e.assetId};return e.readMask!==void 0&&(i.readMask=e.readMask),await this.client.getAsset(i)}catch(i){throw new Error(Ex(i instanceof Error?i.message:String(i),n))}}async getOperation(e){let n=await this.getRequiredCredential();try{return await this.client.getOperation({apiKey:n.apiKey,operationId:e.operationId})}catch(i){throw new Error(Ex(i instanceof Error?i.message:String(i),n))}}async getRequiredCredential(){let e=await this.credentialStore.getCredentialForUse();if(!e)throw new Error("Configure a Roblox Open Cloud API key in WEPPY Dashboard before using Open Cloud asset upload.");return e}};import vq from"node:fs";import Vt from"node:path";wb();var Jfe=/^asset_(image|decal|audio|mesh|model|video|animation)_\d+_[a-z0-9]+$/;function Yfe(t){if(!Number.isInteger(t)||t<0)throw new Error(`Invalid place ID: ${t}`)}function Xfe(t,e){try{return vq.statSync(Vt.join(t,e,".sync-meta.json")).isFile()}catch{return!1}}function Qfe(t,e){Yfe(e.placeId);let n=`place_${e.placeId}`,i=e.placeName?nl(e.placeName):"",r=i?`${n}_${i}`:n,a=[];try{let o=new RegExp(`^place_${e.placeId}(?:_.*)?$`);a=vq.readdirSync(t,{withFileTypes:!0}).filter(s=>s.isDirectory()&&o.test(s.name)).map(s=>s.name).sort()}catch{return r}return i&&a.includes(r)?r:a.find(o=>Xfe(t,o))??(a.includes(r)?r:null)??a[0]??r}function MR(t){let e=Vt.resolve(t.projectSyncRoot),n=Rx(t.category).folder,i=t.scope.kind==="place"?Vt.join(e,Qfe(e,t.scope),"assets",n):Vt.join(e,"shared-assets",n);return{root:i,inbox:Vt.join(i,"inbox"),index:Vt.join(i,".asset-library-index.json")}}function eme(t){let e=Jfe.exec(t);return e?.[1]?e[1]:null}function df(t,e){let n=eme(t);return n?e?n===e:!0:!1}function Tx(t,e){if(!df(t,e))throw new Error(`Invalid asset ID: ${t}`)}function Kr(t,e){let n=Vt.relative(Vt.resolve(t),Vt.resolve(e));return n===""||!n.startsWith("..")&&!Vt.isAbsolute(n)}function tme(t){Tx(t.assetId,t.category);let e=MR(t),n=Vt.resolve(e.root,t.assetId);if(!Kr(e.root,n))throw new Error(`Invalid asset path for ${t.assetId}`);return n}function Ax(t){let e=tme(t),n=Vt.resolve(e,t.relativeFileName);if(!Kr(e,n))throw new Error(`Invalid asset file path for ${t.assetId}`);return n}function pf(t,e){return Vt.relative(Vt.resolve(t),Vt.resolve(e)).split(Vt.sep).join("/")}var Sq=20*1024*1024,ame=200;function wq(t,e){return t.kind!==e.kind?!1:t.kind==="shared"&&e.kind==="shared"?!0:t.kind==="place"&&e.kind==="place"&&t.placeId===e.placeId}function Cq(t,e){let n=jt.extname(t).toLowerCase(),i=Rx(e);if(!i.extensions.includes(n))return null;let r=i.contentTypes[n];return r?{canonicalExt:n,mimeType:r}:null}function LR(t,e,n){if(e!=="image"&&e!=="decal")return!0;let i=jt.extname(t).toLowerCase();return i===".png"?n.length>=8&&n[0]===137&&n[1]===80&&n[2]===78&&n[3]===71&&n[4]===13&&n[5]===10&&n[6]===26&&n[7]===10:i===".jpg"||i===".jpeg"?n.length>=3&&n[0]===255&&n[1]===216&&n[2]===255:i===".bmp"?n.length>=2&&n[0]===66&&n[1]===77:i===".tga"?n.length>0:!1}function Iq(t){return nme("sha256").update(t).digest("hex")}function Ox(t){return t.now?.()??Date.now()}function ome(t){return(t.randomId?.()??zR().replace(/-/g,"").slice(0,6)).toLowerCase().replace(/[^a-z0-9]/g,"").slice(0,12)||"asset"}function kq(t,e){let n=Math.floor(Ox(t)/1e3);for(let i=0;i<20;i++){let r=ome(t),a=i===0?`asset_${t.category}_${n}_${r}`:`asset_${t.category}_${n}_${r}${i}`;if(!e.has(a))return a}return`asset_${t.category}_${n}_${zR().replace(/-/g,"").slice(0,10)}`}function Pq(t){let e=jt.parse(t).name.trim();return e.length>0?e:t}function Eq(t){if(t.mimeType!=="image/png")throw new Error("Asset Library preview must be an image/png thumbnail");if(jt.basename(t.fileName).toLowerCase()!=="thumbnail.png")throw new Error("Asset Library preview file must be thumbnail.png");if(!LR("thumbnail.png","image",t.content))throw new Error("Asset Library preview is not a valid PNG file");return{fileName:"thumbnail.png",content:t.content}}async function UR(t,e){let n=`${t}.tmp.${zR().slice(0,8)}`;await $x(n,JSON.stringify(e,null,2),"utf8"),await _q(n,t)}async function Rq(t,e){try{let n=await bq(jt.join(e,"asset.json"),"utf8"),i=JSON.parse(n);return!df(i.id,t.category)||i.category!==t.category||!wq(i.scope,t.scope)?null:i}catch{return null}}async function ff(t,e){let n;try{n=await xq(e.root,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return[];throw r}let i=[];for(let r of n.sort((a,o)=>a.name.localeCompare(o.name))){if(!r.isDirectory()||!df(r.name,t.category))continue;let a=jt.join(e.root,r.name),o=await Rq(t,a);o&&i.push(o)}return i.sort((r,a)=>a.createdAt.localeCompare(r.createdAt)||a.id.localeCompare(r.id))}async function El(t,e,n){if(Tx(n.id,t.category),n.category!==t.category||!wq(n.scope,t.scope))throw new Error(`Asset metadata does not match library scope/category: ${n.id}`);let i=jt.join(e.root,n.id);if(!Kr(e.root,i))throw new Error(`Invalid asset path for ${n.id}`);await mf(i,{recursive:!0}),await UR(jt.join(i,"asset.json"),n)}async function Tq(t,e){await mf(t.root,{recursive:!0});let n={version:1,generatedAt:new Date().toISOString(),assets:e.map(i=>i.id)};await UR(t.index,n)}function Pi(t,e,n){return{fileName:t,reason:e,message:n}}async function Jr(t){let e=MR(t);return await mf(e.inbox,{recursive:!0}),e}async function Aq(t){let e=await Jr(t),n=await ff(t,e);return await Tq(e,n),n}async function Mt(t,e){Tx(e,t.category);let n=await Jr(t),i=jt.join(n.root,e);if(!Kr(n.root,i))throw new Error(`Invalid asset path for ${e}`);let r=await Rq(t,i);if(!r)throw new Error(`Asset not found: ${e}`);return r}async function Rl(t){let e=await Jr(t),n=await ff(t,e),i={version:1,generatedAt:new Date().toISOString(),assets:n.map(r=>r.id)};return await UR(e.index,i),i}async function $q(t){let e=await Jr(t),n=await ff(t,e),i=new Set(n.map(p=>p.id)),r=new Set(n.map(p=>p.file.sha256)),a=[],o=[],s=t.maxFileSizeBytes??Sq,c=t.maxFilesPerRescan??ame,l;try{l=await xq(e.inbox,{withFileTypes:!0})}catch(p){if(p?.code==="ENOENT")l=[];else throw p}let u=l.sort((p,f)=>p.name.localeCompare(f.name));for(let p=0;p<u.length;p++){let f=u[p];if(p>=c){o.push(Pi(f.name,"maxFileCount","rescan file count limit exceeded"));continue}if(f.name.startsWith(".")){o.push(Pi(f.name,"hidden","hidden or system file"));continue}if(f.isSymbolicLink()){o.push(Pi(f.name,"symlink","symlink files are not followed"));continue}if(f.isDirectory()){o.push(Pi(f.name,"nestedDirectory","nested directories are not scanned"));continue}if(!f.isFile()){o.push(Pi(f.name,"unsupportedType","unsupported inbox entry type"));continue}let m=Cq(f.name,t.category);if(!m){o.push(Pi(f.name,"unsupportedType",`unsupported ${t.category} extension`));continue}let g=jt.join(e.inbox,f.name),y=await ime(g);if(y.size>s){o.push(Pi(f.name,"oversized","asset file is larger than the configured limit"));continue}let v=await bq(g);if(!LR(f.name,t.category,v)){o.push(Pi(f.name,"invalidSignature","file signature does not match the extension"));continue}let x=Iq(v);if(r.has(x)){o.push(Pi(f.name,"duplicate","asset content already exists in Asset Library"));continue}let _=kq(t,i);i.add(_),r.add(x);let w=jt.join(e.root,_),C=`original${m.canonicalExt}`;await mf(w,{recursive:!0}),await _q(g,jt.join(w,C));let O=new Date(Ox(t)).toISOString(),L={version:1,id:_,category:t.category,scope:t.scope,status:"localOnly",displayName:Pq(f.name),description:"",source:{kind:"generated",originalPath:pf(t.projectSyncRoot,g)},file:{original:C,preview:null,mimeType:m.mimeType,sha256:x,sizeBytes:y.size,width:null,height:null,durationMs:null},roblox:{uploaded:!1},usage:{lastScannedAt:null,scanSource:null,references:[]},createdAt:O,updatedAt:O};await El(t,e,L),a.push(L)}let d=await ff(t,e);return await Tq(e,d),{assets:d,adopted:a,skipped:o,adoptedCount:a.length,skippedCount:o.length}}async function Oq(t){let e=await Jr(t),n=Cq(t.originalFileName,t.category);if(!n)throw new Error(`Unsupported ${t.category} extension for Asset Library export`);let i=t.maxFileSizeBytes??Sq;if(t.content.length>i)throw new Error("asset file is larger than the configured limit");if(!LR(t.originalFileName,t.category,t.content))throw new Error("file signature does not match the extension");let r=await ff(t,e),a=Iq(t.content),o=r.find(m=>m.file.sha256===a);if(o)return{asset:o,deduplicated:!0};let s=new Set(r.map(m=>m.id)),c=kq(t,s),l=jt.join(e.root,c);if(!Kr(e.root,l))throw new Error(`Invalid asset path for ${c}`);let u=`original${n.canonicalExt}`;await mf(l,{recursive:!0}),await $x(jt.join(l,u),t.content);let d=null;if(t.preview){let m=Eq(t.preview);d=m.fileName,await $x(jt.join(l,m.fileName),m.content)}let p=new Date(Ox(t)).toISOString(),f={version:1,id:c,category:t.category,scope:t.scope,status:"localOnly",displayName:t.displayName?.trim()||Pq(t.originalFileName),description:t.description??"",source:{...t.source,originalPath:pf(t.projectSyncRoot,jt.join(l,u))},file:{original:u,preview:d,mimeType:n.mimeType,sha256:a,sizeBytes:t.content.length,width:null,height:null,durationMs:null},roblox:{uploaded:!1},usage:{lastScannedAt:null,scanSource:null,references:[]},...t.rbxm?{rbxm:t.rbxm}:{},createdAt:p,updatedAt:p};return await El(t,e,f),await Rl(t),{asset:f,deduplicated:!1}}async function Dq(t){let e=await Jr(t),n=await Mt(t,t.assetId),i=Eq(t.preview),r=Ax({...t,relativeFileName:i.fileName});await $x(r,i.content);let a={...n,file:{...n.file,preview:i.fileName},updatedAt:new Date(Ox(t)).toISOString()};return await El(t,e,a),await Rl(t),{asset:a}}async function Nq(t,e,n){let i=await Jr(t),r=await Mt(t,e),a={...r,displayName:typeof n.displayName=="string"?n.displayName:r.displayName,description:typeof n.description=="string"?n.description:r.description,source:{...r.source,...n.source?.agent!==void 0?{agent:n.source.agent}:{},...n.source?.contextId!==void 0?{contextId:n.source.contextId}:{},...n.source?.prompt!==void 0?{prompt:n.source.prompt}:{}},updatedAt:new Date().toISOString()};return await El(t,i,a),await Rl(t),a}async function jq(t,e,n){let i=await Jr(t),a={...await Mt(t,e),usage:n,updatedAt:new Date().toISOString()};return await El(t,i,a),await Rl(t),a}async function Mq(t,e){let n=await Jr(t);await Mt(t,e);let i=jt.join(n.root,e);if(!Kr(n.root,i))throw new Error(`Invalid asset path for ${e}`);return await rme(i,{recursive:!0}),await Rl(t),{assetId:e,removed:1}}async function Fa(t){let e=await Jr(t);return await El(t,e,t.asset),await Rl(t),t.asset}async function Tl(t){let e=await Mt(t,t.assetId);return Ax({...t,relativeFileName:e.file.original})}async function zq(t){let e=await Mt(t,t.assetId);return Ax({...t,relativeFileName:e.file.preview??e.file.original})}var lme="manage_assets_import_rbxm",FR="manage_assets_generate_thumbnail",qR=new Set([lme,FR]),BR=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm"]),ume=new Set(["model","animation"]);function xn(t){return t&&typeof t=="object"?t:null}function dme(t){if(typeof t!="string"||!ume.has(t))throw new Error(`Unsupported Asset Library .rbxm round-trip category: ${String(t??"(missing)")}`);return t}function pme(t){if(typeof t=="number"&&Number.isInteger(t)&&t>=0)return t;if(typeof t=="string"&&t.trim().length>0){let e=Number.parseInt(t,10);if(Number.isInteger(e)&&e>=0)return e}return null}function Lq(t,e){for(let n of t.pluginClients.values())if(!(typeof n.placeId!="number"||!Number.isFinite(n.placeId))&&!(e!==void 0&&n.placeId!==e))return{placeId:n.placeId,...n.placeName?{placeName:n.placeName}:{}};return null}function HR(t,e){let n=mt(t.config.dataDir),i=dme(e.category),r=typeof e.scope=="string"?e.scope:"place",a=typeof e.assetLibraryAssetId=="string"&&e.assetLibraryAssetId.length>0?e.assetLibraryAssetId:void 0;if(r==="shared")return{projectSyncRoot:n,scope:{kind:"shared"},category:i,...a?{assetId:a}:{}};if(r!=="place")throw new Error(`Invalid Asset Library scope: ${r}`);let o=pme(e.placeId),s=t.syncController?.getDefaultRuntimePlaceId()??null,c=o??s??Lq(t)?.placeId??null;if(c===null)throw new Error("No placeId is available for Asset Library .rbxm round-trip.");let l=Lq(t,c);return{projectSyncRoot:n,scope:{kind:"place",placeId:c,...l?.placeName?{placeName:l.placeName}:{}},category:i,...a?{assetId:a}:{}}}function fme(t){if(cme.extname(t.file.original).toLowerCase()!==".rbxm")throw new Error(`Asset Library Studio round-trip supports original.rbxm only. Unsupported original file: ${t.file.original}`)}function mme(t,e){if(typeof t!="string"||t.trim().length===0)throw new Error(`${e} is missing`);return Buffer.from(t,"base64")}function gme(t,e){let n={kind:"studioExport",originalPath:"studio:selection"},i=xn(e);if(i){let r=typeof i.path=="string"?i.path:typeof i.kind=="string"?i.kind:void 0;r&&(n.originalPath=`studio:${r}`)}return typeof t.contextId=="string"&&(n.contextId=t.contextId),n}function Uq(t){let e=xn(t);if(!e)return;let n={};typeof e.width=="number"&&(n.width=e.width),typeof e.height=="number"&&(n.height=e.height),typeof e.source=="string"&&(n.source=e.source),typeof e.error=="string"&&(n.error=e.error);let i=Dx(e.attempts);return i.length>0&&(n.attempts=i),Object.keys(n).length>0?n:void 0}function wr(t,e){return typeof t!="string"?null:t.slice(0,e)}function Al(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function hme(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=xn(e);if(!n)return[];let i=wr(n.name,256),r=wr(n.className,128),a=wr(n.path,512);return i===null||r===null||a===null?[]:[{name:i,className:r,path:a}]}):[]}function yme(t){let e=xn(t);if(!e)return{};let n={};for(let[i,r]of Object.entries(e).slice(0,100))typeof r!="number"||!Number.isFinite(r)||r<0||(n[i.slice(0,128)]=Math.floor(r));return n}function vme(t){return Array.isArray(t)?t.slice(0,200).flatMap(e=>{let n=xn(e);if(!n)return[];let i=wr(n.path,512),r=wr(n.property,128),a=wr(n.value,1024);if(i===null||r===null||a===null)return[];let o=wr(n.assetId,64);return[{path:i,property:r,value:a,...o?{assetId:o}:{}}]}):[]}function Dx(t){return Array.isArray(t)?t.slice(0,8).flatMap(e=>{let n=xn(e);if(!n)return[];let i=wr(n.method,80),r=n.status==="success"||n.status==="failed"||n.status==="skipped"?n.status:null;if(i===null||r===null)return[];let a=wr(n.message,512);return[{method:i,status:r,...a?{message:a}:{}}]}):[]}function bme(t,e){let n=t.thumbnailMode==="auto"?"auto":"none";if(n==="none")return{mode:n,status:"skipped",message:"Thumbnail generation disabled"};let i=Uq(e),r=xn(e),a=typeof r?.pngBase64=="string"&&r.pngBase64.length>0,o=typeof r?.base64Rgba=="string"&&r.base64Rgba.length>0&&r.format==="rgba8"&&typeof r.width=="number"&&typeof r.height=="number";if(i&&(a||o)){let s=Al(i.width),c=Al(i.height),l=Dx(r?.attempts);return{mode:n,status:"generated",...s!==void 0?{width:s}:{},...c!==void 0?{height:c}:{},...typeof i.source=="string"?{source:i.source.slice(0,128)}:{},...l.length>0?{attempts:l}:{}}}if(i&&typeof i.error=="string"){let s=Dx(xn(e)?.attempts);return{mode:n,status:"failed",message:i.error.slice(0,512),...s.length>0?{attempts:s}:{}}}return{mode:n,status:"skipped",message:"Thumbnail was not returned"}}function xme(t,e){let n=xn(t);if(!n)return e;let i=n.mode==="auto"||n.mode==="none"?n.mode:e.mode,r=n.status==="generated"||n.status==="skipped"||n.status==="failed"?n.status:e.status,a=wr(n.message,512),o=Al(n.width),s=Al(n.height),c=wr(n.source,128),l=Dx(n.attempts);return{mode:i,status:r,...a?{message:a}:{},...o!==void 0?{width:o}:{},...s!==void 0?{height:s}:{},...c?{source:c}:{},...l.length>0?{attempts:l}:{}}}function _me(t){let e=xn(t.value),n=hme(e?.roots),i=yme(e?.classCounts),r=vme(e?.resourceReferences),a=Al(e?.exportedCount)??Al(t.exportedCount)??n.length;return{exportedCount:Math.max(0,Math.floor(a)),roots:n,classCounts:i,resourceReferences:r,thumbnail:xme(e?.thumbnail,t.fallbackThumbnail)}}function Sme(t){return t.length>=8&&t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71&&t[4]===13&&t[5]===10&&t[6]===26&&t[7]===10}function Fq(t){let e=xn(t);if(!e)return;let n=null;if(typeof e.pngBase64=="string"&&e.pngBase64.length>0?n=Buffer.from(e.pngBase64,"base64"):typeof e.base64Rgba=="string"&&e.base64Rgba.length>0&&e.format==="rgba8"&&typeof e.width=="number"&&typeof e.height=="number"&&(n=Buffer.from(dq(e.base64Rgba,e.width,e.height),"base64")),!!n){if(!Sme(n))throw new Error("Thumbnail payload is not a valid PNG image.");return{fileName:"thumbnail.png",content:n,mimeType:"image/png"}}}function wme(t,e){let n=e instanceof Error?e.message:String(e);return t.thumbnail.status!=="generated"?t:{...t,thumbnail:{...t.thumbnail,status:"failed",message:`Thumbnail payload could not be stored: ${n}`.slice(0,512)}}}async function qq(t){if(!qR.has(t.command))return t.params;let e=HR(t.ctx,t.params);if(!e.assetId)throw new Error("assetLibraryAssetId is required for Asset Library .rbxm round-trip.");let n=await Mt(e,e.assetId);fme(n);let i=await Tl({...e,assetId:n.id}),r=await sme(i);return{...t.params,__assetLibraryRbxmBase64:r.toString("base64"),__assetLibraryOriginalFile:n.file.original}}async function Bq(t){if(!BR.has(t.command)||!t.result.success)return t.result;let e=xn(t.result.data);if(!e)return t.result;let n=HR(t.ctx,t.params),i=mme(e.rbxmBase64,"Asset Library .rbxm export payload"),r=typeof t.params.displayName=="string"?t.params.displayName:void 0,a=typeof t.params.description=="string"?t.params.description:void 0,o=`${r?.trim()||"studio-export"}.rbxm`,s,c=null;try{s=Fq(e.thumbnail)}catch(p){c=p,s=void 0}let l=_me({value:e.rbxm,exportedCount:e.exportedCount,fallbackThumbnail:bme(t.params,e.thumbnail)});c&&(l=wme(l,c));let u=await Oq({projectSyncRoot:n.projectSyncRoot,scope:n.scope,category:n.category,originalFileName:o,content:i,...r!==void 0?{displayName:r}:{},...a!==void 0?{description:a}:{},source:gme(t.params,e.source),...s?{preview:s}:{},rbxm:l}),d=Uq(e.thumbnail);return{...t.result,data:{asset:u.asset,deduplicated:u.deduplicated,...typeof e.byteLength=="number"?{byteLength:e.byteLength}:{},...typeof e.exportedCount=="number"?{exportedCount:e.exportedCount}:{},...e.source!==void 0?{source:e.source}:{},...d?{thumbnail:d}:{}}}}async function Hq(t){if(!t.result.success)return t.result;let e=xn(t.result.data),n=xn(e?.thumbnail),i;try{i=Fq(n)}catch(o){return{...t.result,success:!1,error:o instanceof Error?o.message:String(o)}}if(!n||!i)return{...t.result,success:!1,error:typeof n?.error=="string"?n.error:"Thumbnail payload is missing from Asset Library thumbnail generation result."};let r=HR(t.ctx,t.params);if(!r.assetId)throw new Error("assetLibraryAssetId is required for Asset Library thumbnail generation.");let a=await Dq({projectSyncRoot:r.projectSyncRoot,scope:r.scope,category:r.category,assetId:r.assetId,preview:i});return{...t.result,data:{asset:a.asset,...typeof n.width=="number"?{width:n.width}:{},...typeof n.height=="number"?{height:n.height}:{},...typeof n.source=="string"?{source:n.source}:{}}}}function Cme(t){if(t===null||typeof t!="object")return;let e=t.proFallback;if(e===null||typeof e!="object")return;let n=e;if(typeof n.executedCommand!="string")return;let i=Array.isArray(n.alternatives)?n.alternatives.filter(r=>typeof r=="string"):void 0;return{executedCommand:n.executedCommand,...typeof n.requestedCommand=="string"?{requestedCommand:n.requestedCommand}:{},...i?{alternatives:i}:{}}}var Ime=/^Pro action '[^']+' is blocked in Basic mode\. Basic fallback '([^']+)' failed: (.*)$/s,kme=/^Pro action '[^']+' is blocked in Basic mode\.(?! Basic fallback ')/,Pme=/instance not found|not found in|parent not found/,Eme=/is required|missing required/,Rme=/unknown action|unknown command/,Tme=/must be|invalid|cannot/;function Ame(t){let e=Ime.exec(t);return e?{fallbackCommand:e[1],reason:e[2]}:null}function $me(t){return kme.test(t)}function Ome(t){let e=t.toLowerCase();return Pme.test(e)?"not_found":Eme.test(e)?"missing_param":Rme.test(e)?"unknown_action":Tme.test(e)?"validation":"other"}function ZR(t){return t.errorType==="bridge_error"||t.errorType==="command_timeout"||t.errorType==="plugin_runtime"||t.errorType==="exception"||t.errorType==="device_blocked"||t.failureOrigin==="bridge"||t.failureOrigin==="plugin_runtime"||t.failureOrigin==="server_exception"||t.failureOrigin==="product_bug"||t.failureOrigin==="unknown"||t.recoverability==="retry"||t.recoverability==="wait_connection"||t.recoverability==="unknown"?"error":"warning"}function $l(t){if(t.resultSuccess){let e=Cme(t.resultData);return e?{kind:"success_fallback",fallbackCommand:e.executedCommand,...e.alternatives?{alternatives:e.alternatives}:{}}:{kind:"success_ok"}}if(!t.resultError)return{kind:"error"};if(t.tier==="pro"){let e=Ame(t.resultError);if(e)return{kind:"blocked_fallback_failed",fallbackCommand:e.fallbackCommand,blockedDetail:Ome(e.reason)};if($me(t.resultError))return{kind:"blocked_unsupported"}}return t.failureClassification?{kind:ZR(t.failureClassification)}:{kind:"error"}}function xe(t,e,n,i,r={}){return{errorType:t,errorDetail:e,failureOrigin:n,recoverability:i,...r}}function Dme(t){let e=t.toLowerCase();return/^\s*compilation error:/.test(e)?xe("execution_failed","compile_error","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*result too large:/.test(e)?xe("execution_failed","result_too_large","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*execution timed out after/.test(e)?xe("execution_failed","execution_timeout","agent_request","code_fix",{validationStage:"plugin_handler"}):/potentially dangerous infinite loop|blocked in sandbox|access to .* is blocked|forbidden|not allowed|cannot access/.test(e)?xe("execution_failed","blocked_source","roblox_policy","code_fix",{validationStage:"plugin_handler"}):null}function Zq(t){let e=t.toLowerCase();return/upstream_server_down/.test(e)?xe("bridge_error","upstream_down","bridge","wait_connection"):/^http [45]\d\d/.test(e)?xe("bridge_error","http_error","bridge","retry"):/duplicate request\s*id/.test(e)?xe("bridge_error","duplicate_request_id","bridge","code_fix"):/timeout/.test(e)?xe("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|econnreset|epipe|network/.test(e)?xe("bridge_error","connection","bridge","wait_connection"):/abort/.test(e)?xe("command_timeout","aborted","bridge","retry"):/runtime error|traceback|attempt to/.test(e)?xe("plugin_runtime","runtime_error","plugin_runtime","code_fix"):/created instance, but failed to set \d+ propert/.test(e)?xe("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler",partialSuccess:"true"}):/failed to set property/.test(e)?xe("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler"}):/parent(?: instance)? not found/.test(e)?xe("execution_failed","parent_not_found","agent_request","fix_params",{validationStage:"plugin_handler"}):/(?:instance|path|root|source instance|ancestor instance) not found|target\s+(?:path\s+)?(?:['"`][^'"`]+['"`]\s+)?not found|not found in|no synced file found for instance/.test(e)?xe("execution_failed","not_found","user_project_state","fix_params",{validationStage:"plugin_handler"}):/is required|missing required/.test(e)?xe("execution_failed","missing_param","agent_request","fix_params",{validationStage:"schema"}):/invalid classname|invalid class/.test(e)?xe("execution_failed","invalid_class","agent_request","fix_params",{validationStage:"plugin_handler"}):/unknown action|unknown command/.test(e)?xe("execution_failed","unknown_action","agent_request","fix_params",{validationStage:"dispatcher"}):/failed to insert asset/.test(e)?xe("execution_failed","asset_error","roblox_policy","fix_params",{validationStage:"roblox_api"}):/failed to read property|property access denied/.test(e)?xe("execution_failed","property_error","agent_request","fix_params",{validationStage:"plugin_handler"}):/forbidden (?:path|parent path)|exceeds (?:total lines|max(?:imum)?(?: length)?)|is not (?:a|an) /.test(e)?xe("execution_failed","validation","agent_request","fix_params",{validationStage:"plugin_handler"}):/sync controller not available|project sync is not initialized|no active sync place|not found in sync cache/.test(e)?xe("execution_failed","sync_not_ready","user_project_state","wait_connection",{validationStage:"preflight"}):/cannot capture edit-mode screenshot while a playtest is active|play-mode screenshot capture is not supported/.test(e)?xe("execution_failed","unsupported_context","roblox_policy","no_retry",{validationStage:"preflight"}):/editableimage api is not enabled|allow mesh \/ image apis|allow http requests/.test(e)?xe("execution_failed","feature_disabled","roblox_policy","no_retry",{validationStage:"preflight"}):/must be|invalid|cannot/.test(e)?xe("execution_failed","validation","agent_request","fix_params",{validationStage:"plugin_handler"}):xe("execution_failed","other","unknown","unknown")}function Ol(t,e){if(t==="execute_luau"){let i=Dme(e);if(i)return i}let n=Zq(e);return t==="execute_luau"&&n.errorDetail==="runtime_error"&&/^\s*runtime error:/i.test(e)?xe("execution_failed","runtime_error","agent_request","code_fix"):n}function Vq(t){let n=(t instanceof Error?t.message:String(t)).toLowerCase();return/timeout/.test(n)?xe("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|network|econnreset|epipe/.test(n)?xe("bridge_error","connection","bridge","wait_connection"):/eaddrinuse/.test(n)?xe("bridge_error","port_in_use","bridge","no_retry"):xe("exception","unexpected","server_exception","code_fix")}Mx();import{randomBytes as Ume}from"node:crypto";var Fme=["manage_ui_create_tree","manage_ui_update","manage_ui_delete"],eB=["manage_ui_preview","manage_ui_check"],qme=["game_genre","ui_role","style_family","layout_family","device_policy","safe_area_policy","existing_ui_strategy"];function YR(t){return t&&typeof t=="object"?t:void 0}function KR(t){return typeof t=="number"&&Number.isFinite(t)?t:0}function zx(t){let e=YR(t);if(!e)return;let n={};for(let i of qme){let r=e[i];typeof r=="string"&&r.trim().length>0&&(n[i]=r)}return Object.keys(n).length>0?n:void 0}function JR(t){let e=zx(t.qualityPlanSummary);if(e)return e;let n=YR(t.contextSummary),i=zx(n?.qualityPlanSummary);if(i)return i;let r=zx(n?.qualityPlan);if(r)return r;let a=zx(n?.quality_plan);if(a)return a}function tB(t,e){return e?{...t??{},...e}:t}function Bme(t){return typeof t=="string"?{snapshotId:t}:t&&typeof t=="object"?{snapshotId:typeof t.snapshotId=="string"?t.snapshotId:null,...t.designCheckSummary!==void 0&&{designCheckSummary:t.designCheckSummary},...t.capturedAt!==void 0&&{capturedAt:t.capturedAt}}:{snapshotId:null}}function nB(t,e,n,i,r){if(!e)return;let a=KR(e.priority_high),o=KR(e.priority_medium),s=KR(e.priority_low),c=typeof e.total=="number"&&Number.isFinite(e.total)?e.total:a+o+s,l=n??(typeof e.target=="string"?e.target:void 0);return{source:t,...l!==void 0&&{targetPath:l},...typeof i=="string"&&{snapshotId:i},...r!==void 0&&{capturedAt:r},priority_high:a,priority_medium:o,priority_low:s,total:c}}function rB(t,e){if(!e)return t;if(!t)return e;let n=t.targetPath===e.targetPath?t.targetPath:void 0,i=t.snapshotId===e.snapshotId?t.snapshotId:void 0;return{source:e.source,...n!==void 0&&{targetPath:n},...i!==void 0&&{snapshotId:i},...e.capturedAt!==void 0&&{capturedAt:e.capturedAt},priority_high:t.priority_high+e.priority_high,priority_medium:t.priority_medium+e.priority_medium,priority_low:t.priority_low+e.priority_low,total:t.total+e.total}}function Hme(t){let e=YR(t);if(e)for(let n of["userMessage","intent","expectedBehavior"]){let i=e[n];if(typeof i=="string"&&i.trim().length>0)return i.trim().slice(0,80)}}function Zme(){return{source:"unavailable",priority_high:0,priority_medium:0,priority_low:0,total:0}}function iB(t){let e=t.now??Date.now,n=null,i=null,r=u=>`${u}_${e()}_${Ume(3).toString("hex")}`,a=()=>{i&&(clearTimeout(i),i=null)},o=()=>{a(),i=setTimeout(()=>{c("idle_timeout")},t.idleMs)},s=async u=>{try{return Bme(await t.capturePreview(u))}catch{return{snapshotId:null}}},c=async u=>{if(!n)return;a();let d=n;n=null;let p={},f;for(let y of d.affectedPaths)if(d.afterSnapshotsPathPolicy[y]==="skip")p[y]=null;else{let v=await s(y);p[y]=v.snapshotId,f=rB(f,nB("after_snapshot",v.designCheckSummary,y,v.snapshotId,v.capturedAt))}let m=f??d.latestDesignCheckSummary??Zme(),g={requestId:d.requestId,...d.contextId!==void 0&&{contextId:d.contextId},...d.label!==void 0&&{label:d.label},startedAt:d.startedAtIso,closedAt:new Date(e()).toISOString(),closeReason:u,ok:d.ok,affectedPaths:Array.from(d.affectedPaths).sort(),mutationCount:d.mutationCount,beforeSnapshots:d.beforeSnapshots,afterSnapshots:p,childMutationIds:d.childMutationIds,...d.qualityPlanSummary!==void 0&&{qualityPlanSummary:d.qualityPlanSummary},postChangeDesignCheckSummary:m};await Yq(t.placeDir,g)},l=u=>({requestId:r("req"),contextId:u.contextId,label:Hme(u.contextSummary),startedAtIso:new Date(e()).toISOString(),startedAtMs:e(),affectedPaths:new Set,beforeSnapshots:{},afterSnapshotsPathPolicy:{},childMutationIds:[],mutationCount:0,ok:!0,qualityPlanSummary:JR(u),latestDesignCheckSummary:void 0,pendingMutation:void 0});return{async beforeMutation(u){if(eB.includes(u.command)){if(n){let p=r("mut");n.qualityPlanSummary=tB(n.qualityPlanSummary,JR(u)),n.pendingMutation={mutationId:p,startedMs:e(),args:u}}return}if(!Fme.includes(u.command))return;n&&n.contextId!==u.contextId?await c("context_change"):n&&a(),n||(n=l(u)),n.qualityPlanSummary=tB(n.qualityPlanSummary,JR(u)),u.targetPath&&!(u.targetPath in n.beforeSnapshots)&&(n.affectedPaths.add(u.targetPath),u.command==="manage_ui_create_tree"?n.beforeSnapshots[u.targetPath]=null:n.beforeSnapshots[u.targetPath]=(await s(u.targetPath)).snapshotId,u.command==="manage_ui_delete"?n.afterSnapshotsPathPolicy[u.targetPath]="skip":u.targetPath in n.afterSnapshotsPathPolicy||(n.afterSnapshotsPathPolicy[u.targetPath]="capture"));let d=r("mut");n.pendingMutation={mutationId:d,startedMs:e(),args:u}},async afterMutation(u){if(!n?.pendingMutation)return;let{mutationId:d,args:p}=n.pendingMutation,f={mutationId:d,requestId:n.requestId,ts:new Date(e()).toISOString(),command:p.command,origin:p.origin,...p.targetPath!==void 0&&{targetPath:p.targetPath},...p.briefId!==void 0&&{briefId:p.briefId},...u.diffSummary!==void 0&&{diffSummary:u.diffSummary},...u.changeDetails!==void 0&&{changeDetails:u.changeDetails},ok:u.ok,...u.error!==void 0&&{error:u.error},durationMs:u.durationMs};if(await Xq(t.placeDir,f),n.pendingMutation=void 0,eB.includes(p.command)){n.latestDesignCheckSummary=rB(n.latestDesignCheckSummary,nB("check_results",u.designCheckSummary,p.targetPath,u.snapshotId,u.capturedAt));return}if(n.mutationCount++,n.childMutationIds.push(d),u.ok||(n.ok=!1),!n.contextId){await c("legacy_single");return}o()},async flushNow(){n&&await c("explicit")}}}var SB=100,Ige=12e4,kge=15e3,wB=new Set(["manage_ui_create_tree","manage_ui_update","manage_ui_delete"]);function Pge(t,e){return`License required for internal command ${t}. ${e??"Activate Pro license to use this feature."}`}var Ege={Text:{category:"text",label:"\uD14D\uC2A4\uD2B8"},PlaceholderText:{category:"text",label:"\uD50C\uB808\uC774\uC2A4\uD640\uB354"},TextColor3:{category:"color",label:"\uAE00\uC790\uC0C9"},BackgroundColor3:{category:"color",label:"\uBC30\uACBD\uC0C9"},BorderColor3:{category:"color",label:"\uD14C\uB450\uB9AC\uC0C9"},ImageColor3:{category:"color",label:"\uC774\uBBF8\uC9C0\uC0C9"},Size:{category:"size",label:"\uC0AC\uC774\uC988"},TextSize:{category:"size",label:"\uAE00\uC790 \uD06C\uAE30"},Position:{category:"layout",label:"\uC704\uCE58"},AnchorPoint:{category:"layout",label:"\uC575\uCEE4"},Rotation:{category:"layout",label:"\uD68C\uC804"},LayoutOrder:{category:"layout",label:"\uB808\uC774\uC544\uC6C3 \uC21C\uC11C"},Visible:{category:"state",label:"\uD45C\uC2DC \uC0C1\uD0DC"},Active:{category:"state",label:"\uD65C\uC131 \uC0C1\uD0DC"},Interactable:{category:"state",label:"\uC0C1\uD638\uC791\uC6A9 \uC0C1\uD0DC"},Selectable:{category:"state",label:"\uC120\uD0DD \uAC00\uB2A5"},Enabled:{category:"state",label:"\uD65C\uC131\uD654"},Image:{category:"asset",label:"\uC774\uBBF8\uC9C0"},Texture:{category:"asset",label:"\uD14D\uC2A4\uCC98"},SoundId:{category:"asset",label:"\uC0AC\uC6B4\uB4DC"}},Rge={text:"\uD14D\uC2A4\uD2B8",color:"\uCEEC\uB7EC",size:"\uC0AC\uC774\uC988",layout:"\uB808\uC774\uC544\uC6C3",state:"\uC0C1\uD0DC",asset:"\uC5D0\uC14B",property:"\uC18D\uC131"},Tge=Object.entries(kl).reduce((t,[e,n])=>{for(let i of n.validActions)t[`${e}_${i}`]=e;return t},{});function hB(t){return{toolName:Tge[t]||t,commandName:t}}function yB(t,e){if(typeof t.contextId=="string"||!e||typeof e!="object")return t;let n=e.contextId;return typeof n=="string"?{...t,contextId:n}:t}function Lx(t,e){if(t!=="manage_sync_status_current_place")return e;let{placeId:n,...i}=e;return i}function Age(t,e){let n=e.routing;return{requestId:t,success:!1,error:e.message,errorCode:e.code,routing:n,data:{routing:n}}}async function $ge(t,e){let n=t.syncController;if(!n)return null;try{let i=e.placeId,r=n.getDefaultRuntimePlaceId(),a=null;if(typeof i=="number"&&Number.isFinite(i))a=i;else if(typeof i=="string"&&i.trim().length>0){let s=Number.parseInt(i,10);Number.isFinite(s)&&(a=s)}if(a===null&&(a=r),a===null||!Number.isFinite(a))return null;let o=a===r?n.getDefaultRuntimePlaceName():null;return typeof o=="string"&&o.length>0?await n.config.resolvePlaceRoot(a,o):n.config.getPlaceRoot(a)}catch{return null}}function Oge(t){let e=t.tree;if(!e||typeof e!="object")return;let n=e,i=typeof n.name=="string"&&n.name.length>0?n.name:void 0;return i?`${typeof n.parent=="string"&&n.parent.length>0?n.parent:"StarterGui"}.${i}`:void 0}function Dge(t,e){let n=e.targetPath;if(typeof n=="string"&&n.length>0)return n;if(t==="manage_ui_create_tree")return Oge(e)}function Nge(t){let e=Ege[t];if(e)return e;let n=t.toLowerCase();return n.includes("color")?{category:"color",label:"\uC0C9\uC0C1"}:t==="Size"||n.endsWith("size")||n.includes("scale")?{category:"size",label:"\uC0AC\uC774\uC988"}:n.includes("position")||n.includes("anchor")||n.includes("rotation")||n.includes("layout")?{category:"layout",label:"\uB808\uC774\uC544\uC6C3"}:n.includes("visible")||n.includes("active")||n.includes("enabled")||n.includes("selectable")||n.includes("interactable")?{category:"state",label:"\uC0C1\uD0DC"}:n.includes("image")||n.includes("texture")||n.includes("sound")||n.includes("asset")?{category:"asset",label:"\uC5D0\uC14B"}:n.includes("text")||n.includes("placeholder")?{category:"text",label:"\uD14D\uC2A4\uD2B8"}:{category:"property",label:t}}function vB(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function jge(t){if(!t||typeof t!="object")return new Map;let e=t,n=e.changed_properties??e.changedProperties;if(!Array.isArray(n))return new Map;let i=new Map;for(let r of n){if(!r||typeof r!="object")continue;let a=r,o=a.property;if(typeof o!="string"||o.length===0)continue;let s=vB(a,"before"),c=vB(a,"after");i.set(o,{...s&&{before:a.before},...c&&{after:a.after},hasBefore:s,hasAfter:c})}return i}function CB(t,e){let i=t.changes?.properties;if(!i||typeof i!="object")return;let r=jge(e),a=Object.entries(i).map(([o,s])=>{let c=Nge(o),l=r.get(o),u={property:o,category:c.category,label:c.label,after:l?.hasAfter?l.after:s};return l?.hasBefore&&(u.before=l.before),u});return a.length>0?a:void 0}function IB(t){if(!t||t.length===0)return;let e=new Map;for(let r of t)e.set(r.category,(e.get(r.category)??0)+1);let i=["text","color","size","layout","state","asset","property"].map(r=>{let a=e.get(r)??0;return a>0?`${Rge[r]} ${a}\uAC1C`:null}).filter(r=>r!==null);return i.length>0?`${i.join(", ")} \uBCC0\uACBD`:void 0}function bB(t,e){if(t==="manage_ui_update"){let n=e.changes,i=IB(CB(e));if(i)return i;let r=n?.properties?Object.keys(n.properties).length:0,a=Array.isArray(n?.addChildren)?n.addChildren.length:0,o=Array.isArray(n?.removeChildren)?n.removeChildren.length:0;return`${r} props, +${a}, -${o}`}if(t==="manage_ui_create_tree")return"tree \uC0DD\uC131";if(t==="manage_ui_delete")return"\uC81C\uAC70\uB428"}function Cf(t){return t&&typeof t=="object"?t:void 0}function Ux(t,e){let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:0}function kB(t){let e=Cf(t),n=Cf(e?.design_check_summary);if(n)return{priority_high:Ux(n,"priority_high"),priority_medium:Ux(n,"priority_medium"),priority_low:Ux(n,"priority_low"),total:Ux(n,"total"),...typeof n.scope=="string"&&{scope:n.scope},...typeof n.target=="string"&&{target:n.target}}}function PB(t){let n=Cf(t)?.snapshot_id;return typeof n=="string"?n:null}function xB(t){if(typeof t=="string"&&t.trim().length>0)return t;if(typeof t=="number"&&Number.isFinite(t)){let e=t<1e10?t*1e3:t;return new Date(e).toISOString()}}function EB(t){let e=Cf(t),n=Cf(e?.meta);return xB(n?.captured_at)??xB(n?.evaluated_at)}function Mge(t,e){let n=t.uiStudioRecorders.get(e);if(n)return n;let i=iB({placeDir:e,idleMs:kge,capturePreview:async r=>{try{let a=await Ir(t,"manage_ui_preview",{targetPath:r},qx());if(!a.success||!a.data||typeof a.data!="object")return null;let o=kB(a.data),s=EB(a.data);return{snapshotId:PB(a.data),...o!==void 0&&{designCheckSummary:o},...s!==void 0&&{capturedAt:s}}}catch{return null}}});return t.uiStudioRecorders.set(e,i),i}async function zge(t,e,n){if(!wB.has(e))return null;let i=await $ge(t,n);if(!i)return null;let r=Mge(t,i),a=e,o=typeof n.contextId=="string"?n.contextId:void 0,s=n.contextSummary,c=s!==void 0&&typeof s=="object"?s:void 0,l=Dge(a,n),u=typeof n.briefId=="string"?n.briefId:void 0,d={command:a,...o!==void 0&&{contextId:o},...c!==void 0&&{contextSummary:c},...l!==void 0&&{targetPath:l},...u!==void 0&&{briefId:u},origin:n.__origin==="dashboard"?"dashboard":"ai"};try{return await r.beforeMutation(d),{recorder:r,command:a,params:n,startedAt:Date.now()}}catch(p){return h.debug("UI Studio recorder beforeMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:p}),null}}async function _B(t,e){if(t)try{let n=t.command==="manage_ui_update"?CB(t.params,e.data):void 0,i=t.command==="manage_ui_update"?IB(n)??bB(t.command,t.params):bB(t.command,t.params),r=kB(e.data),a=PB(e.data),o=EB(e.data);await t.recorder.afterMutation({ok:e.success,durationMs:Date.now()-t.startedAt,...i!==void 0&&{diffSummary:i},...n!==void 0&&{changeDetails:n},...e.error!==void 0&&{error:e.error},...r!==void 0&&{designCheckSummary:r},...a!==null&&{snapshotId:a},...o!==void 0&&{capturedAt:o}})}catch(n){h.debug("UI Studio recorder afterMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:n})}}async function Fx(t,e,n,i,r,a){if(!t.historyManager)return;let o=!r.success&&r.error?Ol(n,r.error):void 0,s=$l({resultSuccess:r.success,resultData:r.data,resultError:r.error,tier:Nn(n),...o?{failureClassification:o}:{}});if(r.success){let u=s.kind==="success_fallback"&&r.data&&typeof r.data=="object"?{...r.data,outcomeStatus:"fallback",requestedCommand:n,executedCommand:s.fallbackCommand,...s.alternatives?{alternatives:s.alternatives}:{}}:r.data,d=Lx(n,i);r.routing?await t.historyManager.recordSuccess(e,d,u,a,n,void 0,r.routing):await t.historyManager.recordSuccess(e,d,u,a,n);return}if(s.kind==="blocked_unsupported"){await t.historyManager.recordBlockedOutcome(e,Lx(n,i),r.error||"Pro action blocked in Basic mode","blocked_unsupported",{executionTimeMs:a,command:n,...r.routing?{routing:r.routing}:{}});return}if(s.kind==="blocked_fallback_failed"){await t.historyManager.recordBlockedOutcome(e,Lx(n,i),r.error||"Pro action blocked in Basic mode","blocked_fallback_failed",{executionTimeMs:a,command:n,...s.fallbackCommand?{fallbackCommand:s.fallbackCommand}:{},...s.blockedDetail?{blockedDetail:s.blockedDetail}:{},...r.routing?{routing:r.routing}:{}});return}let c=s.kind==="warning"?t.historyManager.recordWarning.bind(t.historyManager):t.historyManager.recordFailure.bind(t.historyManager),l=Lx(n,i);r.routing?await c(e,l,r.error||"Unknown error",a,r.errorCode??o?.errorType.toUpperCase(),n,void 0,r.routing):await c(e,l,r.error||"Unknown error",a,r.errorCode??o?.errorType.toUpperCase(),n)}function tT(t,e,n){let i=t.pendingCommands.get(e)||[];i.length>=SB&&i.shift(),i.push(n),t.pendingCommands.set(e,i)}function Lge(t,e){t.globalPendingCommands.length>=SB&&t.globalPendingCommands.shift(),t.globalPendingCommands.push(e)}function RB(t,e,n){let i=qx(),r={requestId:i,command:e.command,params:e.params,timestamp:Date.now(),queueTimeoutMs:e.queueTimeoutMs,ackedTimeoutMs:e.ackedTimeoutMs,state:pn.QUEUED,targetClientId:n,resolve:()=>{},reject:a=>{h.debug("Auxiliary playtest stop command ended without awaited response",{requestId:i,targetClientId:n,error:a.message})},timeoutId:null};return t.commandQueue.set(i,r),r.timeoutId=setTimeout(()=>{Ub(t,r,r.queueTimeoutMs)},r.queueTimeoutMs),{event:"command",id:i,data:{command:r.command,requestId:i,params:r.params}}}function Uge(t,e,n,i){if(!lf(e.data.command))return;let r=t.commandQueue.get(e.data.requestId);if(!r)return;TB(t,r);let a=n.filter(o=>o.clientId!==i);for(let o of a){let s=RB(t,r,o.clientId);tT(t,o.clientId,s)}a.length>0&&h.info("Fan-out playtest stop command to active plugin clients",{requestId:e.data.requestId,primaryClientId:i,auxiliaryClientIds:a.map(o=>o.clientId)})}function TB(t,e,n){for(let i of sq)setTimeout(()=>{let a=n?[...new Set(n)]:[...new Set(vn(t).map(o=>o.clientId))];for(let o of a){if(!t.pluginClients.get(o))continue;let c=RB(t,e,o);tT(t,o,c)}h.info("Retry playtest stop command to active plugin clients",{sourceRequestId:e.requestId,delayMs:i,targetClientIds:a}),pl(t)},i).unref?.()}function AB(t){return t==="clientId"||t==="targetAlias"||t==="placeId"}function Fge(t,e,n){if(!n||!lf(e.data.command))return!1;let i=t.commandQueue.get(e.data.requestId)?.routing?.selectionMode;return!AB(i)}function qge(t,e,n){h.debug("Broadcasting command",{command:e.data.command,requestId:e.data.requestId,targetClientId:n||"all",activeWebsocketClients:vn(t).length});let i=n;if(n){tT(t,n,e);let r=t.commandQueue.get(e.data.requestId),a=r?.routing?.selectionMode;if(r&&lf(e.data.command)&&AB(a))TB(t,r,[n]);else if(Fge(t,e,n)){let o=vn(t).sort((s,c)=>c.lastSeen-s.lastSeen);Uge(t,e,o,n),i=void 0}}else Lge(t,e);pl(t,i)}async function $B(t,e,n){let i=Date.now(),r="",a={};try{let o=e.body;r=o.command??"",a=o.params||{};let s=o.requestId;if(o.instanceId||(t.serverLastCommandAt=Date.now()),o.instanceId){let m=t.mcpInstances.get(o.instanceId);m&&(m.lastCommandAt=Date.now(),m.lastSeen=m.lastCommandAt)}let c=hB(r),l=typeof o.timeout=="number"&&Number.isFinite(o.timeout)&&o.timeout>0?{timeout:o.timeout}:void 0,u=o.instanceId?t.mcpInstances.get(o.instanceId)?.sessionId??t.sessionId:t.sessionId;if(!r){n.status(400).json({error:"Missing command"});return}if(h.debug("Received execute request",{command:r,requestId:s}),r==="manage_camera_play_screenshot"){let m="manage_camera.play_screenshot is not supported. Screenshot capture is available only in Edit mode via manage_camera.screenshot.",g=Date.now()-i;t.historyManager&&await t.historyManager.recordFailure("manage_camera",a,m,g,"UNSUPPORTED_COMMAND",r),n.json({requestId:s,success:!1,error:m});return}if(r==="get_cached_selection"){let m=a.maxAge,g=cf(t,m!==void 0?m:3e4),y=Date.now()-i;if(!g){let _={requestId:s,success:!0,data:{cached:!1,message:"No cached selection data available. The plugin may not be connected or no selection changes have occurred yet."}};t.historyManager&&await t.historyManager.recordSuccess(c.toolName,a,_.data,y,c.commandName),n.json(_);return}let v=Date.now()-g.timestamp,x={cached:!0,selection:g.selection,count:g.count,timestamp:g.timestamp,age:v};t.historyManager&&await t.historyManager.recordSuccess(c.toolName,a,x,y,c.commandName),n.json({requestId:s,success:!0,data:x});return}if(r==="get_connection_info"){let m=await Cx(t),g=Date.now()-i;t.historyManager&&await t.historyManager.recordSuccess(c.toolName,a,m,g,c.commandName),n.json({requestId:s,success:!0,data:m});return}if(kx(r)==="internal"){if(!t.internalCommandExecutor){n.status(503).json({requestId:s,success:!1,error:`Internal command executor is not initialized for command: ${r}`});return}if(Nn(r)==="pro"){if(!t.licenseState){n.status(503).json({requestId:s,success:!1,error:`License state manager is not initialized for internal command: ${r}`});return}let x=await t.licenseState.evaluateProAccess();if(!x.allowed){let _=Pge(r,x.reason),w=Date.now()-i;t.historyManager&&await Fx(t,c.toolName,c.commandName,a,{success:!1,error:_},w),n.json({requestId:s,success:!1,error:_});return}}let m={...a,__sessionId:u},g=await t.internalCommandExecutor(r,m),y=Date.now()-i,v=yB(m,g.data);t.historyManager&&await Fx(t,c.toolName,c.commandName,v,{success:g.success,data:g.data,error:g.error||"Internal command failed"},y),n.json({requestId:s,...g});return}let d=await Ir(t,r,a,s,l),p=Date.now()-i,f={...yB(a,d.data),__sessionId:u};t.historyManager&&await Fx(t,c.toolName,c.commandName,f,d,p),n.json(d)}catch(o){let s=Date.now()-i,c=Dn(o);if(t.historyManager&&r){let l=hB(r);await t.historyManager.recordFailure(l.toolName,a,c,s,"EXCEPTION",l.commandName)}h.error("Execute request failed",o),n.status(500).json({success:!1,error:c})}}async function OB(t,e,n){let i=Date.now(),r=e.body,a=r.action;if(!a||typeof a!="string"){n.status(400).json({success:!1,error:"Missing required field: action"});return}if(!new Set(["get","set","get_all","set_multiple","get_attr","set_attr","get_all_attrs","delete_attr","add_tag","remove_tag","check_tag","get_tags","get_tagged"]).has(a)){n.status(400).json({success:!1,error:`Unsupported action: ${a}`});return}let s=`manage_properties_${a}`,c=qx(),{action:l,...u}=r;try{t.serverLastCommandAt=Date.now();let d=await Ir(t,s,u,c),p=Date.now()-i;t.historyManager&&await Fx(t,"manage_properties",s,u,d,p),n.json(d)}catch(d){let p=Date.now()-i,f=Dn(d);t.historyManager&&await t.historyManager.recordFailure("manage_properties",u,f,p,"EXCEPTION",s),h.error("/api/properties \uC694\uCCAD \uCC98\uB9AC \uC2E4\uD328",d),n.status(500).json({success:!1,error:f})}}async function Ir(t,e,n,i,r){if(h.debug("Executing command locally",{command:e,requestId:i}),H6(t,i)){let d=`Duplicate requestId '${i}' for command '${e}'. Generate a unique requestId for each command.`;return h.warn("Duplicate execute request rejected",{command:e,requestId:i}),{requestId:i,success:!1,error:d}}let a;try{a=Ix(t,vn(t),n,e)}catch(d){if(d instanceof tn)return h.warn("Command target selection failed",{command:e,requestId:i,errorCode:d.code,routing:d.routing}),Age(i,d);throw d}let o=wB.has(e)?await zge(t,e,n):null,s=t.config.requestTimeout,c=r?.timeout??Math.max(t.config.requestTimeout,Ige),l=qR.has(e)?await qq({ctx:t,command:e,params:n}):n,u=new Promise((d,p)=>{let f=Date.now(),m={requestId:i,command:e,params:l,timestamp:f,queueTimeoutMs:s,ackedTimeoutMs:c,state:pn.QUEUED,...a.targetClientId?{targetClientId:a.targetClientId}:{},routing:a.routing,resolve:d,reject:p,timeoutId:null};t.commandQueue.set(i,m),Nb(t,a.targetClientId,f),m.timeoutId=setTimeout(()=>{Ub(t,m,s)},s)});return qge(t,{event:"command",id:qx(),data:{command:e,requestId:i,params:l}},a.targetClientId),u.then(async d=>{let p=d;if(e==="manage_ui_preview"&&d.success&&d.data)try{let{processPreviewResult:f,resolvePreviewPlaceDirFromCtx:m}=await Promise.resolve().then(()=>(eT(),QR)),g=await m(t,n),y=await f("manage_ui_preview",d.data,g);p={...d,data:y.data,...y.mcpContent?{mcpContent:y.mcpContent}:{}}}catch(f){h.warn("preview post-processing failed",{error:f instanceof Error?f.message:String(f)})}if(e==="manage_ui_check"&&d.success&&d.data&&n.includeVisualAnalysis===!0)try{let{resolvePreviewPlaceDirFromCtx:f}=await Promise.resolve().then(()=>(eT(),QR)),{processCheckResult:m}=await Promise.resolve().then(()=>(gB(),mB)),g=await f(t,n),y=await m("manage_ui_check",d.data,g,n);p={...p,data:y.data}}catch(f){h.warn("check visual post-processing failed",{error:f instanceof Error?f.message:String(f)})}return BR.has(e)?p=await Bq({ctx:t,command:e,params:n,result:p}):e===FR&&(p=await Hq({ctx:t,params:n,result:p})),p}).then(async d=>(await _B(o,{success:d.success,...d.data!==void 0&&{data:d.data},...d.error!==void 0&&{error:d.error}}),d),async d=>{throw await _B(o,{success:!1,error:Dn(d)}),d})}ce();xi();function Bx(t,e){let n={};e.provider!==void 0&&(n.provider=e.provider),e.tier!==void 0&&(n.tier=e.tier),e.status!==void 0&&(n.status=e.status),e.canUsePro!==void 0&&(n.canUsePro=e.canUsePro),e.cleared===!0&&(n.cleared=!0),et(t,"license",n)}function Qr(t,e,n,i){t.status(e).json({success:!1,error:{code:n,message:i}})}function Bge(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();return e.length>0?e:void 0}function Hx(t,e){if(e==="plugin")return t;let n={...t};return delete n.sessionToken,n}function If(t,e,n,i){let r=Bge(i??e.query.provider)??"auto";return t.licenseState?.supportsProvider(r)===!1?(Qr(n,400,"LICENSE_PROVIDER_UNSUPPORTED",`provider "${r}" is not supported`),null):r}function kf(t,e){return t.licenseState?!0:(Qr(e,503,"LICENSE_NOT_INITIALIZED","License system is not initialized"),!1)}function Hge(t){if(!t||typeof t!="object")return!1;let e=t;return(e.canUsePro===!0||e.canUsePro===!1)&&typeof e.status=="string"&&typeof e.checkedAt=="number"}function Pf(t,e,n,i="plugin"){if(!kf(t,n))return;let r=e.body,a=typeof r?.licenseKey=="string"?r.licenseKey:"";if(!a.trim()){Qr(n,400,"LICENSE_KEY_REQUIRED","licenseKey is required");return}let o=If(t,e,n,r?.provider);if(!o)return;let s=typeof r?.pluginClientId=="string"?r.pluginClientId:typeof e.query.clientId=="string"?e.query.clientId:void 0,c=typeof r?.deviceId=="string"?r.deviceId:void 0,l={licenseKey:a,provider:o,clientType:i};s&&(l.pluginClientId=s),c&&(l.deviceId=c),t.licenseState.activateGateway(l).then(u=>{t.analyticsManager?.setTier(u.canUsePro?"pro":"basic"),Bx(t,{provider:u.provider,tier:u.canUsePro?"pro":"basic",status:u.status,canUsePro:u.canUsePro}),n.json(Hx(u,i))}).catch(u=>{h.warn("License activate failed",{error:u instanceof Error?u.message:"unknown_error"}),Qr(n,502,"LICENSE_ACTIVATE_FAILED",u instanceof Error?u.message:"License activation failed")})}function Ef(t,e,n,i="plugin"){if(!kf(t,n))return;let r=If(t,e,n);if(r)try{let a=t.licenseState.getStatus(r);t.analyticsManager?.setTier(a.canUsePro?"pro":"basic"),n.json(Hx(a,i))}catch(a){h.warn("License status check failed",{error:a instanceof Error?a.message:"unknown_error"}),Qr(n,502,"LICENSE_STATUS_FAILED",a instanceof Error?a.message:"License status check failed")}}function Rf(t,e,n,i="plugin"){if(!kf(t,n))return;let r=e.body,a=If(t,e,n,r?.provider);if(!a)return;let o={provider:a,clientType:i};i==="plugin"&&typeof r?.sessionToken=="string"&&r.sessionToken.trim()&&(o.sessionToken=r.sessionToken.trim()),typeof r?.pluginClientId=="string"&&(o.pluginClientId=r.pluginClientId),typeof r?.deviceId=="string"&&(o.deviceId=r.deviceId),t.licenseState.refreshGateway(o).then(s=>{t.analyticsManager?.setTier(s.canUsePro?"pro":"basic"),Bx(t,{provider:s.provider,tier:s.canUsePro?"pro":"basic",status:s.status,canUsePro:s.canUsePro}),n.json(Hx(s,i))}).catch(s=>{h.warn("License refresh failed",{error:s instanceof Error?s.message:"unknown_error"}),Qr(n,502,"LICENSE_REFRESH_FAILED",s instanceof Error?s.message:"License refresh failed")})}function Tf(t,e,n,i="plugin"){if(!kf(t,n))return;let r=e.body,a=If(t,e,n,r?.provider);a&&t.licenseState.resetGateway({provider:a,clientType:i}).then(o=>{t.analyticsManager?.setTier("basic"),Bx(t,{provider:o.provider,tier:"basic",status:o.status,canUsePro:o.canUsePro,cleared:!0}),n.json(Hx(o,i))}).catch(o=>{h.warn("License reset failed",{error:o instanceof Error?o.message:"unknown_error"}),Qr(n,502,"LICENSE_RESET_FAILED",o instanceof Error?o.message:"License reset failed")})}function nT(t,e,n){if(!kf(t,n))return;let i=e.body,r=If(t,e,n,i?.provider);if(!r)return;if(i?.clientType!=="plugin"){Qr(n,400,"LICENSE_CLIENT_TYPE_INVALID","clientType must be plugin");return}let a=typeof i?.sessionToken=="string"&&i.sessionToken.trim()?i.sessionToken.trim():void 0,o=Hge(i?.snapshot)?i.snapshot:void 0;if(!o&&!a){Qr(n,400,"LICENSE_BOOTSTRAP_REQUIRED","snapshot or sessionToken is required");return}let s={provider:r,clientType:"plugin"};o&&(s.snapshot=o),a&&(s.sessionToken=a),t.licenseState.bootstrap(s).then(c=>{t.analyticsManager?.setTier(c.canUsePro?"pro":"basic"),Bx(t,{provider:c.provider,tier:c.canUsePro?"pro":"basic",status:c.status,canUsePro:c.canUsePro}),n.json({ok:!0})}).catch(c=>{h.warn("License bootstrap failed",{error:c instanceof Error?c.message:"unknown_error"}),Qr(n,502,"LICENSE_BOOTSTRAP_FAILED",c instanceof Error?c.message:"License bootstrap failed")})}function DB(t){t.app.post("/license/bootstrap",(e,n)=>nT(t,e,n)),t.app.post("/license/activate",(e,n)=>Pf(t,e,n,"plugin")),t.app.post("/license/refresh",(e,n)=>Rf(t,e,n,"plugin")),t.app.post("/license/reset",(e,n)=>Tf(t,e,n,"plugin")),t.app.get("/license/status",(e,n)=>Ef(t,e,n,"plugin"))}ft();ce();import{promises as Zx}from"fs";import rT from"path";function Zge(t){let e=t.config.appDataDir??it();return rT.join(e,"observability","logs")}async function zl(t,e,n){let i=e.query.clientId;if(i&&t.pluginClients.has(i)){let r=t.pluginClients.get(i);r.lastSeen=Date.now()}try{let r=e.body;if(!r||!Array.isArray(r.logs)){h.warn("Invalid logs request",{body:r}),n.status(400).json({error:"Invalid request body"});return}let a=Zge(t);await Zx.mkdir(a,{recursive:!0});let c=`plugin-${new Date().toISOString().split("T")[0]}.log`,l=rT.join(a,c),u=rT.join(a,"current.log"),d=r.logs.map(p=>`[${new Date(p.timestamp*1e3).toISOString().replace("T"," ").substring(0,19)}] [${p.level}] ${p.message}`).join(`
504
+ `),await al(g)}catch(g){h.warn("Failed to refresh root representative sourcemap after full sync",{placeId:e,error:g instanceof Error?g.message:String(g)})}this.ctx.startFileWatcherForPlace(r).catch(g=>{h.warn("Failed to start reverse detector after full sync",{placeId:e,error:g instanceof Error?g.message:String(g)}),r.fileWatcher=null}),r.writer.setBootstrapMode(!1),r.writer.appendChangeLog(`FULL_SYNC_COMPLETE instances=${r.instanceCount} scripts=${r.scriptCount}`),r.writer.appendHistory({timestamp:new Date().toISOString(),type:"fullSyncComplete",direction:"forward",source:"studio",path:`place_${e}`,details:`instances:${r.instanceCount} scripts:${r.scriptCount}`}),h.info("Full sync completed",{placeId:e,instanceCount:r.instanceCount,scriptCount:r.scriptCount}),i.status(200).json({status:"completed",instanceCount:r.instanceCount,scriptCount:r.scriptCount,syncRoot:this.ctx.config.getPlaceRoot(e)})}catch(f){throw l&&l.endFullSyncReplacement(),f}finally{this.endInitRequest(r)}}setPreserveLocalFiles(e,n){this.preserveLocalFilesMap.set(e,n)}getAndClearPreserveLocalFiles(e){let n=this.preserveLocalFilesMap.get(e)||[];return this.preserveLocalFilesMap.delete(e),n}clearPreserveLocalFiles(e){this.preserveLocalFilesMap.delete(e)}clearPendingServiceTrees(e){this.pendingServiceTrees.delete(e)}startTTLTimerForPlace(e,n){e.incompleteSyncTimer&&(clearTimeout(e.incompleteSyncTimer),e.incompleteSyncTimer=null);let i=setTimeout(async()=>{if(h.warn("Incomplete sync TTL expired, cleaning up",{placeId:e.placeId,syncId:n}),e.incompleteSyncTimer=null,e.activeFullSyncSessionId===n&&e.syncInitRequestsInFlight>0){h.warn("Incomplete sync TTL expired while sync init request is in flight, extending cleanup",{placeId:e.placeId,syncId:n,syncInitRequestsInFlight:e.syncInitRequestsInFlight}),this.startTTLTimerForPlace(e,n);return}let r=this.ctx.config.getPlaceRoot(e.placeId),a=Ne.join(r,`explorer_tmp_${n}`);try{await On.rm(a,{recursive:!0,force:!0})}catch(o){h.error("Failed to clean up expired temp dir",o instanceof Error?o:new Error(String(o)))}e.activeFullSyncSessionId===n&&(e.activeFullSyncSessionId=null,e.activeClientId=null,e.state="idle",e.tmpIndex=null,e.syncInitRequestsInFlight=0,this.pendingServiceTrees.delete(n),e.collisionDirMap=null,e.activeSyncIdentityScope=null,e.tmpWriter&&(e.tmpWriter.stopChangeLogFlusher(),e.tmpWriter=null),this.ctx.activeFullSyncPlaceId===e.placeId&&(this.ctx.activeFullSyncPlaceId=null),this.ctx.clearRuntimePlaceIfMatch(e.placeId))},j8);i&&typeof i=="object"&&"unref"in i&&i.unref(),e.incompleteSyncTimer=i}getOrCreatePendingServiceTree(e,n){let i=this.pendingServiceTrees.get(e);i||(i=new Map,this.pendingServiceTrees.set(e,i));let r=i.get(n.serviceName);if(r)return r;let a={serviceName:n.tree?.name??n.serviceName,serviceClassName:n.tree?.className??n.serviceClassName,zeroBasedChunkIndex:n.chunkIndex===0,instances:[]};return i.set(n.serviceName,a),a}isLastChunk(e,n,i){return i<=1?!0:e.zeroBasedChunkIndex?n>=i-1:n>=i}getPreferredResolvedName(e,n,i){let r=typeof i.sessionDebugId=="string"?i.sessionDebugId:"";if(!n||r==="")return;let a=e.index.getSessionDebugMapping(n,r);if(!a)return;let o=_t(i.path),s=ct(i.path)||i.name;if(!(a.parentPath!==o||a.originalName!==s))return a.resolvedName}recordSessionDebugMapping(e,n,i,r){let a=typeof i.sessionDebugId=="string"?i.sessionDebugId:"";!n||a===""||!e.tmpIndex||e.tmpIndex.setSessionDebugMapping({scope:n,sessionDebugId:a,instancePath:i.path,parentPath:_t(i.path),originalName:ct(i.path)||i.name,siblingIndex:Math.max(1,i.siblingIndex??1),resolvedName:r,className:i.className,updatedAt:new Date().toISOString()})}buildServiceTree(e,n){let i={name:n.serviceName,className:n.serviceClassName,childCount:0,children:[],syncedAt:new Date().toISOString()};for(let r of n.instances){let a=this.resolveEffectiveSegments(e,r.effectivePath),o=Zt(r.originalPath);this.upsertTreeNode(i,a,o,r.className)}return this.recomputeTreeChildCounts(i),i.syncedAt=new Date().toISOString(),i}resolveEffectiveSegments(e,n){return e.tmpIndex?Zt(n).map(i=>e.tmpIndex.sanitizeName(i)):Zt(n)}rewritePendingEffectivePaths(e,n,i,r){let a=Ne.relative(n,i).split(Ne.sep).filter(l=>l.length>0),o=Ne.relative(n,r).split(Ne.sep).filter(l=>l.length>0);if(a.length===0||o.length===0)return;let s=gt(["game",...a]),c=gt(["game",...o]);for(let l of e.instances){if(l.effectivePath===s){l.effectivePath=c;continue}(l.effectivePath.startsWith(`${s}.`)||l.effectivePath.startsWith(`${s}[`))&&(l.effectivePath=`${c}${l.effectivePath.slice(s.length)}`)}}upsertTreeNode(e,n,i,r){if(n.length<=1)return;let a=e.children;for(let o=1;o<n.length;o++){let s=n[o],c=i[o],l=o===n.length-1,u=a.find(d=>d.name===s);u?l&&(u.className=r,c!==void 0&&c!==s&&(u.originalName=c)):(u={name:s,className:l?r:"Folder",childCount:0,children:[]},c!==void 0&&c!==s&&(u.originalName=c),a.push(u)),u.children||(u.children=[]),a=u.children}}recomputeTreeChildCounts(e){let n=i=>{let r=i.children??[];i.children=r;for(let a of r)n(a);i.childCount=r.length};for(let i of e.children)n(i);e.childCount=e.children.length}clearTTLTimerForPlace(e,n){e.incompleteSyncTimer&&e.activeFullSyncSessionId===n&&(clearTimeout(e.incompleteSyncTimer),e.incompleteSyncTimer=null)}beginInitRequest(e){e.syncInitRequestsInFlight++}endInitRequest(e){e.syncInitRequestsInFlight=Math.max(0,e.syncInitRequestsInFlight-1)}async cleanupStaleTempDirs(){let e=this.ctx.config.getSyncRoot();try{let n=await On.readdir(e,{withFileTypes:!0});for(let i of n)if(i.isDirectory()){if(i.name.startsWith("explorer_tmp_")){let r=Ne.join(e,i.name);h.warn("Removing stale temp directory from crashed sync",{dir:i.name});try{await On.rm(r,{recursive:!0,force:!0})}catch(a){h.error(`Failed to remove stale temp dir: ${i.name}`,a instanceof Error?a:new Error(String(a)))}}if(i.name.startsWith("place_")){let r=Ne.join(e,i.name);try{let a=await On.readdir(r,{withFileTypes:!0});for(let o of a)if(o.isDirectory()&&o.name.startsWith("explorer_tmp_")){let s=Ne.join(r,o.name);h.warn("Removing stale temp directory from crashed sync",{dir:`${i.name}/${o.name}`});try{await On.rm(s,{recursive:!0,force:!0})}catch(c){h.error(`Failed to remove stale temp dir: ${i.name}/${o.name}`,c instanceof Error?c:new Error(String(c)))}}}catch{continue}}}}catch(n){if(n.code==="ENOENT")return;h.warn("Failed to scan for stale temp dirs",{error:n instanceof Error?n.message:String(n)})}}};import _r from"path";import{promises as ux}from"fs";yr();ce();var dx=class{constructor(e){this.ctx=e}async handleReversePending(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({pending:0,hasConflicts:!1,lastDetected:null});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}let a={pending:r.fileWatcher?.getPendingCount()??0,hasConflicts:!1,lastDetected:r.fileWatcher?.getLastDetected()??null,forwardRestoreNeeded:r.forwardRestoreQueue.length};this.ctx.touchRuntimePlace(i),n.status(200).json(a)}async handleReverseSyncChanges(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({changes:[],count:0});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}if(r.state!=="syncing"){n.status(400).json({error:"Not syncing",message:"Reverse sync is only available when sync is active"});return}let a=r.fileWatcher?.drainPendingChanges()??[],o=a.length>0?await r.reader.buildChangesFromPending(a):[];this.ctx.touchRuntimePlace(i),n.status(200).json({changes:o,count:o.length})}async handleReverseSyncResult(e,n){let i=e.body,r=i.placeId??this.ctx.getDefaultRuntimePlaceId();if(r==null){n.status(400).json({error:"Validation error",message:"placeId is required (in body or via active sync session)"});return}let a=i.appliedFiles??i.appliedPaths;if(!a||!Array.isArray(a)){n.status(400).json({error:"Validation error",message:"appliedFiles (or appliedPaths) must be an array of relative file paths"});return}let o=this.ctx.places.get(r);if(!o){n.status(404).json({error:"Place not found",message:`No sync context for place ${r}`});return}this.ctx.touchRuntimePlace(r);let s=this.ctx.config.getPlaceRoot(r),c=0,l=[];for(let u of a){let d=_r.resolve(s,u);if(!ax(s,d)){l.push({path:u,error:"Path is outside the place root"});continue}try{let p=await ux.readFile(d,"utf-8"),f=o.index.computeHash(p);o.index.updateHashByValue(d,f),o.index.updateFileHashByValue(d,f),c++}catch(p){let f=p.code;if(f==="ENOENT"){o.index.removeHash(d),o.index.removeHashesUnder(d);let m=this.resolveInstancePathForAppliedPath(o.index,d);if(m){let g=ct(m),y=_t(m);y&&g&&await o.writer.removeFromTree(y,g)}c++}else f==="EISDIR"?c++:l.push({path:u,error:p instanceof Error?p.message:String(p)})}}c>0&&await o.index.saveToDisk(),c>0&&o.writer.appendHistory({timestamp:new Date().toISOString(),type:"reverseApply",direction:"reverse",source:"local",path:`place_${r}`,details:`applied:${c} failed:${l.length}`}),n.status(200).json({updated:c,failed:l.length,errors:l})}async handleResolveConflict(e,n){let i=e.body;if(!i.fsPath||!i.resolution){n.status(400).json({error:"Validation error",message:"fsPath and resolution are required"});return}let{fsPath:r,resolution:a}=i,o=this.ctx.config.getSyncRoot();if(!ax(o,_r.resolve(o,r))){n.status(403).json({error:"Forbidden",message:"Path is outside the sync root"});return}if(a==="skip"){n.status(200).json({status:"skipped",fsPath:r});return}let s;if(i.placeId&&(s=this.ctx.places.get(i.placeId)),!s){let p=r.match(/^place_(\d+)(?:_[^/]+)?\//);if(p){let f=parseInt(p[1],10);s=this.ctx.places.get(f)}else s=Array.from(this.ctx.places.values())[0]}if(!s){n.status(404).json({error:"No active place context",message:"No sync session is active. Start a sync first."});return}let c=this.ctx.config.getPlaceRoot(s.placeId),l=_r.resolve(c,r);if(!ax(c,l)){n.status(403).json({error:"Forbidden",message:"Path is outside the place root"});return}let u=s.index,d=s.reader;if(a==="apply-studio"){if(typeof i.studioContent!="string"){n.status(400).json({error:"Validation error",message:"studioContent is required for apply-studio resolution"});return}await ux.mkdir(_r.dirname(l),{recursive:!0});let p=i.studioContent,f=u.computeHash(p);s.fileWatcher?.suppressPath(l,f),await ux.writeFile(l,p,"utf-8"),u.updateHashByValue(l,f),u.updateFileHashByValue(l,f),await u.saveToDisk(),n.status(200).json({status:"resolved",resolution:"apply-studio",fsPath:r});return}if(a==="apply-file"){let p=await ux.readFile(l,"utf-8"),f=u.computeHash(p);u.resolveFile(l,"apply-file",f),await u.saveToDisk();let m=d.getFileType(l),g=d.resolveInstancePathFromFile(l);n.status(200).json({status:"resolved",resolution:"apply-file",fsPath:r,instancePath:g,fileType:m,content:p});return}n.status(400).json({error:"Invalid resolution",message:`Unknown resolution: ${a}`})}async handleReverseRescan(e,n){let i=this.ctx.resolveQueryPlaceId(e);if(i==null){n.status(200).json({added:0});return}let r=this.ctx.places.get(i);if(!r){n.status(404).json({error:"Place not found",message:`No sync context for place ${i}`});return}if(!r.fileWatcher){n.status(200).json({added:0});return}let a=await r.fileWatcher.rescan();this.ctx.touchRuntimePlace(i),h.info("Reverse rescan completed",{placeId:i,added:a}),n.status(200).json({added:a})}resolveInstancePathForAppliedPath(e,n){let i=e.resolveInstancePathFromFsPath(n);if(i)return i;let r=e.getExplorerRoot(),a=_r.relative(r,n);if(a.startsWith("..")||a===""||_r.isAbsolute(a))return null;let o=a.split(_r.sep).filter(f=>f.length>0);if(o.length<2)return null;let s=_r.basename(n),c=_r.dirname(n),l=e.getOriginalInstance(c,s);if(l)return l.instancePath;let u=s.toLowerCase();if(kb.some(f=>u.endsWith(f))||u==="_tree.json")return null;let d=["game"],p=r;for(let f of o){p=_r.join(p,f);let m=_r.dirname(p);d.push(e.getOriginalNameForDir(m,f))}return gt(d)}};yr();Rb();ce();var kfe=5;function q8(t){if(!t||typeof t!="object")return;let e=t;if(Array.isArray(e.instances))for(let n of e.instances)Array.isArray(n.properties)&&n.properties.length===0&&(n.properties={}),Array.isArray(n.attributes)&&n.attributes.length===0&&(n.attributes={});if(Array.isArray(e.changes))for(let n of e.changes)Array.isArray(n.properties)&&n.properties.length===0&&(n.properties={}),Array.isArray(n.attributes)&&n.attributes.length===0&&(n.attributes={})}function Pfe(t){return t.type==="instanceAdded"||t.type==="instanceRemoved"||t.type==="instanceRenamed"||t.type==="instanceMoved"||t.type==="scriptSourceChanged"}var Wr=class{config;places;apiHandler;changeProcessor;initHandler;reverseHandler;reverseDetectorFactory;activeFullSyncPlaceId=null;activeRuntimeSyncPlaceId=null;currentConnectedPlaceId=null;currentConnectedPlaceName=null;constructor(e,n={}){this.config=new Sb(e,n),this.reverseDetectorFactory=n.reverseDetectorFactory??(i=>new nx(i.explorerRoot,i.syncIndex,{placeId:i.placeId})),this.apiHandler=new cx(this),this.changeProcessor=new ox(this),this.initHandler=new lx(this),this.reverseHandler=new dx(this),this.places=new ex({max:kfe,dispose:(i,r)=>{h.info("Disposing place context (LRU eviction)",{placeId:r}),this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),i.fileWatcher&&(h.info("Disposing place context: stopping reverse detector",{placeId:r,reason:"lru-dispose",mode:lt}),i.fileWatcher.stop("lru-dispose").catch(a=>{h.error("Error stopping reverse detector during dispose",a)}),i.fileWatcher=null),i.writer.stopChangeLogFlusher().catch(a=>{h.error("LRU dispose \uC911 changelog flush \uC2E4\uD328",a)}),i.incompleteSyncTimer&&(clearTimeout(i.incompleteSyncTimer),i.incompleteSyncTimer=null),i.index.clearAllMaps(),i.index.saveToDisk().catch(a=>{h.error("Error saving index during dispose",a)}),i.activeFullSyncSessionId&&this.initHandler.clearPendingServiceTrees(i.activeFullSyncSessionId),i.tmpWriter&&(i.tmpWriter.stopChangeLogFlusher(),i.tmpWriter=null),i.tmpIndex=null,i.collisionDirMap=null,i.activeSyncIdentityScope=null,i.syncInitRequestsInFlight=0}})}getSyncRoot(){return this.config.getSyncRoot()}async getOrCreatePlaceContext(e,n){let i=this.places.get(e);if(i&&n){let r=this.config.getPlaceRoot(e),a=await this.config.resolvePlaceRoot(e,n);a!==r&&(h.info("Place root migrated, recreating context",{placeId:e,from:r,to:a}),this.places.delete(e),i=void 0)}if(!i){let r=await this.config.resolvePlaceRoot(e,n),a=CR.join(r,"explorer");await wl.mkdir(r,{recursive:!0}),await wl.mkdir(a,{recursive:!0});let o=new za(r,a);await o.loadFromDisk();let s=new xl(this.config,o,e),c=new tx(this.config,o,r);s.startChangeLogFlusher(),i={placeId:e,placeName:"",index:o,writer:s,reader:c,fileWatcher:null,state:"idle",activeClientId:null,activeFullSyncSessionId:null,instanceCount:0,scriptCount:0,lastFullSync:null,lastIncrementalSync:null,tmpIndex:null,tmpWriter:null,incompleteSyncTimer:null,syncInitRequestsInFlight:0,changesSinceLastSave:0,directions:{...qo},applyModes:{...Bo},forwardRestoreQueue:[],syncProgress:null,collisionDirMap:null,activeSyncIdentityScope:null},this.places.set(e,i),h.info("Created new place context",{placeId:e,placeRoot:r})}return i}async handleSyncInit(e,n){try{q8(e.body);let i=z8(e.body);if(!i.success){n.status(400).json({error:"Validation error",message:i.error});return}let r=i.data,a=r.phase==="start"?r.placeId??null:r.phase==="chunk"||r.phase==="complete"?this.activeFullSyncPlaceId:null;if(a==null){n.status(400).json({error:"Missing placeId",message:"placeId is required in start phase or must be set by previous start"});return}switch(r.phase){case"start":this.setCurrentConnectedPlace(a,r.placeName),await this.initHandler.handleInitStart(a,r,n);break;case"chunk":await this.initHandler.handleInitChunk(a,r,n);break;case"complete":await this.initHandler.handleInitComplete(a,r,n);break}}catch(i){this.sendError(n,i,"handleSyncInit")}}async handleSyncUpdate(e,n){try{q8(e.body);let i=L8(e.body);if(!i.success){n.status(400).json({error:"Validation error",message:i.error});return}let r=i.data,a=r.placeId??this.getDefaultRuntimePlaceId();if(a==null){n.status(400).json({error:"Missing placeId",message:"placeId is required in body or must have an active sync session"});return}let o=await this.getOrCreatePlaceContext(a);if(this.setCurrentConnectedPlace(a,o.placeName||this.currentConnectedPlaceName),o.activeFullSyncSessionId!==null||o.state==="initializing"){n.status(409).json({error:"Conflict",message:`Full sync in progress for place ${a}`});return}o.activeClientId=r.clientId,this.touchRuntimePlace(a);let s=N8(o,r.changes);h.info("Sync update received",{placeId:a,clientId:r.clientId,changeCount:s.length,receivedCount:r.changes.length,types:s.map(m=>m.type)});let c=[],l=[],u=0,d=!1,p=new Map;for(let m of s)try{let g=await this.changeProcessor.processChangeForPlace(o,m,p);g?l.push(g):(u++,Pfe(m)&&(d=!0))}catch(g){let y="path"in m?m.path:"oldPath"in m?m.oldPath:"unknown";c.push({path:y,error:g instanceof Error?g.message:String(g)})}for(let m of p.values())try{await rx(o,m)}catch(g){c.push({path:m.instancePath,error:g instanceof Error?g.message:String(g)})}if(d)try{let m=this.config.getSyncRoot(),g=this.config.getPlaceRoot(a);await Eb(m,g),await al(m)}catch(m){h.warn("Failed to refresh sourcemaps after incremental sync update",{placeId:a,error:m instanceof Error?m.message:String(m)})}o.changesSinceLastSave+=u,o.changesSinceLastSave>=M8&&(await o.index.saveToDisk(),o.changesSinceLastSave=0),o.lastIncrementalSync=new Date().toISOString();let f={processed:u,failed:c.length,errors:c,syncedAt:o.lastIncrementalSync};l.length>0&&(f.conflicts=l),n.status(200).json(f)}catch(i){this.sendError(n,i,"handleSyncUpdate")}}getDefaultRuntimePlaceId(){return this.currentConnectedPlaceId}getDefaultRuntimePlaceName(){if(this.currentConnectedPlaceName)return this.currentConnectedPlaceName;if(this.currentConnectedPlaceId!==null&&this.currentConnectedPlaceId!==void 0){let e=this.places.get(this.currentConnectedPlaceId);if(e?.placeName)return e.placeName}return null}setCurrentConnectedPlace(e,n){if(this.currentConnectedPlaceId=e,e==null){this.currentConnectedPlaceName=null;return}if(typeof n=="string"&&n.length>0){this.currentConnectedPlaceName=n;let r=this.places.get(e);r&&(r.placeName=n);return}let i=this.places.get(e);i?.placeName&&(this.currentConnectedPlaceName=i.placeName)}clearCurrentConnectedPlaceIfMatch(e){this.currentConnectedPlaceId===e&&(this.currentConnectedPlaceId=null,this.currentConnectedPlaceName=null)}touchRuntimePlace(e){this.activeRuntimeSyncPlaceId=e}clearRuntimePlaceIfMatch(e){this.activeRuntimeSyncPlaceId===e&&(this.activeRuntimeSyncPlaceId=null)}resolveQueryPlaceId(e,n="runtime"){let i=e.query.placeId;if(i){let r=parseInt(i,10);if(!isNaN(r))return r}return n==="full"?this.activeFullSyncPlaceId:this.getDefaultRuntimePlaceId()}async handleSyncStatus(e,n){try{let i=u=>({state:"idle",instanceCount:0,scriptCount:0,lastFullSync:null,lastIncrementalSync:null,syncRoot:u,activeClientId:null,reverseSyncAvailable:!1,modifiedFileCount:0,reverseDetectorActive:!1,reverseDetectorMode:lt,fileWatcherActive:!1}),r=this.resolveQueryPlaceId(e);if(r==null){let u=i(this.config.getSyncRoot());n.status(200).json(u);return}let a=this.places.get(r);if(!a){let u=i(this.config.getPlaceRoot(r));n.status(200).json(u);return}let o=a.fileWatcher?.getPendingCount()??0,s=a.fileWatcher?.isActivelyScanning()??!1,c=a.fileWatcher!==null;this.touchRuntimePlace(r);let l={state:a.state,instanceCount:a.instanceCount,scriptCount:a.scriptCount,lastFullSync:a.lastFullSync,lastIncrementalSync:a.lastIncrementalSync,syncRoot:this.config.getPlaceRoot(r),activeClientId:a.activeClientId,reverseSyncAvailable:o>0,modifiedFileCount:o,applyModes:a.applyModes,directions:a.directions,reverseDetectorActive:s,reverseDetectorMode:lt,fileWatcherActive:c,forwardOnlyClasses:[...il]};n.status(200).json(l)}catch(i){this.sendError(n,i,"handleSyncStatus")}}async handleSyncStop(e,n){try{let i=e.body,r=i.placeId??this.getDefaultRuntimePlaceId();if(h.info("handleSyncStop requested",{placeId:r,clientId:i.clientId??null,reason:i.reason??"requested"}),r==null){n.status(200).json({status:"idle",state:"idle",placeId:null,message:"No active sync place"});return}let a=this.places.get(r);if(!a){h.info("handleSyncStop no place context",{placeId:r,clientId:i.clientId??null}),n.status(200).json({status:"idle",state:"idle",placeId:r,message:`No sync context for place ${r}`});return}if(i.clientId&&a.activeClientId&&i.clientId!==a.activeClientId&&(a.activeFullSyncSessionId!==null||a.state==="syncing"||a.state==="initializing")){h.warn("handleSyncStop rejected due to active client mismatch",{placeId:r,requestedClientId:i.clientId,activeClientId:a.activeClientId,state:a.state,activeFullSyncSessionId:a.activeFullSyncSessionId}),n.status(409).json({error:"Conflict",message:`This sync session belongs to client ${a.activeClientId}`});return}let o=a.activeFullSyncSessionId,s=a.state,c=a.fileWatcher!==null;if(o&&(this.initHandler.clearPreserveLocalFiles(o),this.initHandler.clearPendingServiceTrees(o)),a.fileWatcher&&(h.info("handleSyncStop suspending reverse detector",{placeId:r,state:a.state,activeClientId:a.activeClientId,mode:lt}),a.fileWatcher.beginFullSyncReplacement()),a.incompleteSyncTimer&&(clearTimeout(a.incompleteSyncTimer),a.incompleteSyncTimer=null),o){let l=this.config.getPlaceRoot(r),u=CR.join(l,`explorer_tmp_${o}`);await wl.rm(u,{recursive:!0,force:!0}).catch(()=>{})}a.tmpWriter&&(a.tmpWriter.stopChangeLogFlusher(),a.tmpWriter=null),a.tmpIndex=null,a.collisionDirMap=null,a.activeSyncIdentityScope=null,a.syncInitRequestsInFlight=0,a.activeFullSyncSessionId=null,a.syncProgress=null,a.state="idle",a.activeClientId=null,a.instanceCount=0,a.scriptCount=0,a.forwardRestoreQueue=[],this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),this.clearRuntimePlaceIfMatch(r),h.info("handleSyncStop responding idle",{placeId:r,previousState:s,activeFullSyncSessionId:o,hadWatcher:c}),h.info("Sync stopped",{placeId:r,reason:i.reason??"requested"}),n.status(200).json({status:"stopped",state:"idle",placeId:r})}catch(i){this.sendError(n,i,"handleSyncStop")}}async initialize(){try{await this.config.loadFromMeta(),await this.initHandler.cleanupStaleTempDirs(),h.info("SyncController initialized")}catch(e){h.error("SyncController initialization failed",e instanceof Error?e:new Error(String(e)))}}async shutdown(){try{h.info("SyncController shutdown: clearing place contexts",{placeCount:this.places.size}),this.places.clear(),h.info("SyncController shut down")}catch(e){h.error("SyncController shutdown error",e instanceof Error?e:new Error(String(e)))}}async atomicWriteFile(e,n){let i=e+".tmp."+Ife().slice(0,8);try{await wl.writeFile(i,n,"utf-8"),await wl.rename(i,e)}catch(r){throw await wl.unlink(i).catch(()=>{}),r}}async handlePreCheck(e,n){try{await this.apiHandler.handlePreCheck(e,n)}catch(i){this.sendError(n,i,"handlePreCheck")}}async handleSyncDirections(e,n){try{await this.apiHandler.handleSyncDirections(e,n)}catch(i){this.sendError(n,i,"handleSyncDirections")}}async handleForwardRestoreList(e,n){try{await this.apiHandler.handleForwardRestoreList(e,n)}catch(i){this.sendError(n,i,"handleForwardRestoreList")}}async handleReversePending(e,n){try{await this.reverseHandler.handleReversePending(e,n)}catch(i){this.sendError(n,i,"handleReversePending")}}async handleReverseSyncChanges(e,n){try{await this.reverseHandler.handleReverseSyncChanges(e,n)}catch(i){this.sendError(n,i,"handleReverseSyncChanges")}}async handleReverseSyncResult(e,n){try{await this.reverseHandler.handleReverseSyncResult(e,n)}catch(i){this.sendError(n,i,"handleReverseSyncResult")}}async handleResolveConflict(e,n){try{await this.reverseHandler.handleResolveConflict(e,n)}catch(i){this.sendError(n,i,"handleResolveConflict")}}async handleReverseRescan(e,n){try{await this.reverseHandler.handleReverseRescan(e,n)}catch(i){this.sendError(n,i,"handleReverseRescan")}}async handleSyncHistory(e,n){try{await this.apiHandler.handleSyncHistory(e,n)}catch(i){this.sendError(n,i,"handleSyncHistory")}}async startFileWatcherForPlace(e){if(e.state!=="syncing"){h.debug("Skipping reverse detector start - place not syncing",{placeId:e.placeId,state:e.state});return}if(e.fileWatcher){if(e.fileWatcher.isActivelyScanning()){h.info("startFileWatcherForPlace: reusing active reverse detector",{placeId:e.placeId,mode:lt});return}h.info("startFileWatcherForPlace: resuming paused reverse detector",{placeId:e.placeId,mode:lt}),e.fileWatcher.endFullSyncReplacement();return}let n=this.createReverseChangeDetector(e);this.configureReverseChangeDetector(e,n),e.fileWatcher=n,n.start().then(()=>{e.fileWatcher===n&&h.info("Reverse detector started for reverse sync",{placeId:e.placeId,mode:lt})}).catch(i=>{h.warn("Failed to start reverse detector",{placeId:e.placeId,mode:lt,error:i instanceof Error?i.message:String(i)}),e.fileWatcher===n&&(e.fileWatcher=null)})}createReverseChangeDetector(e){return this.reverseDetectorFactory({explorerRoot:CR.join(this.config.getPlaceRoot(e.placeId),"explorer"),syncIndex:e.index,placeId:e.placeId})}configureReverseChangeDetector(e,n){e.writer.setOnWriteCallback(i=>{n.suppressPath(i)}),n.setDirectionChecker(i=>{let r=v6(i);return e.directions[r]}),n.setOnForwardViolation(i=>{e.forwardRestoreQueue.includes(i)||(e.forwardRestoreQueue.push(i),h.info("Forward violation queued for restore",{placeId:e.placeId,relativePath:i,queueSize:e.forwardRestoreQueue.length}))})}getStatusSummary(){return this.apiHandler.getStatusSummary()}getDirectionForCategory(e){return this.apiHandler.getDirectionForCategory(e)}getStatusDirect(e){return this.apiHandler.getStatusDirect(e)}async getHistoryDirect(e,n){return this.apiHandler.getHistoryDirect(e,n)}getDirectionsDirect(e){return this.apiHandler.getDirectionsDirect(e)}getProgressDirect(e){return this.apiHandler.getProgressDirect(e)}async readSyncedFile(e,n){return this.apiHandler.readSyncedFile(e,n)}async writeSyncedFile(e,n,i){await this.apiHandler.writeSyncedFile(e,n,i)}async executeViaDisk(e,n){return this.apiHandler.executeViaDisk(e,n)}sendError(e,n,i){let r=n instanceof Error?n.message:String(n);if(r.includes("Path traversal detected")){e.status(403).json({error:"Forbidden",message:r});return}let a=n.code;if(a==="ENOSPC"||a==="EPERM"||a==="EACCES"){h.warn(`SyncController.${i} disk error`,{code:a,message:r}),e.status(500).json({error:"Disk error",message:r,code:a,operation:i});return}h.error(`SyncController.${i} failed`,n instanceof Error?n:new Error(r)),e.status(500).json({error:"Internal error",message:`${i}: ${r}`})}};import{randomUUID as Efe}from"crypto";function B8(t,e){let n=Efe(),i=n.replace(/-/g,"").substring(0,8).toUpperCase(),r=`${i.substring(0,4)}-${i.substring(4,8)}`;return{config:t,app:e,instanceId:n,sessionId:r,startTime:Date.now(),baseUrl:`http://${t.httpHost}:${t.httpPort}`,commandQueue:new Map,pendingCommands:new Map,globalPendingCommands:[],totalCommandsProcessed:0,pluginClients:new Map,pluginCommandSessionsByClientId:new Map,pluginCommandClientIdsByProcessToken:new Map,mcpInstances:new Map,cachedSelectionMap:new Map,studioRoutingMode:"recentPriority",pinnedTargetClientId:null,isClientMode:!1,clientModeHealthTimer:null,clientModeConsecutiveHealthFailures:0,clientModeUpstreamReachable:!0,clientModeUpstreamContextCaptureEnabled:!0,clientModeLastHealthSuccessAt:null,clientModeLastHealthFailureAt:null,clientModeLastHealthError:null,shuttingDown:!1,onUpstreamPermanentlyDown:null,clientModeIdleTimeoutMs:t.clientModeIdleTimeoutMs??36e5,clientModeIdleWatchdogTimer:null,shutdownFn:null,historyManager:null,analyticsManager:null,executionContextManager:null,licenseState:null,syncController:null,internalCommandExecutor:null,dashboardFolderPicker:null,assetLibraryOpenCloudServiceFactory:null,activeSyncOwnerInstanceId:null,activeProjectRoot:null,pendingDashboardSyncRootPin:null,playtestControlCommand:null,dashboardSyncRootSwitchInFlight:!1,uiStudioRecorders:new Map,aiClientName:"",pluginVersion:"",syncedSessionToken:null,serverLastCommandAt:null}}var H8=It(Pa(),1);ce();function Z8(t){let e=H8.default.json({limit:"5mb"});t.app.use((n,i,r)=>{if(n.path.startsWith("/sync/")){r();return}e(n,i,r)}),t.app.use((n,i,r)=>{i.setHeader("Access-Control-Allow-Origin","http://localhost:3002"),i.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),i.setHeader("Access-Control-Allow-Headers","Content-Type"),r()}),t.app.use((n,i,r)=>{h.debug(`${n.method} ${n.path}`,{ip:n.ip}),r()})}ya();import{randomUUID as qx}from"crypto";ya();ce();function Rfe(){let t=process.env.WEPPY_ROBLOX_MCP_VERSION?.trim();return t||null}var tt=Rfe()??"2.9.1";xi();Xn();sf();Aa();ll();ya();Aa();var Y8="studio-",Afe=/^studio-[1-9]\d*$/;function gx(t){return Afe.test(t)}function X8(t,e){let n=new Set;for(let i of t)e!==void 0&&i.clientId===e||i.targetAlias&&gx(i.targetAlias)&&n.add(i.targetAlias);return n}function $fe(t,e){let n=X8(t,e),i=1;for(;n.has(`${Y8}${i}`);)i+=1;return`${Y8}${i}`}function hx(t,e){let n=X8(t,e.clientId);return e.targetAlias&&gx(e.targetAlias)&&!n.has(e.targetAlias)||(e.targetAlias=$fe(t,e.clientId)),e.targetAlias}ll();function yx(t){for(let e of t)hx(t,e)}function vx(t){let e={clientId:t.clientId,targetAlias:t.targetAlias??t.clientId.slice(0,8),lastSeen:t.lastSeen,connectedAt:t.connectedAt,transport:"websocket",connectionState:t.commandSessionState??He.CONNECTED};return t.placeId!==void 0&&(e.placeId=t.placeId),t.placeName!==void 0&&(e.placeName=t.placeName),t.pluginVersion!==void 0&&(e.pluginVersion=t.pluginVersion),t.studioVersion!==void 0&&(e.studioVersion=t.studioVersion),t.lastRoutedAt!==void 0&&(e.lastRoutedAt=t.lastRoutedAt),t.processToken!==void 0&&(e.processToken=t.processToken),t.inFlightRequestId!==void 0&&(e.inFlightRequestId=t.inFlightRequestId),e}function AR(t){let e=vn(t);return yx(e),Kp(e.map(vx),null)}function bx(t){let e=new Set;t.aiClientName&&e.add(t.aiClientName);for(let n of t.mcpInstances.values())n.aiClientName&&e.add(n.aiClientName);return Array.from(e)}function Q8(t){let n=Date.now();for(let[i,r]of t.mcpInstances)r.lastSeen&&n-r.lastSeen>15e3&&(t.mcpInstances.delete(i),r.sessionId&&t.executionContextManager?.endSession(r.sessionId),h.debug("Removed stale MCP instance",{instanceId:i,lastSeen:r.lastSeen}))}function eq(t,e,n){let i=e.query.clientId;if(i&&t.pluginClients.has(i)){let r=t.pluginClients.get(i);r.lastSeen=Date.now()}try{let r=e.body;if(!r||!Array.isArray(r.selection)||typeof r.count!="number"){h.warn("Invalid selection update request",{body:r}),n.status(400).json({error:"Invalid request body"});return}let a=i||"unknown",o=Date.now();t.cachedSelectionMap.set(a,{selection:r.selection,count:r.count,timestamp:o,clientId:a}),h.debug("Selection cache updated",{count:r.count,clientId:a,timestamp:o}),n.json({status:"ok",timestamp:o})}catch(r){h.error("Error handling selection update",r),n.status(500).json({error:"Internal server error"})}}function tq(t,e,n){let i=parseInt(e.query.maxAge)||3e4,r=cf(t,i);r?n.json({cached:!0,...r}):n.json({cached:!1,message:"No cached selection available"})}function cf(t,e=3e4,n){if(t.cachedSelectionMap.size===0)return null;let i;if(n)i=t.cachedSelectionMap.get(n);else for(let a of t.cachedSelectionMap.values())(!i||a.timestamp>i.timestamp)&&(i=a);if(!i)return null;let r=Date.now()-i.timestamp;return e===0||r<=e?i:null}function $R(t,e){let n=t.pluginClients.get(e.clientId),i=Date.now(),r=[...t.pluginClients.values()].filter(c=>c.clientId===e.clientId||c.commandSessionState!==He.DISCONNECTED),a=n??{clientId:e.clientId,connectedAt:i,lastSeen:i,commandsProcessed:0,connectionType:"polling"},o=hx(r,a),s={clientId:e.clientId,targetAlias:o,projectName:e.projectName??n?.projectName,placeName:e.placeName??n?.placeName,placeId:e.placeId??n?.placeId,pluginVersion:e.pluginVersion??n?.pluginVersion,studioVersion:e.studioVersion??n?.studioVersion,connectedAt:n?.connectedAt||i,lastSeen:i,commandsProcessed:n?.commandsProcessed||0,connectionType:n?.connectionType||"polling",inFlightRequestId:n?.inFlightRequestId,...n?.commandSessionState?{commandSessionState:n.commandSessionState}:{},...n?.processToken?{processToken:n.processToken}:{}};return t.pluginClients.set(e.clientId,s),t.syncController&&typeof t.syncController.setCurrentConnectedPlace=="function"&&typeof e.placeId=="number"&&Number.isFinite(e.placeId)&&t.syncController.setCurrentConnectedPlace(e.placeId,e.placeName??null),t.pendingCommands.has(e.clientId)||t.pendingCommands.set(e.clientId,[]),e.pluginVersion&&(t.pluginVersion=e.pluginVersion),typeof s.placeId=="number"&&Number.isFinite(s.placeId)&&Hb(t,s.placeId,s.placeName??null),t.analyticsManager&&(e.pluginVersion&&t.analyticsManager.setPluginVersion(e.pluginVersion),t.analyticsManager.trackPluginConnected()),h.info("Plugin client registered",{clientId:e.clientId,targetAlias:o,projectName:e.projectName,placeName:e.placeName,isReconnect:!!n}),{clientInfo:s,sessionId:t.sessionId,mcpVersion:tt,mcpInstanceCount:t.mcpInstances.size+1,aiClientNames:bx(t)}}function OR(t,e){let n=t.pluginClients.get(e),i=t.pluginClients.has(e),r=n?.commandSessionState===He.CONNECTED;if(t.pluginClients.delete(e),t.pendingCommands.delete(e),i&&cl(t,e),i&&t.syncController&&typeof t.syncController.clearCurrentConnectedPlaceIfMatch=="function"&&typeof n?.placeId=="number"&&Number.isFinite(n.placeId)){let a=[...t.pluginClients.values()].filter(o=>typeof o.placeId=="number"&&Number.isFinite(o.placeId)).sort((o,s)=>s.lastSeen-o.lastSeen)[0];a?t.syncController.setCurrentConnectedPlace?.(a.placeId??null,a.placeName??null):t.syncController.clearCurrentConnectedPlaceIfMatch(n.placeId)}return r&&Jp(t,e,"disconnected",n),h.info("Plugin client unregistered",{clientId:e,existed:i}),i}function xx(t,e,n){try{let i=e.body;if(!i.clientId){n.status(400).json({error:"Missing clientId"});return}let r=$R(t,{clientId:i.clientId,projectName:i.projectName,placeName:i.placeName,placeId:i.placeId,pluginVersion:i.pluginVersion,studioVersion:i.studioVersion});n.json({status:"ok",clientId:i.clientId,targetAlias:r.clientInfo.targetAlias,serverInstanceId:t.instanceId,sessionId:r.sessionId,mcpVersion:r.mcpVersion,connectedAt:r.clientInfo.connectedAt,aiClientNames:r.aiClientNames,serverStartTime:t.startTime,mcpInstanceCount:r.mcpInstanceCount})}catch(i){h.error("Error registering plugin client",i),n.status(500).json({error:"Internal server error"})}}function _x(t,e,n){let i=e.body?.clientId;if(!i){n.status(400).json({error:"Missing clientId"});return}let r=OR(t,i);n.json({status:"ok",existed:r})}function nq(t,e,n){try{let i=e.body;if(!i.instanceId){n.status(400).json({error:"Missing instanceId"});return}let r=Date.now(),a={instanceId:i.instanceId,...typeof i.sessionId=="string"?{sessionId:i.sessionId}:{},pid:i.pid,connectedAt:r,isServer:!1,lastSeen:r};i.aiClientName&&(a.aiClientName=i.aiClientName),i.cwd&&(a.cwd=i.cwd),"projectRoot"in i&&(a.projectRoot=i.projectRoot),t.mcpInstances.set(i.instanceId,a),et(t,"mcp_status",{aiClientName:a.aiClientName??"Unknown",instanceId:i.instanceId,status:"registered"}),fl(t,{timestamp:new Date().toISOString(),type:"mcp",status:"registered",instanceId:i.instanceId,message:`MCP registered \u2014 ${a.aiClientName??i.instanceId}`,...a.aiClientName?{aiClientName:a.aiClientName}:{}}),h.info("MCP instance registered (client mode)",{instanceId:i.instanceId,pid:i.pid,cwd:i.cwd}),n.json({status:"ok",instanceId:i.instanceId,serverInstanceId:t.instanceId,sessionId:t.sessionId,mcpVersion:tt,mcpInstanceCount:t.mcpInstances.size+1})}catch(i){h.error("Error registering MCP instance",i),n.status(500).json({error:"Internal server error"})}}function rq(t,e,n){let i=e.body?.instanceId;if(!i){n.status(400).json({error:"Missing instanceId"});return}let r=t.mcpInstances.get(i),a=!!r;t.mcpInstances.delete(i),r?.sessionId&&t.executionContextManager?.endSession(r.sessionId),a&&(et(t,"mcp_status",{aiClientName:r?.aiClientName??"Unknown",instanceId:i,status:"unregistered"}),fl(t,{timestamp:new Date().toISOString(),type:"mcp",status:"unregistered",instanceId:i,message:`MCP unregistered \u2014 ${r?.aiClientName??i}`,...r?.aiClientName?{aiClientName:r.aiClientName}:{}})),h.info("MCP instance unregistered",{instanceId:i,existed:a}),n.json({status:"ok",existed:a})}function iq(t,e,n){let{instanceId:i,aiClientName:r}=e.body;if(i&&r){let a=t.mcpInstances.get(i);a&&(a.aiClientName=r)}n.json({status:"ok"})}function aq(t){let e=3e4,n=Date.now(),i=hr({appDataDir:t.config.appDataDir});for(let[a,o]of t.pluginClients)n-o.lastSeen>e&&(t.pluginClients.delete(a),t.pendingCommands.delete(a),cl(t,a));Q8(t);let r=vn(t);return yx(r),{serverInstanceId:t.instanceId,sessionId:t.sessionId,mcpVersion:tt,uptime:n-t.startTime,serverStartTime:t.startTime,serverExecutable:process.execPath,serverHost:t.config.httpHost,serverPort:t.config.httpPort,serverPid:process.pid,pluginClients:r.map(vx),studioRoutingMode:t.studioRoutingMode,pinnedTargetClientId:t.pinnedTargetClientId,mcpInstances:[{instanceId:t.instanceId,pid:process.pid,connectedAt:t.startTime,isServer:!0,cwd:process.cwd(),projectRoot:i,lastSeen:n,...t.aiClientName?{aiClientName:t.aiClientName}:{}},...Array.from(t.mcpInstances.values())],mcpInstanceCount:t.mcpInstances.size+1}}function Sx(t,e){e.json(aq(t))}function wx(t,e,n){let i=e.query.instanceId;i&&t.mcpInstances.has(i)&&(t.mcpInstances.get(i).lastSeen=Date.now()),Q8(t);let r=vn(t);yx(r);let s={...{status:"online",connectedClients:r.length,queuedCommands:e8(t),uptime:Date.now()-t.startTime,version:tt,enableContextCapture:t.executionContextManager?.isEnabled()??t.config.enableContextCapture??!0,isClientMode:t.isClientMode,shuttingDown:t.shuttingDown,pid:process.pid,sessionId:t.sessionId,nodeVersion:process.version,studioRoutingMode:t.studioRoutingMode,pinnedTargetClientId:t.pinnedTargetClientId},instanceId:t.instanceId,mcpInstanceCount:t.mcpInstances.size+1,aiClientNames:bx(t),pluginVersion:t.pluginVersion||void 0,dashboardSseClients:t.dashboardSseClients?.size??0,websocketClients:r.length,pluginClients:r.map(vx),...t.isClientMode?{upstream:{reachable:t.clientModeUpstreamReachable,consecutiveFailures:t.clientModeConsecutiveHealthFailures,lastSuccessAt:t.clientModeLastHealthSuccessAt,lastFailureAt:t.clientModeLastHealthFailureAt,lastError:t.clientModeLastHealthError,baseUrl:t.baseUrl}}:{}};n.json(s)}function oq(t,e,n,i){let r=e.ip||e.socket.remoteAddress||"";if(!(r==="127.0.0.1"||r==="::1"||r==="::ffff:127.0.0.1"||r==="localhost")){h.warn("Shutdown request rejected from non-localhost",{ip:r}),n.status(403).json({error:"Forbidden: localhost only"});return}h.info("Shutdown request received, initiating graceful shutdown",{requestedBy:r,uptime:Date.now()-t.startTime}),n.json({status:"shutting_down",message:"Server will shutdown gracefully",pid:process.pid}),setTimeout(async()=>{try{await i(),h.info("Graceful shutdown completed"),process.exit(0)}catch(o){h.error("Error during graceful shutdown",o),process.exit(1)}},100)}async function Cx(t){if(t.isClientMode)try{let e=await fetch(`${t.baseUrl}/connection-info`);if(e.ok)return await e.json()}catch(e){h.warn("Failed to fetch connection info from server",{error:e})}return aq(t)}Aa();var ut={bridgeRunTest:"manage_studio_run_test_bridge",placeInfo:"system_info_place_info",clearLogs:"manage_logs_clear",createScript:"manage_scripts_create",getLogs:"manage_logs_get",deleteScript:"manage_scripts_delete",canonical:{playStart:"manage_studio_play_start",playStop:"manage_studio_play_stop",playPause:"manage_studio_play_pause",playResume:"manage_studio_play_resume",playStatus:"manage_studio_play_status",runTest:"manage_studio_run_test"}},Dfe=new Set([ut.canonical.runTest]),Nfe=new Set([ut.canonical.playStop]),s4e=new Set([ut.canonical.playStart,ut.canonical.playStop,ut.canonical.playPause,ut.canonical.playResume,ut.canonical.playStatus]);function Gr(t){return Dfe.has(t)}function lf(t){return Nfe.has(t)}var d4e=ut.canonical.playStop,sq=[5e3,15e3];ll();var jfe=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm","manage_assets_import_rbxm","manage_assets_generate_thumbnail"]),tn=class t extends Error{code;routing;constructor(e,n,i){super(n),this.name="CommandTargetSelectionError",this.code=e,this.routing=i,Object.setPrototypeOf(this,t.prototype)}};function Mfe(t={},e){let n={},i=t.clientId,r=t.targetAlias,a=t.placeId;if(i!==void 0){if(typeof i!="string"||i.trim().length===0)throw new tn("invalid_target_selector","clientId target selector must be a non-empty string",{selectionMode:"clientId",...typeof i=="string"?{requestedClientId:i.trim()}:{}});n.requestedClientId=i.trim()}if(r!==void 0){if(typeof r!="string"||r.trim().length===0)throw new tn("invalid_target_selector","targetAlias target selector must be a non-empty string",{selectionMode:"targetAlias",...typeof r=="string"?{requestedTargetAlias:r.trim()}:{}});n.requestedTargetAlias=r.trim()}if(a!==void 0&&zfe(e,t)){if(typeof a!="number"||!Number.isFinite(a))throw new tn("invalid_target_selector","placeId target selector must be a finite number",{selectionMode:"placeId"});n.requestedPlaceId=a}return n}function Ix(t,e,n={},i){let r=Mfe(n,i),a=A6(e,t.studioRoutingMode==="pinned"?t.pinnedTargetClientId:null);if(r.requestedClientId!==void 0)return Lfe(a,r);if(r.requestedTargetAlias!==void 0)return Ufe(a,r);if(r.requestedPlaceId!==void 0)return Ffe(a,r);if(t.studioRoutingMode==="pinned"&&t.pinnedTargetClientId!==null){let s=a.find(c=>c.clientId===t.pinnedTargetClientId);if(s)return{targetClientId:s.clientId,routing:Sr("pinnedTarget",r,s)}}let o=a[0];return o?{targetClientId:o.clientId,routing:Sr("recentPriority",r,o)}:{routing:{selectionMode:"globalQueue"}}}function zfe(t,e){return!t||!jfe.has(t)?!0:e.scope==="shared"}function Lfe(t,e){let n=t.find(i=>i.clientId===e.requestedClientId);if(!n)throw new tn("target_client_not_found",`Target client not found: ${e.requestedClientId}`,Sr("clientId",e));if(e.requestedTargetAlias!==void 0&&n.targetAlias!==e.requestedTargetAlias)throw new tn("target_selector_mismatch",`Target client ${n.clientId} does not match targetAlias ${e.requestedTargetAlias}`,Sr("clientId",e,n));return cq("clientId",e,n),{targetClientId:n.clientId,routing:Sr("clientId",e,n)}}function Ufe(t,e){let n=t.find(i=>i.targetAlias!==void 0&&gx(i.targetAlias)&&i.targetAlias===e.requestedTargetAlias);if(!n)throw new tn("target_alias_not_found",`Target alias not found: ${e.requestedTargetAlias}`,Sr("targetAlias",e));return cq("targetAlias",e,n),{targetClientId:n.clientId,routing:Sr("targetAlias",e,n)}}function Ffe(t,e){let n=t.filter(r=>r.placeId===e.requestedPlaceId);if(n.length===0)throw new tn("target_place_not_found",`Target place not found: ${e.requestedPlaceId}`,Sr("placeId",e));if(n.length>1)throw new tn("target_place_ambiguous",`Target place is ambiguous: ${e.requestedPlaceId}`,Sr("placeId",e));let i=n[0];return{targetClientId:i.clientId,routing:Sr("placeId",e,i)}}function cq(t,e,n){if(e.requestedPlaceId!==void 0&&n.placeId!==e.requestedPlaceId)throw new tn("target_selector_mismatch",`Target client ${n.clientId} is not connected to placeId ${e.requestedPlaceId}`,Sr(t,e,n))}function Sr(t,e,n){let i={selectionMode:t};return e.requestedClientId!==void 0&&(i.requestedClientId=e.requestedClientId),e.requestedTargetAlias!==void 0&&(i.requestedTargetAlias=e.requestedTargetAlias),e.requestedPlaceId!==void 0&&(i.requestedPlaceId=e.requestedPlaceId),n!==void 0&&(i.actualClientId=n.clientId,n.targetAlias!==void 0&&(i.actualTargetAlias=n.targetAlias),n.placeId!==void 0&&(i.actualPlaceId=n.placeId),n.placeName!==void 0&&(i.actualPlaceName=n.placeName)),i}GE();ce();rf();var kl={query_instances:{discriminator:"action",validActions:new Set(["get","children","find_child","find_descendant","wait_for_child","class_info","search_name","search_class","search_property","search_tag","file_tree","project_structure","descendants","ancestors"]),paramAliases:{query_instances_search_name:{query:"pattern"},query_instances_search_property:{root:"rootPath"},query_instances_search_tag:{root:"rootPath"},query_instances_project_structure:{root:"rootPath"}}},mutate_instances:{discriminator:"action",validActions:new Set(["create","create_with_props","delete","clone","move","rename","pivot","create_tree","mass_create","mass_delete","mass_duplicate","smart_duplicate"]),paramAliases:{mutate_instances_clone:{path:"sourcePath"},mutate_instances_smart_duplicate:{spacing:"offset"}}},manage_properties:{discriminator:"action",validActions:new Set(["get","set","get_all","set_multiple","get_attr","set_attr","get_all_attrs","delete_attr","add_tag","remove_tag","check_tag","get_tags","get_tagged","set_calculated","set_relative","mass_set","mass_get","modify_children"]),paramAliases:{manage_properties_get_tagged:{tagName:"tag",root:"rootPath"},manage_properties_set_relative:{amount:"value"}}},manage_scripts:{discriminator:"action",validActions:new Set(["get_source","set_source","create","delete","edit_replace","edit_insert","edit_delete","search","replace","get_dependencies"]),paramAliases:{manage_scripts_edit_replace:{newLines:"newContent"},manage_scripts_edit_insert:{lines:"content"},manage_scripts_replace:{pattern:"searchPattern"}}},manage_ui:{discriminator:"action",validActions:new Set(["design_brief","create_tree","update","delete","preview","check"])},manage_lighting:{discriminator:"action",validActions:new Set(["lighting","atmosphere","sky","terrain_props","time"])},manage_selection:{discriminator:"action",validActions:new Set(["get","set","clear","cached","context","details","add","remove","watch"])},manage_camera:{discriminator:"action",validActions:new Set(["info","focus_path","focus_position","suggest","screenshot"]),paramAliases:{manage_camera_suggest:{path:"targetPath"}}},manage_tween:{discriminator:"action",validActions:new Set(["create","play","pause","cancel"])},manage_audio:{discriminator:"action",validActions:new Set(["play","stop","pause","resume","set_listener"])},manage_animation:{discriminator:"action",validActions:new Set(["load","play","stop","get_tracks"])},manage_physics:{discriminator:"action",validActions:new Set(["register_group","set_collidable","get_groups"])},manage_effects:{discriminator:"action",validActions:new Set(["emit","clear","toggle"])},manage_terrain:{discriminator:"action",validActions:new Set(["fill_block","fill_ball","fill_cylinder","fill_wedge","clear_region","clear_bounds","replace_material","colors_get","colors_set","read_voxel","read_voxels","write_voxels","generate","smooth"])},spatial_query:{discriminator:"action",validActions:new Set(["raycast","find_ground","check_placement","multi_raycast","scan_area","find_flat","find_spawn","analyze_walkable","spatial_map","find_space","bounds","snap_grid","collision"]),paramAliases:{spatial_query_spatial_map:{path:"rootPath"}}},manage_assets:{discriminator:"action",validActions:new Set(["insert","info","search","search_insert","insert_free","insert_package","export_selection_json","export_selection_rbxm","export_path_rbxm","import_rbxm","generate_thumbnail"]),paramAliases:{manage_assets_search:{maxResults:"limit"}}},manage_open_cloud_assets:{discriminator:"action",validActions:new Set(["credential_status","capabilities","upload","update","info","operation_status"])},manage_sync:{discriminator:"action",validActions:new Set(["status_current_place","history","directions","read_file","write_file","progress"])},workspace_state:{discriminator:"action",validActions:new Set(["sync","snapshot","changes","viewport","clear_history","metadata","scripts","selection_info","clear_cache"])},manage_logs:{discriminator:"action",validActions:new Set(["get","clear","errors"]),paramAliases:{manage_logs_get:{level:"type"}}},system_info:{discriminator:"action",validActions:new Set(["ping","connection","usage","place_info","services","studio_settings"])},manage_studio:{discriminator:"action",validActions:new Set(["toggle_ui_preview","play_start","play_stop","play_pause","play_resume","play_status","run_test"])}};var qfe={manage_selection_cached:"internal",manage_open_cloud_assets_credential_status:"internal",manage_open_cloud_assets_capabilities:"internal",manage_open_cloud_assets_upload:"internal",manage_open_cloud_assets_update:"internal",manage_open_cloud_assets_info:"internal",manage_open_cloud_assets_operation_status:"internal",manage_sync_status_current_place:"internal",manage_sync_history:"internal",manage_sync_directions:"internal",manage_sync_read_file:"internal",manage_sync_write_file:"internal",manage_sync_progress:"internal",system_info_connection:"internal",manage_studio_run_test:"internal"};function kx(t){return qfe[t]||"plugin"}var lq=new Set(["batch_execute","execute_luau","extended_call_method","extended_call_methods","extended_get_properties","extended_get_property","extended_set_properties","extended_set_property","manage_animation_get_tracks","manage_animation_load","manage_animation_play","manage_animation_stop","manage_assets_export_path_rbxm","manage_assets_export_selection_json","manage_assets_export_selection_rbxm","manage_assets_generate_thumbnail","manage_assets_import_rbxm","manage_assets_info","manage_assets_insert","manage_assets_insert_free","manage_assets_insert_package","manage_assets_search","manage_assets_search_insert","manage_audio_pause","manage_audio_play","manage_audio_resume","manage_audio_set_listener","manage_audio_stop","manage_camera_screenshot","manage_effects_clear","manage_effects_emit","manage_effects_toggle","manage_lighting_atmosphere","manage_lighting_lighting","manage_lighting_sky","manage_lighting_terrain_props","manage_lighting_time","manage_open_cloud_assets_capabilities","manage_open_cloud_assets_credential_status","manage_open_cloud_assets_info","manage_open_cloud_assets_operation_status","manage_open_cloud_assets_update","manage_open_cloud_assets_upload","manage_physics_get_groups","manage_physics_register_group","manage_physics_set_collidable","manage_properties_mass_get","manage_properties_mass_set","manage_properties_modify_children","manage_properties_set_calculated","manage_properties_set_relative","manage_scripts_replace","manage_selection_add","manage_selection_context","manage_selection_details","manage_selection_remove","manage_selection_watch","manage_studio_play_pause","manage_studio_play_resume","manage_studio_play_start","manage_studio_play_status","manage_studio_play_stop","manage_studio_run_test","manage_studio_toggle_ui_preview","manage_sync_directions","manage_sync_history","manage_sync_progress","manage_sync_read_file","manage_sync_status_current_place","manage_sync_write_file","manage_terrain_clear_bounds","manage_terrain_clear_region","manage_terrain_colors_get","manage_terrain_colors_set","manage_terrain_fill_ball","manage_terrain_fill_block","manage_terrain_fill_cylinder","manage_terrain_fill_wedge","manage_terrain_generate","manage_terrain_read_voxel","manage_terrain_read_voxels","manage_terrain_replace_material","manage_terrain_smooth","manage_terrain_write_voxels","manage_tween_cancel","manage_tween_create","manage_tween_pause","manage_tween_play","manage_ui_check","manage_ui_create_tree","manage_ui_delete","manage_ui_design_brief","manage_ui_preview","manage_ui_update","mutate_instances_create_tree","mutate_instances_mass_create","mutate_instances_mass_delete","mutate_instances_mass_duplicate","mutate_instances_smart_duplicate","query_instances_ancestors","query_instances_descendants","query_instances_file_tree","query_instances_project_structure","query_instances_search_property","query_instances_search_tag","spatial_query_analyze_walkable","spatial_query_bounds","spatial_query_check_placement","spatial_query_collision","spatial_query_find_flat","spatial_query_find_ground","spatial_query_find_space","spatial_query_find_spawn","spatial_query_multi_raycast","spatial_query_raycast","spatial_query_scan_area","spatial_query_snap_grid","spatial_query_spatial_map","system_info_place_info","system_info_services","system_info_studio_settings","workspace_state_changes","workspace_state_clear_cache","workspace_state_clear_history","workspace_state_metadata","workspace_state_scripts","workspace_state_selection_info","workspace_state_snapshot","workspace_state_sync","workspace_state_viewport"]),DR=new Set(["system_info_connection","system_info_ping","system_info_usage"]);function Nn(t){return lq.has(t)?"pro":"basic"}wi();Px();import{readFile as sme}from"node:fs/promises";import cme from"node:path";import{createHash as nme,randomUUID as zR}from"node:crypto";import{mkdir as mf,readFile as bq,readdir as xq,rename as _q,rm as rme,stat as ime,writeFile as $x}from"node:fs/promises";import jt from"node:path";import{extname as Vfe}from"node:path";import{stat as Wfe}from"node:fs/promises";var Gfe=20*1024*1024,yq=[{category:"image",assetType:"Image",folder:"images",extensions:[".png",".jpeg",".jpg",".bmp",".tga"],supportsContentUpdate:!1,contentTypes:{".png":"image/png",".jpeg":"image/jpeg",".jpg":"image/jpeg",".bmp":"image/bmp",".tga":"image/tga"}},{category:"decal",assetType:"Decal",folder:"decals",extensions:[".png",".jpeg",".jpg",".bmp",".tga"],supportsContentUpdate:!1,contentTypes:{".png":"image/png",".jpeg":"image/jpeg",".jpg":"image/jpeg",".bmp":"image/bmp",".tga":"image/tga"}},{category:"audio",assetType:"Audio",folder:"audio",extensions:[".mp3",".ogg",".wav",".flac"],supportsContentUpdate:!1,contentTypes:{".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".flac":"audio/flac"}},{category:"mesh",assetType:"Mesh",folder:"meshes",extensions:[".mesh"],supportsContentUpdate:!1,contentTypes:{".mesh":"application/octet-stream"}},{category:"model",assetType:"Model",folder:"models",extensions:[".fbx",".gltf",".glb",".rbxm",".rbxmx"],supportsContentUpdate:!0,contentTypes:{".fbx":"model/fbx",".gltf":"model/gltf+json",".glb":"model/gltf-binary",".rbxm":"model/x-rbxm",".rbxmx":"model/x-rbxm"}},{category:"video",assetType:"Video",folder:"videos",extensions:[".mp4",".mov"],supportsContentUpdate:!1,contentTypes:{".mp4":"video/mp4",".mov":"video/quicktime"}},{category:"animation",assetType:"Animation",folder:"animations",extensions:[".rbxm",".rbxmx"],supportsContentUpdate:!0,contentTypes:{".rbxm":"model/x-rbxm",".rbxmx":"model/x-rbxm"}}],Kfe=new Map(yq.map(t=>[t.category,t]));function pq(t){if(!t)throw new Error("Open Cloud asset upload is disabled in WEPPY Dashboard settings.")}function Ex(t,e){return t.split(e.apiKey).join("[redacted]")}function jR(t){let e=Kfe.get(t);if(!e)throw new Error(`Unsupported asset category: ${t}`);return e}function Rx(t){return jR(t)}function fq(t,e){let n=t.creatorType??e.creatorType,i=t.creatorId??e.creatorId;if(!n||!i)throw new Error("creatorType and creatorId are required for Roblox Open Cloud asset upload/update.");return{...t,creatorType:n,creatorId:i}}async function mq(t,e,n){let i=Vfe(e).toLowerCase(),r=t.contentTypes[i];if(!r)throw new Error(`Unsupported file extension ${i||"(none)"} for ${t.category}.`);if((await Wfe(e)).size>n)throw new Error(`Asset file is too large. Maximum size is ${n} bytes.`);return r}function gq(t){return typeof t.path=="string"&&t.path.startsWith("operations/")?t.path:null}function hq(t,e,n,i){let r={apiKey:t.apiKey,operationId:e};return n!==void 0&&(r.intervalMs=n),i!==void 0&&(r.timeoutMs=i),r}var Pl=class{client;credentialStore;isOpenCloudUploadEnabled;maxFileSizeBytes;constructor(e){this.client=e.client,this.credentialStore=e.credentialStore,this.isOpenCloudUploadEnabled=e.isOpenCloudUploadEnabled,this.maxFileSizeBytes=e.maxFileSizeBytes??Gfe}getCapabilities(){return yq.map(({contentTypes:e,...n})=>n)}async uploadAsset(e){pq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=fq(e,n),r=jR(i.category),a=await mq(r,i.filePath,this.maxFileSizeBytes);try{let o={apiKey:n.apiKey,assetType:r.assetType,displayName:i.displayName,description:i.description??"",creatorType:i.creatorType,creatorId:i.creatorId,filePath:i.filePath,contentType:a};i.expectedPrice!==void 0&&(o.expectedPrice=i.expectedPrice);let s=await this.client.createAsset(o);if(i.waitForOperation){let c=gq(s);return c?await this.client.pollOperation(hq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(Ex(o instanceof Error?o.message:String(o),n))}}async updateAsset(e){pq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=fq(e,n),r=jR(i.category),a;if(i.filePath){if(!r.supportsContentUpdate)throw new Error(`${r.category} assets do not support content updates.`);a=await mq(r,i.filePath,this.maxFileSizeBytes)}try{let o={apiKey:n.apiKey,assetId:i.assetId,assetType:r.assetType,creatorType:i.creatorType,creatorId:i.creatorId};i.filePath&&(o.filePath=i.filePath),a!==void 0&&(o.contentType=a),i.displayName!==void 0&&(o.displayName=i.displayName),i.description!==void 0&&(o.description=i.description),i.updateMask!==void 0&&(o.updateMask=i.updateMask),i.expectedPrice!==void 0&&(o.expectedPrice=i.expectedPrice);let s=await this.client.updateAsset(o);if(i.waitForOperation){let c=gq(s);return c?await this.client.pollOperation(hq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(Ex(o instanceof Error?o.message:String(o),n))}}async getAsset(e){let n=await this.getRequiredCredential();try{let i={apiKey:n.apiKey,assetId:e.assetId};return e.readMask!==void 0&&(i.readMask=e.readMask),await this.client.getAsset(i)}catch(i){throw new Error(Ex(i instanceof Error?i.message:String(i),n))}}async getOperation(e){let n=await this.getRequiredCredential();try{return await this.client.getOperation({apiKey:n.apiKey,operationId:e.operationId})}catch(i){throw new Error(Ex(i instanceof Error?i.message:String(i),n))}}async getRequiredCredential(){let e=await this.credentialStore.getCredentialForUse();if(!e)throw new Error("Configure a Roblox Open Cloud API key in WEPPY Dashboard before using Open Cloud asset upload.");return e}};import vq from"node:fs";import Vt from"node:path";wb();var Jfe=/^asset_(image|decal|audio|mesh|model|video|animation)_\d+_[a-z0-9]+$/;function Yfe(t){if(!Number.isInteger(t)||t<0)throw new Error(`Invalid place ID: ${t}`)}function Xfe(t,e){try{return vq.statSync(Vt.join(t,e,".sync-meta.json")).isFile()}catch{return!1}}function Qfe(t,e){Yfe(e.placeId);let n=`place_${e.placeId}`,i=e.placeName?nl(e.placeName):"",r=i?`${n}_${i}`:n,a=[];try{let o=new RegExp(`^place_${e.placeId}(?:_.*)?$`);a=vq.readdirSync(t,{withFileTypes:!0}).filter(s=>s.isDirectory()&&o.test(s.name)).map(s=>s.name).sort()}catch{return r}return i&&a.includes(r)?r:a.find(o=>Xfe(t,o))??(a.includes(r)?r:null)??a[0]??r}function MR(t){let e=Vt.resolve(t.projectSyncRoot),n=Rx(t.category).folder,i=t.scope.kind==="place"?Vt.join(e,Qfe(e,t.scope),"assets",n):Vt.join(e,"shared-assets",n);return{root:i,inbox:Vt.join(i,"inbox"),index:Vt.join(i,".asset-library-index.json")}}function eme(t){let e=Jfe.exec(t);return e?.[1]?e[1]:null}function df(t,e){let n=eme(t);return n?e?n===e:!0:!1}function Tx(t,e){if(!df(t,e))throw new Error(`Invalid asset ID: ${t}`)}function Kr(t,e){let n=Vt.relative(Vt.resolve(t),Vt.resolve(e));return n===""||!n.startsWith("..")&&!Vt.isAbsolute(n)}function tme(t){Tx(t.assetId,t.category);let e=MR(t),n=Vt.resolve(e.root,t.assetId);if(!Kr(e.root,n))throw new Error(`Invalid asset path for ${t.assetId}`);return n}function Ax(t){let e=tme(t),n=Vt.resolve(e,t.relativeFileName);if(!Kr(e,n))throw new Error(`Invalid asset file path for ${t.assetId}`);return n}function pf(t,e){return Vt.relative(Vt.resolve(t),Vt.resolve(e)).split(Vt.sep).join("/")}var Sq=20*1024*1024,ame=200;function wq(t,e){return t.kind!==e.kind?!1:t.kind==="shared"&&e.kind==="shared"?!0:t.kind==="place"&&e.kind==="place"&&t.placeId===e.placeId}function Cq(t,e){let n=jt.extname(t).toLowerCase(),i=Rx(e);if(!i.extensions.includes(n))return null;let r=i.contentTypes[n];return r?{canonicalExt:n,mimeType:r}:null}function LR(t,e,n){if(e!=="image"&&e!=="decal")return!0;let i=jt.extname(t).toLowerCase();return i===".png"?n.length>=8&&n[0]===137&&n[1]===80&&n[2]===78&&n[3]===71&&n[4]===13&&n[5]===10&&n[6]===26&&n[7]===10:i===".jpg"||i===".jpeg"?n.length>=3&&n[0]===255&&n[1]===216&&n[2]===255:i===".bmp"?n.length>=2&&n[0]===66&&n[1]===77:i===".tga"?n.length>0:!1}function Iq(t){return nme("sha256").update(t).digest("hex")}function Ox(t){return t.now?.()??Date.now()}function ome(t){return(t.randomId?.()??zR().replace(/-/g,"").slice(0,6)).toLowerCase().replace(/[^a-z0-9]/g,"").slice(0,12)||"asset"}function kq(t,e){let n=Math.floor(Ox(t)/1e3);for(let i=0;i<20;i++){let r=ome(t),a=i===0?`asset_${t.category}_${n}_${r}`:`asset_${t.category}_${n}_${r}${i}`;if(!e.has(a))return a}return`asset_${t.category}_${n}_${zR().replace(/-/g,"").slice(0,10)}`}function Pq(t){let e=jt.parse(t).name.trim();return e.length>0?e:t}function Eq(t){if(t.mimeType!=="image/png")throw new Error("Asset Library preview must be an image/png thumbnail");if(jt.basename(t.fileName).toLowerCase()!=="thumbnail.png")throw new Error("Asset Library preview file must be thumbnail.png");if(!LR("thumbnail.png","image",t.content))throw new Error("Asset Library preview is not a valid PNG file");return{fileName:"thumbnail.png",content:t.content}}async function UR(t,e){let n=`${t}.tmp.${zR().slice(0,8)}`;await $x(n,JSON.stringify(e,null,2),"utf8"),await _q(n,t)}async function Rq(t,e){try{let n=await bq(jt.join(e,"asset.json"),"utf8"),i=JSON.parse(n);return!df(i.id,t.category)||i.category!==t.category||!wq(i.scope,t.scope)?null:i}catch{return null}}async function ff(t,e){let n;try{n=await xq(e.root,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return[];throw r}let i=[];for(let r of n.sort((a,o)=>a.name.localeCompare(o.name))){if(!r.isDirectory()||!df(r.name,t.category))continue;let a=jt.join(e.root,r.name),o=await Rq(t,a);o&&i.push(o)}return i.sort((r,a)=>a.createdAt.localeCompare(r.createdAt)||a.id.localeCompare(r.id))}async function El(t,e,n){if(Tx(n.id,t.category),n.category!==t.category||!wq(n.scope,t.scope))throw new Error(`Asset metadata does not match library scope/category: ${n.id}`);let i=jt.join(e.root,n.id);if(!Kr(e.root,i))throw new Error(`Invalid asset path for ${n.id}`);await mf(i,{recursive:!0}),await UR(jt.join(i,"asset.json"),n)}async function Tq(t,e){await mf(t.root,{recursive:!0});let n={version:1,generatedAt:new Date().toISOString(),assets:e.map(i=>i.id)};await UR(t.index,n)}function Pi(t,e,n){return{fileName:t,reason:e,message:n}}async function Jr(t){let e=MR(t);return await mf(e.inbox,{recursive:!0}),e}async function Aq(t){let e=await Jr(t),n=await ff(t,e);return await Tq(e,n),n}async function Mt(t,e){Tx(e,t.category);let n=await Jr(t),i=jt.join(n.root,e);if(!Kr(n.root,i))throw new Error(`Invalid asset path for ${e}`);let r=await Rq(t,i);if(!r)throw new Error(`Asset not found: ${e}`);return r}async function Rl(t){let e=await Jr(t),n=await ff(t,e),i={version:1,generatedAt:new Date().toISOString(),assets:n.map(r=>r.id)};return await UR(e.index,i),i}async function $q(t){let e=await Jr(t),n=await ff(t,e),i=new Set(n.map(p=>p.id)),r=new Set(n.map(p=>p.file.sha256)),a=[],o=[],s=t.maxFileSizeBytes??Sq,c=t.maxFilesPerRescan??ame,l;try{l=await xq(e.inbox,{withFileTypes:!0})}catch(p){if(p?.code==="ENOENT")l=[];else throw p}let u=l.sort((p,f)=>p.name.localeCompare(f.name));for(let p=0;p<u.length;p++){let f=u[p];if(p>=c){o.push(Pi(f.name,"maxFileCount","rescan file count limit exceeded"));continue}if(f.name.startsWith(".")){o.push(Pi(f.name,"hidden","hidden or system file"));continue}if(f.isSymbolicLink()){o.push(Pi(f.name,"symlink","symlink files are not followed"));continue}if(f.isDirectory()){o.push(Pi(f.name,"nestedDirectory","nested directories are not scanned"));continue}if(!f.isFile()){o.push(Pi(f.name,"unsupportedType","unsupported inbox entry type"));continue}let m=Cq(f.name,t.category);if(!m){o.push(Pi(f.name,"unsupportedType",`unsupported ${t.category} extension`));continue}let g=jt.join(e.inbox,f.name),y=await ime(g);if(y.size>s){o.push(Pi(f.name,"oversized","asset file is larger than the configured limit"));continue}let v=await bq(g);if(!LR(f.name,t.category,v)){o.push(Pi(f.name,"invalidSignature","file signature does not match the extension"));continue}let x=Iq(v);if(r.has(x)){o.push(Pi(f.name,"duplicate","asset content already exists in Asset Library"));continue}let _=kq(t,i);i.add(_),r.add(x);let w=jt.join(e.root,_),C=`original${m.canonicalExt}`;await mf(w,{recursive:!0}),await _q(g,jt.join(w,C));let O=new Date(Ox(t)).toISOString(),L={version:1,id:_,category:t.category,scope:t.scope,status:"localOnly",displayName:Pq(f.name),description:"",source:{kind:"generated",originalPath:pf(t.projectSyncRoot,g)},file:{original:C,preview:null,mimeType:m.mimeType,sha256:x,sizeBytes:y.size,width:null,height:null,durationMs:null},roblox:{uploaded:!1},usage:{lastScannedAt:null,scanSource:null,references:[]},createdAt:O,updatedAt:O};await El(t,e,L),a.push(L)}let d=await ff(t,e);return await Tq(e,d),{assets:d,adopted:a,skipped:o,adoptedCount:a.length,skippedCount:o.length}}async function Oq(t){let e=await Jr(t),n=Cq(t.originalFileName,t.category);if(!n)throw new Error(`Unsupported ${t.category} extension for Asset Library export`);let i=t.maxFileSizeBytes??Sq;if(t.content.length>i)throw new Error("asset file is larger than the configured limit");if(!LR(t.originalFileName,t.category,t.content))throw new Error("file signature does not match the extension");let r=await ff(t,e),a=Iq(t.content),o=r.find(m=>m.file.sha256===a);if(o)return{asset:o,deduplicated:!0};let s=new Set(r.map(m=>m.id)),c=kq(t,s),l=jt.join(e.root,c);if(!Kr(e.root,l))throw new Error(`Invalid asset path for ${c}`);let u=`original${n.canonicalExt}`;await mf(l,{recursive:!0}),await $x(jt.join(l,u),t.content);let d=null;if(t.preview){let m=Eq(t.preview);d=m.fileName,await $x(jt.join(l,m.fileName),m.content)}let p=new Date(Ox(t)).toISOString(),f={version:1,id:c,category:t.category,scope:t.scope,status:"localOnly",displayName:t.displayName?.trim()||Pq(t.originalFileName),description:t.description??"",source:{...t.source,originalPath:pf(t.projectSyncRoot,jt.join(l,u))},file:{original:u,preview:d,mimeType:n.mimeType,sha256:a,sizeBytes:t.content.length,width:null,height:null,durationMs:null},roblox:{uploaded:!1},usage:{lastScannedAt:null,scanSource:null,references:[]},...t.rbxm?{rbxm:t.rbxm}:{},createdAt:p,updatedAt:p};return await El(t,e,f),await Rl(t),{asset:f,deduplicated:!1}}async function Dq(t){let e=await Jr(t),n=await Mt(t,t.assetId),i=Eq(t.preview),r=Ax({...t,relativeFileName:i.fileName});await $x(r,i.content);let a={...n,file:{...n.file,preview:i.fileName},updatedAt:new Date(Ox(t)).toISOString()};return await El(t,e,a),await Rl(t),{asset:a}}async function Nq(t,e,n){let i=await Jr(t),r=await Mt(t,e),a={...r,displayName:typeof n.displayName=="string"?n.displayName:r.displayName,description:typeof n.description=="string"?n.description:r.description,source:{...r.source,...n.source?.agent!==void 0?{agent:n.source.agent}:{},...n.source?.contextId!==void 0?{contextId:n.source.contextId}:{},...n.source?.prompt!==void 0?{prompt:n.source.prompt}:{}},updatedAt:new Date().toISOString()};return await El(t,i,a),await Rl(t),a}async function jq(t,e,n){let i=await Jr(t),a={...await Mt(t,e),usage:n,updatedAt:new Date().toISOString()};return await El(t,i,a),await Rl(t),a}async function Mq(t,e){let n=await Jr(t);await Mt(t,e);let i=jt.join(n.root,e);if(!Kr(n.root,i))throw new Error(`Invalid asset path for ${e}`);return await rme(i,{recursive:!0}),await Rl(t),{assetId:e,removed:1}}async function Fa(t){let e=await Jr(t);return await El(t,e,t.asset),await Rl(t),t.asset}async function Tl(t){let e=await Mt(t,t.assetId);return Ax({...t,relativeFileName:e.file.original})}async function zq(t){let e=await Mt(t,t.assetId);return Ax({...t,relativeFileName:e.file.preview??e.file.original})}var lme="manage_assets_import_rbxm",FR="manage_assets_generate_thumbnail",qR=new Set([lme,FR]),BR=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm"]),ume=new Set(["model","animation"]);function xn(t){return t&&typeof t=="object"?t:null}function dme(t){if(typeof t!="string"||!ume.has(t))throw new Error(`Unsupported Asset Library .rbxm round-trip category: ${String(t??"(missing)")}`);return t}function pme(t){if(typeof t=="number"&&Number.isInteger(t)&&t>=0)return t;if(typeof t=="string"&&t.trim().length>0){let e=Number.parseInt(t,10);if(Number.isInteger(e)&&e>=0)return e}return null}function Lq(t,e){for(let n of t.pluginClients.values())if(!(typeof n.placeId!="number"||!Number.isFinite(n.placeId))&&!(e!==void 0&&n.placeId!==e))return{placeId:n.placeId,...n.placeName?{placeName:n.placeName}:{}};return null}function HR(t,e){let n=mt(t.config.dataDir),i=dme(e.category),r=typeof e.scope=="string"?e.scope:"place",a=typeof e.assetLibraryAssetId=="string"&&e.assetLibraryAssetId.length>0?e.assetLibraryAssetId:void 0;if(r==="shared")return{projectSyncRoot:n,scope:{kind:"shared"},category:i,...a?{assetId:a}:{}};if(r!=="place")throw new Error(`Invalid Asset Library scope: ${r}`);let o=pme(e.placeId),s=t.syncController?.getDefaultRuntimePlaceId()??null,c=o??s??Lq(t)?.placeId??null;if(c===null)throw new Error("No placeId is available for Asset Library .rbxm round-trip.");let l=Lq(t,c);return{projectSyncRoot:n,scope:{kind:"place",placeId:c,...l?.placeName?{placeName:l.placeName}:{}},category:i,...a?{assetId:a}:{}}}function fme(t){if(cme.extname(t.file.original).toLowerCase()!==".rbxm")throw new Error(`Asset Library Studio round-trip supports original.rbxm only. Unsupported original file: ${t.file.original}`)}function mme(t,e){if(typeof t!="string"||t.trim().length===0)throw new Error(`${e} is missing`);return Buffer.from(t,"base64")}function gme(t,e){let n={kind:"studioExport",originalPath:"studio:selection"},i=xn(e);if(i){let r=typeof i.path=="string"?i.path:typeof i.kind=="string"?i.kind:void 0;r&&(n.originalPath=`studio:${r}`)}return typeof t.contextId=="string"&&(n.contextId=t.contextId),n}function Uq(t){let e=xn(t);if(!e)return;let n={};typeof e.width=="number"&&(n.width=e.width),typeof e.height=="number"&&(n.height=e.height),typeof e.source=="string"&&(n.source=e.source),typeof e.error=="string"&&(n.error=e.error);let i=Dx(e.attempts);return i.length>0&&(n.attempts=i),Object.keys(n).length>0?n:void 0}function wr(t,e){return typeof t!="string"?null:t.slice(0,e)}function Al(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function hme(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=xn(e);if(!n)return[];let i=wr(n.name,256),r=wr(n.className,128),a=wr(n.path,512);return i===null||r===null||a===null?[]:[{name:i,className:r,path:a}]}):[]}function yme(t){let e=xn(t);if(!e)return{};let n={};for(let[i,r]of Object.entries(e).slice(0,100))typeof r!="number"||!Number.isFinite(r)||r<0||(n[i.slice(0,128)]=Math.floor(r));return n}function vme(t){return Array.isArray(t)?t.slice(0,200).flatMap(e=>{let n=xn(e);if(!n)return[];let i=wr(n.path,512),r=wr(n.property,128),a=wr(n.value,1024);if(i===null||r===null||a===null)return[];let o=wr(n.assetId,64);return[{path:i,property:r,value:a,...o?{assetId:o}:{}}]}):[]}function Dx(t){return Array.isArray(t)?t.slice(0,8).flatMap(e=>{let n=xn(e);if(!n)return[];let i=wr(n.method,80),r=n.status==="success"||n.status==="failed"||n.status==="skipped"?n.status:null;if(i===null||r===null)return[];let a=wr(n.message,512);return[{method:i,status:r,...a?{message:a}:{}}]}):[]}function bme(t,e){let n=t.thumbnailMode==="auto"?"auto":"none";if(n==="none")return{mode:n,status:"skipped",message:"Thumbnail generation disabled"};let i=Uq(e),r=xn(e),a=typeof r?.pngBase64=="string"&&r.pngBase64.length>0,o=typeof r?.base64Rgba=="string"&&r.base64Rgba.length>0&&r.format==="rgba8"&&typeof r.width=="number"&&typeof r.height=="number";if(i&&(a||o)){let s=Al(i.width),c=Al(i.height),l=Dx(r?.attempts);return{mode:n,status:"generated",...s!==void 0?{width:s}:{},...c!==void 0?{height:c}:{},...typeof i.source=="string"?{source:i.source.slice(0,128)}:{},...l.length>0?{attempts:l}:{}}}if(i&&typeof i.error=="string"){let s=Dx(xn(e)?.attempts);return{mode:n,status:"failed",message:i.error.slice(0,512),...s.length>0?{attempts:s}:{}}}return{mode:n,status:"skipped",message:"Thumbnail was not returned"}}function xme(t,e){let n=xn(t);if(!n)return e;let i=n.mode==="auto"||n.mode==="none"?n.mode:e.mode,r=n.status==="generated"||n.status==="skipped"||n.status==="failed"?n.status:e.status,a=wr(n.message,512),o=Al(n.width),s=Al(n.height),c=wr(n.source,128),l=Dx(n.attempts);return{mode:i,status:r,...a?{message:a}:{},...o!==void 0?{width:o}:{},...s!==void 0?{height:s}:{},...c?{source:c}:{},...l.length>0?{attempts:l}:{}}}function _me(t){let e=xn(t.value),n=hme(e?.roots),i=yme(e?.classCounts),r=vme(e?.resourceReferences),a=Al(e?.exportedCount)??Al(t.exportedCount)??n.length;return{exportedCount:Math.max(0,Math.floor(a)),roots:n,classCounts:i,resourceReferences:r,thumbnail:xme(e?.thumbnail,t.fallbackThumbnail)}}function Sme(t){return t.length>=8&&t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71&&t[4]===13&&t[5]===10&&t[6]===26&&t[7]===10}function Fq(t){let e=xn(t);if(!e)return;let n=null;if(typeof e.pngBase64=="string"&&e.pngBase64.length>0?n=Buffer.from(e.pngBase64,"base64"):typeof e.base64Rgba=="string"&&e.base64Rgba.length>0&&e.format==="rgba8"&&typeof e.width=="number"&&typeof e.height=="number"&&(n=Buffer.from(dq(e.base64Rgba,e.width,e.height),"base64")),!!n){if(!Sme(n))throw new Error("Thumbnail payload is not a valid PNG image.");return{fileName:"thumbnail.png",content:n,mimeType:"image/png"}}}function wme(t,e){let n=e instanceof Error?e.message:String(e);return t.thumbnail.status!=="generated"?t:{...t,thumbnail:{...t.thumbnail,status:"failed",message:`Thumbnail payload could not be stored: ${n}`.slice(0,512)}}}async function qq(t){if(!qR.has(t.command))return t.params;let e=HR(t.ctx,t.params);if(!e.assetId)throw new Error("assetLibraryAssetId is required for Asset Library .rbxm round-trip.");let n=await Mt(e,e.assetId);fme(n);let i=await Tl({...e,assetId:n.id}),r=await sme(i);return{...t.params,__assetLibraryRbxmBase64:r.toString("base64"),__assetLibraryOriginalFile:n.file.original}}async function Bq(t){if(!BR.has(t.command)||!t.result.success)return t.result;let e=xn(t.result.data);if(!e)return t.result;let n=HR(t.ctx,t.params),i=mme(e.rbxmBase64,"Asset Library .rbxm export payload"),r=typeof t.params.displayName=="string"?t.params.displayName:void 0,a=typeof t.params.description=="string"?t.params.description:void 0,o=`${r?.trim()||"studio-export"}.rbxm`,s,c=null;try{s=Fq(e.thumbnail)}catch(p){c=p,s=void 0}let l=_me({value:e.rbxm,exportedCount:e.exportedCount,fallbackThumbnail:bme(t.params,e.thumbnail)});c&&(l=wme(l,c));let u=await Oq({projectSyncRoot:n.projectSyncRoot,scope:n.scope,category:n.category,originalFileName:o,content:i,...r!==void 0?{displayName:r}:{},...a!==void 0?{description:a}:{},source:gme(t.params,e.source),...s?{preview:s}:{},rbxm:l}),d=Uq(e.thumbnail);return{...t.result,data:{asset:u.asset,deduplicated:u.deduplicated,...typeof e.byteLength=="number"?{byteLength:e.byteLength}:{},...typeof e.exportedCount=="number"?{exportedCount:e.exportedCount}:{},...e.source!==void 0?{source:e.source}:{},...d?{thumbnail:d}:{}}}}async function Hq(t){if(!t.result.success)return t.result;let e=xn(t.result.data),n=xn(e?.thumbnail),i;try{i=Fq(n)}catch(o){return{...t.result,success:!1,error:o instanceof Error?o.message:String(o)}}if(!n||!i)return{...t.result,success:!1,error:typeof n?.error=="string"?n.error:"Thumbnail payload is missing from Asset Library thumbnail generation result."};let r=HR(t.ctx,t.params);if(!r.assetId)throw new Error("assetLibraryAssetId is required for Asset Library thumbnail generation.");let a=await Dq({projectSyncRoot:r.projectSyncRoot,scope:r.scope,category:r.category,assetId:r.assetId,preview:i});return{...t.result,data:{asset:a.asset,...typeof n.width=="number"?{width:n.width}:{},...typeof n.height=="number"?{height:n.height}:{},...typeof n.source=="string"?{source:n.source}:{}}}}function Cme(t){if(t===null||typeof t!="object")return;let e=t.proFallback;if(e===null||typeof e!="object")return;let n=e;if(typeof n.executedCommand!="string")return;let i=Array.isArray(n.alternatives)?n.alternatives.filter(r=>typeof r=="string"):void 0;return{executedCommand:n.executedCommand,...typeof n.requestedCommand=="string"?{requestedCommand:n.requestedCommand}:{},...i?{alternatives:i}:{}}}var Ime=/^Pro action '[^']+' is blocked in Basic mode\. Basic fallback '([^']+)' failed: (.*)$/s,kme=/^Pro action '[^']+' is blocked in Basic mode\.(?! Basic fallback ')/,Pme=/instance not found|not found in|parent not found/,Eme=/is required|missing required/,Rme=/unknown action|unknown command/,Tme=/must be|invalid|cannot/;function Ame(t){let e=Ime.exec(t);return e?{fallbackCommand:e[1],reason:e[2]}:null}function $me(t){return kme.test(t)}function Ome(t){let e=t.toLowerCase();return Pme.test(e)?"not_found":Eme.test(e)?"missing_param":Rme.test(e)?"unknown_action":Tme.test(e)?"validation":"other"}function ZR(t){return t.errorType==="bridge_error"||t.errorType==="command_timeout"||t.errorType==="plugin_runtime"||t.errorType==="exception"||t.errorType==="device_blocked"||t.failureOrigin==="bridge"||t.failureOrigin==="plugin_runtime"||t.failureOrigin==="server_exception"||t.failureOrigin==="product_bug"||t.failureOrigin==="unknown"||t.recoverability==="retry"||t.recoverability==="wait_connection"||t.recoverability==="unknown"?"error":"warning"}function $l(t){if(t.resultSuccess){let e=Cme(t.resultData);return e?{kind:"success_fallback",fallbackCommand:e.executedCommand,...e.alternatives?{alternatives:e.alternatives}:{}}:{kind:"success_ok"}}if(!t.resultError)return{kind:"error"};if(t.tier==="pro"){let e=Ame(t.resultError);if(e)return{kind:"blocked_fallback_failed",fallbackCommand:e.fallbackCommand,blockedDetail:Ome(e.reason)};if($me(t.resultError))return{kind:"blocked_unsupported"}}return t.failureClassification?{kind:ZR(t.failureClassification)}:{kind:"error"}}function xe(t,e,n,i,r={}){return{errorType:t,errorDetail:e,failureOrigin:n,recoverability:i,...r}}function Dme(t){let e=t.toLowerCase();return/^\s*compilation error:/.test(e)?xe("execution_failed","compile_error","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*result too large:/.test(e)?xe("execution_failed","result_too_large","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*execution timed out after/.test(e)?xe("execution_failed","execution_timeout","agent_request","code_fix",{validationStage:"plugin_handler"}):/potentially dangerous infinite loop|blocked in sandbox|access to .* is blocked|forbidden|not allowed|cannot access/.test(e)?xe("execution_failed","blocked_source","roblox_policy","code_fix",{validationStage:"plugin_handler"}):null}function Zq(t){let e=t.toLowerCase();return/upstream_server_down/.test(e)?xe("bridge_error","upstream_down","bridge","wait_connection"):/^http [45]\d\d/.test(e)?xe("bridge_error","http_error","bridge","retry"):/duplicate request\s*id/.test(e)?xe("bridge_error","duplicate_request_id","bridge","code_fix"):/timeout/.test(e)?xe("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|econnreset|epipe|network/.test(e)?xe("bridge_error","connection","bridge","wait_connection"):/abort/.test(e)?xe("command_timeout","aborted","bridge","retry"):/runtime error|traceback|attempt to/.test(e)?xe("plugin_runtime","runtime_error","plugin_runtime","code_fix"):/created instance, but failed to set \d+ propert/.test(e)?xe("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler",partialSuccess:"true"}):/failed to set property/.test(e)?xe("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler"}):/parent(?: instance)? not found/.test(e)?xe("execution_failed","parent_not_found","agent_request","fix_params",{validationStage:"plugin_handler"}):/(?:instance|path|root|source instance|ancestor instance) not found|target\s+(?:path\s+)?(?:['"`][^'"`]+['"`]\s+)?not found|not found in|no synced file found for instance/.test(e)?xe("execution_failed","not_found","user_project_state","fix_params",{validationStage:"plugin_handler"}):/is required|missing required/.test(e)?xe("execution_failed","missing_param","agent_request","fix_params",{validationStage:"schema"}):/invalid classname|invalid class/.test(e)?xe("execution_failed","invalid_class","agent_request","fix_params",{validationStage:"plugin_handler"}):/unknown action|unknown command/.test(e)?xe("execution_failed","unknown_action","agent_request","fix_params",{validationStage:"dispatcher"}):/failed to insert asset/.test(e)?xe("execution_failed","asset_error","roblox_policy","fix_params",{validationStage:"roblox_api"}):/failed to read property|property access denied/.test(e)?xe("execution_failed","property_error","agent_request","fix_params",{validationStage:"plugin_handler"}):/forbidden (?:path|parent path)|exceeds (?:total lines|max(?:imum)?(?: length)?)|is not (?:a|an) /.test(e)?xe("execution_failed","validation","agent_request","fix_params",{validationStage:"plugin_handler"}):/sync controller not available|project sync is not initialized|no active sync place|not found in sync cache/.test(e)?xe("execution_failed","sync_not_ready","user_project_state","wait_connection",{validationStage:"preflight"}):/cannot capture edit-mode screenshot while a playtest is active|play-mode screenshot capture is not supported/.test(e)?xe("execution_failed","unsupported_context","roblox_policy","no_retry",{validationStage:"preflight"}):/editableimage api is not enabled|allow mesh \/ image apis|allow http requests/.test(e)?xe("execution_failed","feature_disabled","roblox_policy","no_retry",{validationStage:"preflight"}):/must be|invalid|cannot/.test(e)?xe("execution_failed","validation","agent_request","fix_params",{validationStage:"plugin_handler"}):xe("execution_failed","other","unknown","unknown")}function Ol(t,e){if(t==="execute_luau"){let i=Dme(e);if(i)return i}let n=Zq(e);return t==="execute_luau"&&n.errorDetail==="runtime_error"&&/^\s*runtime error:/i.test(e)?xe("execution_failed","runtime_error","agent_request","code_fix"):n}function Vq(t){let n=(t instanceof Error?t.message:String(t)).toLowerCase();return/timeout/.test(n)?xe("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|network|econnreset|epipe/.test(n)?xe("bridge_error","connection","bridge","wait_connection"):/eaddrinuse/.test(n)?xe("bridge_error","port_in_use","bridge","no_retry"):xe("exception","unexpected","server_exception","code_fix")}Mx();import{randomBytes as Ume}from"node:crypto";var Fme=["manage_ui_create_tree","manage_ui_update","manage_ui_delete"],eB=["manage_ui_preview","manage_ui_check"],qme=["game_genre","ui_role","style_family","layout_family","device_policy","safe_area_policy","existing_ui_strategy"];function YR(t){return t&&typeof t=="object"?t:void 0}function KR(t){return typeof t=="number"&&Number.isFinite(t)?t:0}function zx(t){let e=YR(t);if(!e)return;let n={};for(let i of qme){let r=e[i];typeof r=="string"&&r.trim().length>0&&(n[i]=r)}return Object.keys(n).length>0?n:void 0}function JR(t){let e=zx(t.qualityPlanSummary);if(e)return e;let n=YR(t.contextSummary),i=zx(n?.qualityPlanSummary);if(i)return i;let r=zx(n?.qualityPlan);if(r)return r;let a=zx(n?.quality_plan);if(a)return a}function tB(t,e){return e?{...t??{},...e}:t}function Bme(t){return typeof t=="string"?{snapshotId:t}:t&&typeof t=="object"?{snapshotId:typeof t.snapshotId=="string"?t.snapshotId:null,...t.designCheckSummary!==void 0&&{designCheckSummary:t.designCheckSummary},...t.capturedAt!==void 0&&{capturedAt:t.capturedAt}}:{snapshotId:null}}function nB(t,e,n,i,r){if(!e)return;let a=KR(e.priority_high),o=KR(e.priority_medium),s=KR(e.priority_low),c=typeof e.total=="number"&&Number.isFinite(e.total)?e.total:a+o+s,l=n??(typeof e.target=="string"?e.target:void 0);return{source:t,...l!==void 0&&{targetPath:l},...typeof i=="string"&&{snapshotId:i},...r!==void 0&&{capturedAt:r},priority_high:a,priority_medium:o,priority_low:s,total:c}}function rB(t,e){if(!e)return t;if(!t)return e;let n=t.targetPath===e.targetPath?t.targetPath:void 0,i=t.snapshotId===e.snapshotId?t.snapshotId:void 0;return{source:e.source,...n!==void 0&&{targetPath:n},...i!==void 0&&{snapshotId:i},...e.capturedAt!==void 0&&{capturedAt:e.capturedAt},priority_high:t.priority_high+e.priority_high,priority_medium:t.priority_medium+e.priority_medium,priority_low:t.priority_low+e.priority_low,total:t.total+e.total}}function Hme(t){let e=YR(t);if(e)for(let n of["userMessage","intent","expectedBehavior"]){let i=e[n];if(typeof i=="string"&&i.trim().length>0)return i.trim().slice(0,80)}}function Zme(){return{source:"unavailable",priority_high:0,priority_medium:0,priority_low:0,total:0}}function iB(t){let e=t.now??Date.now,n=null,i=null,r=u=>`${u}_${e()}_${Ume(3).toString("hex")}`,a=()=>{i&&(clearTimeout(i),i=null)},o=()=>{a(),i=setTimeout(()=>{c("idle_timeout")},t.idleMs)},s=async u=>{try{return Bme(await t.capturePreview(u))}catch{return{snapshotId:null}}},c=async u=>{if(!n)return;a();let d=n;n=null;let p={},f;for(let y of d.affectedPaths)if(d.afterSnapshotsPathPolicy[y]==="skip")p[y]=null;else{let v=await s(y);p[y]=v.snapshotId,f=rB(f,nB("after_snapshot",v.designCheckSummary,y,v.snapshotId,v.capturedAt))}let m=f??d.latestDesignCheckSummary??Zme(),g={requestId:d.requestId,...d.contextId!==void 0&&{contextId:d.contextId},...d.label!==void 0&&{label:d.label},startedAt:d.startedAtIso,closedAt:new Date(e()).toISOString(),closeReason:u,ok:d.ok,affectedPaths:Array.from(d.affectedPaths).sort(),mutationCount:d.mutationCount,beforeSnapshots:d.beforeSnapshots,afterSnapshots:p,childMutationIds:d.childMutationIds,...d.qualityPlanSummary!==void 0&&{qualityPlanSummary:d.qualityPlanSummary},postChangeDesignCheckSummary:m};await Yq(t.placeDir,g)},l=u=>({requestId:r("req"),contextId:u.contextId,label:Hme(u.contextSummary),startedAtIso:new Date(e()).toISOString(),startedAtMs:e(),affectedPaths:new Set,beforeSnapshots:{},afterSnapshotsPathPolicy:{},childMutationIds:[],mutationCount:0,ok:!0,qualityPlanSummary:JR(u),latestDesignCheckSummary:void 0,pendingMutation:void 0});return{async beforeMutation(u){if(eB.includes(u.command)){if(n){let p=r("mut");n.qualityPlanSummary=tB(n.qualityPlanSummary,JR(u)),n.pendingMutation={mutationId:p,startedMs:e(),args:u}}return}if(!Fme.includes(u.command))return;n&&n.contextId!==u.contextId?await c("context_change"):n&&a(),n||(n=l(u)),n.qualityPlanSummary=tB(n.qualityPlanSummary,JR(u)),u.targetPath&&!(u.targetPath in n.beforeSnapshots)&&(n.affectedPaths.add(u.targetPath),u.command==="manage_ui_create_tree"?n.beforeSnapshots[u.targetPath]=null:n.beforeSnapshots[u.targetPath]=(await s(u.targetPath)).snapshotId,u.command==="manage_ui_delete"?n.afterSnapshotsPathPolicy[u.targetPath]="skip":u.targetPath in n.afterSnapshotsPathPolicy||(n.afterSnapshotsPathPolicy[u.targetPath]="capture"));let d=r("mut");n.pendingMutation={mutationId:d,startedMs:e(),args:u}},async afterMutation(u){if(!n?.pendingMutation)return;let{mutationId:d,args:p}=n.pendingMutation,f={mutationId:d,requestId:n.requestId,ts:new Date(e()).toISOString(),command:p.command,origin:p.origin,...p.targetPath!==void 0&&{targetPath:p.targetPath},...p.briefId!==void 0&&{briefId:p.briefId},...u.diffSummary!==void 0&&{diffSummary:u.diffSummary},...u.changeDetails!==void 0&&{changeDetails:u.changeDetails},ok:u.ok,...u.error!==void 0&&{error:u.error},durationMs:u.durationMs};if(await Xq(t.placeDir,f),n.pendingMutation=void 0,eB.includes(p.command)){n.latestDesignCheckSummary=rB(n.latestDesignCheckSummary,nB("check_results",u.designCheckSummary,p.targetPath,u.snapshotId,u.capturedAt));return}if(n.mutationCount++,n.childMutationIds.push(d),u.ok||(n.ok=!1),!n.contextId){await c("legacy_single");return}o()},async flushNow(){n&&await c("explicit")}}}var SB=100,Ige=12e4,kge=15e3,wB=new Set(["manage_ui_create_tree","manage_ui_update","manage_ui_delete"]);function Pge(t,e){return`License required for internal command ${t}. ${e??"Activate Pro license to use this feature."}`}var Ege={Text:{category:"text",label:"\uD14D\uC2A4\uD2B8"},PlaceholderText:{category:"text",label:"\uD50C\uB808\uC774\uC2A4\uD640\uB354"},TextColor3:{category:"color",label:"\uAE00\uC790\uC0C9"},BackgroundColor3:{category:"color",label:"\uBC30\uACBD\uC0C9"},BorderColor3:{category:"color",label:"\uD14C\uB450\uB9AC\uC0C9"},ImageColor3:{category:"color",label:"\uC774\uBBF8\uC9C0\uC0C9"},Size:{category:"size",label:"\uC0AC\uC774\uC988"},TextSize:{category:"size",label:"\uAE00\uC790 \uD06C\uAE30"},Position:{category:"layout",label:"\uC704\uCE58"},AnchorPoint:{category:"layout",label:"\uC575\uCEE4"},Rotation:{category:"layout",label:"\uD68C\uC804"},LayoutOrder:{category:"layout",label:"\uB808\uC774\uC544\uC6C3 \uC21C\uC11C"},Visible:{category:"state",label:"\uD45C\uC2DC \uC0C1\uD0DC"},Active:{category:"state",label:"\uD65C\uC131 \uC0C1\uD0DC"},Interactable:{category:"state",label:"\uC0C1\uD638\uC791\uC6A9 \uC0C1\uD0DC"},Selectable:{category:"state",label:"\uC120\uD0DD \uAC00\uB2A5"},Enabled:{category:"state",label:"\uD65C\uC131\uD654"},Image:{category:"asset",label:"\uC774\uBBF8\uC9C0"},Texture:{category:"asset",label:"\uD14D\uC2A4\uCC98"},SoundId:{category:"asset",label:"\uC0AC\uC6B4\uB4DC"}},Rge={text:"\uD14D\uC2A4\uD2B8",color:"\uCEEC\uB7EC",size:"\uC0AC\uC774\uC988",layout:"\uB808\uC774\uC544\uC6C3",state:"\uC0C1\uD0DC",asset:"\uC5D0\uC14B",property:"\uC18D\uC131"},Tge=Object.entries(kl).reduce((t,[e,n])=>{for(let i of n.validActions)t[`${e}_${i}`]=e;return t},{});function hB(t){return{toolName:Tge[t]||t,commandName:t}}function yB(t,e){if(typeof t.contextId=="string"||!e||typeof e!="object")return t;let n=e.contextId;return typeof n=="string"?{...t,contextId:n}:t}function Lx(t,e){if(t!=="manage_sync_status_current_place")return e;let{placeId:n,...i}=e;return i}function Age(t,e){let n=e.routing;return{requestId:t,success:!1,error:e.message,errorCode:e.code,routing:n,data:{routing:n}}}async function $ge(t,e){let n=t.syncController;if(!n)return null;try{let i=e.placeId,r=n.getDefaultRuntimePlaceId(),a=null;if(typeof i=="number"&&Number.isFinite(i))a=i;else if(typeof i=="string"&&i.trim().length>0){let s=Number.parseInt(i,10);Number.isFinite(s)&&(a=s)}if(a===null&&(a=r),a===null||!Number.isFinite(a))return null;let o=a===r?n.getDefaultRuntimePlaceName():null;return typeof o=="string"&&o.length>0?await n.config.resolvePlaceRoot(a,o):n.config.getPlaceRoot(a)}catch{return null}}function Oge(t){let e=t.tree;if(!e||typeof e!="object")return;let n=e,i=typeof n.name=="string"&&n.name.length>0?n.name:void 0;return i?`${typeof n.parent=="string"&&n.parent.length>0?n.parent:"StarterGui"}.${i}`:void 0}function Dge(t,e){let n=e.targetPath;if(typeof n=="string"&&n.length>0)return n;if(t==="manage_ui_create_tree")return Oge(e)}function Nge(t){let e=Ege[t];if(e)return e;let n=t.toLowerCase();return n.includes("color")?{category:"color",label:"\uC0C9\uC0C1"}:t==="Size"||n.endsWith("size")||n.includes("scale")?{category:"size",label:"\uC0AC\uC774\uC988"}:n.includes("position")||n.includes("anchor")||n.includes("rotation")||n.includes("layout")?{category:"layout",label:"\uB808\uC774\uC544\uC6C3"}:n.includes("visible")||n.includes("active")||n.includes("enabled")||n.includes("selectable")||n.includes("interactable")?{category:"state",label:"\uC0C1\uD0DC"}:n.includes("image")||n.includes("texture")||n.includes("sound")||n.includes("asset")?{category:"asset",label:"\uC5D0\uC14B"}:n.includes("text")||n.includes("placeholder")?{category:"text",label:"\uD14D\uC2A4\uD2B8"}:{category:"property",label:t}}function vB(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function jge(t){if(!t||typeof t!="object")return new Map;let e=t,n=e.changed_properties??e.changedProperties;if(!Array.isArray(n))return new Map;let i=new Map;for(let r of n){if(!r||typeof r!="object")continue;let a=r,o=a.property;if(typeof o!="string"||o.length===0)continue;let s=vB(a,"before"),c=vB(a,"after");i.set(o,{...s&&{before:a.before},...c&&{after:a.after},hasBefore:s,hasAfter:c})}return i}function CB(t,e){let i=t.changes?.properties;if(!i||typeof i!="object")return;let r=jge(e),a=Object.entries(i).map(([o,s])=>{let c=Nge(o),l=r.get(o),u={property:o,category:c.category,label:c.label,after:l?.hasAfter?l.after:s};return l?.hasBefore&&(u.before=l.before),u});return a.length>0?a:void 0}function IB(t){if(!t||t.length===0)return;let e=new Map;for(let r of t)e.set(r.category,(e.get(r.category)??0)+1);let i=["text","color","size","layout","state","asset","property"].map(r=>{let a=e.get(r)??0;return a>0?`${Rge[r]} ${a}\uAC1C`:null}).filter(r=>r!==null);return i.length>0?`${i.join(", ")} \uBCC0\uACBD`:void 0}function bB(t,e){if(t==="manage_ui_update"){let n=e.changes,i=IB(CB(e));if(i)return i;let r=n?.properties?Object.keys(n.properties).length:0,a=Array.isArray(n?.addChildren)?n.addChildren.length:0,o=Array.isArray(n?.removeChildren)?n.removeChildren.length:0;return`${r} props, +${a}, -${o}`}if(t==="manage_ui_create_tree")return"tree \uC0DD\uC131";if(t==="manage_ui_delete")return"\uC81C\uAC70\uB428"}function Cf(t){return t&&typeof t=="object"?t:void 0}function Ux(t,e){let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:0}function kB(t){let e=Cf(t),n=Cf(e?.design_check_summary);if(n)return{priority_high:Ux(n,"priority_high"),priority_medium:Ux(n,"priority_medium"),priority_low:Ux(n,"priority_low"),total:Ux(n,"total"),...typeof n.scope=="string"&&{scope:n.scope},...typeof n.target=="string"&&{target:n.target}}}function PB(t){let n=Cf(t)?.snapshot_id;return typeof n=="string"?n:null}function xB(t){if(typeof t=="string"&&t.trim().length>0)return t;if(typeof t=="number"&&Number.isFinite(t)){let e=t<1e10?t*1e3:t;return new Date(e).toISOString()}}function EB(t){let e=Cf(t),n=Cf(e?.meta);return xB(n?.captured_at)??xB(n?.evaluated_at)}function Mge(t,e){let n=t.uiStudioRecorders.get(e);if(n)return n;let i=iB({placeDir:e,idleMs:kge,capturePreview:async r=>{try{let a=await Ir(t,"manage_ui_preview",{targetPath:r},qx());if(!a.success||!a.data||typeof a.data!="object")return null;let o=kB(a.data),s=EB(a.data);return{snapshotId:PB(a.data),...o!==void 0&&{designCheckSummary:o},...s!==void 0&&{capturedAt:s}}}catch{return null}}});return t.uiStudioRecorders.set(e,i),i}async function zge(t,e,n){if(!wB.has(e))return null;let i=await $ge(t,n);if(!i)return null;let r=Mge(t,i),a=e,o=typeof n.contextId=="string"?n.contextId:void 0,s=n.contextSummary,c=s!==void 0&&typeof s=="object"?s:void 0,l=Dge(a,n),u=typeof n.briefId=="string"?n.briefId:void 0,d={command:a,...o!==void 0&&{contextId:o},...c!==void 0&&{contextSummary:c},...l!==void 0&&{targetPath:l},...u!==void 0&&{briefId:u},origin:n.__origin==="dashboard"?"dashboard":"ai"};try{return await r.beforeMutation(d),{recorder:r,command:a,params:n,startedAt:Date.now()}}catch(p){return h.debug("UI Studio recorder beforeMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:p}),null}}async function _B(t,e){if(t)try{let n=t.command==="manage_ui_update"?CB(t.params,e.data):void 0,i=t.command==="manage_ui_update"?IB(n)??bB(t.command,t.params):bB(t.command,t.params),r=kB(e.data),a=PB(e.data),o=EB(e.data);await t.recorder.afterMutation({ok:e.success,durationMs:Date.now()-t.startedAt,...i!==void 0&&{diffSummary:i},...n!==void 0&&{changeDetails:n},...e.error!==void 0&&{error:e.error},...r!==void 0&&{designCheckSummary:r},...a!==null&&{snapshotId:a},...o!==void 0&&{capturedAt:o}})}catch(n){h.debug("UI Studio recorder afterMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:n})}}async function Fx(t,e,n,i,r,a){if(!t.historyManager)return;let o=!r.success&&r.error?Ol(n,r.error):void 0,s=$l({resultSuccess:r.success,resultData:r.data,resultError:r.error,tier:Nn(n),...o?{failureClassification:o}:{}});if(r.success){let u=s.kind==="success_fallback"&&r.data&&typeof r.data=="object"?{...r.data,outcomeStatus:"fallback",requestedCommand:n,executedCommand:s.fallbackCommand,...s.alternatives?{alternatives:s.alternatives}:{}}:r.data,d=Lx(n,i);r.routing?await t.historyManager.recordSuccess(e,d,u,a,n,void 0,r.routing):await t.historyManager.recordSuccess(e,d,u,a,n);return}if(s.kind==="blocked_unsupported"){await t.historyManager.recordBlockedOutcome(e,Lx(n,i),r.error||"Pro action blocked in Basic mode","blocked_unsupported",{executionTimeMs:a,command:n,...r.routing?{routing:r.routing}:{}});return}if(s.kind==="blocked_fallback_failed"){await t.historyManager.recordBlockedOutcome(e,Lx(n,i),r.error||"Pro action blocked in Basic mode","blocked_fallback_failed",{executionTimeMs:a,command:n,...s.fallbackCommand?{fallbackCommand:s.fallbackCommand}:{},...s.blockedDetail?{blockedDetail:s.blockedDetail}:{},...r.routing?{routing:r.routing}:{}});return}let c=s.kind==="warning"?t.historyManager.recordWarning.bind(t.historyManager):t.historyManager.recordFailure.bind(t.historyManager),l=Lx(n,i);r.routing?await c(e,l,r.error||"Unknown error",a,r.errorCode??o?.errorType.toUpperCase(),n,void 0,r.routing):await c(e,l,r.error||"Unknown error",a,r.errorCode??o?.errorType.toUpperCase(),n)}function tT(t,e,n){let i=t.pendingCommands.get(e)||[];i.length>=SB&&i.shift(),i.push(n),t.pendingCommands.set(e,i)}function Lge(t,e){t.globalPendingCommands.length>=SB&&t.globalPendingCommands.shift(),t.globalPendingCommands.push(e)}function RB(t,e,n){let i=qx(),r={requestId:i,command:e.command,params:e.params,timestamp:Date.now(),queueTimeoutMs:e.queueTimeoutMs,ackedTimeoutMs:e.ackedTimeoutMs,state:pn.QUEUED,targetClientId:n,resolve:()=>{},reject:a=>{h.debug("Auxiliary playtest stop command ended without awaited response",{requestId:i,targetClientId:n,error:a.message})},timeoutId:null};return t.commandQueue.set(i,r),r.timeoutId=setTimeout(()=>{Ub(t,r,r.queueTimeoutMs)},r.queueTimeoutMs),{event:"command",id:i,data:{command:r.command,requestId:i,params:r.params}}}function Uge(t,e,n,i){if(!lf(e.data.command))return;let r=t.commandQueue.get(e.data.requestId);if(!r)return;TB(t,r);let a=n.filter(o=>o.clientId!==i);for(let o of a){let s=RB(t,r,o.clientId);tT(t,o.clientId,s)}a.length>0&&h.info("Fan-out playtest stop command to active plugin clients",{requestId:e.data.requestId,primaryClientId:i,auxiliaryClientIds:a.map(o=>o.clientId)})}function TB(t,e,n){for(let i of sq)setTimeout(()=>{let a=n?[...new Set(n)]:[...new Set(vn(t).map(o=>o.clientId))];for(let o of a){if(!t.pluginClients.get(o))continue;let c=RB(t,e,o);tT(t,o,c)}h.info("Retry playtest stop command to active plugin clients",{sourceRequestId:e.requestId,delayMs:i,targetClientIds:a}),pl(t)},i).unref?.()}function AB(t){return t==="clientId"||t==="targetAlias"||t==="placeId"}function Fge(t,e,n){if(!n||!lf(e.data.command))return!1;let i=t.commandQueue.get(e.data.requestId)?.routing?.selectionMode;return!AB(i)}function qge(t,e,n){h.debug("Broadcasting command",{command:e.data.command,requestId:e.data.requestId,targetClientId:n||"all",activeWebsocketClients:vn(t).length});let i=n;if(n){tT(t,n,e);let r=t.commandQueue.get(e.data.requestId),a=r?.routing?.selectionMode;if(r&&lf(e.data.command)&&AB(a))TB(t,r,[n]);else if(Fge(t,e,n)){let o=vn(t).sort((s,c)=>c.lastSeen-s.lastSeen);Uge(t,e,o,n),i=void 0}}else Lge(t,e);pl(t,i)}async function $B(t,e,n){let i=Date.now(),r="",a={};try{let o=e.body;r=o.command??"",a=o.params||{};let s=o.requestId;if(o.instanceId||(t.serverLastCommandAt=Date.now()),o.instanceId){let m=t.mcpInstances.get(o.instanceId);m&&(m.lastCommandAt=Date.now(),m.lastSeen=m.lastCommandAt)}let c=hB(r),l=typeof o.timeout=="number"&&Number.isFinite(o.timeout)&&o.timeout>0?{timeout:o.timeout}:void 0,u=o.instanceId?t.mcpInstances.get(o.instanceId)?.sessionId??t.sessionId:t.sessionId;if(!r){n.status(400).json({error:"Missing command"});return}if(h.debug("Received execute request",{command:r,requestId:s}),r==="manage_camera_play_screenshot"){let m="manage_camera.play_screenshot is not supported. Screenshot capture is available only in Edit mode via manage_camera.screenshot.",g=Date.now()-i;t.historyManager&&await t.historyManager.recordFailure("manage_camera",a,m,g,"UNSUPPORTED_COMMAND",r),n.json({requestId:s,success:!1,error:m});return}if(r==="get_cached_selection"){let m=a.maxAge,g=cf(t,m!==void 0?m:3e4),y=Date.now()-i;if(!g){let _={requestId:s,success:!0,data:{cached:!1,message:"No cached selection data available. The plugin may not be connected or no selection changes have occurred yet."}};t.historyManager&&await t.historyManager.recordSuccess(c.toolName,a,_.data,y,c.commandName),n.json(_);return}let v=Date.now()-g.timestamp,x={cached:!0,selection:g.selection,count:g.count,timestamp:g.timestamp,age:v};t.historyManager&&await t.historyManager.recordSuccess(c.toolName,a,x,y,c.commandName),n.json({requestId:s,success:!0,data:x});return}if(r==="get_connection_info"){let m=await Cx(t),g=Date.now()-i;t.historyManager&&await t.historyManager.recordSuccess(c.toolName,a,m,g,c.commandName),n.json({requestId:s,success:!0,data:m});return}if(kx(r)==="internal"){if(!t.internalCommandExecutor){n.status(503).json({requestId:s,success:!1,error:`Internal command executor is not initialized for command: ${r}`});return}if(Nn(r)==="pro"){if(!t.licenseState){n.status(503).json({requestId:s,success:!1,error:`License state manager is not initialized for internal command: ${r}`});return}let x=await t.licenseState.evaluateProAccess();if(!x.allowed){let _=Pge(r,x.reason),w=Date.now()-i;t.historyManager&&await Fx(t,c.toolName,c.commandName,a,{success:!1,error:_},w),n.json({requestId:s,success:!1,error:_});return}}let m={...a,__sessionId:u},g=await t.internalCommandExecutor(r,m),y=Date.now()-i,v=yB(m,g.data);t.historyManager&&await Fx(t,c.toolName,c.commandName,v,{success:g.success,data:g.data,error:g.error||"Internal command failed"},y),n.json({requestId:s,...g});return}let d=await Ir(t,r,a,s,l),p=Date.now()-i,f={...yB(a,d.data),__sessionId:u};t.historyManager&&await Fx(t,c.toolName,c.commandName,f,d,p),n.json(d)}catch(o){let s=Date.now()-i,c=Dn(o);if(t.historyManager&&r){let l=hB(r);await t.historyManager.recordFailure(l.toolName,a,c,s,"EXCEPTION",l.commandName)}h.error("Execute request failed",o),n.status(500).json({success:!1,error:c})}}async function OB(t,e,n){let i=Date.now(),r=e.body,a=r.action;if(!a||typeof a!="string"){n.status(400).json({success:!1,error:"Missing required field: action"});return}if(!new Set(["get","set","get_all","set_multiple","get_attr","set_attr","get_all_attrs","delete_attr","add_tag","remove_tag","check_tag","get_tags","get_tagged"]).has(a)){n.status(400).json({success:!1,error:`Unsupported action: ${a}`});return}let s=`manage_properties_${a}`,c=qx(),{action:l,...u}=r;try{t.serverLastCommandAt=Date.now();let d=await Ir(t,s,u,c),p=Date.now()-i;t.historyManager&&await Fx(t,"manage_properties",s,u,d,p),n.json(d)}catch(d){let p=Date.now()-i,f=Dn(d);t.historyManager&&await t.historyManager.recordFailure("manage_properties",u,f,p,"EXCEPTION",s),h.error("/api/properties \uC694\uCCAD \uCC98\uB9AC \uC2E4\uD328",d),n.status(500).json({success:!1,error:f})}}async function Ir(t,e,n,i,r){if(h.debug("Executing command locally",{command:e,requestId:i}),H6(t,i)){let d=`Duplicate requestId '${i}' for command '${e}'. Generate a unique requestId for each command.`;return h.warn("Duplicate execute request rejected",{command:e,requestId:i}),{requestId:i,success:!1,error:d}}let a;try{a=Ix(t,vn(t),n,e)}catch(d){if(d instanceof tn)return h.warn("Command target selection failed",{command:e,requestId:i,errorCode:d.code,routing:d.routing}),Age(i,d);throw d}let o=wB.has(e)?await zge(t,e,n):null,s=t.config.requestTimeout,c=r?.timeout??Math.max(t.config.requestTimeout,Ige),l=qR.has(e)?await qq({ctx:t,command:e,params:n}):n,u=new Promise((d,p)=>{let f=Date.now(),m={requestId:i,command:e,params:l,timestamp:f,queueTimeoutMs:s,ackedTimeoutMs:c,state:pn.QUEUED,...a.targetClientId?{targetClientId:a.targetClientId}:{},routing:a.routing,resolve:d,reject:p,timeoutId:null};t.commandQueue.set(i,m),Nb(t,a.targetClientId,f),m.timeoutId=setTimeout(()=>{Ub(t,m,s)},s)});return qge(t,{event:"command",id:qx(),data:{command:e,requestId:i,params:l}},a.targetClientId),u.then(async d=>{let p=d;if(e==="manage_ui_preview"&&d.success&&d.data)try{let{processPreviewResult:f,resolvePreviewPlaceDirFromCtx:m}=await Promise.resolve().then(()=>(eT(),QR)),g=await m(t,n),y=await f("manage_ui_preview",d.data,g);p={...d,data:y.data,...y.mcpContent?{mcpContent:y.mcpContent}:{}}}catch(f){h.warn("preview post-processing failed",{error:f instanceof Error?f.message:String(f)})}if(e==="manage_ui_check"&&d.success&&d.data&&n.includeVisualAnalysis===!0)try{let{resolvePreviewPlaceDirFromCtx:f}=await Promise.resolve().then(()=>(eT(),QR)),{processCheckResult:m}=await Promise.resolve().then(()=>(gB(),mB)),g=await f(t,n),y=await m("manage_ui_check",d.data,g,n);p={...p,data:y.data}}catch(f){h.warn("check visual post-processing failed",{error:f instanceof Error?f.message:String(f)})}return BR.has(e)?p=await Bq({ctx:t,command:e,params:n,result:p}):e===FR&&(p=await Hq({ctx:t,params:n,result:p})),p}).then(async d=>(await _B(o,{success:d.success,...d.data!==void 0&&{data:d.data},...d.error!==void 0&&{error:d.error}}),d),async d=>{throw await _B(o,{success:!1,error:Dn(d)}),d})}ce();xi();function Bx(t,e){let n={};e.provider!==void 0&&(n.provider=e.provider),e.tier!==void 0&&(n.tier=e.tier),e.status!==void 0&&(n.status=e.status),e.canUsePro!==void 0&&(n.canUsePro=e.canUsePro),e.cleared===!0&&(n.cleared=!0),et(t,"license",n)}function Qr(t,e,n,i){t.status(e).json({success:!1,error:{code:n,message:i}})}function Bge(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();return e.length>0?e:void 0}function Hx(t,e){if(e==="plugin")return t;let n={...t};return delete n.sessionToken,n}function If(t,e,n,i){let r=Bge(i??e.query.provider)??"auto";return t.licenseState?.supportsProvider(r)===!1?(Qr(n,400,"LICENSE_PROVIDER_UNSUPPORTED",`provider "${r}" is not supported`),null):r}function kf(t,e){return t.licenseState?!0:(Qr(e,503,"LICENSE_NOT_INITIALIZED","License system is not initialized"),!1)}function Hge(t){if(!t||typeof t!="object")return!1;let e=t;return(e.canUsePro===!0||e.canUsePro===!1)&&typeof e.status=="string"&&typeof e.checkedAt=="number"}function Pf(t,e,n,i="plugin"){if(!kf(t,n))return;let r=e.body,a=typeof r?.licenseKey=="string"?r.licenseKey:"";if(!a.trim()){Qr(n,400,"LICENSE_KEY_REQUIRED","licenseKey is required");return}let o=If(t,e,n,r?.provider);if(!o)return;let s=typeof r?.pluginClientId=="string"?r.pluginClientId:typeof e.query.clientId=="string"?e.query.clientId:void 0,c=typeof r?.deviceId=="string"?r.deviceId:void 0,l={licenseKey:a,provider:o,clientType:i};s&&(l.pluginClientId=s),c&&(l.deviceId=c),t.licenseState.activateGateway(l).then(u=>{t.analyticsManager?.setTier(u.canUsePro?"pro":"basic"),Bx(t,{provider:u.provider,tier:u.canUsePro?"pro":"basic",status:u.status,canUsePro:u.canUsePro}),n.json(Hx(u,i))}).catch(u=>{h.warn("License activate failed",{error:u instanceof Error?u.message:"unknown_error"}),Qr(n,502,"LICENSE_ACTIVATE_FAILED",u instanceof Error?u.message:"License activation failed")})}function Ef(t,e,n,i="plugin"){if(!kf(t,n))return;let r=If(t,e,n);if(r)try{let a=t.licenseState.getStatus(r);t.analyticsManager?.setTier(a.canUsePro?"pro":"basic"),n.json(Hx(a,i))}catch(a){h.warn("License status check failed",{error:a instanceof Error?a.message:"unknown_error"}),Qr(n,502,"LICENSE_STATUS_FAILED",a instanceof Error?a.message:"License status check failed")}}function Rf(t,e,n,i="plugin"){if(!kf(t,n))return;let r=e.body,a=If(t,e,n,r?.provider);if(!a)return;let o={provider:a,clientType:i};i==="plugin"&&typeof r?.sessionToken=="string"&&r.sessionToken.trim()&&(o.sessionToken=r.sessionToken.trim()),typeof r?.pluginClientId=="string"&&(o.pluginClientId=r.pluginClientId),typeof r?.deviceId=="string"&&(o.deviceId=r.deviceId),t.licenseState.refreshGateway(o).then(s=>{t.analyticsManager?.setTier(s.canUsePro?"pro":"basic"),Bx(t,{provider:s.provider,tier:s.canUsePro?"pro":"basic",status:s.status,canUsePro:s.canUsePro}),n.json(Hx(s,i))}).catch(s=>{h.warn("License refresh failed",{error:s instanceof Error?s.message:"unknown_error"}),Qr(n,502,"LICENSE_REFRESH_FAILED",s instanceof Error?s.message:"License refresh failed")})}function Tf(t,e,n,i="plugin"){if(!kf(t,n))return;let r=e.body,a=If(t,e,n,r?.provider);a&&t.licenseState.resetGateway({provider:a,clientType:i}).then(o=>{t.analyticsManager?.setTier("basic"),Bx(t,{provider:o.provider,tier:"basic",status:o.status,canUsePro:o.canUsePro,cleared:!0}),n.json(Hx(o,i))}).catch(o=>{h.warn("License reset failed",{error:o instanceof Error?o.message:"unknown_error"}),Qr(n,502,"LICENSE_RESET_FAILED",o instanceof Error?o.message:"License reset failed")})}function nT(t,e,n){if(!kf(t,n))return;let i=e.body,r=If(t,e,n,i?.provider);if(!r)return;if(i?.clientType!=="plugin"){Qr(n,400,"LICENSE_CLIENT_TYPE_INVALID","clientType must be plugin");return}let a=typeof i?.sessionToken=="string"&&i.sessionToken.trim()?i.sessionToken.trim():void 0,o=Hge(i?.snapshot)?i.snapshot:void 0;if(!o&&!a){Qr(n,400,"LICENSE_BOOTSTRAP_REQUIRED","snapshot or sessionToken is required");return}let s={provider:r,clientType:"plugin"};o&&(s.snapshot=o),a&&(s.sessionToken=a),t.licenseState.bootstrap(s).then(c=>{t.analyticsManager?.setTier(c.canUsePro?"pro":"basic"),Bx(t,{provider:c.provider,tier:c.canUsePro?"pro":"basic",status:c.status,canUsePro:c.canUsePro}),n.json({ok:!0})}).catch(c=>{h.warn("License bootstrap failed",{error:c instanceof Error?c.message:"unknown_error"}),Qr(n,502,"LICENSE_BOOTSTRAP_FAILED",c instanceof Error?c.message:"License bootstrap failed")})}function DB(t){t.app.post("/license/bootstrap",(e,n)=>nT(t,e,n)),t.app.post("/license/activate",(e,n)=>Pf(t,e,n,"plugin")),t.app.post("/license/refresh",(e,n)=>Rf(t,e,n,"plugin")),t.app.post("/license/reset",(e,n)=>Tf(t,e,n,"plugin")),t.app.get("/license/status",(e,n)=>Ef(t,e,n,"plugin"))}ft();ce();import{promises as Zx}from"fs";import rT from"path";function Zge(t){let e=t.config.appDataDir??it();return rT.join(e,"observability","logs")}async function zl(t,e,n){let i=e.query.clientId;if(i&&t.pluginClients.has(i)){let r=t.pluginClients.get(i);r.lastSeen=Date.now()}try{let r=e.body;if(!r||!Array.isArray(r.logs)){h.warn("Invalid logs request",{body:r}),n.status(400).json({error:"Invalid request body"});return}let a=Zge(t);await Zx.mkdir(a,{recursive:!0});let c=`plugin-${new Date().toISOString().split("T")[0]}.log`,l=rT.join(a,c),u=rT.join(a,"current.log"),d=r.logs.map(p=>`[${new Date(p.timestamp*1e3).toISOString().replace("T"," ").substring(0,19)}] [${p.level}] ${p.message}`).join(`
505
505
  `)+`
506
506
  `;await Zx.appendFile(l,d,"utf-8");try{let p="";try{p=await Zx.readFile(u,"utf-8")}catch{}let m=(p+d).split(`
507
507
  `).slice(-500).join(`