@weppy/roblox-mcp 2.10.3 → 2.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -6
- package/dashboard/dist/assets/{AssetsPage-DFC---br.js → AssetsPage-YhGnZEI3.js} +1 -1
- package/dashboard/dist/assets/{ChangelogDetailPage-gvZDaLft.js → ChangelogDetailPage-C78XiyDy.js} +1 -1
- package/dashboard/dist/assets/{ChangelogPage-eOFIHxbD.js → ChangelogPage-BDUgixCt.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-BqCEvp7Y.js → ConfirmModal-WlE0qUHf.js} +1 -1
- package/dashboard/dist/assets/{ConnectionPage-DAz-lhiE.js → ConnectionPage-7MGw5kBx.js} +1 -1
- package/dashboard/dist/assets/{ControlsPage-CKEswTa6.js → ControlsPage-BUtN2zIN.js} +1 -1
- package/dashboard/dist/assets/{CurrentPlaceScope-C8U9I15o.js → CurrentPlaceScope-CF_xE8My.js} +1 -1
- package/dashboard/dist/assets/{GameChangeDetail-CMSmIwO-.js → GameChangeDetail-1QGJVFSx.js} +1 -1
- package/dashboard/dist/assets/{InfoLabel-BAhsgLcj.js → InfoLabel-BkAQdbWd.js} +1 -1
- package/dashboard/dist/assets/{OverviewPage-COMQ7wYS.js → OverviewPage-D1OcIXB0.js} +1 -1
- package/dashboard/dist/assets/{PageHeader-Bfy2f-GH.js → PageHeader-CD450myM.js} +1 -1
- package/dashboard/dist/assets/{PlaytestPage-BIkP1kCO.js → PlaytestPage-DVo_oYz5.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-ClSPo4J8.js → SettingsPage-CU7CHyaG.js} +1 -1
- package/dashboard/dist/assets/{StatusBadge-Df9BQsJU.js → StatusBadge-C2tcoGvy.js} +1 -1
- package/dashboard/dist/assets/{SyncPage-O1vlpViJ.js → SyncPage-BYVYYvX1.js} +1 -1
- package/dashboard/dist/assets/{Tabs-Ccrw7Hjb.js → Tabs-Bb6imtwV.js} +1 -1
- package/dashboard/dist/assets/{ToolsPage-CdPa3eYv.js → ToolsPage-DuMKAsHP.js} +1 -1
- package/dashboard/dist/assets/{TooltipText-CGH7dKN6.js → TooltipText-0HIROg6e.js} +1 -1
- package/dashboard/dist/assets/{UiStudioPage-io4UBG0Y.js → UiStudioPage-BVuHR29W.js} +1 -1
- package/dashboard/dist/assets/{WhatsNewPage-CGKwvik4.js → WhatsNewPage-CfslOZQY.js} +1 -1
- package/dashboard/dist/assets/{copy-D-nSZB9j.js → copy-ozprzL33.js} +1 -1
- package/dashboard/dist/assets/{index-CnXGGM07.js → index-T_F9Rs-N.js} +35 -3
- package/dashboard/dist/assets/{sample-requests-ythz0BoY.js → sample-requests-D5m4UOF0.js} +1 -1
- package/dashboard/dist/assets/{useLiveUptime-1Et9Q6mq.js → useLiveUptime-DpvpGzTY.js} +1 -1
- package/dashboard/dist/assets/{useSettings-DKMlodE_.js → useSettings-D918ACY5.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
package/dist/index.js
CHANGED
|
@@ -68,7 +68,7 @@ data: ${JSON.stringify(n)}
|
|
|
68
68
|
`;t.dashboardSseClients?.forEach(r=>{r.write(i)})}var wi=ee(()=>{"use strict"});import*as Aa from"fs";import*as b6 from"path";function BR(t){return b6.join(t,yde)}function vde(t){return t.startsWith("/")||/^[A-Z]:\\/i.test(t)}function bde(t){return t==="/"||t==="\\"||/^[A-Z]:\\?$/i.test(t)}function x6(t){return typeof t=="string"&&t!==""&&vde(t)&&!bde(t)}function Gp(t){try{let e=Aa.readFileSync(BR(t),"utf8"),n=JSON.parse(e);return x6(n.projectRoot)?n.projectRoot:null}catch{return null}}function HR(t,e){if(!x6(e))throw new Error("projectRoot override must be an absolute non-root path");let n={projectRoot:e,updatedAt:new Date().toISOString()};return Aa.mkdirSync(t,{recursive:!0}),Aa.writeFileSync(BR(t),JSON.stringify(n,null,2),"utf8"),n}function _6(t){Aa.rmSync(BR(t),{force:!0})}var yde,ZR=ee(()=>{"use strict";yde="project-root-override.json"});import*as Ci from"fs";import*as Tb from"path";function _de(t,e,n){let i=Tb.join(t,xde),r={status:"deprecated",kind:n,legacyPath:t,replacementPath:e,migratedAt:new Date().toISOString()};Ci.writeFileSync(i,JSON.stringify(r,null,2),"utf8")}function Sde(t,e){Ci.mkdirSync(Tb.dirname(e),{recursive:!0}),Ci.cpSync(t,e,{recursive:!0})}function VR({preferredPath:t,legacyPath:e,kind:n}){let i=Ci.existsSync(t);return Ci.existsSync(e)&&(i||Sde(e,t),_de(e,t,n)),t}var xde,S6=ee(()=>{"use strict";xde=".weppy-legacy-path.json"});import*as Kp from"path";import*as Ab from"os";function kde(t){return t.startsWith("/")||/^[A-Z]:\\/i.test(t)}function WR(){try{let t=process.cwd();return t==="/"||t==="\\"||/^[A-Z]:\\?$/i.test(t)||t===Ab.homedir()||!kde(t)?null:t}catch{return null}}function Pde(t={}){return t.appDataDir??ot()}function _r(t={}){let e=t.appDataDir??ot();return Gp(e)??WR()??Pde(t)}function ot(){let t=Kp.join(Ab.homedir(),wde),e=Kp.join(Ab.homedir(),Cde);return VR({preferredPath:t,legacyPath:e,kind:"appData"})}function Ii(t={}){return Gt(_r(t))}function Gt(t){let e=Kp.join(t,Jp),n=Kp.join(t,Ide);return VR({preferredPath:e,legacyPath:n,kind:"projectSync"})}var wde,Jp,Cde,Ide,ft=ee(()=>{"use strict";ZR();S6();wde=".weppy-data",Jp="weppy-project-sync",Cde=".wrox-data",Ide="wrox-project-sync"});import Te from"path";import{promises as xt}from"fs";function ol(t){let e=t.replace(/[^a-zA-Z0-9-]/g,"_");return e=e.replace(/_+/g,"_"),e=e.replace(/^_|_$/g,""),e=e.slice(0,40),e=e.replace(/_$/g,""),e}function Tde(t){return{syncRoot:t,explorerRoot:Te.join(t,"explorer")}}var Rde,Ede,$b,Ob=ee(()=>{"use strict";ce();ft();Rde=["CoreGui","CorePackages","RobloxScript","RobloxScriptSecurity"],Ede=["Workspace","Lighting","ReplicatedStorage","ServerStorage","ServerScriptService","StarterGui","StarterPlayer","StarterPack","ReplicatedFirst","SoundService","TextChatService"];$b=class{config;placeRootCache=new Map;migratedPlaces=new Set;async backupAndDeletePlaceDir(e,n){let i=this.config.syncRoot,r=new Date().toISOString().replace(/[:.]/g,"-"),a=Te.join(i,"_deleted-place-backups",`place_${e}`),o=Te.join(i,n),s=`${r}_${n}`,c=Te.join(a,s);await xt.mkdir(a,{recursive:!0}),await xt.cp(o,c,{recursive:!0,force:!0}),await xt.rm(o,{recursive:!0,force:!0}),y.info("Backed up and deleted duplicate place directory",{placeId:e,from:n,backupTo:Te.relative(i,c)})}constructor(e,n={}){let i=e?Gt(e):Ii({appDataDir:n.appDataDir});this.config=Tde(i)}getSyncRoot(){return this.config.syncRoot}getPlaceRoot(e){let n=this.placeRootCache.get(e);return n?Te.join(this.config.syncRoot,n):Te.join(this.config.syncRoot,`place_${e}`)}async hasPlaceDirectory(e){let n=this.placeRootCache.get(e);if(n)try{if((await xt.stat(Te.join(this.config.syncRoot,n))).isDirectory())return!0}catch{}try{let i=await xt.readdir(this.config.syncRoot,{withFileTypes:!0}),r=new RegExp(`^place_${e}(?:_.*)?$`);return i.some(a=>a.isDirectory()&&r.test(a.name))}catch{return!1}}async resolvePlaceRoot(e,n){let i=this.config.syncRoot,r=`place_${e}`,a=n?ol(n):"",o=a?`${r}_${a}`:r;await xt.mkdir(i,{recursive:!0});let s=new RegExp(`^place_${e}(?:_.*)?$`),c=async()=>(await xt.readdir(i,{withFileTypes:!0})).filter(m=>m.isDirectory()&&s.test(m.name)).map(m=>m.name).sort(),l=await c(),u=a?o:this.placeRootCache.get(e)&&s.test(this.placeRootCache.get(e))?this.placeRootCache.get(e):l[0]??o;if(l.length>0&&!l.includes(u)){let f=l[0],m=Te.join(i,f),g=Te.join(i,u);try{await xt.rename(m,g),y.info("Migrated place directory",{from:f,to:u})}catch(h){y.warn("Failed to migrate place directory, using existing",{from:f,to:u,error:h instanceof Error?h.message:String(h)}),u=f}}let d=Te.join(i,u);await xt.mkdir(d,{recursive:!0}),l=await c();let p=l.filter(f=>f!==u);for(let f of p)try{await this.backupAndDeletePlaceDir(e,f)}catch(m){y.warn("Failed to backup/delete duplicate place directory",{placeId:e,duplicate:f,error:m instanceof Error?m.message:String(m)})}return this.migratedPlaces.has(e)||(await this.migrateSyncLogs(d),this.migratedPlaces.add(e)),this.placeRootCache.set(e,u),d}async migrateSyncLogs(e){let n=[["changes.log",Te.join("observability","sync","changes.log")],["history.jsonl",Te.join("observability","sync","history.jsonl")]];for(let[i,r]of n){let a=Te.join(e,i),o=Te.join(e,r);try{await xt.mkdir(Te.dirname(o),{recursive:!0}),await xt.rename(a,o),y.info("Migrated sync log file",{from:i,to:r})}catch(s){s.code!=="ENOENT"&&y.warn("Failed to migrate sync log",{from:i,error:String(s)})}}}async promotePlaceRoot(e,n,i){let r=this.config.syncRoot,a=i?ol(i):"",o=a?`place_${n}_${a}`:`place_${n}`,s=null;try{let d=await xt.readdir(r,{withFileTypes:!0}),p=new RegExp(`^place_${e}(?:_.*)?$`);for(let f of d)if(f.isDirectory()&&p.test(f.name)){s=f.name;break}}catch{}if(!s)return y.info("No existing directory for place promotion, creating new",{oldId:e,newId:n}),this.resolvePlaceRoot(n,i);let c=Te.join(r,s),l=Te.join(r,o);try{await xt.rename(c,l),y.info("Place directory promoted",{from:s,to:o})}catch(d){return y.warn("Failed to rename place directory during promotion, creating new",{from:s,to:o,error:d instanceof Error?d.message:String(d)}),this.placeRootCache.delete(e),this.resolvePlaceRoot(n,i)}this.placeRootCache.delete(e),this.placeRootCache.set(n,o);let u=Te.join(l,".sync-meta.json");try{let d=await xt.readFile(u,"utf-8"),p=JSON.parse(d);p.placeId=n,i&&(p.placeName=i),await xt.writeFile(u,JSON.stringify(p,null,2)+`
|
|
69
69
|
`,"utf-8"),y.info("Updated .sync-meta.json with new placeId",{newId:n})}catch{}return l}getExplorerRoot(e){return e!==void 0?Te.join(this.getPlaceRoot(e),"explorer"):this.config.explorerRoot}getMetaFilePath(e){return e!==void 0?Te.join(this.getPlaceRoot(e),".sync-meta.json"):Te.join(this.config.syncRoot,".sync-meta.json")}getIndexFilePath(e){return e!==void 0?Te.join(this.getPlaceRoot(e),".sync-index.json"):Te.join(this.config.syncRoot,".sync-index.json")}getHistoryPath(e){return e!==void 0?Te.join(this.getPlaceRoot(e),"observability","sync","history.jsonl"):Te.join(this.config.syncRoot,"observability","sync","history.jsonl")}getChangeLogPath(e){return e!==void 0?Te.join(this.getPlaceRoot(e),"observability","sync","changes.log"):Te.join(this.config.syncRoot,"observability","sync","changes.log")}isForbiddenPath(e){for(let n of Rde)if(e.includes(n))return!0;return!1}isSyncableService(e){return Ede.includes(e)}async loadFromMeta(){let e=this.getMetaFilePath();try{JSON.parse(await xt.readFile(e,"utf-8")),y.info("Loaded sync config from .sync-meta.json")}catch(n){n.code==="ENOENT"?y.debug(".sync-meta.json not found \u2014 using defaults"):y.warn("Failed to read .sync-meta.json \u2014 using defaults",n)}}async saveToMeta(e){let n=this.getMetaFilePath();try{await xt.mkdir(Te.dirname(n),{recursive:!0}),await xt.writeFile(n,JSON.stringify(e,null,2)+`
|
|
70
70
|
`,"utf-8"),y.info("Saved sync metadata to .sync-meta.json")}catch(i){throw y.error("Failed to save .sync-meta.json",i),i}}}});function GR(t){return`${t}.props.json`}function Vo(t,e){return`${t}${Db[e]}`}function KR(t){return`${t}.value.json`}function $a(t,e){let n=t.replace(/~/g,"~~");return e===void 0||e<1?n:`${n}~${e}`}function Gr(t){let e=t.match(/(~+)(\d+)$/);if(!e)return{name:t.replace(/~~/g,"~"),siblingIndex:void 0};let n=e[1],i=parseInt(e[2],10);if(n.length%2===1){let r=t.slice(0,t.length-e[0].length),a=n.slice(0,-1);return{name:(r+a).replace(/~~/g,"~"),siblingIndex:i}}return{name:t.replace(/~~/g,"~"),siblingIndex:void 0}}function w6(t){return sl.has(t)?"script":Ade.has(t)?"value":$de.has(t)?"container":JR.has(t)?"service":"data"}function C6(t){switch(t){case"scriptSourceChanged":return"scripts";case"propertyChanged":return"data";case"instanceAdded":case"instanceRemoved":case"instanceRenamed":case"instanceMoved":return"containers";default:return"data"}}function I6(t){return t.endsWith(".server.luau")||t.endsWith(".client.luau")||t.endsWith(".module.luau")?"scripts":t.endsWith(".value.json")?"values":t.endsWith(".props.json")?"data":"containers"}var Db,Nb,jb,sl,Ade,$de,cl,JR,Wo,Go,Sr=ee(()=>{"use strict";Db={Script:".server.luau",LocalScript:".client.luau",ModuleScript:".module.luau"},Nb=2,jb=[".props.json",".server.luau",".client.luau",".module.luau",".value.json"];sl=new Set(["Script","LocalScript","ModuleScript"]),Ade=new Set(["StringValue","IntValue","BoolValue","NumberValue","ObjectValue","Color3Value","Vector3Value","CFrameValue","BrickColorValue","RayValue"]),$de=new Set(["Folder","Model","Configuration","Camera","WorldModel"]),cl=new Set(["Camera","Terrain"]),JR=new Set(["Workspace","Lighting","ReplicatedFirst","ReplicatedStorage","ServerScriptService","ServerStorage","StarterGui","StarterPack","StarterPlayer","SoundService","Teams","Chat","TextChatService","LocalizationService","TestService"]);Wo={scripts:"forward",values:"forward",containers:"forward",data:"forward",services:"forward"},Go={scripts:"manual",values:"manual",containers:"manual",data:"manual",services:"manual"}});import _t from"path";import{randomUUID as Ode}from"crypto";import{promises as wr}from"fs";function Dde(t){return t==="Script"||t==="LocalScript"||t==="ModuleScript"}function Nde(t,e){return _t.relative(t,e).split(_t.sep).join(_t.posix.sep)}async function XR(t){try{return await wr.access(t),!0}catch{return!1}}async function Bde(t){let e=_t.join(t,jde);try{let n=await wr.readFile(e,"utf-8"),i=JSON.parse(n);return{lastActivePlaceId:typeof i.lastActivePlaceId=="number"&&Number.isFinite(i.lastActivePlaceId)?i.lastActivePlaceId:null,lastActivePlaceName:typeof i.lastActivePlaceName=="string"?i.lastActivePlaceName:null}}catch{return{lastActivePlaceId:null,lastActivePlaceName:null}}}async function Hde(t){try{let e=await wr.readFile(_t.join(t,Mde),"utf-8"),n=JSON.parse(e);return typeof n.placeName=="string"?n.placeName:null}catch{return null}}function Zde(t){if(t===".."||t===".")return"_";let e=t.replace(zde,"_");return e=e.replace(Ude,"_"),e=e.replace(Lde,"_"),qde.test(e)?"_unnamed":(Fde.test(e)&&(e=`${e}_`),e)}async function Vde(t){let{lastActivePlaceId:e,lastActivePlaceName:n}=await Bde(t);if(e===null)return null;try{let r=(await wr.readdir(t,{withFileTypes:!0})).filter(a=>a.isDirectory()&&new RegExp(`^${k6}${e}(?:_|$)`).test(a.name)).map(a=>a.name).sort((a,o)=>a.localeCompare(o));if(r.length===0)return null;if(n){let a=`${k6}${e}_${ol(n)}`;if(r.includes(a))return _t.join(t,a)}if(n){for(let a of r)if(await Hde(_t.join(t,a))===n)return _t.join(t,a)}return _t.join(t,r[0])}catch{return null}}async function P6(t,e,n){let i={name:n.originalName??n.name,className:n.className},r=_t.join(e,n.name);if(Dde(n.className)){let o=Zde(n.originalName??n.name),s=_t.join(r,Vo(o,n.className));await XR(s)&&(i.filePaths=[Nde(t,s)])}let a=n.children??[];return a.length>0&&(i.children=await Promise.all(a.map(o=>P6(t,r,o)))),i}async function Wde(t){let e=_t.join(t,"_tree.json");if(!await XR(e))return null;let n=await wr.readFile(e,"utf-8");try{return JSON.parse(n)}catch(i){throw i instanceof SyntaxError?new Error(`Failed to parse sourcemap tree file ${e}: ${i.message}`):i}}async function R6(t,e){let n=`${t}.tmp.${Ode().slice(0,8)}`;try{await wr.writeFile(n,e,"utf-8"),await wr.rename(n,t)}catch(i){throw await wr.unlink(n).catch(()=>{}),i}}async function YR(t){try{await wr.unlink(_t.join(t,Mb))}catch(e){if(e.code!=="ENOENT")throw e}}async function Gde(t,e){let n=_t.join(e,"explorer");if(!await XR(n))return[];let r=(await wr.readdir(n,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name).sort((o,s)=>o.localeCompare(s)),a=[];for(let o of r){let s=_t.join(n,o),c=await Wde(s);if(!c)continue;let l={name:c.name,className:c.className};c.children.length>0&&(l.children=await Promise.all(c.children.map(u=>P6(t,s,u)))),a.push(l)}return a}async function Kde(t,e){return{name:"DataModel",className:"DataModel",children:await Gde(t,e)}}async function zb(t,e){let n=await Kde(t,e),i=_t.join(e,Mb);return await R6(i,JSON.stringify(n,null,2)+`
|
|
71
|
-
`),n}async function ll(t){let e=await Vde(t);if(!e)return await YR(t),!1;let n=_t.join(e,Mb),i;try{i=await wr.readFile(n,"utf-8")}catch{return await YR(t),!1}try{JSON.parse(i)}catch{return await YR(t),!1}return await R6(_t.join(t,Mb),i),!0}var jde,Mb,Mde,k6,zde,Lde,Ude,Fde,qde,Lb=ee(()=>{"use strict";Ob();Sr();jde=".project-meta.json",Mb="sourcemap.json",Mde=".sync-meta.json",k6="place_",zde=/[\u0000-\u001f<>:"/\\|?*[\]]/g,Lde=/[. ]+$/,Ude=/\.\./g,Fde=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i,qde=/^\s*$/});import*as Ub from"fs";import*as Ge from"path";function mt(t){if(!t)return Gt(process.cwd());let e=Ge.normalize(t);if(Ge.basename(e)===Jp)return e;let i=Gt(e);return Ub.existsSync(i)?i:e}function Yde(t){return(t??"").trim().replace(/[\\/:"*?<>|]+/g,"_").replace(/\s+/g,"_").replace(/_+/g,"_").replace(/^_+|_+$/g,"")}async function Xde(t,e,n){if(e==null||!Number.isFinite(e))return Jde;let i=`place_${e}`;try{let o=(await Ub.promises.readdir(t,{withFileTypes:!0})).filter(s=>s.isDirectory()&&new RegExp(`^${i}(?:_.*)?$`).test(s.name)).map(s=>s.name).sort();if(o.length>0)return o[0]}catch{}let r=Yde(n);return r?`${i}_${r}`:i}async function E6(t,e,n){let i=await Xde(t,e,n);return Ge.join(t,i)}async function Yp(t,e,n){return Ge.join(await E6(t,e,n),"observability")}async function T6(t,e,n){return Ge.join(await E6(t,e,n),"tests")}function Qde(t){return Ge.join(t,"observability")}function epe(t){return Ge.join(Qde(t),"connection")}function Oa(t){return Ge.join(epe(t),"history.jsonl")}async function Ko(t,e,n){return Ge.join(await Yp(t,e,n),"tools")}async function Fb(t,e,n){return Ge.join(await Ko(t,e,n),"history")}async function A6(t,e,n){return Ge.join(await Ko(t,e,n),"stats.json")}async function qb(t,e,n){return Ge.join(await Ko(t,e,n),"failures.jsonl")}async function Bb(t,e,n){return Ge.join(await Ko(t,e,n),"warnings.jsonl")}async function Hb(t,e,n){return Ge.join(await Ko(t,e,n),"blocked-outcomes.jsonl")}async function $6(t,e,n){return Ge.join(await Yp(t,e,n),"changelog")}async function O6(t,e,n){return Ge.join(await Yp(t,e,n),"sync")}async function Xp(t,e,n){return Ge.join(await O6(t,e,n),"history.jsonl")}async function Qp(t,e,n){return Ge.join(await O6(t,e,n),"changes.log")}async function ul(t,e,n){return Ge.join(await $6(t,e,n),"sessions")}function tpe(t){return t.replace(/[:/\\*?"<>|]/g,"_")}async function D6(t,e,n,i){let r=await ul(t,n,i);return Ge.join(r,`${tpe(e)}.jsonl`)}async function Jo(t,e,n){return Ge.join(await $6(t,e,n),"contexts.jsonl")}var Jde,ki=ee(()=>{"use strict";ft();Jde="place_unassigned"});function Pi(t){return npe[t]||"mutating"}var npe,QR=ee(()=>{"use strict";npe={batch_execute:"mutating",execute_luau:"mutating",manage_animation_get_tracks:"readonly",manage_animation_load:"mutating",manage_animation_play:"mutating",manage_animation_stop:"mutating",manage_assets_export_path_rbxm:"mutating",manage_assets_export_selection_json:"readonly",manage_assets_export_selection_rbxm:"mutating",manage_assets_generate_model:"mutating",manage_assets_generate_thumbnail:"mutating",manage_assets_import_rbxm:"mutating",manage_assets_info:"readonly",manage_assets_insert:"mutating",manage_assets_insert_free:"mutating",manage_assets_insert_package:"mutating",manage_assets_review_model:"mutating",manage_assets_search:"readonly",manage_assets_search_insert:"mutating",manage_assets_upload_asset:"mutating",manage_audio_pause:"mutating",manage_audio_play:"mutating",manage_audio_resume:"mutating",manage_audio_set_listener:"mutating",manage_audio_stop:"mutating",manage_camera_focus_path:"mutating",manage_camera_focus_position:"mutating",manage_camera_info:"readonly",manage_camera_screenshot:"mutating",manage_camera_suggest:"readonly",manage_effects_clear:"mutating",manage_effects_emit:"mutating",manage_effects_toggle:"mutating",manage_lighting_atmosphere:"mutating",manage_lighting_lighting:"mutating",manage_lighting_sky:"mutating",manage_lighting_terrain_props:"mutating",manage_lighting_time:"mutating",manage_logs_clear:"readonly",manage_logs_errors:"readonly",manage_logs_get:"readonly",manage_open_cloud_assets_capabilities:"readonly",manage_open_cloud_assets_credential_status:"readonly",manage_open_cloud_assets_info:"readonly",manage_open_cloud_assets_operation_status:"readonly",manage_open_cloud_assets_update:"mutating",manage_open_cloud_assets_upload:"mutating",manage_physics_get_groups:"readonly",manage_physics_register_group:"mutating",manage_physics_set_collidable:"mutating",manage_properties_add_tag:"mutating",manage_properties_check_tag:"readonly",manage_properties_delete_attr:"mutating",manage_properties_get:"readonly",manage_properties_get_all:"readonly",manage_properties_get_all_attrs:"readonly",manage_properties_get_attr:"readonly",manage_properties_get_tagged:"readonly",manage_properties_get_tags:"readonly",manage_properties_mass_get:"readonly",manage_properties_mass_set:"mutating",manage_properties_modify_children:"mutating",manage_properties_remove_tag:"mutating",manage_properties_set:"mutating",manage_properties_set_attr:"mutating",manage_properties_set_calculated:"mutating",manage_properties_set_multiple:"mutating",manage_properties_set_relative:"mutating",manage_scripts_create:"mutating",manage_scripts_delete:"mutating",manage_scripts_edit_delete:"mutating",manage_scripts_edit_insert:"mutating",manage_scripts_edit_replace:"mutating",manage_scripts_get_dependencies:"readonly",manage_scripts_get_source:"readonly",manage_scripts_replace:"mutating",manage_scripts_search:"readonly",manage_scripts_set_source:"mutating",manage_selection_add:"mutating",manage_selection_cached:"readonly",manage_selection_clear:"mutating",manage_selection_context:"readonly",manage_selection_details:"readonly",manage_selection_get:"readonly",manage_selection_remove:"mutating",manage_selection_set:"mutating",manage_selection_watch:"mutating",manage_studio_play_pause:"mutating",manage_studio_play_resume:"mutating",manage_studio_play_start:"mutating",manage_studio_play_status:"readonly",manage_studio_play_stop:"mutating",manage_studio_run_test:"mutating",manage_studio_toggle_ui_preview:"mutating",manage_sync_directions:"readonly",manage_sync_history:"readonly",manage_sync_progress:"readonly",manage_sync_read_file:"readonly",manage_sync_status_current_place:"readonly",manage_sync_write_file:"mutating",manage_terrain_clear_bounds:"mutating",manage_terrain_clear_region:"mutating",manage_terrain_colors_get:"readonly",manage_terrain_colors_set:"mutating",manage_terrain_fill_ball:"mutating",manage_terrain_fill_block:"mutating",manage_terrain_fill_cylinder:"mutating",manage_terrain_fill_wedge:"mutating",manage_terrain_generate:"mutating",manage_terrain_read_voxel:"readonly",manage_terrain_read_voxels:"readonly",manage_terrain_replace_material:"mutating",manage_terrain_smooth:"mutating",manage_terrain_write_voxels:"mutating",manage_tween_cancel:"mutating",manage_tween_create:"mutating",manage_tween_pause:"mutating",manage_tween_play:"mutating",manage_ui_check:"mutating",manage_ui_create_tree:"mutating",manage_ui_delete:"mutating",manage_ui_design_brief:"mutating",manage_ui_preview:"mutating",manage_ui_update:"mutating",mutate_instances_clone:"mutating",mutate_instances_create:"mutating",mutate_instances_create_tree:"mutating",mutate_instances_create_with_props:"mutating",mutate_instances_delete:"mutating",mutate_instances_mass_create:"mutating",mutate_instances_mass_delete:"mutating",mutate_instances_mass_duplicate:"mutating",mutate_instances_move:"mutating",mutate_instances_pivot:"mutating",mutate_instances_rename:"mutating",mutate_instances_smart_duplicate:"mutating",query_instances_ancestors:"readonly",query_instances_children:"readonly",query_instances_class_info:"readonly",query_instances_descendants:"readonly",query_instances_file_tree:"readonly",query_instances_find_child:"readonly",query_instances_find_descendant:"readonly",query_instances_get:"readonly",query_instances_project_structure:"readonly",query_instances_search_class:"readonly",query_instances_search_name:"readonly",query_instances_search_property:"readonly",query_instances_search_tag:"readonly",query_instances_wait_for_child:"readonly",spatial_query_analyze_walkable:"readonly",spatial_query_bounds:"readonly",spatial_query_check_placement:"readonly",spatial_query_collision:"readonly",spatial_query_find_flat:"readonly",spatial_query_find_ground:"readonly",spatial_query_find_space:"readonly",spatial_query_find_spawn:"readonly",spatial_query_multi_raycast:"readonly",spatial_query_raycast:"readonly",spatial_query_scan_area:"readonly",spatial_query_snap_grid:"readonly",spatial_query_spatial_map:"readonly",system_info_connection:"readonly",system_info_ping:"readonly",system_info_place_info:"readonly",system_info_services:"readonly",system_info_studio_settings:"readonly",system_info_usage:"readonly",workspace_state_changes:"readonly",workspace_state_clear_cache:"mutating",workspace_state_clear_history:"mutating",workspace_state_metadata:"readonly",workspace_state_scripts:"readonly",workspace_state_selection_info:"readonly",workspace_state_snapshot:"readonly",workspace_state_sync:"readonly",workspace_state_viewport:"readonly"}});function rpe(t,e){return t.pluginCommandClientIdsByProcessToken.get(e)}function N6(t,e){let n=t.pluginCommandSessionsByClientId.get(e);n&&(t.pluginCommandClientIdsByProcessToken.delete(n.processToken),t.pluginCommandSessionsByClientId.delete(e))}function dl(t,e){return t.pluginCommandSessionsByClientId.get(e)??null}function j6(t,e){let n=rpe(t,e.processToken);return n&&n!==e.clientId&&N6(t,n),N6(t,e.clientId),t.pluginCommandSessionsByClientId.set(e.clientId,e),t.pluginCommandClientIdsByProcessToken.set(e.processToken,e.clientId),e}var M6=ee(()=>{"use strict"});function pl(t,e){t.pinnedTargetClientId===e&&(t.studioRoutingMode="recentPriority",t.pinnedTargetClientId=null)}function z6(t,e){return[...t].sort((n,i)=>L6(n,i,e))}function ef(t,e){return[...t].sort((n,i)=>L6(n,i,e))}function L6(t,e,n){if(n){let c=t.clientId===n,l=e.clientId===n;if(c!==l)return c?-1:1}let i=t.lastRoutedAt,r=e.lastRoutedAt,a=i!==void 0;if(a!==(r!==void 0))return a?-1:1;if(i!==void 0&&r!==void 0&&i!==r)return r-i;let s=(t.connectedAt??0)-(e.connectedAt??0);return s!==0?s:t.clientId.localeCompare(e.clientId)}var fl=ee(()=>{"use strict"});function Zb(t,e,n=Date.now()){if(!e)return;let i=t.pluginClients.get(e);i&&(i.lastRoutedAt=n)}var eE=ee(()=>{"use strict"});function ml(t){let e=F6.get(t);return e||(e=new Map,F6.set(t,e)),e}function Vb(t){let e=q6.get(t);return e||(e=new Map,q6.set(t,e)),e}function K6(t){let e=B6.get(t);return e||(e=new Map,B6.set(t,e)),e}function tE(t){let e=H6.get(t);return e||(e=new Map,H6.set(t,e)),e}function nE(t,e,n){(t.readyState===ipe||t.readyState===W6)&&t.close(e,n)}function spe(t){try{let e={type:"heartbeat",timestamp:Date.now()};return t.send(JSON.stringify(e)),!0}catch{return!1}}function J6(t,e,n){rt(t,"connection",{status:"updated",reason:e,...n?{clientId:n}:{},studioRoutingMode:t.studioRoutingMode,pinnedTargetClientId:t.pinnedTargetClientId})}function tf(t,e,n,i=t.pluginClients.get(e)){let r={clientId:e,status:n,...i?.targetAlias?{targetAlias:i.targetAlias}:{},...typeof i?.placeId=="number"?{placeId:i.placeId}:{},...i?.placeName?{placeName:i.placeName}:{}};rt(t,"connection",r),Promise.resolve().then(()=>(tr(),f8)).then(({appendConnectionHistoryEntry:a})=>a(t,{timestamp:new Date().toISOString(),type:"plugin",status:n,clientId:e,...i?.targetAlias?{targetAlias:i.targetAlias}:{},...typeof i?.placeId=="number"?{placeId:i.placeId}:{},...i?.placeName?{placeName:i.placeName}:{},message:`Plugin ${n} \u2014 ${e}`}))}function Wb(t,e,n){return ml(t).get(e)===n}function gl(t,e){let n=Date.now(),i=t.pluginCommandSessionsByClientId.get(e);i&&(i.lastSeen=n);let r=t.pluginClients.get(e);r&&(r.lastSeen=n)}function cpe(t){if(t===dp.EDIT||t===dp.RUNNING||t===dp.PAUSED||t===dp.UNKNOWN)return t}function lpe(t){if(t===pp.THREAD||t===pp.PLUGIN_CONNECTION||t===pp.RUN_SERVICE||t===pp.UNKNOWN)return t}function upe(t){if(t==="play"||t==="run"||t==="unknown")return t}function Z6(t,e){let n=!1,i=cpe(e.studioState);i!==void 0&&t.studioState!==i&&(t.studioState=i,n=!0);let r=lpe(e.studioStateSource);r!==void 0&&t.studioStateSource!==r&&(t.studioStateSource=r,n=!0);let a=e.studioStateUpdatedAt;typeof a=="number"&&Number.isFinite(a)&&t.studioStateUpdatedAt!==a&&(t.studioStateUpdatedAt=a,n=!0);let o=upe(e.playtestMode);return o!==void 0&&t.playtestMode!==o&&(t.playtestMode=o,n=!0),n}function dpe(t,e,n){let i=!1,r=t.pluginCommandSessionsByClientId.get(e);r&&(i=Z6(r,n)||i);let a=t.pluginClients.get(e);return a&&(i=Z6(a,n)||i),i}function Gb(t,e,n){let i=Date.now();n!==Ze.CONNECTED&&pl(t,e);let r=t.pluginCommandSessionsByClientId.get(e);r&&(r.state=n,r.lastSeen=i);let a=t.pluginClients.get(e);a&&(a.connectionType="websocket",a.commandSessionState=n,a.lastSeen=i)}function Y6(t,e){let n=K6(t),i=n.get(e);i&&(clearTimeout(i.timeoutId),n.delete(e))}function X6(t,e){let n=dl(t,e);if(!n)return;Y6(t,e);let i=n.processToken,r=K6(t),a=setTimeout(()=>{let o=dl(t,e);o&&o.processToken===i&&o.state===Ze.RECONNECTING&&Gb(t,e,Ze.DISCONNECTED),r.get(e)?.timeoutId===a&&r.delete(e)},ope);r.set(e,{processToken:i,timeoutId:a})}function ppe(t,e){let n=Vb(t);n.delete(e),n.set(e,!0)}function Q6(t,e){return t.commandQueue.has(e)||Vb(t).has(e)}function Kb(t,e){for(let[n,i]of t.pendingCommands){let r=i.filter(a=>a.data.requestId!==e);r.length!==i.length&&t.pendingCommands.set(n,r)}t.globalPendingCommands=t.globalPendingCommands.filter(n=>n.data.requestId!==e)}function fpe(t){return{event:"command",id:t.requestId,data:{command:t.command,requestId:t.requestId,params:t.params}}}function e8(t,e,n,i=!1){if(n){let r=t.pendingCommands.get(n)||[];i?r.unshift(e):r.push(e),t.pendingCommands.set(n,r);return}i?t.globalPendingCommands.unshift(e):t.globalPendingCommands.push(e)}function t8(t,e,n){if(!e)return;let i=t.pluginClients.get(e);i?.inFlightRequestId===n&&(i.inFlightRequestId=void 0)}function n8(t){t.timeoutId&&(clearTimeout(t.timeoutId),t.timeoutId=null)}function rE(t,e,n){if(!e.routing||e.routing.actualClientId)return;let i=t.pluginClients.get(n);i&&(e.routing={...e.routing,actualClientId:i.clientId,...i.targetAlias!==void 0?{actualTargetAlias:i.targetAlias}:{},...i.placeId!==void 0?{actualPlaceId:i.placeId}:{},...i.placeName!==void 0?{actualPlaceName:i.placeName}:{}})}function mpe(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function gpe(t,e){return t===void 0?{routing:e}:mpe(t)?{...t,routing:e}:{value:t,routing:e}}function hpe(t,e){if(!e.routing)return t;let n={...t,routing:e.routing};return t.success||(n.data=gpe(t.data,e.routing)),n}function ype(t,e,n){n8(e),e.timeoutId=setTimeout(()=>{Jb(t,e,n)},n)}function V6(t,e){if(t.length===0)return[];let n=t[0];if(Pi(n.data.command)!=="readonly")return[t.shift()];let i=[];for(;t.length>0&&i.length<e;){let r=t[0];if(Pi(r.data.command)!=="readonly")break;i.push(t.shift())}return i}function vpe(t,e){let n=t.pendingCommands.get(e)||[],i=V6(n,U6);return t.pendingCommands.set(e,n),i.length>0?i:V6(t.globalPendingCommands,U6)}function r8(t,e,n){return!n||n.readyState!==W6?!1:t.pluginClients.get(e)?.commandSessionState===Ze.CONNECTED}function i8(t,e,n){let i=ml(t),r=t.pluginCommandClientIdsByProcessToken.get(n.processToken),a=i.get(n.clientId),s=dl(t,n.clientId)?.state??t.pluginClients.get(n.clientId)?.commandSessionState,c=r&&r!==n.clientId?i.get(r):null,l=s===Ze.RECONNECTING||s===Ze.DISCONNECTED||s===Ze.CONNECTED?"reconnected":"connected";tE(t).set(n.clientId,l),c&&c!==e&&nE(c,4e3,"replaced by new websocket session"),a&&a!==e&&(s===Ze.CONNECTED&&J6(t,"session-replacement",n.clientId),nE(a,4e3,"replaced by new websocket session")),Y6(t,n.clientId),i.set(n.clientId,e),j6(t,{...n,connectedAt:Date.now(),lastSeen:Date.now(),state:Ze.HANDSHAKING});let u=t.pluginClients.get(n.clientId);u&&(n.targetAlias!==void 0&&(u.targetAlias=n.targetAlias),u.connectionType="websocket",u.commandSessionState=Ze.HANDSHAKING,u.processToken=n.processToken,u.lastSeen=Date.now())}function a8(t,e,n){if(typeof n.clientId!="string"||typeof n.processToken!="string")return"ignored";if(!Wb(t,n.clientId,e))return"conflict";let i=dl(t,n.clientId);if(!i||i.processToken!==n.processToken)return"conflict";let r=new Set;for(let o of n.ackedRequestIds||[])r.add(o);for(let o of n.runningRequestIds||[])r.add(o);for(let o of r)u8(t,o,n.clientId);for(let o of n.finishedResults||[])iE(t,o,n.clientId);if(!spe(e))return"ignored";Gb(t,n.clientId,Ze.CONNECTED);let a=tE(t).get(n.clientId)??"connected";return tE(t).delete(n.clientId),tf(t,n.clientId,a),hl(t,n.clientId),"connected"}function o8(t,e,n,i={}){if(!Wb(t,n,e))return;let r=dpe(t,n,i);gl(t,n),r&&J6(t,"studio-state",n)}function s8(t,e,n){let i=ml(t);if(i.get(n)!==e)return;let r=t.pluginClients.get(n),a=r?.commandSessionState===Ze.CONNECTED;i.delete(n),Gb(t,n,Ze.RECONNECTING),a&&tf(t,n,"disconnected",r),X6(t,n);for(let o of t.commandQueue.values())o.targetClientId===n&&o.state===vn.DELIVERED&&xpe(t,o.requestId)}function c8(t,e=Date.now()){let n=ml(t),i=0;for(let[r,a]of n){let o=dl(t,r);if(!o){n.delete(r),pl(t,r);continue}if(o.state!==Ze.CONNECTED||e-o.lastSeen<=ape)continue;let s=t.pluginClients.get(r);Gb(t,r,Ze.RECONNECTING),tf(t,r,"disconnected",s),X6(t,r),nE(a,4001,"stale websocket session"),i++}return i}function l8(t){let e=0;for(let n of t.commandQueue.values())n.state!==vn.COMPLETED&&e++;return e}function Cn(t){let e=ml(t),n=[];for(let[i,r]of e){if(!r8(t,i,r))continue;let a=t.pluginClients.get(i);a&&n.push(a)}return n}function bpe(t,e,n){let i=t.commandQueue.get(e);if(!i)return!1;Kb(t,e);let r=!i.targetClientId&&i.routing?.selectionMode==="globalQueue"&&!i.routing.actualClientId;i.state=vn.DELIVERED,i.targetClientId=n,rE(t,i,n),i.deliveredAt=Date.now(),r&&Zb(t,n,i.deliveredAt),gl(t,n);let a=t.pluginClients.get(n);return a&&Pi(i.command)==="mutating"&&(a.inFlightRequestId=e),!0}function u8(t,e,n){let i=t.commandQueue.get(e);if(!i)return Vb(t).has(e)?"duplicate":"unknown";if(i.state===vn.COMPLETED)return"duplicate";if(n&&i.targetClientId&&i.targetClientId!==n&&i.state!==vn.QUEUED)return"conflict";Kb(t,e),i.state=vn.ACKED,i.ackedAt=Date.now(),n&&(i.targetClientId=n,rE(t,i,n),gl(t,n)),ype(t,i,i.ackedTimeoutMs);let r=n?t.pluginClients.get(n):null;return r&&Pi(i.command)==="mutating"&&(r.inFlightRequestId=e),"acked"}function iE(t,e,n){let i=t.commandQueue.get(e.requestId);if(!i)return Vb(t).has(e.requestId)?"duplicate":"unknown";if(i.state===vn.COMPLETED)return"duplicate";if(n&&i.targetClientId&&i.targetClientId!==n)return"conflict";n8(i),t8(t,n??i.targetClientId,e.requestId),Kb(t,e.requestId),i.state=vn.COMPLETED,i.completedAt=Date.now(),n&&(i.targetClientId=n,rE(t,i,n),gl(t,n));let r=hpe(e,i);return i.completedResult=r,i.resolve(r),t.totalCommandsProcessed++,ppe(t,e.requestId),t.commandQueue.delete(e.requestId),"completed"}function Jb(t,e,n){let i=e.targetClientId,r=`Command timeout after ${n}ms while ${e.state}: ${e.command}`,a=iE(t,{requestId:e.requestId,success:!1,error:r,errorCode:"command_timeout"},i);return a==="completed"&&hl(t,i),a}function xpe(t,e){let n=t.commandQueue.get(e);return!n||n.state!==vn.DELIVERED?!1:(t8(t,n.targetClientId,e),Kb(t,e),n.state=vn.QUEUED,delete n.deliveredAt,e8(t,fpe(n),n.targetClientId,!0),!0)}function d8(t,e,n,i){return Wb(t,n,e)?(gl(t,n),u8(t,i,n)):"conflict"}function p8(t,e,n,i){if(!Wb(t,n,e))return"conflict";gl(t,n);let r=iE(t,i,n);return r==="completed"&&hl(t,n),r}async function hl(t,e){let n=ml(t),i=e?[e]:Array.from(n.keys()),r=0;for(let a of i){let o=n.get(a);if(!r8(t,a,o))continue;let s=t.pluginClients.get(a)?.inFlightRequestId;if(s&&t.commandQueue.has(s))continue;let c=vpe(t,a);if(c.length!==0)for(let l=0;l<c.length;l++){let u=c[l],d=t.commandQueue.get(u.data.requestId);if(d)try{o.send(JSON.stringify({type:"command",requestId:d.requestId,data:{command:d.command,params:d.params},executionMode:Pi(d.command)})),bpe(t,d.requestId,a),r++}catch{for(let p=c.length-1;p>=l;p--)e8(t,c[p],a,!0);break}}}return r}var ipe,W6,ape,ope,G6,U6,F6,q6,B6,H6,Da=ee(()=>{"use strict";xa();QR();M6();fl();wi();eE();ipe=0,W6=1,ape=15e3,ope=5e3,G6=1e3,U6=4,F6=new WeakMap,q6=new WeakMap,B6=new WeakMap,H6=new WeakMap});var f8={};qt(f8,{JSONL_TAIL_DEFAULT_LINES:()=>Yb,appendChangelogEntry:()=>vl,appendConnectionHistoryEntry:()=>yl,appendJsonlLine:()=>cE,clearChangelogForPlace:()=>pE,clearConnectionHistory:()=>dE,clearDirectoryChildren:()=>tx,clearFile:()=>af,clearMatchingFiles:()=>kpe,enrichWithExecutionContext:()=>Ma,getAuthoritativeDashboardPluginClients:()=>Xb,getChangelogEntriesForPlace:()=>Yo,getConnectionHistoryEntries:()=>uE,getDashboardPlaceSummary:()=>sE,getDashboardSyncRoot:()=>nr,getExecutionContextSnapshotMapForPlace:()=>Xo,getExecutionContextSnapshotsForPlace:()=>v8,getPlaceObservabilityPath:()=>Ppe,getPlaceTestsPath:()=>bl,isDashboardPluginConnected:()=>Qb,loadProjectMeta:()=>oE,parseDashboardPlaceIdQuery:()=>Na,persistLastActivePlace:()=>ex,pickPrimaryExecutionContext:()=>nx,readJsonlFile:()=>lE,readJsonlFileTail:()=>rf,readTestContextFile:()=>rx,resolveActiveDashboardPlaceId:()=>nf,resolveActiveDashboardPlaceName:()=>Nn,resolveDashboardPlaceId:()=>ja,saveProjectMeta:()=>h8,trimJsonlFileTail:()=>y8});import*as je from"fs";import*as In from"path";function g8(t){return In.join(t,".project-meta.json")}function nr(t){return mt(t.config.dataDir)}function Xb(t){return Cn(t).sort((e,n)=>n.lastSeen-e.lastSeen)}function Qb(t){return Xb(t).length>0}function Ipe(t){try{let e=t.syncController?.getSyncRoot();if(typeof e!="string"||e.length===0)return null;let n=je.readdirSync(e,{withFileTypes:!0}),i=-1,r=null;for(let a of n){if(!a.isDirectory())continue;let o=a.name.match(/^place_(\d+)/);if(!o)continue;let s=parseInt(o[1]??"",10);if(Number.isFinite(s))try{let c=je.statSync(In.join(e,a.name));c.mtimeMs>i&&(i=c.mtimeMs,r=s)}catch{}}return r}catch{return null}}function nf(t){let e=t.syncController?.getDefaultRuntimePlaceId();if(typeof e=="number"&&Number.isFinite(e))return e;let n=Xb(t).filter(i=>typeof i.placeId=="number"&&Number.isFinite(i.placeId))[0];return typeof n?.placeId=="number"&&Number.isFinite(n.placeId)?n.placeId:Ipe(t)}function Na(t){if(typeof t!="string"||t.trim().length===0)return null;let e=Number.parseInt(t,10);return!Number.isInteger(e)||e<0?null:e}function ja(t,e){return typeof e=="number"&&Number.isFinite(e)?e:nf(t)}function Nn(t,e){if(e==null)return null;let n=t.syncController?.getDefaultRuntimePlaceName?.();return typeof n=="string"&&n.length>0&&t.syncController?.getDefaultRuntimePlaceId()===e?n:Xb(t).filter(r=>r.placeId===e)[0]?.placeName??null}async function oE(t){try{let e=await je.promises.readFile(g8(t),"utf-8"),n=JSON.parse(e);return typeof n.lastActivePlaceId!="number"&&n.lastActivePlaceId!==null?null:{version:1,lastActivePlaceId:n.lastActivePlaceId??null,lastActivePlaceName:typeof n.lastActivePlaceName=="string"?n.lastActivePlaceName:null,lastActiveAt:typeof n.lastActiveAt=="string"?n.lastActiveAt:null}}catch{return null}}async function h8(t,e){await je.promises.mkdir(t,{recursive:!0}),await je.promises.writeFile(g8(t),JSON.stringify(e,null,2))}async function ex(t,e,n){if(!Number.isFinite(e))return;let i=nr(t),r=await oE(i),o=n??null??(r?.lastActivePlaceId===e?r.lastActivePlaceName:null),s=r?.lastActivePlaceId===e&&r.lastActivePlaceName===o;s||await h8(i,{version:1,lastActivePlaceId:e,lastActivePlaceName:o,lastActiveAt:new Date().toISOString()});try{!await ll(i)&&!s&&y.warn("Failed to refresh root representative sourcemap after updating last active place",{syncRoot:i,placeId:e,placeName:o})}catch(c){y.warn("Failed to refresh root representative sourcemap after updating last active place",{syncRoot:i,placeId:e,placeName:o,error:c instanceof Error?c.message:String(c)})}}async function sE(t){let e=nr(t),n=Qb(t),i=nf(t),r=Nn(t,i);typeof i=="number"&&Number.isFinite(i)&&await ex(t,i,r);let a=await oE(e),o=await je.promises.readdir(e,{withFileTypes:!0}).catch(()=>[]),s=(await Promise.all(o.filter(c=>c.isDirectory()&&c.name.startsWith("place_")).map(async c=>{let l=In.join(e,c.name,".sync-meta.json");try{let u=await je.promises.readFile(l,"utf-8"),d=JSON.parse(u);return typeof d.placeId!="number"||typeof d.placeName!="string"?null:{placeId:d.placeId,placeName:d.placeName,placeDirName:c.name,testsPath:In.join(e,c.name,"tests"),lastFullSync:typeof d.lastFullSync=="string"?d.lastFullSync:null,instanceCount:typeof d.instanceCount=="number"?d.instanceCount:null,scriptCount:typeof d.scriptCount=="number"?d.scriptCount:null,isActive:d.placeId===i,isConnected:d.placeId===i&&n}}catch{return null}}))).filter(c=>c!==null);return s.sort((c,l)=>c.isActive!==l.isActive?c.isActive?-1:1:c.placeName.localeCompare(l.placeName)),{pluginConnected:n,activePlaceId:i,activePlaceName:r,lastActivePlaceId:a?.lastActivePlaceId??null,lastActivePlaceName:a?.lastActivePlaceName??null,places:s}}async function cE(t,e){await je.promises.mkdir(In.dirname(t),{recursive:!0}),await je.promises.appendFile(t,JSON.stringify(e)+`
|
|
71
|
+
`),n}async function ll(t){let e=await Vde(t);if(!e)return await YR(t),!1;let n=_t.join(e,Mb),i;try{i=await wr.readFile(n,"utf-8")}catch{return await YR(t),!1}try{JSON.parse(i)}catch{return await YR(t),!1}return await R6(_t.join(t,Mb),i),!0}var jde,Mb,Mde,k6,zde,Lde,Ude,Fde,qde,Lb=ee(()=>{"use strict";Ob();Sr();jde=".project-meta.json",Mb="sourcemap.json",Mde=".sync-meta.json",k6="place_",zde=/[\u0000-\u001f<>:"/\\|?*[\]]/g,Lde=/[. ]+$/,Ude=/\.\./g,Fde=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i,qde=/^\s*$/});import*as Ub from"fs";import*as Ge from"path";function mt(t){if(!t)return Gt(process.cwd());let e=Ge.normalize(t);if(Ge.basename(e)===Jp)return e;let i=Gt(e);return Ub.existsSync(i)?i:e}function Yde(t){return(t??"").trim().replace(/[\\/:"*?<>|]+/g,"_").replace(/\s+/g,"_").replace(/_+/g,"_").replace(/^_+|_+$/g,"")}async function Xde(t,e,n){if(e==null||!Number.isFinite(e))return Jde;let i=`place_${e}`;try{let o=(await Ub.promises.readdir(t,{withFileTypes:!0})).filter(s=>s.isDirectory()&&new RegExp(`^${i}(?:_.*)?$`).test(s.name)).map(s=>s.name).sort();if(o.length>0)return o[0]}catch{}let r=Yde(n);return r?`${i}_${r}`:i}async function E6(t,e,n){let i=await Xde(t,e,n);return Ge.join(t,i)}async function Yp(t,e,n){return Ge.join(await E6(t,e,n),"observability")}async function T6(t,e,n){return Ge.join(await E6(t,e,n),"tests")}function Qde(t){return Ge.join(t,"observability")}function epe(t){return Ge.join(Qde(t),"connection")}function Oa(t){return Ge.join(epe(t),"history.jsonl")}async function Ko(t,e,n){return Ge.join(await Yp(t,e,n),"tools")}async function Fb(t,e,n){return Ge.join(await Ko(t,e,n),"history")}async function A6(t,e,n){return Ge.join(await Ko(t,e,n),"stats.json")}async function qb(t,e,n){return Ge.join(await Ko(t,e,n),"failures.jsonl")}async function Bb(t,e,n){return Ge.join(await Ko(t,e,n),"warnings.jsonl")}async function Hb(t,e,n){return Ge.join(await Ko(t,e,n),"blocked-outcomes.jsonl")}async function $6(t,e,n){return Ge.join(await Yp(t,e,n),"changelog")}async function O6(t,e,n){return Ge.join(await Yp(t,e,n),"sync")}async function Xp(t,e,n){return Ge.join(await O6(t,e,n),"history.jsonl")}async function Qp(t,e,n){return Ge.join(await O6(t,e,n),"changes.log")}async function ul(t,e,n){return Ge.join(await $6(t,e,n),"sessions")}function tpe(t){return t.replace(/[:/\\*?"<>|]/g,"_")}async function D6(t,e,n,i){let r=await ul(t,n,i);return Ge.join(r,`${tpe(e)}.jsonl`)}async function Jo(t,e,n){return Ge.join(await $6(t,e,n),"contexts.jsonl")}var Jde,ki=ee(()=>{"use strict";ft();Jde="place_unassigned"});function Pi(t){return npe[t]||"mutating"}var npe,QR=ee(()=>{"use strict";npe={batch_execute:"mutating",execute_luau:"mutating",manage_animation_get_tracks:"readonly",manage_animation_load:"mutating",manage_animation_play:"mutating",manage_animation_stop:"mutating",manage_assets_export_path_rbxm:"mutating",manage_assets_export_selection_json:"readonly",manage_assets_export_selection_rbxm:"mutating",manage_assets_generate_model:"mutating",manage_assets_generate_thumbnail:"mutating",manage_assets_import_rbxm:"mutating",manage_assets_info:"readonly",manage_assets_insert:"mutating",manage_assets_insert_free:"mutating",manage_assets_insert_package:"mutating",manage_assets_review_model:"mutating",manage_assets_search:"readonly",manage_assets_search_insert:"mutating",manage_assets_upload_asset:"mutating",manage_audio_pause:"mutating",manage_audio_play:"mutating",manage_audio_resume:"mutating",manage_audio_set_listener:"mutating",manage_audio_stop:"mutating",manage_camera_focus_path:"mutating",manage_camera_focus_position:"mutating",manage_camera_info:"readonly",manage_camera_screenshot:"mutating",manage_camera_suggest:"readonly",manage_effects_clear:"mutating",manage_effects_emit:"mutating",manage_effects_toggle:"mutating",manage_lighting_atmosphere:"mutating",manage_lighting_lighting:"mutating",manage_lighting_mood:"mutating",manage_lighting_sky:"mutating",manage_lighting_terrain_props:"mutating",manage_lighting_time:"mutating",manage_logs_clear:"readonly",manage_logs_errors:"readonly",manage_logs_get:"readonly",manage_open_cloud_assets_capabilities:"readonly",manage_open_cloud_assets_credential_status:"readonly",manage_open_cloud_assets_info:"readonly",manage_open_cloud_assets_operation_status:"readonly",manage_open_cloud_assets_update:"mutating",manage_open_cloud_assets_upload:"mutating",manage_physics_get_groups:"readonly",manage_physics_register_group:"mutating",manage_physics_set_collidable:"mutating",manage_properties_add_tag:"mutating",manage_properties_check_tag:"readonly",manage_properties_delete_attr:"mutating",manage_properties_get:"readonly",manage_properties_get_all:"readonly",manage_properties_get_all_attrs:"readonly",manage_properties_get_attr:"readonly",manage_properties_get_tagged:"readonly",manage_properties_get_tags:"readonly",manage_properties_mass_get:"readonly",manage_properties_mass_set:"mutating",manage_properties_modify_children:"mutating",manage_properties_remove_tag:"mutating",manage_properties_set:"mutating",manage_properties_set_attr:"mutating",manage_properties_set_calculated:"mutating",manage_properties_set_multiple:"mutating",manage_properties_set_relative:"mutating",manage_scripts_create:"mutating",manage_scripts_delete:"mutating",manage_scripts_edit_delete:"mutating",manage_scripts_edit_insert:"mutating",manage_scripts_edit_replace:"mutating",manage_scripts_get_dependencies:"readonly",manage_scripts_get_source:"readonly",manage_scripts_replace:"mutating",manage_scripts_search:"readonly",manage_scripts_set_source:"mutating",manage_selection_add:"mutating",manage_selection_cached:"readonly",manage_selection_clear:"mutating",manage_selection_context:"readonly",manage_selection_details:"readonly",manage_selection_get:"readonly",manage_selection_remove:"mutating",manage_selection_set:"mutating",manage_selection_watch:"mutating",manage_studio_play_pause:"mutating",manage_studio_play_resume:"mutating",manage_studio_play_start:"mutating",manage_studio_play_status:"readonly",manage_studio_play_stop:"mutating",manage_studio_run_test:"mutating",manage_studio_toggle_ui_preview:"mutating",manage_sync_directions:"readonly",manage_sync_history:"readonly",manage_sync_progress:"readonly",manage_sync_read_file:"readonly",manage_sync_status_current_place:"readonly",manage_sync_write_file:"mutating",manage_terrain_clear_bounds:"mutating",manage_terrain_clear_region:"mutating",manage_terrain_colors_get:"readonly",manage_terrain_colors_set:"mutating",manage_terrain_fill_ball:"mutating",manage_terrain_fill_block:"mutating",manage_terrain_fill_cylinder:"mutating",manage_terrain_fill_wedge:"mutating",manage_terrain_generate:"mutating",manage_terrain_read_voxel:"readonly",manage_terrain_read_voxels:"readonly",manage_terrain_replace_material:"mutating",manage_terrain_smooth:"mutating",manage_terrain_write_voxels:"mutating",manage_tween_cancel:"mutating",manage_tween_create:"mutating",manage_tween_pause:"mutating",manage_tween_play:"mutating",manage_ui_check:"mutating",manage_ui_create_tree:"mutating",manage_ui_delete:"mutating",manage_ui_design_brief:"mutating",manage_ui_preview:"mutating",manage_ui_update:"mutating",mutate_instances_clone:"mutating",mutate_instances_create:"mutating",mutate_instances_create_tree:"mutating",mutate_instances_create_with_props:"mutating",mutate_instances_delete:"mutating",mutate_instances_mass_create:"mutating",mutate_instances_mass_delete:"mutating",mutate_instances_mass_duplicate:"mutating",mutate_instances_move:"mutating",mutate_instances_pivot:"mutating",mutate_instances_rename:"mutating",mutate_instances_scatter:"mutating",mutate_instances_smart_duplicate:"mutating",query_instances_ancestors:"readonly",query_instances_children:"readonly",query_instances_class_info:"readonly",query_instances_descendants:"readonly",query_instances_file_tree:"readonly",query_instances_find_child:"readonly",query_instances_find_descendant:"readonly",query_instances_get:"readonly",query_instances_project_structure:"readonly",query_instances_search_class:"readonly",query_instances_search_name:"readonly",query_instances_search_property:"readonly",query_instances_search_tag:"readonly",query_instances_wait_for_child:"readonly",spatial_query_analyze_walkable:"readonly",spatial_query_bounds:"readonly",spatial_query_check_placement:"readonly",spatial_query_collision:"readonly",spatial_query_find_flat:"readonly",spatial_query_find_ground:"readonly",spatial_query_find_space:"readonly",spatial_query_find_spawn:"readonly",spatial_query_multi_raycast:"readonly",spatial_query_raycast:"readonly",spatial_query_scan_area:"readonly",spatial_query_snap_grid:"readonly",spatial_query_spatial_map:"readonly",system_info_connection:"readonly",system_info_ping:"readonly",system_info_place_info:"readonly",system_info_services:"readonly",system_info_studio_settings:"readonly",system_info_usage:"readonly",workspace_state_changes:"readonly",workspace_state_clear_cache:"mutating",workspace_state_clear_history:"mutating",workspace_state_metadata:"readonly",workspace_state_scripts:"readonly",workspace_state_selection_info:"readonly",workspace_state_snapshot:"readonly",workspace_state_sync:"readonly",workspace_state_viewport:"readonly"}});function rpe(t,e){return t.pluginCommandClientIdsByProcessToken.get(e)}function N6(t,e){let n=t.pluginCommandSessionsByClientId.get(e);n&&(t.pluginCommandClientIdsByProcessToken.delete(n.processToken),t.pluginCommandSessionsByClientId.delete(e))}function dl(t,e){return t.pluginCommandSessionsByClientId.get(e)??null}function j6(t,e){let n=rpe(t,e.processToken);return n&&n!==e.clientId&&N6(t,n),N6(t,e.clientId),t.pluginCommandSessionsByClientId.set(e.clientId,e),t.pluginCommandClientIdsByProcessToken.set(e.processToken,e.clientId),e}var M6=ee(()=>{"use strict"});function pl(t,e){t.pinnedTargetClientId===e&&(t.studioRoutingMode="recentPriority",t.pinnedTargetClientId=null)}function z6(t,e){return[...t].sort((n,i)=>L6(n,i,e))}function ef(t,e){return[...t].sort((n,i)=>L6(n,i,e))}function L6(t,e,n){if(n){let c=t.clientId===n,l=e.clientId===n;if(c!==l)return c?-1:1}let i=t.lastRoutedAt,r=e.lastRoutedAt,a=i!==void 0;if(a!==(r!==void 0))return a?-1:1;if(i!==void 0&&r!==void 0&&i!==r)return r-i;let s=(t.connectedAt??0)-(e.connectedAt??0);return s!==0?s:t.clientId.localeCompare(e.clientId)}var fl=ee(()=>{"use strict"});function Zb(t,e,n=Date.now()){if(!e)return;let i=t.pluginClients.get(e);i&&(i.lastRoutedAt=n)}var eE=ee(()=>{"use strict"});function ml(t){let e=F6.get(t);return e||(e=new Map,F6.set(t,e)),e}function Vb(t){let e=q6.get(t);return e||(e=new Map,q6.set(t,e)),e}function K6(t){let e=B6.get(t);return e||(e=new Map,B6.set(t,e)),e}function tE(t){let e=H6.get(t);return e||(e=new Map,H6.set(t,e)),e}function nE(t,e,n){(t.readyState===ipe||t.readyState===W6)&&t.close(e,n)}function spe(t){try{let e={type:"heartbeat",timestamp:Date.now()};return t.send(JSON.stringify(e)),!0}catch{return!1}}function J6(t,e,n){rt(t,"connection",{status:"updated",reason:e,...n?{clientId:n}:{},studioRoutingMode:t.studioRoutingMode,pinnedTargetClientId:t.pinnedTargetClientId})}function tf(t,e,n,i=t.pluginClients.get(e)){let r={clientId:e,status:n,...i?.targetAlias?{targetAlias:i.targetAlias}:{},...typeof i?.placeId=="number"?{placeId:i.placeId}:{},...i?.placeName?{placeName:i.placeName}:{}};rt(t,"connection",r),Promise.resolve().then(()=>(tr(),f8)).then(({appendConnectionHistoryEntry:a})=>a(t,{timestamp:new Date().toISOString(),type:"plugin",status:n,clientId:e,...i?.targetAlias?{targetAlias:i.targetAlias}:{},...typeof i?.placeId=="number"?{placeId:i.placeId}:{},...i?.placeName?{placeName:i.placeName}:{},message:`Plugin ${n} \u2014 ${e}`}))}function Wb(t,e,n){return ml(t).get(e)===n}function gl(t,e){let n=Date.now(),i=t.pluginCommandSessionsByClientId.get(e);i&&(i.lastSeen=n);let r=t.pluginClients.get(e);r&&(r.lastSeen=n)}function cpe(t){if(t===dp.EDIT||t===dp.RUNNING||t===dp.PAUSED||t===dp.UNKNOWN)return t}function lpe(t){if(t===pp.THREAD||t===pp.PLUGIN_CONNECTION||t===pp.RUN_SERVICE||t===pp.UNKNOWN)return t}function upe(t){if(t==="play"||t==="run"||t==="unknown")return t}function Z6(t,e){let n=!1,i=cpe(e.studioState);i!==void 0&&t.studioState!==i&&(t.studioState=i,n=!0);let r=lpe(e.studioStateSource);r!==void 0&&t.studioStateSource!==r&&(t.studioStateSource=r,n=!0);let a=e.studioStateUpdatedAt;typeof a=="number"&&Number.isFinite(a)&&t.studioStateUpdatedAt!==a&&(t.studioStateUpdatedAt=a,n=!0);let o=upe(e.playtestMode);return o!==void 0&&t.playtestMode!==o&&(t.playtestMode=o,n=!0),n}function dpe(t,e,n){let i=!1,r=t.pluginCommandSessionsByClientId.get(e);r&&(i=Z6(r,n)||i);let a=t.pluginClients.get(e);return a&&(i=Z6(a,n)||i),i}function Gb(t,e,n){let i=Date.now();n!==Ze.CONNECTED&&pl(t,e);let r=t.pluginCommandSessionsByClientId.get(e);r&&(r.state=n,r.lastSeen=i);let a=t.pluginClients.get(e);a&&(a.connectionType="websocket",a.commandSessionState=n,a.lastSeen=i)}function Y6(t,e){let n=K6(t),i=n.get(e);i&&(clearTimeout(i.timeoutId),n.delete(e))}function X6(t,e){let n=dl(t,e);if(!n)return;Y6(t,e);let i=n.processToken,r=K6(t),a=setTimeout(()=>{let o=dl(t,e);o&&o.processToken===i&&o.state===Ze.RECONNECTING&&Gb(t,e,Ze.DISCONNECTED),r.get(e)?.timeoutId===a&&r.delete(e)},ope);r.set(e,{processToken:i,timeoutId:a})}function ppe(t,e){let n=Vb(t);n.delete(e),n.set(e,!0)}function Q6(t,e){return t.commandQueue.has(e)||Vb(t).has(e)}function Kb(t,e){for(let[n,i]of t.pendingCommands){let r=i.filter(a=>a.data.requestId!==e);r.length!==i.length&&t.pendingCommands.set(n,r)}t.globalPendingCommands=t.globalPendingCommands.filter(n=>n.data.requestId!==e)}function fpe(t){return{event:"command",id:t.requestId,data:{command:t.command,requestId:t.requestId,params:t.params}}}function e8(t,e,n,i=!1){if(n){let r=t.pendingCommands.get(n)||[];i?r.unshift(e):r.push(e),t.pendingCommands.set(n,r);return}i?t.globalPendingCommands.unshift(e):t.globalPendingCommands.push(e)}function t8(t,e,n){if(!e)return;let i=t.pluginClients.get(e);i?.inFlightRequestId===n&&(i.inFlightRequestId=void 0)}function n8(t){t.timeoutId&&(clearTimeout(t.timeoutId),t.timeoutId=null)}function rE(t,e,n){if(!e.routing||e.routing.actualClientId)return;let i=t.pluginClients.get(n);i&&(e.routing={...e.routing,actualClientId:i.clientId,...i.targetAlias!==void 0?{actualTargetAlias:i.targetAlias}:{},...i.placeId!==void 0?{actualPlaceId:i.placeId}:{},...i.placeName!==void 0?{actualPlaceName:i.placeName}:{}})}function mpe(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function gpe(t,e){return t===void 0?{routing:e}:mpe(t)?{...t,routing:e}:{value:t,routing:e}}function hpe(t,e){if(!e.routing)return t;let n={...t,routing:e.routing};return t.success||(n.data=gpe(t.data,e.routing)),n}function ype(t,e,n){n8(e),e.timeoutId=setTimeout(()=>{Jb(t,e,n)},n)}function V6(t,e){if(t.length===0)return[];let n=t[0];if(Pi(n.data.command)!=="readonly")return[t.shift()];let i=[];for(;t.length>0&&i.length<e;){let r=t[0];if(Pi(r.data.command)!=="readonly")break;i.push(t.shift())}return i}function vpe(t,e){let n=t.pendingCommands.get(e)||[],i=V6(n,U6);return t.pendingCommands.set(e,n),i.length>0?i:V6(t.globalPendingCommands,U6)}function r8(t,e,n){return!n||n.readyState!==W6?!1:t.pluginClients.get(e)?.commandSessionState===Ze.CONNECTED}function i8(t,e,n){let i=ml(t),r=t.pluginCommandClientIdsByProcessToken.get(n.processToken),a=i.get(n.clientId),s=dl(t,n.clientId)?.state??t.pluginClients.get(n.clientId)?.commandSessionState,c=r&&r!==n.clientId?i.get(r):null,l=s===Ze.RECONNECTING||s===Ze.DISCONNECTED||s===Ze.CONNECTED?"reconnected":"connected";tE(t).set(n.clientId,l),c&&c!==e&&nE(c,4e3,"replaced by new websocket session"),a&&a!==e&&(s===Ze.CONNECTED&&J6(t,"session-replacement",n.clientId),nE(a,4e3,"replaced by new websocket session")),Y6(t,n.clientId),i.set(n.clientId,e),j6(t,{...n,connectedAt:Date.now(),lastSeen:Date.now(),state:Ze.HANDSHAKING});let u=t.pluginClients.get(n.clientId);u&&(n.targetAlias!==void 0&&(u.targetAlias=n.targetAlias),u.connectionType="websocket",u.commandSessionState=Ze.HANDSHAKING,u.processToken=n.processToken,u.lastSeen=Date.now())}function a8(t,e,n){if(typeof n.clientId!="string"||typeof n.processToken!="string")return"ignored";if(!Wb(t,n.clientId,e))return"conflict";let i=dl(t,n.clientId);if(!i||i.processToken!==n.processToken)return"conflict";let r=new Set;for(let o of n.ackedRequestIds||[])r.add(o);for(let o of n.runningRequestIds||[])r.add(o);for(let o of r)u8(t,o,n.clientId);for(let o of n.finishedResults||[])iE(t,o,n.clientId);if(!spe(e))return"ignored";Gb(t,n.clientId,Ze.CONNECTED);let a=tE(t).get(n.clientId)??"connected";return tE(t).delete(n.clientId),tf(t,n.clientId,a),hl(t,n.clientId),"connected"}function o8(t,e,n,i={}){if(!Wb(t,n,e))return;let r=dpe(t,n,i);gl(t,n),r&&J6(t,"studio-state",n)}function s8(t,e,n){let i=ml(t);if(i.get(n)!==e)return;let r=t.pluginClients.get(n),a=r?.commandSessionState===Ze.CONNECTED;i.delete(n),Gb(t,n,Ze.RECONNECTING),a&&tf(t,n,"disconnected",r),X6(t,n);for(let o of t.commandQueue.values())o.targetClientId===n&&o.state===vn.DELIVERED&&xpe(t,o.requestId)}function c8(t,e=Date.now()){let n=ml(t),i=0;for(let[r,a]of n){let o=dl(t,r);if(!o){n.delete(r),pl(t,r);continue}if(o.state!==Ze.CONNECTED||e-o.lastSeen<=ape)continue;let s=t.pluginClients.get(r);Gb(t,r,Ze.RECONNECTING),tf(t,r,"disconnected",s),X6(t,r),nE(a,4001,"stale websocket session"),i++}return i}function l8(t){let e=0;for(let n of t.commandQueue.values())n.state!==vn.COMPLETED&&e++;return e}function Cn(t){let e=ml(t),n=[];for(let[i,r]of e){if(!r8(t,i,r))continue;let a=t.pluginClients.get(i);a&&n.push(a)}return n}function bpe(t,e,n){let i=t.commandQueue.get(e);if(!i)return!1;Kb(t,e);let r=!i.targetClientId&&i.routing?.selectionMode==="globalQueue"&&!i.routing.actualClientId;i.state=vn.DELIVERED,i.targetClientId=n,rE(t,i,n),i.deliveredAt=Date.now(),r&&Zb(t,n,i.deliveredAt),gl(t,n);let a=t.pluginClients.get(n);return a&&Pi(i.command)==="mutating"&&(a.inFlightRequestId=e),!0}function u8(t,e,n){let i=t.commandQueue.get(e);if(!i)return Vb(t).has(e)?"duplicate":"unknown";if(i.state===vn.COMPLETED)return"duplicate";if(n&&i.targetClientId&&i.targetClientId!==n&&i.state!==vn.QUEUED)return"conflict";Kb(t,e),i.state=vn.ACKED,i.ackedAt=Date.now(),n&&(i.targetClientId=n,rE(t,i,n),gl(t,n)),ype(t,i,i.ackedTimeoutMs);let r=n?t.pluginClients.get(n):null;return r&&Pi(i.command)==="mutating"&&(r.inFlightRequestId=e),"acked"}function iE(t,e,n){let i=t.commandQueue.get(e.requestId);if(!i)return Vb(t).has(e.requestId)?"duplicate":"unknown";if(i.state===vn.COMPLETED)return"duplicate";if(n&&i.targetClientId&&i.targetClientId!==n)return"conflict";n8(i),t8(t,n??i.targetClientId,e.requestId),Kb(t,e.requestId),i.state=vn.COMPLETED,i.completedAt=Date.now(),n&&(i.targetClientId=n,rE(t,i,n),gl(t,n));let r=hpe(e,i);return i.completedResult=r,i.resolve(r),t.totalCommandsProcessed++,ppe(t,e.requestId),t.commandQueue.delete(e.requestId),"completed"}function Jb(t,e,n){let i=e.targetClientId,r=`Command timeout after ${n}ms while ${e.state}: ${e.command}`,a=iE(t,{requestId:e.requestId,success:!1,error:r,errorCode:"command_timeout"},i);return a==="completed"&&hl(t,i),a}function xpe(t,e){let n=t.commandQueue.get(e);return!n||n.state!==vn.DELIVERED?!1:(t8(t,n.targetClientId,e),Kb(t,e),n.state=vn.QUEUED,delete n.deliveredAt,e8(t,fpe(n),n.targetClientId,!0),!0)}function d8(t,e,n,i){return Wb(t,n,e)?(gl(t,n),u8(t,i,n)):"conflict"}function p8(t,e,n,i){if(!Wb(t,n,e))return"conflict";gl(t,n);let r=iE(t,i,n);return r==="completed"&&hl(t,n),r}async function hl(t,e){let n=ml(t),i=e?[e]:Array.from(n.keys()),r=0;for(let a of i){let o=n.get(a);if(!r8(t,a,o))continue;let s=t.pluginClients.get(a)?.inFlightRequestId;if(s&&t.commandQueue.has(s))continue;let c=vpe(t,a);if(c.length!==0)for(let l=0;l<c.length;l++){let u=c[l],d=t.commandQueue.get(u.data.requestId);if(d)try{o.send(JSON.stringify({type:"command",requestId:d.requestId,data:{command:d.command,params:d.params},executionMode:Pi(d.command)})),bpe(t,d.requestId,a),r++}catch{for(let p=c.length-1;p>=l;p--)e8(t,c[p],a,!0);break}}}return r}var ipe,W6,ape,ope,G6,U6,F6,q6,B6,H6,Da=ee(()=>{"use strict";xa();QR();M6();fl();wi();eE();ipe=0,W6=1,ape=15e3,ope=5e3,G6=1e3,U6=4,F6=new WeakMap,q6=new WeakMap,B6=new WeakMap,H6=new WeakMap});var f8={};qt(f8,{JSONL_TAIL_DEFAULT_LINES:()=>Yb,appendChangelogEntry:()=>vl,appendConnectionHistoryEntry:()=>yl,appendJsonlLine:()=>cE,clearChangelogForPlace:()=>pE,clearConnectionHistory:()=>dE,clearDirectoryChildren:()=>tx,clearFile:()=>af,clearMatchingFiles:()=>kpe,enrichWithExecutionContext:()=>Ma,getAuthoritativeDashboardPluginClients:()=>Xb,getChangelogEntriesForPlace:()=>Yo,getConnectionHistoryEntries:()=>uE,getDashboardPlaceSummary:()=>sE,getDashboardSyncRoot:()=>nr,getExecutionContextSnapshotMapForPlace:()=>Xo,getExecutionContextSnapshotsForPlace:()=>v8,getPlaceObservabilityPath:()=>Ppe,getPlaceTestsPath:()=>bl,isDashboardPluginConnected:()=>Qb,loadProjectMeta:()=>oE,parseDashboardPlaceIdQuery:()=>Na,persistLastActivePlace:()=>ex,pickPrimaryExecutionContext:()=>nx,readJsonlFile:()=>lE,readJsonlFileTail:()=>rf,readTestContextFile:()=>rx,resolveActiveDashboardPlaceId:()=>nf,resolveActiveDashboardPlaceName:()=>Nn,resolveDashboardPlaceId:()=>ja,saveProjectMeta:()=>h8,trimJsonlFileTail:()=>y8});import*as je from"fs";import*as In from"path";function g8(t){return In.join(t,".project-meta.json")}function nr(t){return mt(t.config.dataDir)}function Xb(t){return Cn(t).sort((e,n)=>n.lastSeen-e.lastSeen)}function Qb(t){return Xb(t).length>0}function Ipe(t){try{let e=t.syncController?.getSyncRoot();if(typeof e!="string"||e.length===0)return null;let n=je.readdirSync(e,{withFileTypes:!0}),i=-1,r=null;for(let a of n){if(!a.isDirectory())continue;let o=a.name.match(/^place_(\d+)/);if(!o)continue;let s=parseInt(o[1]??"",10);if(Number.isFinite(s))try{let c=je.statSync(In.join(e,a.name));c.mtimeMs>i&&(i=c.mtimeMs,r=s)}catch{}}return r}catch{return null}}function nf(t){let e=t.syncController?.getDefaultRuntimePlaceId();if(typeof e=="number"&&Number.isFinite(e))return e;let n=Xb(t).filter(i=>typeof i.placeId=="number"&&Number.isFinite(i.placeId))[0];return typeof n?.placeId=="number"&&Number.isFinite(n.placeId)?n.placeId:Ipe(t)}function Na(t){if(typeof t!="string"||t.trim().length===0)return null;let e=Number.parseInt(t,10);return!Number.isInteger(e)||e<0?null:e}function ja(t,e){return typeof e=="number"&&Number.isFinite(e)?e:nf(t)}function Nn(t,e){if(e==null)return null;let n=t.syncController?.getDefaultRuntimePlaceName?.();return typeof n=="string"&&n.length>0&&t.syncController?.getDefaultRuntimePlaceId()===e?n:Xb(t).filter(r=>r.placeId===e)[0]?.placeName??null}async function oE(t){try{let e=await je.promises.readFile(g8(t),"utf-8"),n=JSON.parse(e);return typeof n.lastActivePlaceId!="number"&&n.lastActivePlaceId!==null?null:{version:1,lastActivePlaceId:n.lastActivePlaceId??null,lastActivePlaceName:typeof n.lastActivePlaceName=="string"?n.lastActivePlaceName:null,lastActiveAt:typeof n.lastActiveAt=="string"?n.lastActiveAt:null}}catch{return null}}async function h8(t,e){await je.promises.mkdir(t,{recursive:!0}),await je.promises.writeFile(g8(t),JSON.stringify(e,null,2))}async function ex(t,e,n){if(!Number.isFinite(e))return;let i=nr(t),r=await oE(i),o=n??null??(r?.lastActivePlaceId===e?r.lastActivePlaceName:null),s=r?.lastActivePlaceId===e&&r.lastActivePlaceName===o;s||await h8(i,{version:1,lastActivePlaceId:e,lastActivePlaceName:o,lastActiveAt:new Date().toISOString()});try{!await ll(i)&&!s&&y.warn("Failed to refresh root representative sourcemap after updating last active place",{syncRoot:i,placeId:e,placeName:o})}catch(c){y.warn("Failed to refresh root representative sourcemap after updating last active place",{syncRoot:i,placeId:e,placeName:o,error:c instanceof Error?c.message:String(c)})}}async function sE(t){let e=nr(t),n=Qb(t),i=nf(t),r=Nn(t,i);typeof i=="number"&&Number.isFinite(i)&&await ex(t,i,r);let a=await oE(e),o=await je.promises.readdir(e,{withFileTypes:!0}).catch(()=>[]),s=(await Promise.all(o.filter(c=>c.isDirectory()&&c.name.startsWith("place_")).map(async c=>{let l=In.join(e,c.name,".sync-meta.json");try{let u=await je.promises.readFile(l,"utf-8"),d=JSON.parse(u);return typeof d.placeId!="number"||typeof d.placeName!="string"?null:{placeId:d.placeId,placeName:d.placeName,placeDirName:c.name,testsPath:In.join(e,c.name,"tests"),lastFullSync:typeof d.lastFullSync=="string"?d.lastFullSync:null,instanceCount:typeof d.instanceCount=="number"?d.instanceCount:null,scriptCount:typeof d.scriptCount=="number"?d.scriptCount:null,isActive:d.placeId===i,isConnected:d.placeId===i&&n}}catch{return null}}))).filter(c=>c!==null);return s.sort((c,l)=>c.isActive!==l.isActive?c.isActive?-1:1:c.placeName.localeCompare(l.placeName)),{pluginConnected:n,activePlaceId:i,activePlaceName:r,lastActivePlaceId:a?.lastActivePlaceId??null,lastActivePlaceName:a?.lastActivePlaceName??null,places:s}}async function cE(t,e){await je.promises.mkdir(In.dirname(t),{recursive:!0}),await je.promises.appendFile(t,JSON.stringify(e)+`
|
|
72
72
|
`);let n=(m8.get(t)??0)+1;if(m8.set(t,n),n%_pe===0)try{(await je.promises.stat(t)).size>=Spe&&await y8(t,wpe)}catch{}}async function lE(t){try{return(await je.promises.readFile(t,"utf-8")).split(`
|
|
73
73
|
`).map(n=>n.trim()).filter(n=>n.length>0&&!n.startsWith("#")).flatMap(n=>{try{return[JSON.parse(n)]}catch{return[]}})}catch{return[]}}async function y8(t,e){let n;try{n=await je.promises.readFile(t,"utf-8")}catch{return}let i=n.split(`
|
|
74
74
|
`).filter(o=>o.length>0);if(i.length<=e)return;let r=i.slice(i.length-e).join(`
|
|
@@ -128,7 +128,7 @@ tell application "System Events" to get value of property list item "CFBundleNam
|
|
|
128
128
|
|
|
129
129
|
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let o of t.seen.entries()){let s=o[1];if(e===o[0]){a(o);continue}if(t.external){let l=t.external.registry.get(o[0])?.id;if(e!==o[0]&&l){a(o);continue}}if(t.metadataRegistry.get(o[0])?.id){a(o);continue}if(s.cycle){a(o);continue}if(s.count>1&&t.reused==="ref"){a(o);continue}}}function sa(t,e){let n=t.seen.get(e);if(!n)throw new Error("Unprocessed schema. This is a bug in Zod.");let i=o=>{let s=t.seen.get(o);if(s.ref===null)return;let c=s.def??s.schema,l={...c},u=s.ref;if(s.ref=null,u){i(u);let p=t.seen.get(u),f=p.schema;if(f.$ref&&(t.target==="draft-07"||t.target==="draft-04"||t.target==="openapi-3.0")?(c.allOf=c.allOf??[],c.allOf.push(f)):Object.assign(c,f),Object.assign(c,l),o._zod.parent===u)for(let g in c)g==="$ref"||g==="allOf"||g in l||delete c[g];if(f.$ref&&p.def)for(let g in c)g==="$ref"||g==="allOf"||g in p.def&&JSON.stringify(c[g])===JSON.stringify(p.def[g])&&delete c[g]}let d=o._zod.parent;if(d&&d!==u){i(d);let p=t.seen.get(d);if(p?.schema.$ref&&(c.$ref=p.schema.$ref,p.def))for(let f in c)f==="$ref"||f==="allOf"||f in p.def&&JSON.stringify(c[f])===JSON.stringify(p.def[f])&&delete c[f]}t.override({zodSchema:o,jsonSchema:c,path:s.path??[]})};for(let o of[...t.seen.entries()].reverse())i(o[0]);let r={};if(t.target==="draft-2020-12"?r.$schema="https://json-schema.org/draft/2020-12/schema":t.target==="draft-07"?r.$schema="http://json-schema.org/draft-07/schema#":t.target==="draft-04"?r.$schema="http://json-schema.org/draft-04/schema#":t.target,t.external?.uri){let o=t.external.registry.get(e)?.id;if(!o)throw new Error("Schema is missing an `id` property");r.$id=t.external.uri(o)}Object.assign(r,n.def??n.schema);let a=t.external?.defs??{};for(let o of t.seen.entries()){let s=o[1];s.def&&s.defId&&(a[s.defId]=s.def)}t.external||Object.keys(a).length>0&&(t.target==="draft-2020-12"?r.$defs=a:r.definitions=a);try{let o=JSON.parse(JSON.stringify(r));return Object.defineProperty(o,"~standard",{value:{...e["~standard"],jsonSchema:{input:ic(e,"input",t.processors),output:ic(e,"output",t.processors)}},enumerable:!1,writable:!1}),o}catch{throw new Error("Error converting schema to JSON.")}}function en(t,e){let n=e??{seen:new Set};if(n.seen.has(t))return!1;n.seen.add(t);let i=t._zod.def;if(i.type==="transform")return!0;if(i.type==="array")return en(i.element,n);if(i.type==="set")return en(i.valueType,n);if(i.type==="lazy")return en(i.getter(),n);if(i.type==="promise"||i.type==="optional"||i.type==="nonoptional"||i.type==="nullable"||i.type==="readonly"||i.type==="default"||i.type==="prefault")return en(i.innerType,n);if(i.type==="intersection")return en(i.left,n)||en(i.right,n);if(i.type==="record"||i.type==="map")return en(i.keyType,n)||en(i.valueType,n);if(i.type==="pipe")return en(i.in,n)||en(i.out,n);if(i.type==="object"){for(let r in i.shape)if(en(i.shape[r],n))return!0;return!1}if(i.type==="union"){for(let r of i.options)if(en(r,n))return!0;return!1}if(i.type==="tuple"){for(let r of i.items)if(en(r,n))return!0;return!!(i.rest&&en(i.rest,n))}return!1}var pw=(t,e={})=>n=>{let i=aa({...n,processors:e});return Ie(t,i),oa(i,t),sa(i,t)},ic=(t,e,n={})=>i=>{let{libraryOptions:r,target:a}=i??{},o=aa({...r??{},target:a,io:e,processors:n});return Ie(t,o),oa(o,t),sa(o,t)};var R7={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},fw=(t,e,n,i)=>{let r=n;r.type="string";let{minimum:a,maximum:o,format:s,patterns:c,contentEncoding:l}=t._zod.bag;if(typeof a=="number"&&(r.minLength=a),typeof o=="number"&&(r.maxLength=o),s&&(r.format=R7[s]??s,r.format===""&&delete r.format,s==="time"&&delete r.format),l&&(r.contentEncoding=l),c&&c.size>0){let u=[...c];u.length===1?r.pattern=u[0].source:u.length>1&&(r.allOf=[...u.map(d=>({...e.target==="draft-07"||e.target==="draft-04"||e.target==="openapi-3.0"?{type:"string"}:{},pattern:d.source}))])}},mw=(t,e,n,i)=>{let r=n,{minimum:a,maximum:o,format:s,multipleOf:c,exclusiveMaximum:l,exclusiveMinimum:u}=t._zod.bag;typeof s=="string"&&s.includes("int")?r.type="integer":r.type="number",typeof u=="number"&&(e.target==="draft-04"||e.target==="openapi-3.0"?(r.minimum=u,r.exclusiveMinimum=!0):r.exclusiveMinimum=u),typeof a=="number"&&(r.minimum=a,typeof u=="number"&&e.target!=="draft-04"&&(u>=a?delete r.minimum:delete r.exclusiveMinimum)),typeof l=="number"&&(e.target==="draft-04"||e.target==="openapi-3.0"?(r.maximum=l,r.exclusiveMaximum=!0):r.exclusiveMaximum=l),typeof o=="number"&&(r.maximum=o,typeof l=="number"&&e.target!=="draft-04"&&(l<=o?delete r.maximum:delete r.exclusiveMaximum)),typeof c=="number"&&(r.multipleOf=c)},gw=(t,e,n,i)=>{n.type="boolean"},hw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("BigInt cannot be represented in JSON Schema")},yw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Symbols cannot be represented in JSON Schema")},vw=(t,e,n,i)=>{e.target==="openapi-3.0"?(n.type="string",n.nullable=!0,n.enum=[null]):n.type="null"},bw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Undefined cannot be represented in JSON Schema")},xw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Void cannot be represented in JSON Schema")},_w=(t,e,n,i)=>{n.not={}},Sw=(t,e,n,i)=>{},ww=(t,e,n,i)=>{},Cw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Date cannot be represented in JSON Schema")},Iw=(t,e,n,i)=>{let r=t._zod.def,a=ku(r.entries);a.every(o=>typeof o=="number")&&(n.type="number"),a.every(o=>typeof o=="string")&&(n.type="string"),n.enum=a},kw=(t,e,n,i)=>{let r=t._zod.def,a=[];for(let o of r.values)if(o===void 0){if(e.unrepresentable==="throw")throw new Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof o=="bigint"){if(e.unrepresentable==="throw")throw new Error("BigInt literals cannot be represented in JSON Schema");a.push(Number(o))}else a.push(o);if(a.length!==0)if(a.length===1){let o=a[0];n.type=o===null?"null":typeof o,e.target==="draft-04"||e.target==="openapi-3.0"?n.enum=[o]:n.const=o}else a.every(o=>typeof o=="number")&&(n.type="number"),a.every(o=>typeof o=="string")&&(n.type="string"),a.every(o=>typeof o=="boolean")&&(n.type="boolean"),a.every(o=>o===null)&&(n.type="null"),n.enum=a},Pw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("NaN cannot be represented in JSON Schema")},Rw=(t,e,n,i)=>{let r=n,a=t._zod.pattern;if(!a)throw new Error("Pattern not found in template literal");r.type="string",r.pattern=a.source},Ew=(t,e,n,i)=>{let r=n,a={type:"string",format:"binary",contentEncoding:"binary"},{minimum:o,maximum:s,mime:c}=t._zod.bag;o!==void 0&&(a.minLength=o),s!==void 0&&(a.maxLength=s),c?c.length===1?(a.contentMediaType=c[0],Object.assign(r,a)):(Object.assign(r,a),r.anyOf=c.map(l=>({contentMediaType:l}))):Object.assign(r,a)},Tw=(t,e,n,i)=>{n.type="boolean"},Aw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},$w=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Function types cannot be represented in JSON Schema")},Ow=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},Dw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Map cannot be represented in JSON Schema")},Nw=(t,e,n,i)=>{if(e.unrepresentable==="throw")throw new Error("Set cannot be represented in JSON Schema")},jw=(t,e,n,i)=>{let r=n,a=t._zod.def,{minimum:o,maximum:s}=t._zod.bag;typeof o=="number"&&(r.minItems=o),typeof s=="number"&&(r.maxItems=s),r.type="array",r.items=Ie(a.element,e,{...i,path:[...i.path,"items"]})},Mw=(t,e,n,i)=>{let r=n,a=t._zod.def;r.type="object",r.properties={};let o=a.shape;for(let l in o)r.properties[l]=Ie(o[l],e,{...i,path:[...i.path,"properties",l]});let s=new Set(Object.keys(o)),c=new Set([...s].filter(l=>{let u=a.shape[l]._zod;return e.io==="input"?u.optin===void 0:u.optout===void 0}));c.size>0&&(r.required=Array.from(c)),a.catchall?._zod.def.type==="never"?r.additionalProperties=!1:a.catchall?a.catchall&&(r.additionalProperties=Ie(a.catchall,e,{...i,path:[...i.path,"additionalProperties"]})):e.io==="output"&&(r.additionalProperties=!1)},Mh=(t,e,n,i)=>{let r=t._zod.def,a=r.inclusive===!1,o=r.options.map((s,c)=>Ie(s,e,{...i,path:[...i.path,a?"oneOf":"anyOf",c]}));a?n.oneOf=o:n.anyOf=o},zw=(t,e,n,i)=>{let r=t._zod.def,a=Ie(r.left,e,{...i,path:[...i.path,"allOf",0]}),o=Ie(r.right,e,{...i,path:[...i.path,"allOf",1]}),s=l=>"allOf"in l&&Object.keys(l).length===1,c=[...s(a)?a.allOf:[a],...s(o)?o.allOf:[o]];n.allOf=c},Lw=(t,e,n,i)=>{let r=n,a=t._zod.def;r.type="array";let o=e.target==="draft-2020-12"?"prefixItems":"items",s=e.target==="draft-2020-12"||e.target==="openapi-3.0"?"items":"additionalItems",c=a.items.map((p,f)=>Ie(p,e,{...i,path:[...i.path,o,f]})),l=a.rest?Ie(a.rest,e,{...i,path:[...i.path,s,...e.target==="openapi-3.0"?[a.items.length]:[]]}):null;e.target==="draft-2020-12"?(r.prefixItems=c,l&&(r.items=l)):e.target==="openapi-3.0"?(r.items={anyOf:c},l&&r.items.anyOf.push(l),r.minItems=c.length,l||(r.maxItems=c.length)):(r.items=c,l&&(r.additionalItems=l));let{minimum:u,maximum:d}=t._zod.bag;typeof u=="number"&&(r.minItems=u),typeof d=="number"&&(r.maxItems=d)},Uw=(t,e,n,i)=>{let r=n,a=t._zod.def;r.type="object";let o=a.keyType,c=o._zod.bag?.patterns;if(a.mode==="loose"&&c&&c.size>0){let u=Ie(a.valueType,e,{...i,path:[...i.path,"patternProperties","*"]});r.patternProperties={};for(let d of c)r.patternProperties[d.source]=u}else(e.target==="draft-07"||e.target==="draft-2020-12")&&(r.propertyNames=Ie(a.keyType,e,{...i,path:[...i.path,"propertyNames"]})),r.additionalProperties=Ie(a.valueType,e,{...i,path:[...i.path,"additionalProperties"]});let l=o._zod.values;if(l){let u=[...l].filter(d=>typeof d=="string"||typeof d=="number");u.length>0&&(r.required=u)}},Fw=(t,e,n,i)=>{let r=t._zod.def,a=Ie(r.innerType,e,i),o=e.seen.get(t);e.target==="openapi-3.0"?(o.ref=r.innerType,n.nullable=!0):n.anyOf=[a,{type:"null"}]},qw=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType},Bw=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType,n.default=JSON.parse(JSON.stringify(r.defaultValue))},Hw=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType,e.io==="input"&&(n._prefault=JSON.parse(JSON.stringify(r.defaultValue)))},Zw=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType;let o;try{o=r.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}n.default=o},Vw=(t,e,n,i)=>{let r=t._zod.def,a=e.io==="input"?r.in._zod.def.type==="transform"?r.out:r.in:r.out;Ie(a,e,i);let o=e.seen.get(t);o.ref=a},Ww=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType,n.readOnly=!0},Gw=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType},zh=(t,e,n,i)=>{let r=t._zod.def;Ie(r.innerType,e,i);let a=e.seen.get(t);a.ref=r.innerType},Kw=(t,e,n,i)=>{let r=t._zod.innerType;Ie(r,e,i);let a=e.seen.get(t);a.ref=r},jh={string:fw,number:mw,boolean:gw,bigint:hw,symbol:yw,null:vw,undefined:bw,void:xw,never:_w,any:Sw,unknown:ww,date:Cw,enum:Iw,literal:kw,nan:Pw,template_literal:Rw,file:Ew,success:Tw,custom:Aw,function:$w,transform:Ow,map:Dw,set:Nw,array:jw,object:Mw,union:Mh,intersection:zw,tuple:Lw,record:Uw,nullable:Fw,nonoptional:qw,default:Bw,prefault:Hw,catch:Zw,pipe:Vw,readonly:Ww,promise:Gw,optional:zh,lazy:Kw};function ac(t,e){if("_idmap"in t){let i=t,r=aa({...e,processors:jh}),a={};for(let c of i._idmap.entries()){let[l,u]=c;Ie(u,r)}let o={},s={registry:i,uri:e?.uri,defs:a};r.external=s;for(let c of i._idmap.entries()){let[l,u]=c;oa(r,u),o[l]=sa(r,u)}if(Object.keys(a).length>0){let c=r.target==="draft-2020-12"?"$defs":"definitions";o.__shared={[c]:a}}return{schemas:o}}let n=aa({...e,processors:jh});return Ie(t,n),oa(n,t),sa(n,t)}var Lh=class{get metadataRegistry(){return this.ctx.metadataRegistry}get target(){return this.ctx.target}get unrepresentable(){return this.ctx.unrepresentable}get override(){return this.ctx.override}get io(){return this.ctx.io}get counter(){return this.ctx.counter}set counter(e){this.ctx.counter=e}get seen(){return this.ctx.seen}constructor(e){let n=e?.target??"draft-2020-12";n==="draft-4"&&(n="draft-04"),n==="draft-7"&&(n="draft-07"),this.ctx=aa({processors:jh,target:n,...e?.metadata&&{metadata:e.metadata},...e?.unrepresentable&&{unrepresentable:e.unrepresentable},...e?.override&&{override:e.override},...e?.io&&{io:e.io}})}process(e,n={path:[],schemaPath:[]}){return Ie(e,this.ctx,n)}emit(e,n){n&&(n.cycles&&(this.ctx.cycles=n.cycles),n.reused&&(this.ctx.reused=n.reused),n.external&&(this.ctx.external=n.external)),oa(this.ctx,e);let i=sa(this.ctx,e),{"~standard":r,...a}=i;return a}};var Z$={};function oc(t){return!!t._zod}function ca(t,e){return oc(t)?ao(t,e):t.safeParse(e)}function Uh(t){if(!t)return;let e;if(oc(t)?e=t._zod?.def?.shape:e=t.shape,!!e){if(typeof e=="function")try{return e()}catch{return}return e}}function G$(t){if(oc(t)){let a=t._zod?.def;if(a){if(a.value!==void 0)return a.value;if(Array.isArray(a.values)&&a.values.length>0)return a.values[0]}}let n=t._def;if(n){if(n.value!==void 0)return n.value;if(Array.isArray(n.values)&&n.values.length>0)return n.values[0]}let i=t.value;if(i!==void 0)return i}var A={};qt(A,{$brand:()=>Cu,$input:()=>Yg,$output:()=>Jg,NEVER:()=>hm,TimePrecision:()=>th,ZodAny:()=>h0,ZodArray:()=>x0,ZodBase64:()=>oy,ZodBase64URL:()=>sy,ZodBigInt:()=>pc,ZodBigIntFormat:()=>uy,ZodBoolean:()=>dc,ZodCIDRv4:()=>iy,ZodCIDRv6:()=>ay,ZodCUID:()=>Yh,ZodCUID2:()=>Xh,ZodCatch:()=>U0,ZodCodec:()=>hy,ZodCustom:()=>Sd,ZodCustomStringFormat:()=>lc,ZodDate:()=>yd,ZodDefault:()=>D0,ZodDiscriminatedUnion:()=>S0,ZodE164:()=>cy,ZodEmail:()=>Gh,ZodEmoji:()=>Kh,ZodEnum:()=>sc,ZodError:()=>D7,ZodExactOptional:()=>A0,ZodFile:()=>E0,ZodFirstPartyTypeKind:()=>X0,ZodFunction:()=>K0,ZodGUID:()=>fd,ZodIPv4:()=>ny,ZodIPv6:()=>ry,ZodISODate:()=>Bh,ZodISODateTime:()=>qh,ZodISODuration:()=>Zh,ZodISOTime:()=>Hh,ZodIntersection:()=>w0,ZodIssueCode:()=>j7,ZodJWT:()=>ly,ZodKSUID:()=>ty,ZodLazy:()=>V0,ZodLiteral:()=>R0,ZodMAC:()=>p0,ZodMap:()=>k0,ZodNaN:()=>q0,ZodNanoID:()=>Jh,ZodNever:()=>v0,ZodNonOptional:()=>my,ZodNull:()=>g0,ZodNullable:()=>O0,ZodNumber:()=>uc,ZodNumberFormat:()=>xo,ZodObject:()=>vd,ZodOptional:()=>fy,ZodPipe:()=>gy,ZodPrefault:()=>j0,ZodPromise:()=>G0,ZodReadonly:()=>B0,ZodRealError:()=>fn,ZodRecord:()=>_d,ZodSet:()=>P0,ZodString:()=>cc,ZodStringFormat:()=>$e,ZodSuccess:()=>L0,ZodSymbol:()=>f0,ZodTemplateLiteral:()=>Z0,ZodTransform:()=>T0,ZodTuple:()=>C0,ZodType:()=>Q,ZodULID:()=>Qh,ZodURL:()=>hd,ZodUUID:()=>Dr,ZodUndefined:()=>m0,ZodUnion:()=>bd,ZodUnknown:()=>y0,ZodVoid:()=>b0,ZodXID:()=>ey,ZodXor:()=>_0,_ZodString:()=>Wh,_default:()=>N0,_function:()=>YO,any:()=>OO,array:()=>oe,base64:()=>hO,base64url:()=>yO,bigint:()=>RO,boolean:()=>it,catch:()=>F0,check:()=>XO,cidrv4:()=>mO,cidrv6:()=>gO,clone:()=>Rt,codec:()=>GO,coerce:()=>Q0,config:()=>Je,core:()=>$n,cuid:()=>oO,cuid2:()=>sO,custom:()=>yy,date:()=>NO,decode:()=>a0,decodeAsync:()=>s0,describe:()=>QO,discriminatedUnion:()=>xd,e164:()=>vO,email:()=>J$,emoji:()=>iO,encode:()=>i0,encodeAsync:()=>o0,endsWith:()=>fo,enum:()=>At,exactOptional:()=>$0,file:()=>HO,flattenError:()=>Us,float32:()=>CO,float64:()=>IO,formatError:()=>Fs,fromJSONSchema:()=>aD,function:()=>YO,getErrorMap:()=>z7,globalRegistry:()=>yt,gt:()=>dr,gte:()=>Et,guid:()=>Y$,hash:()=>wO,hex:()=>SO,hostname:()=>_O,httpUrl:()=>rO,includes:()=>uo,instanceof:()=>tD,int:()=>Vh,int32:()=>kO,int64:()=>EO,intersection:()=>mc,ipv4:()=>dO,ipv6:()=>fO,iso:()=>la,json:()=>rD,jwt:()=>bO,keyof:()=>jO,ksuid:()=>uO,lazy:()=>W0,length:()=>ia,literal:()=>q,locales:()=>ec,looseObject:()=>Tt,looseRecord:()=>UO,lowercase:()=>co,lt:()=>ur,lte:()=>Qt,mac:()=>pO,map:()=>FO,maxLength:()=>ra,maxSize:()=>mi,meta:()=>eD,mime:()=>mo,minLength:()=>Or,minSize:()=>pr,multipleOf:()=>fi,nan:()=>WO,nanoid:()=>aO,nativeEnum:()=>BO,negative:()=>cd,never:()=>dy,nonnegative:()=>ud,nonoptional:()=>z0,nonpositive:()=>ld,normalize:()=>go,null:()=>fc,nullable:()=>md,nullish:()=>ZO,number:()=>_e,object:()=>L,optional:()=>Fe,overwrite:()=>Hn,parse:()=>e0,parseAsync:()=>t0,partialRecord:()=>LO,pipe:()=>gd,positive:()=>sd,prefault:()=>M0,preprocess:()=>wd,prettifyError:()=>_m,promise:()=>JO,property:()=>dd,readonly:()=>H0,record:()=>ze,refine:()=>J0,regex:()=>so,regexes:()=>pn,registry:()=>Uu,safeDecode:()=>l0,safeDecodeAsync:()=>d0,safeEncode:()=>c0,safeEncodeAsync:()=>u0,safeParse:()=>n0,safeParseAsync:()=>r0,set:()=>qO,setErrorMap:()=>M7,size:()=>na,slugify:()=>rc,startsWith:()=>po,strictObject:()=>MO,string:()=>k,stringFormat:()=>xO,stringbool:()=>nD,success:()=>VO,superRefine:()=>Y0,symbol:()=>AO,templateLiteral:()=>KO,toJSONSchema:()=>ac,toLowerCase:()=>yo,toUpperCase:()=>vo,transform:()=>py,treeifyError:()=>xm,trim:()=>ho,tuple:()=>I0,uint32:()=>PO,uint64:()=>TO,ulid:()=>cO,undefined:()=>$O,union:()=>Ee,unknown:()=>Oe,uppercase:()=>lo,url:()=>nO,util:()=>E,uuid:()=>X$,uuidv4:()=>Q$,uuidv6:()=>eO,uuidv7:()=>tO,void:()=>DO,xid:()=>lO,xor:()=>zO});var pd={};qt(pd,{ZodAny:()=>h0,ZodArray:()=>x0,ZodBase64:()=>oy,ZodBase64URL:()=>sy,ZodBigInt:()=>pc,ZodBigIntFormat:()=>uy,ZodBoolean:()=>dc,ZodCIDRv4:()=>iy,ZodCIDRv6:()=>ay,ZodCUID:()=>Yh,ZodCUID2:()=>Xh,ZodCatch:()=>U0,ZodCodec:()=>hy,ZodCustom:()=>Sd,ZodCustomStringFormat:()=>lc,ZodDate:()=>yd,ZodDefault:()=>D0,ZodDiscriminatedUnion:()=>S0,ZodE164:()=>cy,ZodEmail:()=>Gh,ZodEmoji:()=>Kh,ZodEnum:()=>sc,ZodExactOptional:()=>A0,ZodFile:()=>E0,ZodFunction:()=>K0,ZodGUID:()=>fd,ZodIPv4:()=>ny,ZodIPv6:()=>ry,ZodIntersection:()=>w0,ZodJWT:()=>ly,ZodKSUID:()=>ty,ZodLazy:()=>V0,ZodLiteral:()=>R0,ZodMAC:()=>p0,ZodMap:()=>k0,ZodNaN:()=>q0,ZodNanoID:()=>Jh,ZodNever:()=>v0,ZodNonOptional:()=>my,ZodNull:()=>g0,ZodNullable:()=>O0,ZodNumber:()=>uc,ZodNumberFormat:()=>xo,ZodObject:()=>vd,ZodOptional:()=>fy,ZodPipe:()=>gy,ZodPrefault:()=>j0,ZodPromise:()=>G0,ZodReadonly:()=>B0,ZodRecord:()=>_d,ZodSet:()=>P0,ZodString:()=>cc,ZodStringFormat:()=>$e,ZodSuccess:()=>L0,ZodSymbol:()=>f0,ZodTemplateLiteral:()=>Z0,ZodTransform:()=>T0,ZodTuple:()=>C0,ZodType:()=>Q,ZodULID:()=>Qh,ZodURL:()=>hd,ZodUUID:()=>Dr,ZodUndefined:()=>m0,ZodUnion:()=>bd,ZodUnknown:()=>y0,ZodVoid:()=>b0,ZodXID:()=>ey,ZodXor:()=>_0,_ZodString:()=>Wh,_default:()=>N0,_function:()=>YO,any:()=>OO,array:()=>oe,base64:()=>hO,base64url:()=>yO,bigint:()=>RO,boolean:()=>it,catch:()=>F0,check:()=>XO,cidrv4:()=>mO,cidrv6:()=>gO,codec:()=>GO,cuid:()=>oO,cuid2:()=>sO,custom:()=>yy,date:()=>NO,describe:()=>QO,discriminatedUnion:()=>xd,e164:()=>vO,email:()=>J$,emoji:()=>iO,enum:()=>At,exactOptional:()=>$0,file:()=>HO,float32:()=>CO,float64:()=>IO,function:()=>YO,guid:()=>Y$,hash:()=>wO,hex:()=>SO,hostname:()=>_O,httpUrl:()=>rO,instanceof:()=>tD,int:()=>Vh,int32:()=>kO,int64:()=>EO,intersection:()=>mc,ipv4:()=>dO,ipv6:()=>fO,json:()=>rD,jwt:()=>bO,keyof:()=>jO,ksuid:()=>uO,lazy:()=>W0,literal:()=>q,looseObject:()=>Tt,looseRecord:()=>UO,mac:()=>pO,map:()=>FO,meta:()=>eD,nan:()=>WO,nanoid:()=>aO,nativeEnum:()=>BO,never:()=>dy,nonoptional:()=>z0,null:()=>fc,nullable:()=>md,nullish:()=>ZO,number:()=>_e,object:()=>L,optional:()=>Fe,partialRecord:()=>LO,pipe:()=>gd,prefault:()=>M0,preprocess:()=>wd,promise:()=>JO,readonly:()=>H0,record:()=>ze,refine:()=>J0,set:()=>qO,strictObject:()=>MO,string:()=>k,stringFormat:()=>xO,stringbool:()=>nD,success:()=>VO,superRefine:()=>Y0,symbol:()=>AO,templateLiteral:()=>KO,transform:()=>py,tuple:()=>I0,uint32:()=>PO,uint64:()=>TO,ulid:()=>cO,undefined:()=>$O,union:()=>Ee,unknown:()=>Oe,url:()=>nO,uuid:()=>X$,uuidv4:()=>Q$,uuidv6:()=>eO,uuidv7:()=>tO,void:()=>DO,xid:()=>lO,xor:()=>zO});var Fh={};qt(Fh,{endsWith:()=>fo,gt:()=>dr,gte:()=>Et,includes:()=>uo,length:()=>ia,lowercase:()=>co,lt:()=>ur,lte:()=>Qt,maxLength:()=>ra,maxSize:()=>mi,mime:()=>mo,minLength:()=>Or,minSize:()=>pr,multipleOf:()=>fi,negative:()=>cd,nonnegative:()=>ud,nonpositive:()=>ld,normalize:()=>go,overwrite:()=>Hn,positive:()=>sd,property:()=>dd,regex:()=>so,size:()=>na,slugify:()=>rc,startsWith:()=>po,toLowerCase:()=>yo,toUpperCase:()=>vo,trim:()=>ho,uppercase:()=>lo});var la={};qt(la,{ZodISODate:()=>Bh,ZodISODateTime:()=>qh,ZodISODuration:()=>Zh,ZodISOTime:()=>Hh,date:()=>Yw,datetime:()=>Jw,duration:()=>Qw,time:()=>Xw});var qh=S("ZodISODateTime",(t,e)=>{Jm.init(t,e),$e.init(t,e)});function Jw(t){return nh(qh,t)}var Bh=S("ZodISODate",(t,e)=>{Ym.init(t,e),$e.init(t,e)});function Yw(t){return rh(Bh,t)}var Hh=S("ZodISOTime",(t,e)=>{Xm.init(t,e),$e.init(t,e)});function Xw(t){return ih(Hh,t)}var Zh=S("ZodISODuration",(t,e)=>{Qm.init(t,e),$e.init(t,e)});function Qw(t){return ah(Zh,t)}var K$=(t,e)=>{Au.init(t,e),t.name="ZodError",Object.defineProperties(t,{format:{value:n=>Fs(t,n)},flatten:{value:n=>Us(t,n)},addIssue:{value:n=>{t.issues.push(n),t.message=JSON.stringify(t.issues,Ms,2)}},addIssues:{value:n=>{t.issues.push(...n),t.message=JSON.stringify(t.issues,Ms,2)}},isEmpty:{get(){return t.issues.length===0}}})},D7=S("ZodError",K$),fn=S("ZodError",K$,{Parent:Error});var e0=qs(fn),t0=Hs(fn),n0=Vs(fn),r0=Ws(fn),i0=Sm(fn),a0=wm(fn),o0=Cm(fn),s0=Im(fn),c0=km(fn),l0=Pm(fn),u0=Rm(fn),d0=Em(fn);var Q=S("ZodType",(t,e)=>(W.init(t,e),Object.assign(t["~standard"],{jsonSchema:{input:ic(t,"input"),output:ic(t,"output")}}),t.toJSONSchema=pw(t,{}),t.def=e,t.type=e.type,Object.defineProperty(t,"_def",{value:e}),t.check=(...n)=>t.clone(E.mergeDefs(e,{checks:[...e.checks??[],...n.map(i=>typeof i=="function"?{_zod:{check:i,def:{check:"custom"},onattach:[]}}:i)]}),{parent:!0}),t.with=t.check,t.clone=(n,i)=>Rt(t,n,i),t.brand=()=>t,t.register=(n,i)=>(n.add(t,i),t),t.parse=(n,i)=>e0(t,n,i,{callee:t.parse}),t.safeParse=(n,i)=>n0(t,n,i),t.parseAsync=async(n,i)=>t0(t,n,i,{callee:t.parseAsync}),t.safeParseAsync=async(n,i)=>r0(t,n,i),t.spa=t.safeParseAsync,t.encode=(n,i)=>i0(t,n,i),t.decode=(n,i)=>a0(t,n,i),t.encodeAsync=async(n,i)=>o0(t,n,i),t.decodeAsync=async(n,i)=>s0(t,n,i),t.safeEncode=(n,i)=>c0(t,n,i),t.safeDecode=(n,i)=>l0(t,n,i),t.safeEncodeAsync=async(n,i)=>u0(t,n,i),t.safeDecodeAsync=async(n,i)=>d0(t,n,i),t.refine=(n,i)=>t.check(J0(n,i)),t.superRefine=n=>t.check(Y0(n)),t.overwrite=n=>t.check(Hn(n)),t.optional=()=>Fe(t),t.exactOptional=()=>$0(t),t.nullable=()=>md(t),t.nullish=()=>Fe(md(t)),t.nonoptional=n=>z0(t,n),t.array=()=>oe(t),t.or=n=>Ee([t,n]),t.and=n=>mc(t,n),t.transform=n=>gd(t,py(n)),t.default=n=>N0(t,n),t.prefault=n=>M0(t,n),t.catch=n=>F0(t,n),t.pipe=n=>gd(t,n),t.readonly=()=>H0(t),t.describe=n=>{let i=t.clone();return yt.add(i,{description:n}),i},Object.defineProperty(t,"description",{get(){return yt.get(t)?.description},configurable:!0}),t.meta=(...n)=>{if(n.length===0)return yt.get(t);let i=t.clone();return yt.add(i,n[0]),i},t.isOptional=()=>t.safeParse(void 0).success,t.isNullable=()=>t.safeParse(null).success,t.apply=n=>n(t),t)),Wh=S("_ZodString",(t,e)=>{ta.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(i,r,a)=>fw(t,i,r,a);let n=t._zod.bag;t.format=n.format??null,t.minLength=n.minimum??null,t.maxLength=n.maximum??null,t.regex=(...i)=>t.check(so(...i)),t.includes=(...i)=>t.check(uo(...i)),t.startsWith=(...i)=>t.check(po(...i)),t.endsWith=(...i)=>t.check(fo(...i)),t.min=(...i)=>t.check(Or(...i)),t.max=(...i)=>t.check(ra(...i)),t.length=(...i)=>t.check(ia(...i)),t.nonempty=(...i)=>t.check(Or(1,...i)),t.lowercase=i=>t.check(co(i)),t.uppercase=i=>t.check(lo(i)),t.trim=()=>t.check(ho()),t.normalize=(...i)=>t.check(go(...i)),t.toLowerCase=()=>t.check(yo()),t.toUpperCase=()=>t.check(vo()),t.slugify=()=>t.check(rc())}),cc=S("ZodString",(t,e)=>{ta.init(t,e),Wh.init(t,e),t.email=n=>t.check(Fu(Gh,n)),t.url=n=>t.check(nc(hd,n)),t.jwt=n=>t.check(od(ly,n)),t.emoji=n=>t.check(Vu(Kh,n)),t.guid=n=>t.check(tc(fd,n)),t.uuid=n=>t.check(qu(Dr,n)),t.uuidv4=n=>t.check(Bu(Dr,n)),t.uuidv6=n=>t.check(Hu(Dr,n)),t.uuidv7=n=>t.check(Zu(Dr,n)),t.nanoid=n=>t.check(Wu(Jh,n)),t.guid=n=>t.check(tc(fd,n)),t.cuid=n=>t.check(Gu(Yh,n)),t.cuid2=n=>t.check(Ku(Xh,n)),t.ulid=n=>t.check(Ju(Qh,n)),t.base64=n=>t.check(rd(oy,n)),t.base64url=n=>t.check(id(sy,n)),t.xid=n=>t.check(Yu(ey,n)),t.ksuid=n=>t.check(Xu(ty,n)),t.ipv4=n=>t.check(Qu(ny,n)),t.ipv6=n=>t.check(ed(ry,n)),t.cidrv4=n=>t.check(td(iy,n)),t.cidrv6=n=>t.check(nd(ay,n)),t.e164=n=>t.check(ad(cy,n)),t.datetime=n=>t.check(Jw(n)),t.date=n=>t.check(Yw(n)),t.time=n=>t.check(Xw(n)),t.duration=n=>t.check(Qw(n))});function k(t){return Xg(cc,t)}var $e=S("ZodStringFormat",(t,e)=>{Re.init(t,e),Wh.init(t,e)}),Gh=S("ZodEmail",(t,e)=>{Fm.init(t,e),$e.init(t,e)});function J$(t){return Fu(Gh,t)}var fd=S("ZodGUID",(t,e)=>{Lm.init(t,e),$e.init(t,e)});function Y$(t){return tc(fd,t)}var Dr=S("ZodUUID",(t,e)=>{Um.init(t,e),$e.init(t,e)});function X$(t){return qu(Dr,t)}function Q$(t){return Bu(Dr,t)}function eO(t){return Hu(Dr,t)}function tO(t){return Zu(Dr,t)}var hd=S("ZodURL",(t,e)=>{qm.init(t,e),$e.init(t,e)});function nO(t){return nc(hd,t)}function rO(t){return nc(hd,{protocol:/^https?$/,hostname:pn.domain,...E.normalizeParams(t)})}var Kh=S("ZodEmoji",(t,e)=>{Bm.init(t,e),$e.init(t,e)});function iO(t){return Vu(Kh,t)}var Jh=S("ZodNanoID",(t,e)=>{Hm.init(t,e),$e.init(t,e)});function aO(t){return Wu(Jh,t)}var Yh=S("ZodCUID",(t,e)=>{Zm.init(t,e),$e.init(t,e)});function oO(t){return Gu(Yh,t)}var Xh=S("ZodCUID2",(t,e)=>{Vm.init(t,e),$e.init(t,e)});function sO(t){return Ku(Xh,t)}var Qh=S("ZodULID",(t,e)=>{Wm.init(t,e),$e.init(t,e)});function cO(t){return Ju(Qh,t)}var ey=S("ZodXID",(t,e)=>{Gm.init(t,e),$e.init(t,e)});function lO(t){return Yu(ey,t)}var ty=S("ZodKSUID",(t,e)=>{Km.init(t,e),$e.init(t,e)});function uO(t){return Xu(ty,t)}var ny=S("ZodIPv4",(t,e)=>{eg.init(t,e),$e.init(t,e)});function dO(t){return Qu(ny,t)}var p0=S("ZodMAC",(t,e)=>{ng.init(t,e),$e.init(t,e)});function pO(t){return eh(p0,t)}var ry=S("ZodIPv6",(t,e)=>{tg.init(t,e),$e.init(t,e)});function fO(t){return ed(ry,t)}var iy=S("ZodCIDRv4",(t,e)=>{rg.init(t,e),$e.init(t,e)});function mO(t){return td(iy,t)}var ay=S("ZodCIDRv6",(t,e)=>{ig.init(t,e),$e.init(t,e)});function gO(t){return nd(ay,t)}var oy=S("ZodBase64",(t,e)=>{ag.init(t,e),$e.init(t,e)});function hO(t){return rd(oy,t)}var sy=S("ZodBase64URL",(t,e)=>{og.init(t,e),$e.init(t,e)});function yO(t){return id(sy,t)}var cy=S("ZodE164",(t,e)=>{sg.init(t,e),$e.init(t,e)});function vO(t){return ad(cy,t)}var ly=S("ZodJWT",(t,e)=>{cg.init(t,e),$e.init(t,e)});function bO(t){return od(ly,t)}var lc=S("ZodCustomStringFormat",(t,e)=>{lg.init(t,e),$e.init(t,e)});function xO(t,e,n={}){return bo(lc,t,e,n)}function _O(t){return bo(lc,"hostname",pn.hostname,t)}function SO(t){return bo(lc,"hex",pn.hex,t)}function wO(t,e){let n=e?.enc??"hex",i=`${t}_${n}`,r=pn[i];if(!r)throw new Error(`Unrecognized hash format: ${i}`);return bo(lc,i,r,e)}var uc=S("ZodNumber",(t,e)=>{Nu.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(i,r,a)=>mw(t,i,r,a),t.gt=(i,r)=>t.check(dr(i,r)),t.gte=(i,r)=>t.check(Et(i,r)),t.min=(i,r)=>t.check(Et(i,r)),t.lt=(i,r)=>t.check(ur(i,r)),t.lte=(i,r)=>t.check(Qt(i,r)),t.max=(i,r)=>t.check(Qt(i,r)),t.int=i=>t.check(Vh(i)),t.safe=i=>t.check(Vh(i)),t.positive=i=>t.check(dr(0,i)),t.nonnegative=i=>t.check(Et(0,i)),t.negative=i=>t.check(ur(0,i)),t.nonpositive=i=>t.check(Qt(0,i)),t.multipleOf=(i,r)=>t.check(fi(i,r)),t.step=(i,r)=>t.check(fi(i,r)),t.finite=()=>t;let n=t._zod.bag;t.minValue=Math.max(n.minimum??Number.NEGATIVE_INFINITY,n.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,t.maxValue=Math.min(n.maximum??Number.POSITIVE_INFINITY,n.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,t.isInt=(n.format??"").includes("int")||Number.isSafeInteger(n.multipleOf??.5),t.isFinite=!0,t.format=n.format??null});function _e(t){return oh(uc,t)}var xo=S("ZodNumberFormat",(t,e)=>{ug.init(t,e),uc.init(t,e)});function Vh(t){return ch(xo,t)}function CO(t){return lh(xo,t)}function IO(t){return uh(xo,t)}function kO(t){return dh(xo,t)}function PO(t){return ph(xo,t)}var dc=S("ZodBoolean",(t,e)=>{Js.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>gw(t,n,i,r)});function it(t){return fh(dc,t)}var pc=S("ZodBigInt",(t,e)=>{ju.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(i,r,a)=>hw(t,i,r,a),t.gte=(i,r)=>t.check(Et(i,r)),t.min=(i,r)=>t.check(Et(i,r)),t.gt=(i,r)=>t.check(dr(i,r)),t.gte=(i,r)=>t.check(Et(i,r)),t.min=(i,r)=>t.check(Et(i,r)),t.lt=(i,r)=>t.check(ur(i,r)),t.lte=(i,r)=>t.check(Qt(i,r)),t.max=(i,r)=>t.check(Qt(i,r)),t.positive=i=>t.check(dr(BigInt(0),i)),t.negative=i=>t.check(ur(BigInt(0),i)),t.nonpositive=i=>t.check(Qt(BigInt(0),i)),t.nonnegative=i=>t.check(Et(BigInt(0),i)),t.multipleOf=(i,r)=>t.check(fi(i,r));let n=t._zod.bag;t.minValue=n.minimum??null,t.maxValue=n.maximum??null,t.format=n.format??null});function RO(t){return gh(pc,t)}var uy=S("ZodBigIntFormat",(t,e)=>{dg.init(t,e),pc.init(t,e)});function EO(t){return yh(uy,t)}function TO(t){return vh(uy,t)}var f0=S("ZodSymbol",(t,e)=>{pg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>yw(t,n,i,r)});function AO(t){return bh(f0,t)}var m0=S("ZodUndefined",(t,e)=>{fg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>bw(t,n,i,r)});function $O(t){return xh(m0,t)}var g0=S("ZodNull",(t,e)=>{mg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>vw(t,n,i,r)});function fc(t){return _h(g0,t)}var h0=S("ZodAny",(t,e)=>{gg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Sw(t,n,i,r)});function OO(){return Sh(h0)}var y0=S("ZodUnknown",(t,e)=>{hg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>ww(t,n,i,r)});function Oe(){return wh(y0)}var v0=S("ZodNever",(t,e)=>{yg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>_w(t,n,i,r)});function dy(t){return Ch(v0,t)}var b0=S("ZodVoid",(t,e)=>{vg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>xw(t,n,i,r)});function DO(t){return Ih(b0,t)}var yd=S("ZodDate",(t,e)=>{bg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(i,r,a)=>Cw(t,i,r,a),t.min=(i,r)=>t.check(Et(i,r)),t.max=(i,r)=>t.check(Qt(i,r));let n=t._zod.bag;t.minDate=n.minimum?new Date(n.minimum):null,t.maxDate=n.maximum?new Date(n.maximum):null});function NO(t){return kh(yd,t)}var x0=S("ZodArray",(t,e)=>{xg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>jw(t,n,i,r),t.element=e.element,t.min=(n,i)=>t.check(Or(n,i)),t.nonempty=n=>t.check(Or(1,n)),t.max=(n,i)=>t.check(ra(n,i)),t.length=(n,i)=>t.check(ia(n,i)),t.unwrap=()=>t.element});function oe(t,e){return dw(x0,t,e)}function jO(t){let e=t._zod.def.shape;return At(Object.keys(e))}var vd=S("ZodObject",(t,e)=>{uw.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Mw(t,n,i,r),E.defineLazy(t,"shape",()=>e.shape),t.keyof=()=>At(Object.keys(t._zod.def.shape)),t.catchall=n=>t.clone({...t._zod.def,catchall:n}),t.passthrough=()=>t.clone({...t._zod.def,catchall:Oe()}),t.loose=()=>t.clone({...t._zod.def,catchall:Oe()}),t.strict=()=>t.clone({...t._zod.def,catchall:dy()}),t.strip=()=>t.clone({...t._zod.def,catchall:void 0}),t.extend=n=>E.extend(t,n),t.safeExtend=n=>E.safeExtend(t,n),t.merge=n=>E.merge(t,n),t.pick=n=>E.pick(t,n),t.omit=n=>E.omit(t,n),t.partial=(...n)=>E.partial(fy,t,n[0]),t.required=(...n)=>E.required(my,t,n[0])});function L(t,e){let n={type:"object",shape:t??{},...E.normalizeParams(e)};return new vd(n)}function MO(t,e){return new vd({type:"object",shape:t,catchall:dy(),...E.normalizeParams(e)})}function Tt(t,e){return new vd({type:"object",shape:t,catchall:Oe(),...E.normalizeParams(e)})}var bd=S("ZodUnion",(t,e)=>{Ys.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Mh(t,n,i,r),t.options=e.options});function Ee(t,e){return new bd({type:"union",options:t,...E.normalizeParams(e)})}var _0=S("ZodXor",(t,e)=>{bd.init(t,e),_g.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Mh(t,n,i,r),t.options=e.options});function zO(t,e){return new _0({type:"union",options:t,inclusive:!1,...E.normalizeParams(e)})}var S0=S("ZodDiscriminatedUnion",(t,e)=>{bd.init(t,e),Sg.init(t,e)});function xd(t,e,n){return new S0({type:"union",options:e,discriminator:t,...E.normalizeParams(n)})}var w0=S("ZodIntersection",(t,e)=>{wg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>zw(t,n,i,r)});function mc(t,e){return new w0({type:"intersection",left:t,right:e})}var C0=S("ZodTuple",(t,e)=>{Mu.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Lw(t,n,i,r),t.rest=n=>t.clone({...t._zod.def,rest:n})});function I0(t,e,n){let i=e instanceof W,r=i?n:e,a=i?e:null;return new C0({type:"tuple",items:t,rest:a,...E.normalizeParams(r)})}var _d=S("ZodRecord",(t,e)=>{Cg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Uw(t,n,i,r),t.keyType=e.keyType,t.valueType=e.valueType});function ze(t,e,n){return new _d({type:"record",keyType:t,valueType:e,...E.normalizeParams(n)})}function LO(t,e,n){let i=Rt(t);return i._zod.values=void 0,new _d({type:"record",keyType:i,valueType:e,...E.normalizeParams(n)})}function UO(t,e,n){return new _d({type:"record",keyType:t,valueType:e,mode:"loose",...E.normalizeParams(n)})}var k0=S("ZodMap",(t,e)=>{Ig.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Dw(t,n,i,r),t.keyType=e.keyType,t.valueType=e.valueType,t.min=(...n)=>t.check(pr(...n)),t.nonempty=n=>t.check(pr(1,n)),t.max=(...n)=>t.check(mi(...n)),t.size=(...n)=>t.check(na(...n))});function FO(t,e,n){return new k0({type:"map",keyType:t,valueType:e,...E.normalizeParams(n)})}var P0=S("ZodSet",(t,e)=>{kg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Nw(t,n,i,r),t.min=(...n)=>t.check(pr(...n)),t.nonempty=n=>t.check(pr(1,n)),t.max=(...n)=>t.check(mi(...n)),t.size=(...n)=>t.check(na(...n))});function qO(t,e){return new P0({type:"set",valueType:t,...E.normalizeParams(e)})}var sc=S("ZodEnum",(t,e)=>{Pg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(i,r,a)=>Iw(t,i,r,a),t.enum=e.entries,t.options=Object.values(e.entries);let n=new Set(Object.keys(e.entries));t.extract=(i,r)=>{let a={};for(let o of i)if(n.has(o))a[o]=e.entries[o];else throw new Error(`Key ${o} not found in enum`);return new sc({...e,checks:[],...E.normalizeParams(r),entries:a})},t.exclude=(i,r)=>{let a={...e.entries};for(let o of i)if(n.has(o))delete a[o];else throw new Error(`Key ${o} not found in enum`);return new sc({...e,checks:[],...E.normalizeParams(r),entries:a})}});function At(t,e){let n=Array.isArray(t)?Object.fromEntries(t.map(i=>[i,i])):t;return new sc({type:"enum",entries:n,...E.normalizeParams(e)})}function BO(t,e){return new sc({type:"enum",entries:t,...E.normalizeParams(e)})}var R0=S("ZodLiteral",(t,e)=>{Rg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>kw(t,n,i,r),t.values=new Set(e.values),Object.defineProperty(t,"value",{get(){if(e.values.length>1)throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");return e.values[0]}})});function q(t,e){return new R0({type:"literal",values:Array.isArray(t)?t:[t],...E.normalizeParams(e)})}var E0=S("ZodFile",(t,e)=>{Eg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Ew(t,n,i,r),t.min=(n,i)=>t.check(pr(n,i)),t.max=(n,i)=>t.check(mi(n,i)),t.mime=(n,i)=>t.check(mo(Array.isArray(n)?n:[n],i))});function HO(t){return Eh(E0,t)}var T0=S("ZodTransform",(t,e)=>{Tg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Ow(t,n,i,r),t._zod.parse=(n,i)=>{if(i.direction==="backward")throw new Ji(t.constructor.name);n.addIssue=a=>{if(typeof a=="string")n.issues.push(E.issue(a,n.value,e));else{let o=a;o.fatal&&(o.continue=!1),o.code??(o.code="custom"),o.input??(o.input=n.value),o.inst??(o.inst=t),n.issues.push(E.issue(o))}};let r=e.transform(n.value,n);return r instanceof Promise?r.then(a=>(n.value=a,n)):(n.value=r,n)}});function py(t){return new T0({type:"transform",transform:t})}var fy=S("ZodOptional",(t,e)=>{zu.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>zh(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function Fe(t){return new fy({type:"optional",innerType:t})}var A0=S("ZodExactOptional",(t,e)=>{Ag.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>zh(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function $0(t){return new A0({type:"optional",innerType:t})}var O0=S("ZodNullable",(t,e)=>{$g.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Fw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function md(t){return new O0({type:"nullable",innerType:t})}function ZO(t){return Fe(md(t))}var D0=S("ZodDefault",(t,e)=>{Og.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Bw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType,t.removeDefault=t.unwrap});function N0(t,e){return new D0({type:"default",innerType:t,get defaultValue(){return typeof e=="function"?e():E.shallowClone(e)}})}var j0=S("ZodPrefault",(t,e)=>{Dg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Hw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function M0(t,e){return new j0({type:"prefault",innerType:t,get defaultValue(){return typeof e=="function"?e():E.shallowClone(e)}})}var my=S("ZodNonOptional",(t,e)=>{Ng.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>qw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function z0(t,e){return new my({type:"nonoptional",innerType:t,...E.normalizeParams(e)})}var L0=S("ZodSuccess",(t,e)=>{jg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Tw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function VO(t){return new L0({type:"success",innerType:t})}var U0=S("ZodCatch",(t,e)=>{Mg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Zw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType,t.removeCatch=t.unwrap});function F0(t,e){return new U0({type:"catch",innerType:t,catchValue:typeof e=="function"?e:()=>e})}var q0=S("ZodNaN",(t,e)=>{zg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Pw(t,n,i,r)});function WO(t){return Rh(q0,t)}var gy=S("ZodPipe",(t,e)=>{Lg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Vw(t,n,i,r),t.in=e.in,t.out=e.out});function gd(t,e){return new gy({type:"pipe",in:t,out:e})}var hy=S("ZodCodec",(t,e)=>{gy.init(t,e),Xs.init(t,e)});function GO(t,e,n){return new hy({type:"pipe",in:t,out:e,transform:n.decode,reverseTransform:n.encode})}var B0=S("ZodReadonly",(t,e)=>{Ug.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Ww(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function H0(t){return new B0({type:"readonly",innerType:t})}var Z0=S("ZodTemplateLiteral",(t,e)=>{Fg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Rw(t,n,i,r)});function KO(t,e){return new Z0({type:"template_literal",parts:t,...E.normalizeParams(e)})}var V0=S("ZodLazy",(t,e)=>{Hg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Kw(t,n,i,r),t.unwrap=()=>t._zod.def.getter()});function W0(t){return new V0({type:"lazy",getter:t})}var G0=S("ZodPromise",(t,e)=>{Bg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Gw(t,n,i,r),t.unwrap=()=>t._zod.def.innerType});function JO(t){return new G0({type:"promise",innerType:t})}var K0=S("ZodFunction",(t,e)=>{qg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>$w(t,n,i,r)});function YO(t){return new K0({type:"function",input:Array.isArray(t?.input)?I0(t?.input):t?.input??oe(Oe()),output:t?.output??Oe()})}var Sd=S("ZodCustom",(t,e)=>{Zg.init(t,e),Q.init(t,e),t._zod.processJSONSchema=(n,i,r)=>Aw(t,n,i,r)});function XO(t){let e=new Ae({check:"custom"});return e._zod.check=t,e}function yy(t,e){return Th(Sd,t??(()=>!0),e)}function J0(t,e={}){return Ah(Sd,t,e)}function Y0(t){return $h(t)}var QO=Oh,eD=Dh;function tD(t,e={}){let n=new Sd({type:"custom",check:"custom",fn:i=>i instanceof t,abort:!0,...E.normalizeParams(e)});return n._zod.bag.Class=t,n._zod.check=i=>{i.value instanceof t||i.issues.push({code:"invalid_type",expected:t.name,input:i.value,inst:n,path:[...n._zod.def.path??[]]})},n}var nD=(...t)=>Nh({Codec:hy,Boolean:dc,String:cc},...t);function rD(t){let e=W0(()=>Ee([k(t),_e(),it(),fc(),oe(e),ze(k(),e)]));return e}function wd(t,e){return gd(py(t),e)}var j7={invalid_type:"invalid_type",too_big:"too_big",too_small:"too_small",invalid_format:"invalid_format",not_multiple_of:"not_multiple_of",unrecognized_keys:"unrecognized_keys",invalid_union:"invalid_union",invalid_key:"invalid_key",invalid_element:"invalid_element",invalid_value:"invalid_value",custom:"custom"};function M7(t){Je({customError:t})}function z7(){return Je().customError}var X0;X0||(X0={});var j={...pd,...Fh,iso:la},L7=new Set(["$schema","$ref","$defs","definitions","$id","id","$comment","$anchor","$vocabulary","$dynamicRef","$dynamicAnchor","type","enum","const","anyOf","oneOf","allOf","not","properties","required","additionalProperties","patternProperties","propertyNames","minProperties","maxProperties","items","prefixItems","additionalItems","minItems","maxItems","uniqueItems","contains","minContains","maxContains","minLength","maxLength","pattern","format","minimum","maximum","exclusiveMinimum","exclusiveMaximum","multipleOf","description","default","contentEncoding","contentMediaType","contentSchema","unevaluatedItems","unevaluatedProperties","if","then","else","dependentSchemas","dependentRequired","nullable","readOnly"]);function U7(t,e){let n=t.$schema;return n==="https://json-schema.org/draft/2020-12/schema"?"draft-2020-12":n==="http://json-schema.org/draft-07/schema#"?"draft-7":n==="http://json-schema.org/draft-04/schema#"?"draft-4":e??"draft-2020-12"}function F7(t,e){if(!t.startsWith("#"))throw new Error("External $ref is not supported, only local refs (#/...) are allowed");let n=t.slice(1).split("/").filter(Boolean);if(n.length===0)return e.rootSchema;let i=e.version==="draft-2020-12"?"$defs":"definitions";if(n[0]===i){let r=n[1];if(!r||!e.defs[r])throw new Error(`Reference not found: ${t}`);return e.defs[r]}throw new Error(`Reference not found: ${t}`)}function iD(t,e){if(t.not!==void 0){if(typeof t.not=="object"&&Object.keys(t.not).length===0)return j.never();throw new Error("not is not supported in Zod (except { not: {} } for never)")}if(t.unevaluatedItems!==void 0)throw new Error("unevaluatedItems is not supported");if(t.unevaluatedProperties!==void 0)throw new Error("unevaluatedProperties is not supported");if(t.if!==void 0||t.then!==void 0||t.else!==void 0)throw new Error("Conditional schemas (if/then/else) are not supported");if(t.dependentSchemas!==void 0||t.dependentRequired!==void 0)throw new Error("dependentSchemas and dependentRequired are not supported");if(t.$ref){let r=t.$ref;if(e.refs.has(r))return e.refs.get(r);if(e.processing.has(r))return j.lazy(()=>{if(!e.refs.has(r))throw new Error(`Circular reference not resolved: ${r}`);return e.refs.get(r)});e.processing.add(r);let a=F7(r,e),o=Ht(a,e);return e.refs.set(r,o),e.processing.delete(r),o}if(t.enum!==void 0){let r=t.enum;if(e.version==="openapi-3.0"&&t.nullable===!0&&r.length===1&&r[0]===null)return j.null();if(r.length===0)return j.never();if(r.length===1)return j.literal(r[0]);if(r.every(o=>typeof o=="string"))return j.enum(r);let a=r.map(o=>j.literal(o));return a.length<2?a[0]:j.union([a[0],a[1],...a.slice(2)])}if(t.const!==void 0)return j.literal(t.const);let n=t.type;if(Array.isArray(n)){let r=n.map(a=>{let o={...t,type:a};return iD(o,e)});return r.length===0?j.never():r.length===1?r[0]:j.union(r)}if(!n)return j.any();let i;switch(n){case"string":{let r=j.string();if(t.format){let a=t.format;a==="email"?r=r.check(j.email()):a==="uri"||a==="uri-reference"?r=r.check(j.url()):a==="uuid"||a==="guid"?r=r.check(j.uuid()):a==="date-time"?r=r.check(j.iso.datetime()):a==="date"?r=r.check(j.iso.date()):a==="time"?r=r.check(j.iso.time()):a==="duration"?r=r.check(j.iso.duration()):a==="ipv4"?r=r.check(j.ipv4()):a==="ipv6"?r=r.check(j.ipv6()):a==="mac"?r=r.check(j.mac()):a==="cidr"?r=r.check(j.cidrv4()):a==="cidr-v6"?r=r.check(j.cidrv6()):a==="base64"?r=r.check(j.base64()):a==="base64url"?r=r.check(j.base64url()):a==="e164"?r=r.check(j.e164()):a==="jwt"?r=r.check(j.jwt()):a==="emoji"?r=r.check(j.emoji()):a==="nanoid"?r=r.check(j.nanoid()):a==="cuid"?r=r.check(j.cuid()):a==="cuid2"?r=r.check(j.cuid2()):a==="ulid"?r=r.check(j.ulid()):a==="xid"?r=r.check(j.xid()):a==="ksuid"&&(r=r.check(j.ksuid()))}typeof t.minLength=="number"&&(r=r.min(t.minLength)),typeof t.maxLength=="number"&&(r=r.max(t.maxLength)),t.pattern&&(r=r.regex(new RegExp(t.pattern))),i=r;break}case"number":case"integer":{let r=n==="integer"?j.number().int():j.number();typeof t.minimum=="number"&&(r=r.min(t.minimum)),typeof t.maximum=="number"&&(r=r.max(t.maximum)),typeof t.exclusiveMinimum=="number"?r=r.gt(t.exclusiveMinimum):t.exclusiveMinimum===!0&&typeof t.minimum=="number"&&(r=r.gt(t.minimum)),typeof t.exclusiveMaximum=="number"?r=r.lt(t.exclusiveMaximum):t.exclusiveMaximum===!0&&typeof t.maximum=="number"&&(r=r.lt(t.maximum)),typeof t.multipleOf=="number"&&(r=r.multipleOf(t.multipleOf)),i=r;break}case"boolean":{i=j.boolean();break}case"null":{i=j.null();break}case"object":{let r={},a=t.properties||{},o=new Set(t.required||[]);for(let[c,l]of Object.entries(a)){let u=Ht(l,e);r[c]=o.has(c)?u:u.optional()}if(t.propertyNames){let c=Ht(t.propertyNames,e),l=t.additionalProperties&&typeof t.additionalProperties=="object"?Ht(t.additionalProperties,e):j.any();if(Object.keys(r).length===0){i=j.record(c,l);break}let u=j.object(r).passthrough(),d=j.looseRecord(c,l);i=j.intersection(u,d);break}if(t.patternProperties){let c=t.patternProperties,l=Object.keys(c),u=[];for(let p of l){let f=Ht(c[p],e),m=j.string().regex(new RegExp(p));u.push(j.looseRecord(m,f))}let d=[];if(Object.keys(r).length>0&&d.push(j.object(r).passthrough()),d.push(...u),d.length===0)i=j.object({}).passthrough();else if(d.length===1)i=d[0];else{let p=j.intersection(d[0],d[1]);for(let f=2;f<d.length;f++)p=j.intersection(p,d[f]);i=p}break}let s=j.object(r);t.additionalProperties===!1?i=s.strict():typeof t.additionalProperties=="object"?i=s.catchall(Ht(t.additionalProperties,e)):i=s.passthrough();break}case"array":{let r=t.prefixItems,a=t.items;if(r&&Array.isArray(r)){let o=r.map(c=>Ht(c,e)),s=a&&typeof a=="object"&&!Array.isArray(a)?Ht(a,e):void 0;s?i=j.tuple(o).rest(s):i=j.tuple(o),typeof t.minItems=="number"&&(i=i.check(j.minLength(t.minItems))),typeof t.maxItems=="number"&&(i=i.check(j.maxLength(t.maxItems)))}else if(Array.isArray(a)){let o=a.map(c=>Ht(c,e)),s=t.additionalItems&&typeof t.additionalItems=="object"?Ht(t.additionalItems,e):void 0;s?i=j.tuple(o).rest(s):i=j.tuple(o),typeof t.minItems=="number"&&(i=i.check(j.minLength(t.minItems))),typeof t.maxItems=="number"&&(i=i.check(j.maxLength(t.maxItems)))}else if(a!==void 0){let o=Ht(a,e),s=j.array(o);typeof t.minItems=="number"&&(s=s.min(t.minItems)),typeof t.maxItems=="number"&&(s=s.max(t.maxItems)),i=s}else i=j.array(j.any());break}default:throw new Error(`Unsupported type: ${n}`)}return t.description&&(i=i.describe(t.description)),t.default!==void 0&&(i=i.default(t.default)),i}function Ht(t,e){if(typeof t=="boolean")return t?j.any():j.never();let n=iD(t,e),i=t.type||t.enum!==void 0||t.const!==void 0;if(t.anyOf&&Array.isArray(t.anyOf)){let s=t.anyOf.map(l=>Ht(l,e)),c=j.union(s);n=i?j.intersection(n,c):c}if(t.oneOf&&Array.isArray(t.oneOf)){let s=t.oneOf.map(l=>Ht(l,e)),c=j.xor(s);n=i?j.intersection(n,c):c}if(t.allOf&&Array.isArray(t.allOf))if(t.allOf.length===0)n=i?n:j.any();else{let s=i?n:Ht(t.allOf[0],e),c=i?0:1;for(let l=c;l<t.allOf.length;l++)s=j.intersection(s,Ht(t.allOf[l],e));n=s}t.nullable===!0&&e.version==="openapi-3.0"&&(n=j.nullable(n)),t.readOnly===!0&&(n=j.readonly(n));let r={},a=["$id","id","$comment","$anchor","$vocabulary","$dynamicRef","$dynamicAnchor"];for(let s of a)s in t&&(r[s]=t[s]);let o=["contentEncoding","contentMediaType","contentSchema"];for(let s of o)s in t&&(r[s]=t[s]);for(let s of Object.keys(t))L7.has(s)||(r[s]=t[s]);return Object.keys(r).length>0&&e.registry.add(n,r),n}function aD(t,e){if(typeof t=="boolean")return t?j.any():j.never();let n=U7(t,e?.defaultTarget),i=t.$defs||t.definitions||{},r={version:n,defs:i,refs:new Map,processing:new Set,rootSchema:t,registry:e?.registry??yt};return Ht(t,r)}var Q0={};qt(Q0,{bigint:()=>Z7,boolean:()=>H7,date:()=>V7,number:()=>B7,string:()=>q7});function q7(t){return Qg(cc,t)}function B7(t){return sh(uc,t)}function H7(t){return mh(dc,t)}function Z7(t){return hh(pc,t)}function V7(t){return Ph(yd,t)}Je(Vg());var tC="2025-11-25";var oD=[tC,"2025-06-18","2025-03-26","2024-11-05","2024-10-07"],ua="io.modelcontextprotocol/related-task",by="2.0",$t=yy(t=>t!==null&&(typeof t=="object"||typeof t=="function")),sD=Ee([k(),_e().int()]),cD=k(),gPe=Tt({ttl:Ee([_e(),fc()]).optional(),pollInterval:_e().optional()}),G7=L({ttl:_e().optional()}),K7=L({taskId:k()}),nC=Tt({progressToken:sD.optional(),[ua]:K7.optional()}),On=L({_meta:nC.optional()}),Cd=On.extend({task:G7.optional()}),lD=t=>Cd.safeParse(t).success,Ot=L({method:k(),params:On.loose().optional()}),Zn=L({_meta:nC.optional()}),Vn=L({method:k(),params:Zn.loose().optional()}),Dt=Tt({_meta:nC.optional()}),xy=Ee([k(),_e().int()]),uD=L({jsonrpc:q(by),id:xy,...Ot.shape}).strict(),rC=t=>uD.safeParse(t).success,dD=L({jsonrpc:q(by),...Vn.shape}).strict(),pD=t=>dD.safeParse(t).success,iC=L({jsonrpc:q(by),id:xy,result:Dt}).strict(),Id=t=>iC.safeParse(t).success;var fe;(function(t){t[t.ConnectionClosed=-32e3]="ConnectionClosed",t[t.RequestTimeout=-32001]="RequestTimeout",t[t.ParseError=-32700]="ParseError",t[t.InvalidRequest=-32600]="InvalidRequest",t[t.MethodNotFound=-32601]="MethodNotFound",t[t.InvalidParams=-32602]="InvalidParams",t[t.InternalError=-32603]="InternalError",t[t.UrlElicitationRequired=-32042]="UrlElicitationRequired"})(fe||(fe={}));var aC=L({jsonrpc:q(by),id:xy.optional(),error:L({code:_e().int(),message:k(),data:Oe().optional()})}).strict();var fD=t=>aC.safeParse(t).success;var mD=Ee([uD,dD,iC,aC]),hPe=Ee([iC,aC]),_y=Dt.strict(),J7=Zn.extend({requestId:xy.optional(),reason:k().optional()}),Sy=Vn.extend({method:q("notifications/cancelled"),params:J7}),Y7=L({src:k(),mimeType:k().optional(),sizes:oe(k()).optional(),theme:At(["light","dark"]).optional()}),kd=L({icons:oe(Y7).optional()}),gc=L({name:k(),title:k().optional()}),gD=gc.extend({...gc.shape,...kd.shape,version:k(),websiteUrl:k().optional(),description:k().optional()}),X7=mc(L({applyDefaults:it().optional()}),ze(k(),Oe())),Q7=wd(t=>t&&typeof t=="object"&&!Array.isArray(t)&&Object.keys(t).length===0?{form:{}}:t,mc(L({form:X7.optional(),url:$t.optional()}),ze(k(),Oe()).optional())),eG=Tt({list:$t.optional(),cancel:$t.optional(),requests:Tt({sampling:Tt({createMessage:$t.optional()}).optional(),elicitation:Tt({create:$t.optional()}).optional()}).optional()}),tG=Tt({list:$t.optional(),cancel:$t.optional(),requests:Tt({tools:Tt({call:$t.optional()}).optional()}).optional()}),nG=L({experimental:ze(k(),$t).optional(),sampling:L({context:$t.optional(),tools:$t.optional()}).optional(),elicitation:Q7.optional(),roots:L({listChanged:it().optional()}).optional(),tasks:eG.optional()}),rG=On.extend({protocolVersion:k(),capabilities:nG,clientInfo:gD}),oC=Ot.extend({method:q("initialize"),params:rG});var iG=L({experimental:ze(k(),$t).optional(),logging:$t.optional(),completions:$t.optional(),prompts:L({listChanged:it().optional()}).optional(),resources:L({subscribe:it().optional(),listChanged:it().optional()}).optional(),tools:L({listChanged:it().optional()}).optional(),tasks:tG.optional()}),aG=Dt.extend({protocolVersion:k(),capabilities:iG,serverInfo:gD,instructions:k().optional()}),sC=Vn.extend({method:q("notifications/initialized"),params:Zn.optional()});var wy=Ot.extend({method:q("ping"),params:On.optional()}),oG=L({progress:_e(),total:Fe(_e()),message:Fe(k())}),sG=L({...Zn.shape,...oG.shape,progressToken:sD}),Cy=Vn.extend({method:q("notifications/progress"),params:sG}),cG=On.extend({cursor:cD.optional()}),Pd=Ot.extend({params:cG.optional()}),Rd=Dt.extend({nextCursor:cD.optional()}),lG=At(["working","input_required","completed","failed","cancelled"]),Ed=L({taskId:k(),status:lG,ttl:Ee([_e(),fc()]),createdAt:k(),lastUpdatedAt:k(),pollInterval:Fe(_e()),statusMessage:Fe(k())}),hc=Dt.extend({task:Ed}),uG=Zn.merge(Ed),Td=Vn.extend({method:q("notifications/tasks/status"),params:uG}),Iy=Ot.extend({method:q("tasks/get"),params:On.extend({taskId:k()})}),ky=Dt.merge(Ed),Py=Ot.extend({method:q("tasks/result"),params:On.extend({taskId:k()})}),yPe=Dt.loose(),Ry=Pd.extend({method:q("tasks/list")}),Ey=Rd.extend({tasks:oe(Ed)}),Ty=Ot.extend({method:q("tasks/cancel"),params:On.extend({taskId:k()})}),hD=Dt.merge(Ed),yD=L({uri:k(),mimeType:Fe(k()),_meta:ze(k(),Oe()).optional()}),vD=yD.extend({text:k()}),cC=k().refine(t=>{try{return atob(t),!0}catch{return!1}},{message:"Invalid Base64 string"}),bD=yD.extend({blob:cC}),Ad=At(["user","assistant"]),yc=L({audience:oe(Ad).optional(),priority:_e().min(0).max(1).optional(),lastModified:la.datetime({offset:!0}).optional()}),xD=L({...gc.shape,...kd.shape,uri:k(),description:Fe(k()),mimeType:Fe(k()),annotations:yc.optional(),_meta:Fe(Tt({}))}),dG=L({...gc.shape,...kd.shape,uriTemplate:k(),description:Fe(k()),mimeType:Fe(k()),annotations:yc.optional(),_meta:Fe(Tt({}))}),lC=Pd.extend({method:q("resources/list")}),pG=Rd.extend({resources:oe(xD)}),fG=Pd.extend({method:q("resources/templates/list")}),mG=Rd.extend({resourceTemplates:oe(dG)}),uC=On.extend({uri:k()}),gG=uC,dC=Ot.extend({method:q("resources/read"),params:gG}),hG=Dt.extend({contents:oe(Ee([vD,bD]))}),yG=Vn.extend({method:q("notifications/resources/list_changed"),params:Zn.optional()}),vG=uC,bG=Ot.extend({method:q("resources/subscribe"),params:vG}),xG=uC,_G=Ot.extend({method:q("resources/unsubscribe"),params:xG}),SG=Zn.extend({uri:k()}),wG=Vn.extend({method:q("notifications/resources/updated"),params:SG}),CG=L({name:k(),description:Fe(k()),required:Fe(it())}),IG=L({...gc.shape,...kd.shape,description:Fe(k()),arguments:Fe(oe(CG)),_meta:Fe(Tt({}))}),kG=Pd.extend({method:q("prompts/list")}),PG=Rd.extend({prompts:oe(IG)}),RG=On.extend({name:k(),arguments:ze(k(),k()).optional()}),EG=Ot.extend({method:q("prompts/get"),params:RG}),pC=L({type:q("text"),text:k(),annotations:yc.optional(),_meta:ze(k(),Oe()).optional()}),fC=L({type:q("image"),data:cC,mimeType:k(),annotations:yc.optional(),_meta:ze(k(),Oe()).optional()}),mC=L({type:q("audio"),data:cC,mimeType:k(),annotations:yc.optional(),_meta:ze(k(),Oe()).optional()}),TG=L({type:q("tool_use"),name:k(),id:k(),input:ze(k(),Oe()),_meta:ze(k(),Oe()).optional()}),AG=L({type:q("resource"),resource:Ee([vD,bD]),annotations:yc.optional(),_meta:ze(k(),Oe()).optional()}),$G=xD.extend({type:q("resource_link")}),gC=Ee([pC,fC,mC,$G,AG]),OG=L({role:Ad,content:gC}),DG=Dt.extend({description:k().optional(),messages:oe(OG)}),NG=Vn.extend({method:q("notifications/prompts/list_changed"),params:Zn.optional()}),jG=L({title:k().optional(),readOnlyHint:it().optional(),destructiveHint:it().optional(),idempotentHint:it().optional(),openWorldHint:it().optional()}),MG=L({taskSupport:At(["required","optional","forbidden"]).optional()}),_D=L({...gc.shape,...kd.shape,description:k().optional(),inputSchema:L({type:q("object"),properties:ze(k(),$t).optional(),required:oe(k()).optional()}).catchall(Oe()),outputSchema:L({type:q("object"),properties:ze(k(),$t).optional(),required:oe(k()).optional()}).catchall(Oe()).optional(),annotations:jG.optional(),execution:MG.optional(),_meta:ze(k(),Oe()).optional()}),hC=Pd.extend({method:q("tools/list")}),zG=Rd.extend({tools:oe(_D)}),Ay=Dt.extend({content:oe(gC).default([]),structuredContent:ze(k(),Oe()).optional(),isError:it().optional()}),vPe=Ay.or(Dt.extend({toolResult:Oe()})),LG=Cd.extend({name:k(),arguments:ze(k(),Oe()).optional()}),$d=Ot.extend({method:q("tools/call"),params:LG}),UG=Vn.extend({method:q("notifications/tools/list_changed"),params:Zn.optional()}),bPe=L({autoRefresh:it().default(!0),debounceMs:_e().int().nonnegative().default(300)}),Od=At(["debug","info","notice","warning","error","critical","alert","emergency"]),FG=On.extend({level:Od}),yC=Ot.extend({method:q("logging/setLevel"),params:FG}),qG=Zn.extend({level:Od,logger:k().optional(),data:Oe()}),BG=Vn.extend({method:q("notifications/message"),params:qG}),HG=L({name:k().optional()}),ZG=L({hints:oe(HG).optional(),costPriority:_e().min(0).max(1).optional(),speedPriority:_e().min(0).max(1).optional(),intelligencePriority:_e().min(0).max(1).optional()}),VG=L({mode:At(["auto","required","none"]).optional()}),WG=L({type:q("tool_result"),toolUseId:k().describe("The unique identifier for the corresponding tool call."),content:oe(gC).default([]),structuredContent:L({}).loose().optional(),isError:it().optional(),_meta:ze(k(),Oe()).optional()}),GG=xd("type",[pC,fC,mC]),vy=xd("type",[pC,fC,mC,TG,WG]),KG=L({role:Ad,content:Ee([vy,oe(vy)]),_meta:ze(k(),Oe()).optional()}),JG=Cd.extend({messages:oe(KG),modelPreferences:ZG.optional(),systemPrompt:k().optional(),includeContext:At(["none","thisServer","allServers"]).optional(),temperature:_e().optional(),maxTokens:_e().int(),stopSequences:oe(k()).optional(),metadata:$t.optional(),tools:oe(_D).optional(),toolChoice:VG.optional()}),YG=Ot.extend({method:q("sampling/createMessage"),params:JG}),vC=Dt.extend({model:k(),stopReason:Fe(At(["endTurn","stopSequence","maxTokens"]).or(k())),role:Ad,content:GG}),bC=Dt.extend({model:k(),stopReason:Fe(At(["endTurn","stopSequence","maxTokens","toolUse"]).or(k())),role:Ad,content:Ee([vy,oe(vy)])}),XG=L({type:q("boolean"),title:k().optional(),description:k().optional(),default:it().optional()}),QG=L({type:q("string"),title:k().optional(),description:k().optional(),minLength:_e().optional(),maxLength:_e().optional(),format:At(["email","uri","date","date-time"]).optional(),default:k().optional()}),eK=L({type:At(["number","integer"]),title:k().optional(),description:k().optional(),minimum:_e().optional(),maximum:_e().optional(),default:_e().optional()}),tK=L({type:q("string"),title:k().optional(),description:k().optional(),enum:oe(k()),default:k().optional()}),nK=L({type:q("string"),title:k().optional(),description:k().optional(),oneOf:oe(L({const:k(),title:k()})),default:k().optional()}),rK=L({type:q("string"),title:k().optional(),description:k().optional(),enum:oe(k()),enumNames:oe(k()).optional(),default:k().optional()}),iK=Ee([tK,nK]),aK=L({type:q("array"),title:k().optional(),description:k().optional(),minItems:_e().optional(),maxItems:_e().optional(),items:L({type:q("string"),enum:oe(k())}),default:oe(k()).optional()}),oK=L({type:q("array"),title:k().optional(),description:k().optional(),minItems:_e().optional(),maxItems:_e().optional(),items:L({anyOf:oe(L({const:k(),title:k()}))}),default:oe(k()).optional()}),sK=Ee([aK,oK]),cK=Ee([rK,iK,sK]),lK=Ee([cK,XG,QG,eK]),uK=Cd.extend({mode:q("form").optional(),message:k(),requestedSchema:L({type:q("object"),properties:ze(k(),lK),required:oe(k()).optional()})}),dK=Cd.extend({mode:q("url"),message:k(),elicitationId:k(),url:k().url()}),pK=Ee([uK,dK]),fK=Ot.extend({method:q("elicitation/create"),params:pK}),mK=Zn.extend({elicitationId:k()}),gK=Vn.extend({method:q("notifications/elicitation/complete"),params:mK}),$y=Dt.extend({action:At(["accept","decline","cancel"]),content:wd(t=>t===null?void 0:t,ze(k(),Ee([k(),_e(),it(),oe(k())])).optional())}),hK=L({type:q("ref/resource"),uri:k()});var yK=L({type:q("ref/prompt"),name:k()}),vK=On.extend({ref:Ee([yK,hK]),argument:L({name:k(),value:k()}),context:L({arguments:ze(k(),k()).optional()}).optional()}),bK=Ot.extend({method:q("completion/complete"),params:vK});var xK=Dt.extend({completion:Tt({values:oe(k()).max(100),total:Fe(_e().int()),hasMore:Fe(it())})}),_K=L({uri:k().startsWith("file://"),name:k().optional(),_meta:ze(k(),Oe()).optional()}),SK=Ot.extend({method:q("roots/list"),params:On.optional()}),xC=Dt.extend({roots:oe(_K)}),wK=Vn.extend({method:q("notifications/roots/list_changed"),params:Zn.optional()}),xPe=Ee([wy,oC,bK,yC,EG,kG,lC,fG,dC,bG,_G,$d,hC,Iy,Py,Ry,Ty]),_Pe=Ee([Sy,Cy,sC,wK,Td]),SPe=Ee([_y,vC,bC,$y,xC,ky,Ey,hc]),wPe=Ee([wy,YG,fK,SK,Iy,Py,Ry,Ty]),CPe=Ee([Sy,Cy,BG,wG,yG,UG,NG,Td,gK]),IPe=Ee([_y,aG,xK,DG,PG,pG,mG,hG,Ay,zG,ky,Ey,hc]),re=class t extends Error{constructor(e,n,i){super(`MCP error ${e}: ${n}`),this.code=e,this.data=i,this.name="McpError"}static fromError(e,n,i){if(e===fe.UrlElicitationRequired&&i){let r=i;if(r.elicitations)return new eC(r.elicitations,n)}return new t(e,n,i)}},eC=class extends re{constructor(e,n=`URL elicitation${e.length>1?"s":""} required`){super(fe.UrlElicitationRequired,n,{elicitations:e})}get elicitations(){return this.data?.elicitations??[]}};function da(t){return t==="completed"||t==="failed"||t==="cancelled"}var CK=Symbol("Let zodToJsonSchema decide on which parser to use");var aRe=new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");function _C(t){let n=Uh(t)?.method;if(!n)throw new Error("Schema is missing a method literal");let i=G$(n);if(typeof i!="string")throw new Error("Schema method literal must be a string");return i}function SC(t,e){let n=ca(t,e);if(!n.success)throw n.error;return n.data}var TK=6e4,Oy=class{constructor(e){this._options=e,this._requestMessageId=0,this._requestHandlers=new Map,this._requestHandlerAbortControllers=new Map,this._notificationHandlers=new Map,this._responseHandlers=new Map,this._progressHandlers=new Map,this._timeoutInfo=new Map,this._pendingDebouncedNotifications=new Set,this._taskProgressTokens=new Map,this._requestResolvers=new Map,this.setNotificationHandler(Sy,n=>{this._oncancel(n)}),this.setNotificationHandler(Cy,n=>{this._onprogress(n)}),this.setRequestHandler(wy,n=>({})),this._taskStore=e?.taskStore,this._taskMessageQueue=e?.taskMessageQueue,this._taskStore&&(this.setRequestHandler(Iy,async(n,i)=>{let r=await this._taskStore.getTask(n.params.taskId,i.sessionId);if(!r)throw new re(fe.InvalidParams,"Failed to retrieve task: Task not found");return{...r}}),this.setRequestHandler(Py,async(n,i)=>{let r=async()=>{let a=n.params.taskId;if(this._taskMessageQueue){let s;for(;s=await this._taskMessageQueue.dequeue(a,i.sessionId);){if(s.type==="response"||s.type==="error"){let c=s.message,l=c.id,u=this._requestResolvers.get(l);if(u)if(this._requestResolvers.delete(l),s.type==="response")u(c);else{let d=c,p=new re(d.error.code,d.error.message,d.error.data);u(p)}else{let d=s.type==="response"?"Response":"Error";this._onerror(new Error(`${d} handler missing for request ${l}`))}continue}await this._transport?.send(s.message,{relatedRequestId:i.requestId})}}let o=await this._taskStore.getTask(a,i.sessionId);if(!o)throw new re(fe.InvalidParams,`Task not found: ${a}`);if(!da(o.status))return await this._waitForTaskUpdate(a,i.signal),await r();if(da(o.status)){let s=await this._taskStore.getTaskResult(a,i.sessionId);return this._clearTaskQueue(a),{...s,_meta:{...s._meta,[ua]:{taskId:a}}}}return await r()};return await r()}),this.setRequestHandler(Ry,async(n,i)=>{try{let{tasks:r,nextCursor:a}=await this._taskStore.listTasks(n.params?.cursor,i.sessionId);return{tasks:r,nextCursor:a,_meta:{}}}catch(r){throw new re(fe.InvalidParams,`Failed to list tasks: ${r instanceof Error?r.message:String(r)}`)}}),this.setRequestHandler(Ty,async(n,i)=>{try{let r=await this._taskStore.getTask(n.params.taskId,i.sessionId);if(!r)throw new re(fe.InvalidParams,`Task not found: ${n.params.taskId}`);if(da(r.status))throw new re(fe.InvalidParams,`Cannot cancel task in terminal status: ${r.status}`);await this._taskStore.updateTaskStatus(n.params.taskId,"cancelled","Client cancelled task execution.",i.sessionId),this._clearTaskQueue(n.params.taskId);let a=await this._taskStore.getTask(n.params.taskId,i.sessionId);if(!a)throw new re(fe.InvalidParams,`Task not found after cancellation: ${n.params.taskId}`);return{_meta:{},...a}}catch(r){throw r instanceof re?r:new re(fe.InvalidRequest,`Failed to cancel task: ${r instanceof Error?r.message:String(r)}`)}}))}async _oncancel(e){if(!e.params.requestId)return;this._requestHandlerAbortControllers.get(e.params.requestId)?.abort(e.params.reason)}_setupTimeout(e,n,i,r,a=!1){this._timeoutInfo.set(e,{timeoutId:setTimeout(r,n),startTime:Date.now(),timeout:n,maxTotalTimeout:i,resetTimeoutOnProgress:a,onTimeout:r})}_resetTimeout(e){let n=this._timeoutInfo.get(e);if(!n)return!1;let i=Date.now()-n.startTime;if(n.maxTotalTimeout&&i>=n.maxTotalTimeout)throw this._timeoutInfo.delete(e),re.fromError(fe.RequestTimeout,"Maximum total timeout exceeded",{maxTotalTimeout:n.maxTotalTimeout,totalElapsed:i});return clearTimeout(n.timeoutId),n.timeoutId=setTimeout(n.onTimeout,n.timeout),!0}_cleanupTimeout(e){let n=this._timeoutInfo.get(e);n&&(clearTimeout(n.timeoutId),this._timeoutInfo.delete(e))}async connect(e){this._transport=e;let n=this.transport?.onclose;this._transport.onclose=()=>{n?.(),this._onclose()};let i=this.transport?.onerror;this._transport.onerror=a=>{i?.(a),this._onerror(a)};let r=this._transport?.onmessage;this._transport.onmessage=(a,o)=>{r?.(a,o),Id(a)||fD(a)?this._onresponse(a):rC(a)?this._onrequest(a,o):pD(a)?this._onnotification(a):this._onerror(new Error(`Unknown message type: ${JSON.stringify(a)}`))},await this._transport.start()}_onclose(){let e=this._responseHandlers;this._responseHandlers=new Map,this._progressHandlers.clear(),this._taskProgressTokens.clear(),this._pendingDebouncedNotifications.clear();let n=re.fromError(fe.ConnectionClosed,"Connection closed");this._transport=void 0,this.onclose?.();for(let i of e.values())i(n)}_onerror(e){this.onerror?.(e)}_onnotification(e){let n=this._notificationHandlers.get(e.method)??this.fallbackNotificationHandler;n!==void 0&&Promise.resolve().then(()=>n(e)).catch(i=>this._onerror(new Error(`Uncaught error in notification handler: ${i}`)))}_onrequest(e,n){let i=this._requestHandlers.get(e.method)??this.fallbackRequestHandler,r=this._transport,a=e.params?._meta?.[ua]?.taskId;if(i===void 0){let u={jsonrpc:"2.0",id:e.id,error:{code:fe.MethodNotFound,message:"Method not found"}};a&&this._taskMessageQueue?this._enqueueTaskMessage(a,{type:"error",message:u,timestamp:Date.now()},r?.sessionId).catch(d=>this._onerror(new Error(`Failed to enqueue error response: ${d}`))):r?.send(u).catch(d=>this._onerror(new Error(`Failed to send an error response: ${d}`)));return}let o=new AbortController;this._requestHandlerAbortControllers.set(e.id,o);let s=lD(e.params)?e.params.task:void 0,c=this._taskStore?this.requestTaskStore(e,r?.sessionId):void 0,l={signal:o.signal,sessionId:r?.sessionId,_meta:e.params?._meta,sendNotification:async u=>{let d={relatedRequestId:e.id};a&&(d.relatedTask={taskId:a}),await this.notification(u,d)},sendRequest:async(u,d,p)=>{let f={...p,relatedRequestId:e.id};a&&!f.relatedTask&&(f.relatedTask={taskId:a});let m=f.relatedTask?.taskId??a;return m&&c&&await c.updateTaskStatus(m,"input_required"),await this.request(u,d,f)},authInfo:n?.authInfo,requestId:e.id,requestInfo:n?.requestInfo,taskId:a,taskStore:c,taskRequestedTtl:s?.ttl,closeSSEStream:n?.closeSSEStream,closeStandaloneSSEStream:n?.closeStandaloneSSEStream};Promise.resolve().then(()=>{s&&this.assertTaskHandlerCapability(e.method)}).then(()=>i(e,l)).then(async u=>{if(o.signal.aborted)return;let d={result:u,jsonrpc:"2.0",id:e.id};a&&this._taskMessageQueue?await this._enqueueTaskMessage(a,{type:"response",message:d,timestamp:Date.now()},r?.sessionId):await r?.send(d)},async u=>{if(o.signal.aborted)return;let d={jsonrpc:"2.0",id:e.id,error:{code:Number.isSafeInteger(u.code)?u.code:fe.InternalError,message:u.message??"Internal error",...u.data!==void 0&&{data:u.data}}};a&&this._taskMessageQueue?await this._enqueueTaskMessage(a,{type:"error",message:d,timestamp:Date.now()},r?.sessionId):await r?.send(d)}).catch(u=>this._onerror(new Error(`Failed to send response: ${u}`))).finally(()=>{this._requestHandlerAbortControllers.delete(e.id)})}_onprogress(e){let{progressToken:n,...i}=e.params,r=Number(n),a=this._progressHandlers.get(r);if(!a){this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(e)}`));return}let o=this._responseHandlers.get(r),s=this._timeoutInfo.get(r);if(s&&o&&s.resetTimeoutOnProgress)try{this._resetTimeout(r)}catch(c){this._responseHandlers.delete(r),this._progressHandlers.delete(r),this._cleanupTimeout(r),o(c);return}a(i)}_onresponse(e){let n=Number(e.id),i=this._requestResolvers.get(n);if(i){if(this._requestResolvers.delete(n),Id(e))i(e);else{let o=new re(e.error.code,e.error.message,e.error.data);i(o)}return}let r=this._responseHandlers.get(n);if(r===void 0){this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(e)}`));return}this._responseHandlers.delete(n),this._cleanupTimeout(n);let a=!1;if(Id(e)&&e.result&&typeof e.result=="object"){let o=e.result;if(o.task&&typeof o.task=="object"){let s=o.task;typeof s.taskId=="string"&&(a=!0,this._taskProgressTokens.set(s.taskId,n))}}if(a||this._progressHandlers.delete(n),Id(e))r(e);else{let o=re.fromError(e.error.code,e.error.message,e.error.data);r(o)}}get transport(){return this._transport}async close(){await this._transport?.close()}async*requestStream(e,n,i){let{task:r}=i??{};if(!r){try{yield{type:"result",result:await this.request(e,n,i)}}catch(o){yield{type:"error",error:o instanceof re?o:new re(fe.InternalError,String(o))}}return}let a;try{let o=await this.request(e,hc,i);if(o.task)a=o.task.taskId,yield{type:"taskCreated",task:o.task};else throw new re(fe.InternalError,"Task creation did not return a task");for(;;){let s=await this.getTask({taskId:a},i);if(yield{type:"taskStatus",task:s},da(s.status)){s.status==="completed"?yield{type:"result",result:await this.getTaskResult({taskId:a},n,i)}:s.status==="failed"?yield{type:"error",error:new re(fe.InternalError,`Task ${a} failed`)}:s.status==="cancelled"&&(yield{type:"error",error:new re(fe.InternalError,`Task ${a} was cancelled`)});return}if(s.status==="input_required"){yield{type:"result",result:await this.getTaskResult({taskId:a},n,i)};return}let c=s.pollInterval??this._options?.defaultTaskPollInterval??1e3;await new Promise(l=>setTimeout(l,c)),i?.signal?.throwIfAborted()}}catch(o){yield{type:"error",error:o instanceof re?o:new re(fe.InternalError,String(o))}}}request(e,n,i){let{relatedRequestId:r,resumptionToken:a,onresumptiontoken:o,task:s,relatedTask:c}=i??{};return new Promise((l,u)=>{let d=x=>{u(x)};if(!this._transport){d(new Error("Not connected"));return}if(this._options?.enforceStrictCapabilities===!0)try{this.assertCapabilityForMethod(e.method),s&&this.assertTaskCapability(e.method)}catch(x){d(x);return}i?.signal?.throwIfAborted();let p=this._requestMessageId++,f={...e,jsonrpc:"2.0",id:p};i?.onprogress&&(this._progressHandlers.set(p,i.onprogress),f.params={...e.params,_meta:{...e.params?._meta||{},progressToken:p}}),s&&(f.params={...f.params,task:s}),c&&(f.params={...f.params,_meta:{...f.params?._meta||{},[ua]:c}});let m=x=>{this._responseHandlers.delete(p),this._progressHandlers.delete(p),this._cleanupTimeout(p),this._transport?.send({jsonrpc:"2.0",method:"notifications/cancelled",params:{requestId:p,reason:String(x)}},{relatedRequestId:r,resumptionToken:a,onresumptiontoken:o}).catch(I=>this._onerror(new Error(`Failed to send cancellation: ${I}`)));let _=x instanceof re?x:new re(fe.RequestTimeout,String(x));u(_)};this._responseHandlers.set(p,x=>{if(!i?.signal?.aborted){if(x instanceof Error)return u(x);try{let _=ca(n,x.result);_.success?l(_.data):u(_.error)}catch(_){u(_)}}}),i?.signal?.addEventListener("abort",()=>{m(i?.signal?.reason)});let g=i?.timeout??TK,h=()=>m(re.fromError(fe.RequestTimeout,"Request timed out",{timeout:g}));this._setupTimeout(p,g,i?.maxTotalTimeout,h,i?.resetTimeoutOnProgress??!1);let v=c?.taskId;if(v){let x=_=>{let I=this._responseHandlers.get(p);I?I(_):this._onerror(new Error(`Response handler missing for side-channeled request ${p}`))};this._requestResolvers.set(p,x),this._enqueueTaskMessage(v,{type:"request",message:f,timestamp:Date.now()}).catch(_=>{this._cleanupTimeout(p),u(_)})}else this._transport.send(f,{relatedRequestId:r,resumptionToken:a,onresumptiontoken:o}).catch(x=>{this._cleanupTimeout(p),u(x)})})}async getTask(e,n){return this.request({method:"tasks/get",params:e},ky,n)}async getTaskResult(e,n,i){return this.request({method:"tasks/result",params:e},n,i)}async listTasks(e,n){return this.request({method:"tasks/list",params:e},Ey,n)}async cancelTask(e,n){return this.request({method:"tasks/cancel",params:e},hD,n)}async notification(e,n){if(!this._transport)throw new Error("Not connected");this.assertNotificationCapability(e.method);let i=n?.relatedTask?.taskId;if(i){let s={...e,jsonrpc:"2.0",params:{...e.params,_meta:{...e.params?._meta||{},[ua]:n.relatedTask}}};await this._enqueueTaskMessage(i,{type:"notification",message:s,timestamp:Date.now()});return}if((this._options?.debouncedNotificationMethods??[]).includes(e.method)&&!e.params&&!n?.relatedRequestId&&!n?.relatedTask){if(this._pendingDebouncedNotifications.has(e.method))return;this._pendingDebouncedNotifications.add(e.method),Promise.resolve().then(()=>{if(this._pendingDebouncedNotifications.delete(e.method),!this._transport)return;let s={...e,jsonrpc:"2.0"};n?.relatedTask&&(s={...s,params:{...s.params,_meta:{...s.params?._meta||{},[ua]:n.relatedTask}}}),this._transport?.send(s,n).catch(c=>this._onerror(c))});return}let o={...e,jsonrpc:"2.0"};n?.relatedTask&&(o={...o,params:{...o.params,_meta:{...o.params?._meta||{},[ua]:n.relatedTask}}}),await this._transport.send(o,n)}setRequestHandler(e,n){let i=_C(e);this.assertRequestHandlerCapability(i),this._requestHandlers.set(i,(r,a)=>{let o=SC(e,r);return Promise.resolve(n(o,a))})}removeRequestHandler(e){this._requestHandlers.delete(e)}assertCanSetRequestHandler(e){if(this._requestHandlers.has(e))throw new Error(`A request handler for ${e} already exists, which would be overridden`)}setNotificationHandler(e,n){let i=_C(e);this._notificationHandlers.set(i,r=>{let a=SC(e,r);return Promise.resolve(n(a))})}removeNotificationHandler(e){this._notificationHandlers.delete(e)}_cleanupTaskProgressHandler(e){let n=this._taskProgressTokens.get(e);n!==void 0&&(this._progressHandlers.delete(n),this._taskProgressTokens.delete(e))}async _enqueueTaskMessage(e,n,i){if(!this._taskStore||!this._taskMessageQueue)throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");let r=this._options?.maxTaskQueueSize;await this._taskMessageQueue.enqueue(e,n,i,r)}async _clearTaskQueue(e,n){if(this._taskMessageQueue){let i=await this._taskMessageQueue.dequeueAll(e,n);for(let r of i)if(r.type==="request"&&rC(r.message)){let a=r.message.id,o=this._requestResolvers.get(a);o?(o(new re(fe.InternalError,"Task cancelled or completed")),this._requestResolvers.delete(a)):this._onerror(new Error(`Resolver missing for request ${a} during task ${e} cleanup`))}}}async _waitForTaskUpdate(e,n){let i=this._options?.defaultTaskPollInterval??1e3;try{let r=await this._taskStore?.getTask(e);r?.pollInterval&&(i=r.pollInterval)}catch{}return new Promise((r,a)=>{if(n.aborted){a(new re(fe.InvalidRequest,"Request cancelled"));return}let o=setTimeout(r,i);n.addEventListener("abort",()=>{clearTimeout(o),a(new re(fe.InvalidRequest,"Request cancelled"))},{once:!0})})}requestTaskStore(e,n){let i=this._taskStore;if(!i)throw new Error("No task store configured");return{createTask:async r=>{if(!e)throw new Error("No request provided");return await i.createTask(r,e.id,{method:e.method,params:e.params},n)},getTask:async r=>{let a=await i.getTask(r,n);if(!a)throw new re(fe.InvalidParams,"Failed to retrieve task: Task not found");return a},storeTaskResult:async(r,a,o)=>{await i.storeTaskResult(r,a,o,n);let s=await i.getTask(r,n);if(s){let c=Td.parse({method:"notifications/tasks/status",params:s});await this.notification(c),da(s.status)&&this._cleanupTaskProgressHandler(r)}},getTaskResult:r=>i.getTaskResult(r,n),updateTaskStatus:async(r,a,o)=>{let s=await i.getTask(r,n);if(!s)throw new re(fe.InvalidParams,`Task "${r}" not found - it may have been cleaned up`);if(da(s.status))throw new re(fe.InvalidParams,`Cannot update task "${r}" from terminal status "${s.status}" to "${a}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);await i.updateTaskStatus(r,a,o,n);let c=await i.getTask(r,n);if(c){let l=Td.parse({method:"notifications/tasks/status",params:c});await this.notification(l),da(c.status)&&this._cleanupTaskProgressHandler(r)}},listTasks:r=>i.listTasks(r,n)}}};function SD(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function wD(t,e){let n={...t};for(let i in e){let r=i,a=e[r];if(a===void 0)continue;let o=n[r];SD(o)&&SD(a)?n[r]={...o,...a}:n[r]=a}return n}var lM=Pt(sk(),1),uM=Pt(cM(),1);function xte(){let t=new lM.default({strict:!1,validateFormats:!0,validateSchema:!1,allErrors:!0});return(0,uM.default)(t),t}var hv=class{constructor(e){this._ajv=e??xte()}getValidator(e){let n="$id"in e&&typeof e.$id=="string"?this._ajv.getSchema(e.$id)??this._ajv.compile(e):this._ajv.compile(e);return i=>n(i)?{valid:!0,data:i,errorMessage:void 0}:{valid:!1,data:void 0,errorMessage:this._ajv.errorsText(n.errors)}}};var yv=class{constructor(e){this._server=e}requestStream(e,n,i){return this._server.requestStream(e,n,i)}async getTask(e,n){return this._server.getTask({taskId:e},n)}async getTaskResult(e,n,i){return this._server.getTaskResult({taskId:e},n,i)}async listTasks(e,n){return this._server.listTasks(e?{cursor:e}:void 0,n)}async cancelTask(e,n){return this._server.cancelTask({taskId:e},n)}};function dM(t,e,n){if(!t)throw new Error(`${n} does not support task creation (required for ${e})`);switch(e){case"tools/call":if(!t.tools?.call)throw new Error(`${n} does not support task creation for tools/call (required for ${e})`);break;default:break}}function pM(t,e,n){if(!t)throw new Error(`${n} does not support task creation (required for ${e})`);switch(e){case"sampling/createMessage":if(!t.sampling?.createMessage)throw new Error(`${n} does not support task creation for sampling/createMessage (required for ${e})`);break;case"elicitation/create":if(!t.elicitation?.create)throw new Error(`${n} does not support task creation for elicitation/create (required for ${e})`);break;default:break}}var vv=class extends Oy{constructor(e,n){super(n),this._serverInfo=e,this._loggingLevels=new Map,this.LOG_LEVEL_SEVERITY=new Map(Od.options.map((i,r)=>[i,r])),this.isMessageIgnored=(i,r)=>{let a=this._loggingLevels.get(r);return a?this.LOG_LEVEL_SEVERITY.get(i)<this.LOG_LEVEL_SEVERITY.get(a):!1},this._capabilities=n?.capabilities??{},this._instructions=n?.instructions,this._jsonSchemaValidator=n?.jsonSchemaValidator??new hv,this.setRequestHandler(oC,i=>this._oninitialize(i)),this.setNotificationHandler(sC,()=>this.oninitialized?.()),this._capabilities.logging&&this.setRequestHandler(yC,async(i,r)=>{let a=r.sessionId||r.requestInfo?.headers["mcp-session-id"]||void 0,{level:o}=i.params,s=Od.safeParse(o);return s.success&&this._loggingLevels.set(a,s.data),{}})}get experimental(){return this._experimental||(this._experimental={tasks:new yv(this)}),this._experimental}registerCapabilities(e){if(this.transport)throw new Error("Cannot register capabilities after connecting to transport");this._capabilities=wD(this._capabilities,e)}setRequestHandler(e,n){let r=Uh(e)?.method;if(!r)throw new Error("Schema is missing a method literal");let a;if(oc(r)){let s=r;a=s._zod?.def?.value??s.value}else{let s=r;a=s._def?.value??s.value}if(typeof a!="string")throw new Error("Schema method literal must be a string");if(a==="tools/call"){let s=async(c,l)=>{let u=ca($d,c);if(!u.success){let m=u.error instanceof Error?u.error.message:String(u.error);throw new re(fe.InvalidParams,`Invalid tools/call request: ${m}`)}let{params:d}=u.data,p=await Promise.resolve(n(c,l));if(d.task){let m=ca(hc,p);if(!m.success){let g=m.error instanceof Error?m.error.message:String(m.error);throw new re(fe.InvalidParams,`Invalid task creation result: ${g}`)}return m.data}let f=ca(Ay,p);if(!f.success){let m=f.error instanceof Error?f.error.message:String(f.error);throw new re(fe.InvalidParams,`Invalid tools/call result: ${m}`)}return f.data};return super.setRequestHandler(e,s)}return super.setRequestHandler(e,n)}assertCapabilityForMethod(e){switch(e){case"sampling/createMessage":if(!this._clientCapabilities?.sampling)throw new Error(`Client does not support sampling (required for ${e})`);break;case"elicitation/create":if(!this._clientCapabilities?.elicitation)throw new Error(`Client does not support elicitation (required for ${e})`);break;case"roots/list":if(!this._clientCapabilities?.roots)throw new Error(`Client does not support listing roots (required for ${e})`);break;case"ping":break}}assertNotificationCapability(e){switch(e){case"notifications/message":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${e})`);break;case"notifications/resources/updated":case"notifications/resources/list_changed":if(!this._capabilities.resources)throw new Error(`Server does not support notifying about resources (required for ${e})`);break;case"notifications/tools/list_changed":if(!this._capabilities.tools)throw new Error(`Server does not support notifying of tool list changes (required for ${e})`);break;case"notifications/prompts/list_changed":if(!this._capabilities.prompts)throw new Error(`Server does not support notifying of prompt list changes (required for ${e})`);break;case"notifications/elicitation/complete":if(!this._clientCapabilities?.elicitation?.url)throw new Error(`Client does not support URL elicitation (required for ${e})`);break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(e){if(this._capabilities)switch(e){case"completion/complete":if(!this._capabilities.completions)throw new Error(`Server does not support completions (required for ${e})`);break;case"logging/setLevel":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${e})`);break;case"prompts/get":case"prompts/list":if(!this._capabilities.prompts)throw new Error(`Server does not support prompts (required for ${e})`);break;case"resources/list":case"resources/templates/list":case"resources/read":if(!this._capabilities.resources)throw new Error(`Server does not support resources (required for ${e})`);break;case"tools/call":case"tools/list":if(!this._capabilities.tools)throw new Error(`Server does not support tools (required for ${e})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw new Error(`Server does not support tasks capability (required for ${e})`);break;case"ping":case"initialize":break}}assertTaskCapability(e){pM(this._clientCapabilities?.tasks?.requests,e,"Client")}assertTaskHandlerCapability(e){this._capabilities&&dM(this._capabilities.tasks?.requests,e,"Server")}async _oninitialize(e){let n=e.params.protocolVersion;return this._clientCapabilities=e.params.capabilities,this._clientVersion=e.params.clientInfo,{protocolVersion:oD.includes(n)?n:tC,capabilities:this.getCapabilities(),serverInfo:this._serverInfo,...this._instructions&&{instructions:this._instructions}}}getClientCapabilities(){return this._clientCapabilities}getClientVersion(){return this._clientVersion}getCapabilities(){return this._capabilities}async ping(){return this.request({method:"ping"},_y)}async createMessage(e,n){if((e.tools||e.toolChoice)&&!this._clientCapabilities?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(e.messages.length>0){let i=e.messages[e.messages.length-1],r=Array.isArray(i.content)?i.content:[i.content],a=r.some(l=>l.type==="tool_result"),o=e.messages.length>1?e.messages[e.messages.length-2]:void 0,s=o?Array.isArray(o.content)?o.content:[o.content]:[],c=s.some(l=>l.type==="tool_use");if(a){if(r.some(l=>l.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!c)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(c){let l=new Set(s.filter(d=>d.type==="tool_use").map(d=>d.id)),u=new Set(r.filter(d=>d.type==="tool_result").map(d=>d.toolUseId));if(l.size!==u.size||![...l].every(d=>u.has(d)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return e.tools?this.request({method:"sampling/createMessage",params:e},bC,n):this.request({method:"sampling/createMessage",params:e},vC,n)}async elicitInput(e,n){switch(e.mode??"form"){case"url":{if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support url elicitation.");let r=e;return this.request({method:"elicitation/create",params:r},$y,n)}case"form":{if(!this._clientCapabilities?.elicitation?.form)throw new Error("Client does not support form elicitation.");let r=e.mode==="form"?e:{...e,mode:"form"},a=await this.request({method:"elicitation/create",params:r},$y,n);if(a.action==="accept"&&a.content&&r.requestedSchema)try{let s=this._jsonSchemaValidator.getValidator(r.requestedSchema)(a.content);if(!s.valid)throw new re(fe.InvalidParams,`Elicitation response content does not match requested schema: ${s.errorMessage}`)}catch(o){throw o instanceof re?o:new re(fe.InternalError,`Error validating elicitation response: ${o instanceof Error?o.message:String(o)}`)}return a}}}createElicitationCompletionNotifier(e,n){if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support URL elicitation (required for notifications/elicitation/complete)");return()=>this.notification({method:"notifications/elicitation/complete",params:{elicitationId:e}},n)}async listRoots(e,n){return this.request({method:"roots/list",params:e},xC,n)}async sendLoggingMessage(e,n){if(this._capabilities.logging&&!this.isMessageIgnored(e.level,n))return this.notification({method:"notifications/message",params:e})}async sendResourceUpdated(e){return this.notification({method:"notifications/resources/updated",params:e})}async sendResourceListChanged(){return this.notification({method:"notifications/resources/list_changed"})}async sendToolListChanged(){return this.notification({method:"notifications/tools/list_changed"})}async sendPromptListChanged(){return this.notification({method:"notifications/prompts/list_changed"})}};import mM from"node:process";var bv=class{append(e){this._buffer=this._buffer?Buffer.concat([this._buffer,e]):e}readMessage(){if(!this._buffer)return null;let e=this._buffer.indexOf(`
|
|
130
130
|
`);if(e===-1)return null;let n=this._buffer.toString("utf8",0,e).replace(/\r$/,"");return this._buffer=this._buffer.subarray(e+1),_te(n)}clear(){this._buffer=void 0}};function _te(t){return mD.parse(JSON.parse(t))}function fM(t){return JSON.stringify(t)+`
|
|
131
|
-
`}var xv=class{constructor(e=mM.stdin,n=mM.stdout){this._stdin=e,this._stdout=n,this._readBuffer=new bv,this._started=!1,this._ondata=i=>{this._readBuffer.append(i),this.processReadBuffer()},this._onerror=i=>{this.onerror?.(i)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let e=this._readBuffer.readMessage();if(e===null)break;this.onmessage?.(e)}catch(e){this.onerror?.(e)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(e){return new Promise(n=>{let i=fM(e);this._stdout.write(i)?n():this._stdout.once("drain",n)})}};var gk={name:"query_instances",description:"Query Roblox instances: get, children, find child/descendant, wait for child, class info, search by name/class. [PRO] file_tree, project_structure, descendants, ancestors, search by property/tag.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["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"],description:"Query action to perform. Basic: get, children, find_child, find_descendant, wait_for_child, class_info, search_name, search_class. [PRO]: search_property, search_tag, file_tree, project_structure, descendants, ancestors."},path:{type:"string",description:'Instance path to query (e.g., "game.Workspace.Part"). Used by: get, children, find_child, find_descendant, wait_for_child, descendants, ancestors.'},sessionDebugId:{type:"string",description:"Optional same Studio/plugin session debug identity for resolving duplicate-named path targets. Used by: get, children, descendants, ancestors."},siblingIndex:{type:"number",description:"Optional 1-based same-name sibling index fallback for resolving duplicate-named path targets. Used by: get, children, descendants, ancestors."},childName:{type:"string",description:"Name of the child instance to find. Used by: find_child, wait_for_child."},descendantName:{type:"string",description:"Name of the descendant instance to find. Used by: find_descendant."},className:{type:"string",description:"Roblox class name. Used by: find_child/find_descendant (optional filter), class_info (required), search_class (required)."},recursive:{type:"boolean",description:"If true, returns all descendants instead of just immediate children. Used by: children. Default: false."},maxDepth:{type:"number",description:"Maximum depth for recursive traversal. Used by: children (default: 10), file_tree (default: 5)."},timeout:{type:"number",description:"Maximum time to wait in seconds. Used by: wait_for_child. Default: 5. Maximum: 30."},root:{type:"string",description:'Root path to search/scan from. Used by: search_name, search_class, search_property, search_tag, file_tree, project_structure. Default: "game".'},query:{type:"string",description:"Search pattern for name search (supports * and ? wildcards). Used by: search_name."},propertyName:{type:"string",description:"[PRO] Property name to search by. Used by: search_property."},propertyValue:{description:"[PRO] Property value to match. Used by: search_property."},tag:{type:"string",description:"[PRO] Tag string to search by (case-sensitive). Used by: search_tag."},includeServices:{type:"boolean",description:'[PRO] Include Roblox services when root is "game". Used by: file_tree. Default: true.'},includeSubclasses:{type:"boolean",description:"Include subclasses in class search (e.g., BasePart finds Part, MeshPart). Used by: search_class. Default: true."},caseSensitive:{type:"boolean",description:"Case-sensitive name search. Used by: search_name. Default: false."},maxResults:{type:"number",description:"Maximum results to return. Used by: search_name, search_class, search_property, search_tag, descendants. Default: 100."},depth:{type:"number",description:"[PRO] Maximum depth for project structure traversal. Used by: project_structure. Default: 3."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"get"}}},then:{required:["path"]}},{if:{properties:{action:{const:"children"}}},then:{required:["path"]}},{if:{properties:{action:{const:"find_child"}}},then:{required:["path","childName"]}},{if:{properties:{action:{const:"find_descendant"}}},then:{required:["path","descendantName"]}},{if:{properties:{action:{const:"wait_for_child"}}},then:{required:["path","childName"]}},{if:{properties:{action:{const:"class_info"}}},then:{required:["className"]}},{if:{properties:{action:{const:"search_name"}}},then:{required:["query"]}},{if:{properties:{action:{const:"search_class"}}},then:{required:["className"]}},{if:{properties:{action:{const:"search_property"}}},then:{required:["propertyName"]}},{if:{properties:{action:{const:"search_tag"}}},then:{required:["tag"]}},{if:{properties:{action:{const:"descendants"}}},then:{required:["path"]}},{if:{properties:{action:{const:"ancestors"}}},then:{required:["path"]}}],required:["action"]}};var hk={name:"mutate_instances",description:"Create, delete, clone, move, rename, or pivot instances. [PRO] create_tree, mass_create, mass_delete, mass_duplicate, smart_duplicate.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","create_with_props","delete","clone","move","rename","pivot","create_tree","mass_create","mass_delete","mass_duplicate","smart_duplicate"],description:"Mutation action. Basic: create, create_with_props, delete, clone, move, rename, pivot. [PRO]: create_tree, mass_create, mass_delete, mass_duplicate, smart_duplicate."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},className:{type:"string",description:"Roblox class name (e.g., Part, Script, Folder). Used by: create, create_with_props."},parent:{type:"string",description:"Parent path for new instance. Used by: create, create_with_props."},name:{type:"string",description:"Name for the instance. Used by: create (optional), create_with_props (required)."},properties:{type:"object",description:"Properties to set on the instance. Supports Vector3, Color3, CFrame, UDim2, Enum types. Used by: create (optional), create_with_props (required).",additionalProperties:!0},path:{type:"string",description:"Instance path to operate on. Used by: delete, clone (as sourcePath), move, rename, pivot, smart_duplicate."},sessionDebugId:{type:"string",description:"Optional same Studio/plugin session debug identity for verifying a duplicate-named target. Used by: delete, clone, move, rename, pivot, smart_duplicate."},siblingIndex:{type:"number",description:"Optional 1-based same-name sibling index fallback for verifying a duplicate-named target. Used by: delete, clone, move, rename, pivot, smart_duplicate."},sourcePath:{type:"string",description:"Source instance path to clone from. Used by: clone. Alternative to path."},targetParent:{type:"string",description:"Target parent for cloned/duplicated instances. Used by: clone, mass_duplicate, smart_duplicate."},newName:{type:"string",description:"New name for instance. Used by: rename (required), clone (optional)."},newParent:{type:"string",description:"New parent path to move instance to. Used by: move."},position:{type:"object",description:"Target position as Vector3 {x, y, z}. Used by: pivot.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},cframe:{type:"array",description:"Target CFrame as 12-number array [x, y, z, r00, r01, r02, r10, r11, r12, r20, r21, r22]. Used by: pivot.",minItems:12,maxItems:12,items:{type:"number"}},offset:{type:"object",description:"Relative offset to move by (ignores position/cframe). Used by: pivot, smart_duplicate.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},tree:{type:"object",description:"[PRO] Instance tree specification for hierarchical creation. Used by: create_tree.",additionalProperties:!0},instances:{type:"array",description:"[PRO] Array of instance specifications for batch creation. Used by: mass_create. Each item: {className, name, parentPath, properties?}.",items:{type:"object",required:["className","name","parentPath"],properties:{className:{type:"string"},name:{type:"string"},parentPath:{type:"string"},properties:{type:"object",additionalProperties:!0}}}},paths:{type:"array",description:"[PRO] Array of instance paths. Used by: mass_delete, mass_duplicate.",items:{type:"string"}},count:{type:"number",description:"[PRO] Number of copies to create. Used by: smart_duplicate."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"create"}}},then:{required:["className","parent"]}},{if:{properties:{action:{const:"create_with_props"}}},then:{required:["className","parent","name","properties"]}},{if:{properties:{action:{const:"delete"}}},then:{required:["path"]}},{if:{properties:{action:{const:"clone"}}},then:{required:["sourcePath"]}},{if:{properties:{action:{const:"move"}}},then:{required:["path","newParent"]}},{if:{properties:{action:{const:"rename"}}},then:{required:["path","newName"]}},{if:{properties:{action:{const:"pivot"}}},then:{required:["path"]}},{if:{properties:{action:{const:"create_tree"}}},then:{required:["parent","tree"]}},{if:{properties:{action:{const:"mass_create"}}},then:{required:["instances"]}},{if:{properties:{action:{const:"mass_delete"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"mass_duplicate"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"smart_duplicate"}}},then:{required:["path","offset"]}}],required:["action"]}};var yk={name:"manage_properties",description:"Get/set properties, attributes, and tags on instances. [PRO] set_calculated, set_relative, mass_set, mass_get, modify_children.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["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"],description:"Property action. Basic: 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. [PRO]: set_calculated, set_relative, mass_set, mass_get, modify_children."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Instance path. Used by: get, set, get_all, set_multiple, get_attr, set_attr, get_all_attrs, delete_attr, add_tag, remove_tag, check_tag, get_tags, set_calculated, set_relative."},property:{type:"string",description:'Property name (e.g., "Size", "Position", "Anchored"). Used by: get, set.'},value:{description:"Value to set. Supports primitives, Vector3 {x,y,z}, Color3 {r,g,b} (0-255), CFrame (12-number array), UDim2 {xScale,xOffset,yScale,yOffset}, Enum strings. Used by: set, set_attr, set_relative."},properties:{type:"object",description:"Dictionary of property names to values. Used by: set_multiple.",additionalProperties:!0},attribute:{type:"string",description:"Attribute name. Used by: get_attr, set_attr, delete_attr."},tag:{type:"string",description:"Tag string (case-sensitive). Used by: add_tag, remove_tag, check_tag."},tagName:{type:"string",description:"Tag to search for. Used by: get_tagged."},root:{type:"string",description:"Root path to filter get_tagged results. Used by: get_tagged."},maxResults:{type:"number",description:"Maximum results for get_tagged. Default: 100."},expression:{type:"string",description:'[PRO] Mathematical expression to evaluate. Used by: set_calculated. Example: "baseValue * multiplier".'},variables:{type:"object",description:'[PRO] Variable name to value/path mapping. Used by: set_calculated. Example: {"baseValue": "workspace.Config.BaseValue", "multiplier": 2}.',additionalProperties:!0},operation:{type:"string",description:"[PRO] Mathematical operation for relative property change. Used by: set_relative.",enum:["add","subtract","multiply","divide"]},amount:{description:"[PRO] Value for relative operation. Can be number, Vector3, etc. Used by: set_relative. Alias for value in set_relative context."},paths:{type:"array",description:"[PRO] Array of instance paths for bulk operations. Used by: mass_set, mass_get.",items:{type:"string"}},parentPath:{type:"string",description:"[PRO] Parent path whose children will be modified. Used by: modify_children."},modifications:{type:"object",description:"[PRO] Properties to set on children. Used by: modify_children. Contains propertyName, propertyValue, filter, recursive.",properties:{propertyName:{type:"string",description:"Property name to set on all children."},propertyValue:{description:"Value to set on all children."},filter:{type:"string",description:"Optional class name filter for children."},recursive:{type:"boolean",description:"If true, modifies all descendants. Default: false."}}},propertyName:{type:"string",description:"[PRO] Property name for mass operations or set_calculated/set_relative. Used by: mass_set, mass_get, set_calculated, set_relative, modify_children."},propertyValue:{description:"[PRO] Property value for mass_set and modify_children."},filter:{type:"string",description:"[PRO] Class name filter for modify_children."},recursive:{type:"boolean",description:"[PRO] Modify all descendants, not just immediate children. Used by: modify_children. Default: false."},includeReadOnly:{type:"boolean",description:"Include read-only properties. Used by: get_all. Default: false."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"get"}}},then:{required:["path","property"]}},{if:{properties:{action:{const:"set"}}},then:{required:["path","property","value"]}},{if:{properties:{action:{const:"get_all"}}},then:{required:["path"]}},{if:{properties:{action:{const:"set_multiple"}}},then:{required:["path","properties"]}},{if:{properties:{action:{const:"get_attr"}}},then:{required:["path","attribute"]}},{if:{properties:{action:{const:"set_attr"}}},then:{required:["path","value","attribute"]}},{if:{properties:{action:{const:"get_all_attrs"}}},then:{required:["path"]}},{if:{properties:{action:{const:"delete_attr"}}},then:{required:["path","attribute"]}},{if:{properties:{action:{const:"add_tag"}}},then:{required:["path","tag"]}},{if:{properties:{action:{const:"remove_tag"}}},then:{required:["path","tag"]}},{if:{properties:{action:{const:"check_tag"}}},then:{required:["path","tag"]}},{if:{properties:{action:{const:"get_tags"}}},then:{required:["path"]}},{if:{properties:{action:{const:"get_tagged"}}},then:{required:["tagName"]}},{if:{properties:{action:{const:"set_calculated"}}},then:{required:["path","expression","propertyName"]}},{if:{properties:{action:{const:"set_relative"}}},then:{required:["path","operation","propertyName"]}},{if:{properties:{action:{const:"mass_set"}}},then:{required:["paths","propertyName","propertyValue"]}},{if:{properties:{action:{const:"mass_get"}}},then:{required:["paths","propertyName"]}},{if:{properties:{action:{const:"modify_children"}}},then:{required:["parentPath"]}}],required:["action"]}};var vk={name:"manage_scripts",description:"Manage script source code: read, write, create, delete, edit lines, search. [PRO] replace across scripts.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get_source","set_source","create","delete","edit_replace","edit_insert","edit_delete","search","replace","get_dependencies"],description:"Script action. Basic: get_source, set_source, create, delete, edit_replace, edit_insert, edit_delete, search, get_dependencies. [PRO]: replace."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the script instance. Used by: get_source, set_source, delete, edit_replace, edit_insert, edit_delete, search, get_dependencies, replace."},source:{type:"string",description:"Script source code. Used by: set_source (required), create (optional initial source)."},scriptType:{type:"string",description:"Type of script to create. Used by: create.",enum:["Script","LocalScript","ModuleScript"]},parent:{type:"string",description:"Parent path for new script. Used by: create."},name:{type:"string",description:"Name for new script. Used by: create."},startLine:{type:"number",description:"Starting line number, 1-based inclusive. Used by: edit_replace, edit_delete."},endLine:{type:"number",description:"Ending line number, 1-based inclusive. Used by: edit_replace, edit_delete."},newLines:{type:"string",description:"New content to replace specified lines. Used by: edit_replace. Can be multi-line."},lines:{type:"string",description:"Content to insert after afterLine. Used by: edit_insert. Can be multi-line. Alias for content."},afterLine:{type:"number",description:"Line number after which to insert. Used by: edit_insert. Use 0 to insert at beginning."},content:{type:"string",description:"Content to insert. Used by: edit_insert. Can be multi-line."},pattern:{type:"string",description:"Search pattern (plain text or Lua pattern). Used by: search, replace."},replacement:{type:"string",description:"[PRO] Replacement text. Used by: replace."},caseSensitive:{type:"boolean",description:"Case-sensitive search. Used by: search. Default: false."},wholeWord:{type:"boolean",description:"Match whole words only. Used by: search. Default: false."},usePattern:{type:"boolean",description:"Treat pattern as Lua pattern instead of plain text. Used by: search, replace. Default: false."},dryRun:{type:"boolean",description:"[PRO] Show what would be replaced without making changes. Used by: replace. Default: false."},maxResults:{type:"number",description:"Maximum results to return. Used by: search. Default: 100."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"get_source"}}},then:{required:["path"]}},{if:{properties:{action:{const:"set_source"}}},then:{required:["path","source"]}},{if:{properties:{action:{const:"create"}}},then:{required:["scriptType","parent"]}},{if:{properties:{action:{const:"delete"}}},then:{required:["path"]}},{if:{properties:{action:{const:"edit_replace"}}},then:{required:["path","startLine","endLine","newLines"]}},{if:{properties:{action:{const:"edit_insert"}}},then:{required:["path","afterLine","content"]}},{if:{properties:{action:{const:"edit_delete"}}},then:{required:["path","startLine","endLine"]}},{if:{properties:{action:{const:"search"}}},then:{required:["path","pattern"]}},{if:{properties:{action:{const:"replace"}}},then:{required:["path","pattern","replacement"]}},{if:{properties:{action:{const:"get_dependencies"}}},then:{required:["path"]}}],required:["action"]}};var bk={name:"manage_ui",description:"Create / update / verify Roblox in-game UI (ScreenGui / Frame / TextLabel / \u2026). Always start a new UI task with the `design_brief` action \u2014 it accepts an omitted or partial brief, inspects Studio context, then returns a current-state summary, recommended mode/change scopes, candidate brief patches, and one user-facing confirmation or clarification question. design_brief may return asset recommendation candidates from existing UI images, user references, or conservative manage_assets.search results; do not use a recommended asset until the user accepts it. Do not dump enum lists at the user; map natural language to internal purpose/platform/tone values through recommendations, and only finalize identity-defining fields after the user accepts a recommendation or provides equivalent intent. Read MCP resource `weppy://ui-studio/guide` for the full guide; it is split into Floor (non-negotiable accessibility), Vocabulary (style menu \u2014 pick ONE family per dimension; do not blend everything), Direction (brief \u2192 choices), and Tree encoding (Roblox property JSON shapes). Floor essentials suggested by Design Check (`check`): (1) mobile touch target \u2265 44 px (2) text contrast \u2265 4.5:1 (3) prefer explicit `TextSize` over `TextScaled` (4) respect platform safe zones (5) warn on full-screen opaque roots for non-modal purposes. Style is brief-driven; reject the default AI look (uniform 8 px corners + generic blue + glass card + Gotham everywhere) \u2014 each game deserves its own visual identity.\n",inputSchema:{type:"object",properties:{action:{type:"string",enum:["design_brief","create_tree","update","delete","preview","check"],description:`UI action. [PRO]: design_brief, create_tree, update, delete, preview, check. (M2+\uC5D0\uC11C propose_layout/apply_asset \uCD94\uAC00 \uC608\uC815.)
|
|
131
|
+
`}var xv=class{constructor(e=mM.stdin,n=mM.stdout){this._stdin=e,this._stdout=n,this._readBuffer=new bv,this._started=!1,this._ondata=i=>{this._readBuffer.append(i),this.processReadBuffer()},this._onerror=i=>{this.onerror?.(i)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let e=this._readBuffer.readMessage();if(e===null)break;this.onmessage?.(e)}catch(e){this.onerror?.(e)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(e){return new Promise(n=>{let i=fM(e);this._stdout.write(i)?n():this._stdout.once("drain",n)})}};var gk={name:"query_instances",description:"Query Roblox instances: get, children, find child/descendant, wait for child, class info, search by name/class. [PRO] file_tree, project_structure, descendants, ancestors, search by property/tag.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["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"],description:"Query action to perform. Basic: get, children, find_child, find_descendant, wait_for_child, class_info, search_name, search_class. [PRO]: search_property, search_tag, file_tree, project_structure, descendants, ancestors."},path:{type:"string",description:'Instance path to query (e.g., "game.Workspace.Part"). Used by: get, children, find_child, find_descendant, wait_for_child, descendants, ancestors.'},sessionDebugId:{type:"string",description:"Optional same Studio/plugin session debug identity for resolving duplicate-named path targets. Used by: get, children, descendants, ancestors."},siblingIndex:{type:"number",description:"Optional 1-based same-name sibling index fallback for resolving duplicate-named path targets. Used by: get, children, descendants, ancestors."},childName:{type:"string",description:"Name of the child instance to find. Used by: find_child, wait_for_child."},descendantName:{type:"string",description:"Name of the descendant instance to find. Used by: find_descendant."},className:{type:"string",description:"Roblox class name. Used by: find_child/find_descendant (optional filter), class_info (required), search_class (required)."},recursive:{type:"boolean",description:"If true, returns all descendants instead of just immediate children. Used by: children. Default: false."},maxDepth:{type:"number",description:"Maximum depth for recursive traversal. Used by: children (default: 10), file_tree (default: 5)."},timeout:{type:"number",description:"Maximum time to wait in seconds. Used by: wait_for_child. Default: 5. Maximum: 30."},root:{type:"string",description:'Root path to search/scan from. Used by: search_name, search_class, search_property, search_tag, file_tree, project_structure. Default: "game".'},query:{type:"string",description:"Search pattern for name search (supports * and ? wildcards). Used by: search_name."},propertyName:{type:"string",description:"[PRO] Property name to search by. Used by: search_property."},propertyValue:{description:"[PRO] Property value to match. Used by: search_property."},tag:{type:"string",description:"[PRO] Tag string to search by (case-sensitive). Used by: search_tag."},includeServices:{type:"boolean",description:'[PRO] Include Roblox services when root is "game". Used by: file_tree. Default: true.'},includeSubclasses:{type:"boolean",description:"Include subclasses in class search (e.g., BasePart finds Part, MeshPart). Used by: search_class. Default: true."},caseSensitive:{type:"boolean",description:"Case-sensitive name search. Used by: search_name. Default: false."},maxResults:{type:"number",description:"Maximum results to return. Used by: search_name, search_class, search_property, search_tag, descendants. Default: 100."},depth:{type:"number",description:"[PRO] Maximum depth for project structure traversal. Used by: project_structure. Default: 3."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"get"}}},then:{required:["path"]}},{if:{properties:{action:{const:"children"}}},then:{required:["path"]}},{if:{properties:{action:{const:"find_child"}}},then:{required:["path","childName"]}},{if:{properties:{action:{const:"find_descendant"}}},then:{required:["path","descendantName"]}},{if:{properties:{action:{const:"wait_for_child"}}},then:{required:["path","childName"]}},{if:{properties:{action:{const:"class_info"}}},then:{required:["className"]}},{if:{properties:{action:{const:"search_name"}}},then:{required:["query"]}},{if:{properties:{action:{const:"search_class"}}},then:{required:["className"]}},{if:{properties:{action:{const:"search_property"}}},then:{required:["propertyName"]}},{if:{properties:{action:{const:"search_tag"}}},then:{required:["tag"]}},{if:{properties:{action:{const:"descendants"}}},then:{required:["path"]}},{if:{properties:{action:{const:"ancestors"}}},then:{required:["path"]}}],required:["action"]}};var hk={name:"mutate_instances",description:"Create, delete, clone, move, rename, or pivot instances. [PRO] create_tree, mass_create, mass_delete, mass_duplicate, smart_duplicate, scatter.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","create_with_props","delete","clone","move","rename","pivot","create_tree","mass_create","mass_delete","mass_duplicate","smart_duplicate","scatter"],description:"Mutation action. Basic: create, create_with_props, delete, clone, move, rename, pivot. [PRO]: create_tree, mass_create, mass_delete, mass_duplicate, smart_duplicate, scatter."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},className:{type:"string",description:"Roblox class name (e.g., Part, Script, Folder). Used by: create, create_with_props."},parent:{type:"string",description:"Parent path for new instance. Used by: create, create_with_props."},name:{type:"string",description:"Name for the instance. Used by: create (optional), create_with_props (required)."},properties:{type:"object",description:"Properties to set on the instance. Supports Vector3, Color3, CFrame, UDim2, Enum types. Used by: create (optional), create_with_props (required).",additionalProperties:!0},path:{type:"string",description:"Instance path to operate on. Used by: delete, clone (as sourcePath), move, rename, pivot, smart_duplicate."},sessionDebugId:{type:"string",description:"Optional same Studio/plugin session debug identity for verifying a duplicate-named target. Used by: delete, clone, move, rename, pivot, smart_duplicate."},siblingIndex:{type:"number",description:"Optional 1-based same-name sibling index fallback for verifying a duplicate-named target. Used by: delete, clone, move, rename, pivot, smart_duplicate."},sourcePath:{type:"string",description:"Source instance path to clone from. Used by: clone. Alternative to path."},targetParent:{type:"string",description:"Target parent for cloned/duplicated instances. Used by: clone, mass_duplicate, smart_duplicate."},newName:{type:"string",description:"New name for instance. Used by: rename (required), clone (optional)."},newParent:{type:"string",description:"New parent path to move instance to. Used by: move."},position:{type:"object",description:"Target position as Vector3 {x, y, z}. Used by: pivot.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},cframe:{type:"array",description:"Target CFrame as 12-number array [x, y, z, r00, r01, r02, r10, r11, r12, r20, r21, r22]. Used by: pivot.",minItems:12,maxItems:12,items:{type:"number"}},offset:{type:"object",description:"Relative offset to move by (ignores position/cframe). Used by: pivot, smart_duplicate.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},tree:{type:"object",description:"[PRO] Instance tree specification for hierarchical creation. Used by: create_tree.",additionalProperties:!0},instances:{type:"array",description:"[PRO] Array of instance specifications for batch creation. Used by: mass_create. Each item: {className, name, parentPath, properties?}.",items:{type:"object",required:["className","name","parentPath"],properties:{className:{type:"string"},name:{type:"string"},parentPath:{type:"string"},properties:{type:"object",additionalProperties:!0}}}},paths:{type:"array",description:"[PRO] Array of instance paths. Used by: mass_delete, mass_duplicate.",items:{type:"string"}},count:{type:"number",description:"[PRO] Number of copies to create. Used by: smart_duplicate, scatter."},templatePaths:{type:"array",description:"Template instance paths to clone. Used by: scatter. Multiple templates are picked uniformly at random.",items:{type:"string"}},region:{type:"object",description:"Placement region {min, max} in world studs (XZ used for sampling, Y bounds the ground raycast). Used by: scatter.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},seed:{type:"number",description:"Deterministic placement seed. Used by: scatter."},maxSlope:{type:"number",description:"Maximum ground slope in degrees for placement. Used by: scatter. Default: 30."},avoidWater:{type:"boolean",description:"Skip points whose ground is Water. Used by: scatter. Default: true."},alignToNormal:{type:"boolean",description:"Align instances to the surface normal (yaw jitter always applies). Used by: scatter. Default: false."},scaleJitter:{type:"object",description:"Uniform scale jitter range. Used by: scatter. Default: {min: 0.85, max: 1.25}.",properties:{min:{type:"number"},max:{type:"number"}}},minSpacing:{type:"number",description:"Minimum distance between placements in studs. Used by: scatter."},parentName:{type:"string",description:"Folder name that groups the results. Used by: scatter. Default: WeppyScatter_<seed>."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"create"}}},then:{required:["className","parent"]}},{if:{properties:{action:{const:"create_with_props"}}},then:{required:["className","parent","name","properties"]}},{if:{properties:{action:{const:"delete"}}},then:{required:["path"]}},{if:{properties:{action:{const:"clone"}}},then:{required:["sourcePath"]}},{if:{properties:{action:{const:"move"}}},then:{required:["path","newParent"]}},{if:{properties:{action:{const:"rename"}}},then:{required:["path","newName"]}},{if:{properties:{action:{const:"pivot"}}},then:{required:["path"]}},{if:{properties:{action:{const:"create_tree"}}},then:{required:["parent","tree"]}},{if:{properties:{action:{const:"mass_create"}}},then:{required:["instances"]}},{if:{properties:{action:{const:"mass_delete"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"mass_duplicate"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"smart_duplicate"}}},then:{required:["path","offset"]}},{if:{properties:{action:{const:"scatter"}}},then:{required:["templatePaths","region","count"]}}],required:["action"]}};var yk={name:"manage_properties",description:"Get/set properties, attributes, and tags on instances. [PRO] set_calculated, set_relative, mass_set, mass_get, modify_children.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["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"],description:"Property action. Basic: 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. [PRO]: set_calculated, set_relative, mass_set, mass_get, modify_children."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Instance path. Used by: get, set, get_all, set_multiple, get_attr, set_attr, get_all_attrs, delete_attr, add_tag, remove_tag, check_tag, get_tags, set_calculated, set_relative."},property:{type:"string",description:'Property name (e.g., "Size", "Position", "Anchored"). Used by: get, set.'},value:{description:"Value to set. Supports primitives, Vector3 {x,y,z}, Color3 {r,g,b} (0-255), CFrame (12-number array), UDim2 {xScale,xOffset,yScale,yOffset}, Enum strings. Used by: set, set_attr, set_relative."},properties:{type:"object",description:"Dictionary of property names to values. Used by: set_multiple.",additionalProperties:!0},attribute:{type:"string",description:"Attribute name. Used by: get_attr, set_attr, delete_attr."},tag:{type:"string",description:"Tag string (case-sensitive). Used by: add_tag, remove_tag, check_tag."},tagName:{type:"string",description:"Tag to search for. Used by: get_tagged."},root:{type:"string",description:"Root path to filter get_tagged results. Used by: get_tagged."},maxResults:{type:"number",description:"Maximum results for get_tagged. Default: 100."},expression:{type:"string",description:'[PRO] Mathematical expression to evaluate. Used by: set_calculated. Example: "baseValue * multiplier".'},variables:{type:"object",description:'[PRO] Variable name to value/path mapping. Used by: set_calculated. Example: {"baseValue": "workspace.Config.BaseValue", "multiplier": 2}.',additionalProperties:!0},operation:{type:"string",description:"[PRO] Mathematical operation for relative property change. Used by: set_relative.",enum:["add","subtract","multiply","divide"]},amount:{description:"[PRO] Value for relative operation. Can be number, Vector3, etc. Used by: set_relative. Alias for value in set_relative context."},paths:{type:"array",description:"[PRO] Array of instance paths for bulk operations. Used by: mass_set, mass_get.",items:{type:"string"}},parentPath:{type:"string",description:"[PRO] Parent path whose children will be modified. Used by: modify_children."},modifications:{type:"object",description:"[PRO] Properties to set on children. Used by: modify_children. Contains propertyName, propertyValue, filter, recursive.",properties:{propertyName:{type:"string",description:"Property name to set on all children."},propertyValue:{description:"Value to set on all children."},filter:{type:"string",description:"Optional class name filter for children."},recursive:{type:"boolean",description:"If true, modifies all descendants. Default: false."}}},propertyName:{type:"string",description:"[PRO] Property name for mass operations or set_calculated/set_relative. Used by: mass_set, mass_get, set_calculated, set_relative, modify_children."},propertyValue:{description:"[PRO] Property value for mass_set and modify_children."},filter:{type:"string",description:"[PRO] Class name filter for modify_children."},recursive:{type:"boolean",description:"[PRO] Modify all descendants, not just immediate children. Used by: modify_children. Default: false."},includeReadOnly:{type:"boolean",description:"Include read-only properties. Used by: get_all. Default: false."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"get"}}},then:{required:["path","property"]}},{if:{properties:{action:{const:"set"}}},then:{required:["path","property","value"]}},{if:{properties:{action:{const:"get_all"}}},then:{required:["path"]}},{if:{properties:{action:{const:"set_multiple"}}},then:{required:["path","properties"]}},{if:{properties:{action:{const:"get_attr"}}},then:{required:["path","attribute"]}},{if:{properties:{action:{const:"set_attr"}}},then:{required:["path","value","attribute"]}},{if:{properties:{action:{const:"get_all_attrs"}}},then:{required:["path"]}},{if:{properties:{action:{const:"delete_attr"}}},then:{required:["path","attribute"]}},{if:{properties:{action:{const:"add_tag"}}},then:{required:["path","tag"]}},{if:{properties:{action:{const:"remove_tag"}}},then:{required:["path","tag"]}},{if:{properties:{action:{const:"check_tag"}}},then:{required:["path","tag"]}},{if:{properties:{action:{const:"get_tags"}}},then:{required:["path"]}},{if:{properties:{action:{const:"get_tagged"}}},then:{required:["tagName"]}},{if:{properties:{action:{const:"set_calculated"}}},then:{required:["path","expression","propertyName"]}},{if:{properties:{action:{const:"set_relative"}}},then:{required:["path","operation","propertyName"]}},{if:{properties:{action:{const:"mass_set"}}},then:{required:["paths","propertyName","propertyValue"]}},{if:{properties:{action:{const:"mass_get"}}},then:{required:["paths","propertyName"]}},{if:{properties:{action:{const:"modify_children"}}},then:{required:["parentPath"]}}],required:["action"]}};var vk={name:"manage_scripts",description:"Manage script source code: read, write, create, delete, edit lines, search. [PRO] replace across scripts.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get_source","set_source","create","delete","edit_replace","edit_insert","edit_delete","search","replace","get_dependencies"],description:"Script action. Basic: get_source, set_source, create, delete, edit_replace, edit_insert, edit_delete, search, get_dependencies. [PRO]: replace."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the script instance. Used by: get_source, set_source, delete, edit_replace, edit_insert, edit_delete, search, get_dependencies, replace."},source:{type:"string",description:"Script source code. Used by: set_source (required), create (optional initial source)."},scriptType:{type:"string",description:"Type of script to create. Used by: create.",enum:["Script","LocalScript","ModuleScript"]},parent:{type:"string",description:"Parent path for new script. Used by: create."},name:{type:"string",description:"Name for new script. Used by: create."},startLine:{type:"number",description:"Starting line number, 1-based inclusive. Used by: edit_replace, edit_delete."},endLine:{type:"number",description:"Ending line number, 1-based inclusive. Used by: edit_replace, edit_delete."},newLines:{type:"string",description:"New content to replace specified lines. Used by: edit_replace. Can be multi-line."},lines:{type:"string",description:"Content to insert after afterLine. Used by: edit_insert. Can be multi-line. Alias for content."},afterLine:{type:"number",description:"Line number after which to insert. Used by: edit_insert. Use 0 to insert at beginning."},content:{type:"string",description:"Content to insert. Used by: edit_insert. Can be multi-line."},pattern:{type:"string",description:"Search pattern (plain text or Lua pattern). Used by: search, replace."},replacement:{type:"string",description:"[PRO] Replacement text. Used by: replace."},caseSensitive:{type:"boolean",description:"Case-sensitive search. Used by: search. Default: false."},wholeWord:{type:"boolean",description:"Match whole words only. Used by: search. Default: false."},usePattern:{type:"boolean",description:"Treat pattern as Lua pattern instead of plain text. Used by: search, replace. Default: false."},dryRun:{type:"boolean",description:"[PRO] Show what would be replaced without making changes. Used by: replace. Default: false."},maxResults:{type:"number",description:"Maximum results to return. Used by: search. Default: 100."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"get_source"}}},then:{required:["path"]}},{if:{properties:{action:{const:"set_source"}}},then:{required:["path","source"]}},{if:{properties:{action:{const:"create"}}},then:{required:["scriptType","parent"]}},{if:{properties:{action:{const:"delete"}}},then:{required:["path"]}},{if:{properties:{action:{const:"edit_replace"}}},then:{required:["path","startLine","endLine","newLines"]}},{if:{properties:{action:{const:"edit_insert"}}},then:{required:["path","afterLine","content"]}},{if:{properties:{action:{const:"edit_delete"}}},then:{required:["path","startLine","endLine"]}},{if:{properties:{action:{const:"search"}}},then:{required:["path","pattern"]}},{if:{properties:{action:{const:"replace"}}},then:{required:["path","pattern","replacement"]}},{if:{properties:{action:{const:"get_dependencies"}}},then:{required:["path"]}}],required:["action"]}};var bk={name:"manage_ui",description:"Create / update / verify Roblox in-game UI (ScreenGui / Frame / TextLabel / \u2026). Always start a new UI task with the `design_brief` action \u2014 it accepts an omitted or partial brief, inspects Studio context, then returns a current-state summary, recommended mode/change scopes, candidate brief patches, and one user-facing confirmation or clarification question. design_brief may return asset recommendation candidates from existing UI images, user references, or conservative manage_assets.search results; do not use a recommended asset until the user accepts it. Do not dump enum lists at the user; map natural language to internal purpose/platform/tone values through recommendations, and only finalize identity-defining fields after the user accepts a recommendation or provides equivalent intent. Read MCP resource `weppy://ui-studio/guide` for the full guide; it is split into Floor (non-negotiable accessibility), Vocabulary (style menu \u2014 pick ONE family per dimension; do not blend everything), Direction (brief \u2192 choices), and Tree encoding (Roblox property JSON shapes). Floor essentials suggested by Design Check (`check`): (1) mobile touch target \u2265 44 px (2) text contrast \u2265 4.5:1 (3) prefer explicit `TextSize` over `TextScaled` (4) respect platform safe zones (5) warn on full-screen opaque roots for non-modal purposes. Style is brief-driven; reject the default AI look (uniform 8 px corners + generic blue + glass card + Gotham everywhere) \u2014 each game deserves its own visual identity.\n",inputSchema:{type:"object",properties:{action:{type:"string",enum:["design_brief","create_tree","update","delete","preview","check"],description:`UI action. [PRO]: design_brief, create_tree, update, delete, preview, check. (M2+\uC5D0\uC11C propose_layout/apply_asset \uCD94\uAC00 \uC608\uC815.)
|
|
132
132
|
`},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},brief:{type:"object",description:"\uC644\uC131 \uB610\uB294 \uBD80\uBD84 design_brief \uAD6C\uC870\uCCB4. Used by: design_brief (optional; partial allowed).",properties:{purpose:{type:"string",enum:["button","HUD","menu","modal","toast","card","form"]},platform:{type:"string",enum:["mobile","desktop","console","all"]},tone:{type:"string",enum:["modern","retro","casual","dark","minimalist","playful"]},reference_assets:{type:"array",description:"User-provided reference images or Roblox asset IDs. User references outrank existing UI images and Creator Store search candidates in the asset recommendation gate.",items:{type:"object",required:["type","value"],properties:{type:{type:"string",enum:["rbxassetid","image_url"]},value:{type:"string"}}}},resolution_targets:{type:"object",properties:{primary:{type:"string",enum:["1080p","720p","1440p"]},safezone:{type:"string",enum:["tv90","mobile_notch","none"]}}},color_palette:{type:"object",description:'source="tokens"\uC774\uBA74 tokens_ref\uB9CC \uC0AC\uC6A9, source="custom"\uC774\uBA74 custom\uB9CC \uC0AC\uC6A9. \uC11C\uBC84\uB294 source \uAE30\uC900 \uD55C\uCABD\uB9CC \uCC44\uD0DD.',properties:{source:{type:"string",enum:["tokens","custom"]},tokens_ref:{type:"string",description:"Key under `palettes` in `weppy://ui-studio/tokens` (e.g. modern_dark, brutalist_concrete, cottagecore_warm). Read tokens for the full menu and each palette's mood / pairs_with / avoid_for metadata before choosing."},custom:{type:"object",additionalProperties:{type:"string"}}}},accessibility:{type:"object",properties:{min_text_size:{type:"number"},contrast_ratio:{type:"number"}}}}},briefId:{type:"string",description:"design_brief \uAC00 \uBC18\uD658\uD55C brief \uC2DD\uBCC4\uC790. Used by: create_tree, update, delete (optional)."},tree:{type:"object",description:`UI \uD2B8\uB9AC \uC120\uC5B8\uD615 JSON. \uB8E8\uD2B8\uB294 ScreenGui.
|
|
133
133
|
\uC2A4\uD0A4\uB9C8: {className: string, name?: string, parent?: string, properties?: {...}, children?: Tree[]}
|
|
134
134
|
parent \uC0DD\uB7B5 \uC2DC StarterGui. className\uC740 Roblox GUI \uACC4\uC5F4(ScreenGui/Frame/TextLabel/TextButton/ImageLabel/ImageButton/ScrollingFrame/TextBox/UIListLayout/UIGridLayout/UIPadding/UICorner/UIStroke/UIAspectRatioConstraint/UIGradient/UITextSizeConstraint/UISizeConstraint) \uD55C\uC815.
|
|
@@ -138,7 +138,7 @@ ScreenGui > Frame(BackgroundTransparency=1) > \uC2E4\uC81C UI \uC694\uC18C. Scre
|
|
|
138
138
|
|
|
139
139
|
Property \uAC12 \uC778\uCF54\uB529:
|
|
140
140
|
UDim2\uB294 {xScale, xOffset, yScale, yOffset}, UDim\uC740 {scale, offset}, Color3\uB294 {r, g, b}, Vector2/Vector3\uB294 {x,y}/{x,y,z}, Enum\uC740 item name string\uC744 \uC0AC\uC6A9\uD55C\uB2E4.
|
|
141
|
-
`},targetPath:{type:"string",description:"Path to existing UI instance. Both `StarterGui.MyGui` and `game.StarterGui.MyGui` are accepted. Used by: update, delete (required)."},changes:{type:"object",description:"\uBD80\uBD84 \uBCC0\uACBD \uC2A4\uD399. {properties?: {...}, addChildren?: Tree[], removeChildren?: [string]}\nproperties\uB294 `Instance:SetPropertyValue` \uD638\uD658 \uD0A4\xB7\uAC12 \uC30D. \uAC12 \uC778\uCF54\uB529\uC740 tree \uC124\uBA85\uC758 Property \uAC12 \uC778\uCF54\uB529\uC744 \uB530\uB978\uB2E4.\n"},includeVisualAnalysis:{type:"boolean",description:"Opt-in only. Used by: check. When true, the server may read a saved preview snapshot PNG + visible GUI metadata and merge AI visual suggestions into check_results. Default false; no screenshot capture is triggered by check."},snapshotId:{type:"string",description:"Saved manage_ui.preview snapshot_id to use for visual analysis. Used by: check when includeVisualAnalysis=true. If omitted, the latest compatible saved snapshot is used when available."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"create_tree"}}},then:{required:["tree"]}},{if:{properties:{action:{const:"update"}}},then:{required:["targetPath","changes"]}},{if:{properties:{action:{const:"delete"}}},then:{required:["targetPath"]}}],required:["action"]}};var xk={name:"manage_lighting",description:"[PRO] Configure environment: lighting, atmosphere, sky, terrain properties, time of day.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["lighting","atmosphere","sky","terrain_props","time"],description:"[PRO] Environment action. lighting: set Lighting service properties. atmosphere: set Atmosphere properties. sky: set Sky properties. terrain_props: set Terrain water/visual properties. time: set time of day."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},properties:{type:"object",description:"Dictionary of properties to set. Used by: lighting, atmosphere, sky, terrain_props. Supports Color3 {r,g,b} (0-255), numbers, booleans, Enum strings.",additionalProperties:!0},createIfMissing:{type:"boolean",description:"Create Atmosphere/Sky instance if missing. Used by: atmosphere, sky. Default: true."},time:{type:"string",description:'Time string in "HH:MM:SS" format (e.g., "14:30:00"). Used by: time. Provide this OR clockTime.'},clockTime:{type:"number",description:"Numeric time in 24-hour format (e.g., 14.5 for 2:30 PM). Used by: time. Provide this OR time."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var _k={name:"manage_selection",description:"Get, set, or clear selection. [PRO] context, details, add/remove items, watch changes.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set","clear","cached","context","details","add","remove","watch"],description:"Selection action. Basic: get (current selection), set (replace selection), clear (deselect all), cached (from cache without round-trip). [PRO]: context (detailed with source/properties), details (hierarchical with ancestors/descendants), add (add to selection), remove (remove from selection), watch (monitor changes)."},paths:{type:"array",description:"Array of instance paths. Used by: set (required), add (required), remove (required).",items:{type:"string"}},maxAge:{type:"number",description:"Maximum age of cached data in milliseconds. Used by: cached. Default: 30000. Set to 0 for any age."},maxDepth:{type:"number",description:"[PRO] Maximum depth for descendant tree traversal. Used by: details. Default: 1."},includeSource:{type:"boolean",description:"[PRO] Include script source code. Used by: context. Default: true."},includeProperties:{type:"boolean",description:"[PRO] Include all readable properties. Used by: context. Default: true."},includeChildren:{type:"boolean",description:"[PRO] Include immediate children. Used by: context. Default: false."},includeAncestors:{type:"boolean",description:"[PRO] Include full ancestor chain. Used by: details. Default: false."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"set"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"add"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"remove"}}},then:{required:["paths"]}}],required:["action"]}};var Sk={name:"manage_camera",description:"Camera operations: get info, focus on instance/position, suggest view, capture Edit-mode viewport screenshot (Edit mode only; not usable during playtest).",inputSchema:{type:"object",properties:{action:{type:"string",enum:["info","focus_path","focus_position","suggest","screenshot"],description:'Camera action. info: get current camera position, rotation, FOV, viewport size. focus_path: move camera to focus on instance by path. focus_position: move camera to focus on world position. suggest: get suggested camera view for a target. [PRO] screenshot: **EDIT MODE ONLY \u2014 DO NOT call while a playtest is active.** Captures the current Studio Edit-mode viewport as a PNG image (returns MCP image content). If you are uncertain whether a playtest is running, call manage_studio.play_status first and only proceed when state == "edit"; otherwise the call returns an error. Requires "Allow Mesh / Image APIs" Studio setting (Game Settings > Security). Resolution capped by plugin setting screenshotMaxDimension (default 1024px on longest side; kept at full resolution by Claude while reducing token cost ~40% vs 1280). Play-mode capture is not supported in v1 because Roblox platform blocks converting CaptureService temporary contentId into EditableImage from any non-edit-DM context.'},path:{type:"string",description:"Instance path to focus on. Used by: focus_path (if not provided, focuses on selection), suggest (if not provided, uses selection)."},position:{type:"object",description:"World position to focus on as Vector3. Used by: focus_position (required).",required:["x","y","z"],properties:{x:{type:"number",description:"X coordinate"},y:{type:"number",description:"Y coordinate"},z:{type:"number",description:"Z coordinate"}}},distance:{type:"number",description:"Distance from target in studs. Used by: focus_path, focus_position. Auto-calculated if not provided."},duration:{type:"number",description:"Animation duration in seconds. Used by: focus_path, focus_position. Default: 0.5."},offset:{type:"object",description:"Camera offset direction from target (normalized and scaled by distance). Used by: focus_path, focus_position. Default: {x:1, y:0.5, z:1}.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},lookAt:{type:"object",description:"Point for camera to look at. Used by: focus_position.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},respectAutoFocusSetting:{type:"boolean",description:"If true, only focus when plugin Auto Focus setting is enabled. Used by: focus_path, focus_position. Default: false."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"focus_position"}}},then:{required:["position"]}}],required:["action"]}};var wk={name:"manage_tween",description:"[PRO] Tween service: create, play, pause, cancel tweens for smooth animations.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","play","pause","cancel"],description:"[PRO] Tween action. create: create a new tween with target properties. play: play a created tween. pause: pause a running tween. cancel: cancel a tween."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Instance path to tween. Used by: create (required)."},tweenInfo:{type:"object",description:"Tween configuration. Used by: create.",properties:{time:{type:"number",description:"Duration in seconds. Default: 1."},easingStyle:{type:"string",description:'Easing style (e.g., "Linear", "Quad", "Cubic", "Sine", "Bounce", "Elastic"). Default: "Quad".'},easingDirection:{type:"string",description:'Easing direction. Default: "Out".',enum:["In","Out","InOut"]},repeatCount:{type:"number",description:"Number of times to repeat. -1 for infinite. Default: 0."},reverses:{type:"boolean",description:"Whether the tween reverses on each repeat. Default: false."},delayTime:{type:"number",description:"Delay before tween starts in seconds. Default: 0."}}},properties:{type:"object",description:"Target property values to tween to. Used by: create. Supports Vector3, Color3, numbers, etc.",additionalProperties:!0},tweenId:{type:"string",description:"Tween identifier returned by create. Used by: play, pause, cancel."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"create"}}},then:{required:["path"]}}],required:["action"]}};var Ck={name:"manage_audio",description:"[PRO] Audio management: play, stop, pause, resume sounds. Set audio listener.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["play","stop","pause","resume","set_listener"],description:"[PRO] Audio action. play: play a sound (creates Sound if needed). stop: stop a playing sound. pause: pause a playing sound. resume: resume a paused sound. set_listener: set the audio listener type/target."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the Sound instance or parent to create Sound in. Used by: play, stop, pause, resume."},soundId:{type:"string",description:'Roblox sound asset ID (e.g., "rbxassetid://1234567"). Used by: play (if creating a new Sound).'},volume:{type:"number",description:"Sound volume (0-10). Used by: play. Default: 0.5."},looped:{type:"boolean",description:"Whether the sound loops. Used by: play. Default: false."},playbackSpeed:{type:"number",description:"Playback speed multiplier. Used by: play. Default: 1."},listenerType:{type:"string",description:"Listener type for SoundService. Used by: set_listener.",enum:["Camera","CFrame","ObjectPosition","ObjectCFrame"]},listenerPath:{type:"string",description:"Instance path for ObjectPosition/ObjectCFrame listener type. Used by: set_listener."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Ik={name:"manage_animation",description:"[PRO] Animation: load, play, stop animations. Get animation tracks from humanoid/controller.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["load","play","stop","get_tracks"],description:"[PRO] Animation action. load: load an animation on a Humanoid/AnimationController. play: play a loaded animation track. stop: stop a playing animation. get_tracks: list all loaded animation tracks."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the Humanoid, AnimationController, or Model containing one. Used by: load, play, stop, get_tracks."},animationId:{type:"string",description:'Roblox animation asset ID (e.g., "rbxassetid://1234567"). Used by: load.'},trackId:{type:"string",description:"Animation track identifier returned by load. Used by: play (required), stop (required)."},speed:{type:"number",description:"Playback speed multiplier. Used by: play. Default: 1."},fadeTime:{type:"number",description:"Fade time in seconds when starting/stopping. Used by: play, stop. Default: 0.1."},weight:{type:"number",description:"Animation weight (0-1) for blending. Used by: play. Default: 1."},priority:{type:"string",description:"Animation priority. Used by: play.",enum:["Core","Idle","Movement","Action","Action2","Action3","Action4"]},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"play"}}},then:{required:["trackId"]}},{if:{properties:{action:{const:"stop"}}},then:{required:["trackId"]}}],required:["action"]}};var kk={name:"manage_physics",description:"[PRO] Physics collision groups: register, set collidable between groups, list groups.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["register_group","set_collidable","get_groups"],description:"[PRO] Physics action. register_group: register a new collision group with PhysicsService. set_collidable: set whether two groups can collide. get_groups: list all registered collision groups."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},groupName:{type:"string",description:"Collision group name. Used by: register_group (required)."},group1:{type:"string",description:"First collision group name. Used by: set_collidable (required)."},group2:{type:"string",description:"Second collision group name. Used by: set_collidable (required)."},collidable:{type:"boolean",description:"Whether the two groups can collide. Used by: set_collidable (required)."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"register_group"}}},then:{required:["groupName"]}},{if:{properties:{action:{const:"set_collidable"}}},then:{required:["group1","group2","collidable"]}}],required:["action"]}};var Pk={name:"manage_effects",description:"[PRO] Particle effects: emit particles, clear all particles, toggle effect enabled state.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["emit","clear","toggle"],description:"[PRO] Effects action. emit: emit a burst of particles from a ParticleEmitter. clear: clear all particles from a ParticleEmitter or all emitters under an instance. toggle: enable or disable a ParticleEmitter, Beam, Trail, or other effect."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the effect instance (ParticleEmitter, Beam, Trail) or parent containing effects. Used by: emit, clear, toggle."},count:{type:"number",description:"Number of particles to emit in a burst. Used by: emit. Default: 16."},enabled:{type:"boolean",description:"Enable or disable the effect. Used by: toggle."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Rk={name:"manage_terrain",description:"[PRO] Terrain operations: fill shapes, clear regions, replace materials, manage colors, read/write voxels, generate procedural terrain, smooth terrain.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["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"],description:"[PRO] Terrain action. fill_block/fill_ball/fill_cylinder/fill_wedge: fill shapes with material. clear_region/clear_bounds: clear terrain. replace_material: swap materials in region. colors_get/colors_set: manage material colors. read_voxel: single voxel. read_voxels/write_voxels: bulk voxels. generate: procedural terrain. smooth: smooth terrain."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},material:{type:"string",description:"Terrain material name (e.g., Grass, Rock, Water, Sand, Slate, Concrete). Used by: fill_*, replace_material, colors_get, colors_set."},center:{type:"object",description:"Center position as Vector3. Used by: fill_ball.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},position:{type:"object",description:"Position as Vector3. Used by: read_voxel.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},cframe:{type:"object",description:"Position and rotation for fill shapes. Used by: fill_block, fill_cylinder, fill_wedge.",required:["position"],properties:{position:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},rotation:{type:"object",description:"Optional rotation in degrees.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},size:{type:"object",description:"Size in studs. Used by: fill_block, fill_wedge.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},radius:{type:"number",description:"Radius in studs. Used by: fill_ball, fill_cylinder."},height:{type:"number",description:"Height in studs. Used by: fill_cylinder."},region:{type:"object",description:"Rectangular region with min/max corners. Used by: clear_region, replace_material, read_voxels, write_voxels, generate, smooth.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},min:{type:"object",description:"Minimum corner for bounds-based clear. Used by: clear_bounds.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",description:"Maximum corner for bounds-based clear. Used by: clear_bounds.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},sourceMaterial:{type:"string",description:"Material to replace. Used by: replace_material."},targetMaterial:{type:"string",description:"Replacement material. Used by: replace_material."},color:{type:"object",description:"RGB color (0-255). Used by: colors_set.",required:["r","g","b"],properties:{r:{type:"number",minimum:0,maximum:255},g:{type:"number",minimum:0,maximum:255},b:{type:"number",minimum:0,maximum:255}}},resolution:{type:"number",description:"Voxel resolution (studs per voxel). Used by: read_voxels, write_voxels. Default: 4."},materials:{type:"array",description:"3D array of material names [x][y][z]. Used by: write_voxels.",items:{type:"array",items:{type:"array",items:{type:"string"}}}},occupancy:{type:"array",description:"3D array of occupancy values [x][y][z] (0-1). Used by: write_voxels.",items:{type:"array",items:{type:"array",items:{type:"number",minimum:0,maximum:1}}}},baseHeight:{type:"number",description:"Base terrain height in studs. Used by: generate. Default: 32."},amplitude:{type:"number",description:"Height variation amplitude in studs. Used by: generate. Default: 24."},frequency:{type:"number",description:"Noise frequency (0.001-0.1). Used by: generate. Default: 0.01.",minimum:.001,maximum:.1},seed:{type:"number",description:"Random seed for terrain generation. Used by: generate."},layers:{type:"array",description:"Material layers by height. Used by: generate. Each: {material, maxHeight}.",items:{type:"object",required:["material","maxHeight"],properties:{material:{type:"string"},maxHeight:{type:"number"}}}},intensity:{type:"number",description:"Smoothing intensity (0-1). Used by: smooth. Default: 0.5.",minimum:0,maximum:1},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Ek={name:"spatial_query",description:"[PRO] Spatial queries: raycast, find ground, check placement, multi-raycast, scan area, find flat areas, find spawn positions, analyze walkable, spatial map, find empty space, get bounds, snap to grid, check collision.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["raycast","find_ground","check_placement","multi_raycast","scan_area","find_flat","find_spawn","analyze_walkable","spatial_map","find_space","bounds","snap_grid","collision"],description:"[PRO] Spatial action. raycast: single ray. find_ground: ground below point. check_placement: collision-free placement check. multi_raycast: batch rays. scan_area: heightmap generation. find_flat: flat areas for building. find_spawn: spawn positions. analyze_walkable: walkability grid. spatial_map: all BasePart positions. find_space: empty space for object. bounds: bounding box. snap_grid: snap position to grid. collision: AABB collision check."},origin:{type:"object",description:"Ray origin as Vector3. Used by: raycast.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},direction:{type:"object",description:"Ray direction and length as Vector3. Used by: raycast.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},maxDistance:{type:"number",description:"Maximum distance for ground search. Used by: find_ground. Default: 1000."},position:{type:"object",description:"Position as Vector3. Used by: find_ground (cast from here), check_placement (center), collision (hypothetical position).",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},size:{type:"object",description:"Size as Vector3. Used by: check_placement (object size), find_space (required space size), scan_area (area X/Z dimensions).",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},filterType:{type:"string",description:'Raycast filter type. Used by: raycast, multi_raycast. Default: "Exclude".',enum:["Exclude","Include"]},filterList:{type:"array",description:"Instance paths to filter. Used by: raycast, multi_raycast, find_ground, check_placement, scan_area. Alias: filterInstances.",items:{type:"string"}},filterInstances:{type:"array",description:"Instance paths to filter (alias for filterList). Used by: raycast, multi_raycast, find_ground, check_placement, scan_area.",items:{type:"string"}},ignoreWater:{type:"boolean",description:"Ignore terrain water. Used by: raycast, multi_raycast. Default: false."},rays:{type:"array",description:"Array of ray specifications. Used by: multi_raycast. Max 50 rays.",maxItems:50,items:{type:"object",required:["origin","direction"],properties:{origin:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},direction:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}}},center:{type:"object",description:"Center point for area scan. Used by: scan_area.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},area:{type:"object",description:"Bounding box for analysis. Used by: analyze_walkable. Contains min/max.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},searchArea:{type:"object",description:"Bounding box for search. Used by: find_flat, find_spawn, find_space.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},minSize:{type:"object",description:"Minimum flat area size. Used by: find_flat.",required:["x","z"],properties:{x:{type:"number"},z:{type:"number"}}},maxSlope:{type:"number",description:"Maximum slope in degrees. Used by: find_flat (default: 10), analyze_walkable (default: 45)."},resolution:{type:"number",description:"Grid resolution in studs. Used by: scan_area, analyze_walkable. Default: 4."},gridSize:{type:"number",description:"Grid snap size in studs. Used by: snap_grid (default: 4), find_space (default: 4)."},path:{type:"string",description:"Instance path. Used by: bounds (optional), snap_grid (required), collision (required), spatial_map (rootPath alias)."},paths:{type:"array",description:"Multiple instance paths for batch bounds. Used by: bounds.",items:{type:"string"}},tolerance:{type:"number",description:"Height variation tolerance in studs. Used by: find_flat."},gridSnap:{type:"number",description:"Grid snap size. Alias for gridSize."},axes:{type:"array",description:'Axes to snap. Used by: snap_grid. Default: ["x","y","z"]. Use ["x","z"] for horizontal only.',items:{type:"string",enum:["x","y","z"]}},ignorePaths:{type:"array",description:"Instance paths to ignore in collision check. Used by: collision.",items:{type:"string"}},offset:{type:"number",description:"Vertical offset for ground position. Used by: find_ground. Default: 0."},rotation:{type:"object",description:"Rotation in degrees. Used by: check_placement.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},checkGround:{type:"boolean",description:"Verify ground support for placement. Used by: check_placement. Default: true."},spawnSize:{type:"object",description:"Size of spawning entity. Used by: find_spawn. Default: {x:4, y:5, z:4}.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},minSpacing:{type:"number",description:"Minimum distance between spawn positions. Used by: find_spawn. Default: 10."},preferOutdoor:{type:"boolean",description:"Prefer open sky positions. Used by: find_spawn. Default: false."},count:{type:"number",description:"Number of results to find. Used by: find_spawn. Default: 10."},characterHeight:{type:"number",description:"Character height for clearance checks. Used by: analyze_walkable. Default: 5."},maxStepHeight:{type:"number",description:"Maximum step height. Used by: analyze_walkable. Default: 2."},rootPath:{type:"string",description:'Root path for spatial map scan. Used by: spatial_map. Default: "game.Workspace".'},includeModels:{type:"boolean",description:"Include Model bounding boxes. Used by: spatial_map. Default: true."},maxResults:{type:"number",description:"Maximum results. Used by: spatial_map (default: 500), scan_area (default: 500), find_flat (default: 10)."},padding:{type:"number",description:"Minimum distance from other objects. Used by: find_space. Default: 1."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"snap_grid"}}},then:{required:["path"]}},{if:{properties:{action:{const:"collision"}}},then:{required:["path"]}}],required:["action"]}};var Tk={name:"manage_assets",description:"[PRO] Asset management: insert models by ID, get asset info, search creator store, insert free models/packages, export selection JSON, generate/review Roblox models, round-trip .rbxm files through Asset Library, and generate local thumbnails.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["insert","info","search","search_insert","insert_free","insert_package","export_selection_json","export_selection_rbxm","export_path_rbxm","review_model","generate_model","upload_asset","import_rbxm","generate_thumbnail"],description:"[PRO] Asset action. insert: insert model by asset ID. info: get asset metadata. search: search Creator Store. search_insert: search and insert first match. insert_free: insert free model. insert_package: insert package. export_selection_json: JSON snapshot of current selection. export_selection_rbxm/export_path_rbxm: save Studio content to Asset Library .rbxm. review_model: QA a selected/path model and optionally register it in Asset Library. generate_model: generate a Roblox model in Studio via GenerationService only. upload_asset: upload the selected Studio asset through Studio-local AssetService with automatic Model/Mesh/Image type selection. import_rbxm: import Asset Library .rbxm into Studio. generate_thumbnail: create or replace thumbnail.png for an Asset Library .rbxm."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},assetId:{type:"number",description:"Roblox asset ID. Used by: insert (required), info (required), insert_free (required), insert_package (required)."},parent:{type:"string",description:'Parent path for inserted asset. Used by: insert, search_insert, insert_free, insert_package. Default: "game.Workspace".'},name:{type:"string",description:"Optional name for inserted instance."},position:{type:"object",description:"Position to place the model. Used by: insert, insert_free.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},query:{type:"string",description:'Search keyword. Used by: search (required), search_insert (required). E.g., "monster", "tree", "car".'},maxResults:{type:"number",description:"Maximum search results. Used by: search. Default: 10."},category:{type:"string",description:"Asset category filter. Used by: search, export_selection_rbxm, export_path_rbxm, review_model, generate_model, import_rbxm, generate_thumbnail. upload_asset may omit this and use assetType/selection auto-detection."},sortType:{type:"string",description:"Sort order for search results. Used by: search."},format:{type:"string",description:"Export format. Used by: export_selection_json."},includeProperties:{type:"boolean",description:"Include all properties in export. Used by: export_selection_json. Default: false."},includeChildren:{type:"boolean",description:"Include children in export. Used by: export_selection_json. Default: false."},maxDepth:{type:"number",description:"Maximum depth for recursive child export. Used by: export_selection_json. Default: 5."},scope:{type:"string",description:"Asset Library scope. Used by: export_selection_rbxm, export_path_rbxm, review_model, import_rbxm, generate_thumbnail. Default: place.",enum:["place","shared"]},placeId:{type:"number",description:"Place ID for place-scoped Asset Library .rbxm round-trip operations. For other manage_assets Studio/plugin actions, this also acts as an optional Studio target selector."},assetLibraryAssetId:{type:"string",description:"Asset Library asset ID. Used by: import_rbxm, generate_thumbnail."},targetParent:{type:"string",description:"Studio parent path for imported/generated instances. Used by: import_rbxm, generate_model. Default: game.Workspace."},sourcePath:{type:"string",description:"Studio instance path to export, review, or upload. Used by: export_path_rbxm, review_model, upload_asset."},displayName:{type:"string",description:"Asset Library display name or Studio upload display name. Used by: export_selection_rbxm, export_path_rbxm, review_model, generate_model, upload_asset."},description:{type:"string",description:"Asset Library description or Studio upload description. Used by: export_selection_rbxm, export_path_rbxm, review_model, upload_asset."},assetType:{type:"string",description:"Roblox Studio-local upload asset type. Used by: upload_asset. Default: auto, which selects Model/Mesh/Image from the selected Studio object.",enum:["auto","model","mesh","image"]},thumbnailMode:{type:"string",description:"Thumbnail capture mode. Used by: export_selection_rbxm, export_path_rbxm, review_model. Default: none.",enum:["none","auto"]},uploadMode:{type:"string",description:"Studio-local upload behavior for .rbxm registration actions. auto uploads the selected object as a Roblox Model asset first, model requires that path, embeddedResources uploads only generated Mesh/Image resources, and localOnly skips Roblox upload. Used by: export_selection_rbxm, export_path_rbxm, review_model. Default: localOnly.",enum:["auto","model","embeddedResources","localOnly"]},uploadTemporaryAssets:{type:"boolean",description:"Explicit user approval for Studio-local CreateAssetAsync uploads before .rbxm registration. Used by: export_selection_rbxm, export_path_rbxm, review_model. Default: false; set true only after user approval."},creatorType:{type:"string",description:"Optional Roblox creator type for Studio-local temporary asset upload. Used with uploadTemporaryAssets by .rbxm registration actions. Omit to use the logged-in Studio user.",enum:["user","group"]},creatorId:{type:"string",description:"Optional Roblox user or group ID for Studio-local temporary asset upload. Used with uploadTemporaryAssets by .rbxm registration actions."},prompt:{type:"string",description:"Text prompt for Roblox GenerationService model generation. Used by: generate_model."},schemaMode:{type:"string",description:"Generation schema mode. Used by: generate_model. Default: predefined.",enum:["predefined","custom"]},predefinedSchema:{type:"string",description:"Roblox predefined model schema. Used by: generate_model when schemaMode=predefined. Default: Body1.",enum:["Body1","Car5"]},schemaGroups:{type:"array",description:"Custom schema group names for generated model segmentation. Used by: generate_model when schemaMode=custom.",items:{type:"string"}},size:{type:"object",description:"Requested approximate generated model bounds in studs. Used by: generate_model.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},maxTriangles:{type:"number",description:"Maximum triangle budget requested from Roblox GenerationService. Used by: generate_model."},generateTextures:{type:"boolean",description:"Whether Roblox GenerationService should generate textures. Used by: generate_model. Default: true."},review:{type:"boolean",description:"Whether to run post-generation/review QA. Used by: generate_model. Default: true."},exportToLibrary:{type:"boolean",description:"Whether to register the reviewed model as an Asset Library .rbxm asset. Used by: review_model. Default: false."},expectedUse:{type:"string",description:"Expected model use for QA heuristics. Used by: review_model, generate_model. Default: unknown.",enum:["decorative","interactive","vehicle","character","unknown"]},expectedGroups:{type:"array",description:"Expected child/group names for generated or reviewed model QA. Used by: review_model, generate_model.",items:{type:"string"}},maxDescendants:{type:"number",description:"Maximum descendants to inspect during model QA. Used by: review_model, generate_model. Default: 500."},readiness:{type:"string",description:"Optional readiness gate for Asset Library registration decisions. Used by: review_model, generate_model.",enum:["ready","review","blocked"]},anchorMode:{type:"string",description:"How to anchor generated BaseParts before review/export. Used by: generate_model. Default: all.",enum:["none","all"]},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"insert"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"info"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"search"}}},then:{required:["query"]}},{if:{properties:{action:{const:"search_insert"}}},then:{required:["query"]}},{if:{properties:{action:{const:"insert_free"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"insert_package"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"export_selection_rbxm"}}},then:{required:["category"]}},{if:{properties:{action:{const:"export_path_rbxm"}}},then:{required:["category","sourcePath"]}},{if:{properties:{action:{const:"review_model"}}},then:{required:["category"]}},{if:{properties:{action:{const:"generate_model"}}},then:{required:["prompt"]}},{if:{properties:{action:{const:"import_rbxm"}}},then:{required:["category","assetLibraryAssetId"]}},{if:{properties:{action:{const:"generate_thumbnail"}}},then:{required:["category","assetLibraryAssetId"]}}],required:["action"]}};var Ak={name:"manage_open_cloud_assets",description:"[PRO] Roblox Open Cloud asset upload: credential status, category capabilities, upload local files, update assets, read metadata, and poll operation status. Does not expose delete/archive/restore actions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["credential_status","capabilities","upload","update","info","operation_status"],description:"[PRO] Open Cloud asset action. credential_status: check local API key status. capabilities: list supported upload categories. upload: create an asset from a local file. update: update an existing asset. info: read asset metadata. operation_status: check upload/update processing."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},assetId:{type:"string",description:"Roblox asset ID. Used by: update (required), info (required)."},operationId:{type:"string",description:"Roblox Open Cloud operation ID or operations/{id} path. Used by: operation_status."},filePath:{type:"string",description:"Local file path on the MCP server machine. Used by: upload, update."},category:{type:"string",description:"WEPPY asset category. Used by: upload, update.",enum:["image","decal","audio","mesh","model","video","animation"]},displayName:{type:"string",description:"Roblox asset display name. Used by: upload, update."},description:{type:"string",description:"Roblox asset description. Used by: upload, update."},creatorType:{type:"string",description:"Asset creator owner type. Used by: upload, update. Defaults to saved credential metadata when available.",enum:["user","group"]},creatorId:{type:"string",description:"User ID or group ID for the asset creator. Used by: upload, update. Defaults to saved credential metadata when available."},expectedPrice:{type:"number",description:"Expected upload fee in Robux. Used by: upload, update when Roblox requires an expected price."},readMask:{type:"array",description:"Asset metadata fields to retrieve. Used by: info.",items:{type:"string"}},updateMask:{type:"array",description:"Metadata fields to update. Used by: update.",items:{type:"string"}},waitForOperation:{type:"boolean",description:"When true, poll the returned Open Cloud operation until done or timeout. Used by: upload, update."},operationPollTimeoutMs:{type:"number",description:"Maximum operation polling time in milliseconds. Used by: upload, update when waitForOperation is true."},operationPollIntervalMs:{type:"number",description:"Operation polling interval in milliseconds. Used by: upload, update when waitForOperation is true."}},allOf:[{if:{properties:{action:{const:"upload"}}},then:{required:["filePath","category","displayName"]}},{if:{properties:{action:{const:"update"}}},then:{required:["assetId","category"]}},{if:{properties:{action:{const:"info"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"operation_status"}}},then:{required:["operationId"]}}],required:["action"]}};var $k={name:"manage_sync",description:"[PRO] Project sync management: status, history, direction settings, read/write synced files.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["status_current_place","history","directions","read_file","write_file","progress"],description:"[PRO] Sync action. status_current_place: get sync status for the current connected place. history: get change history. directions: get per-type sync directions. read_file: read a synced file. write_file: write to a synced file. progress: get real-time sync progress and bandwidth."},placeId:{type:"number",description:"Place ID for sync operations. Used by: history, directions, read_file, write_file."},instancePath:{type:"string",description:"Instance path for file read/write. Used by: read_file, write_file."},content:{type:"string",description:"File content to write. Used by: write_file."},query:{type:"object",description:"Query parameters for history. Used by: history.",properties:{limit:{type:"number",description:"Maximum entries to return."},offset:{type:"number",description:"Number of entries to skip."}}}},allOf:[{if:{properties:{action:{const:"read_file"}}},then:{required:["placeId","instancePath"]}},{if:{properties:{action:{const:"write_file"}}},then:{required:["placeId","instancePath","content"]}}],required:["action"]}};var Ok={name:"workspace_state",description:"[PRO] Workspace state: full sync, snapshot, recent changes, viewport info, clear history, metadata, scripts, selection info, clear cache.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["sync","snapshot","changes","viewport","clear_history","metadata","scripts","selection_info","clear_cache"],description:"[PRO] State action. sync: fetch current Workspace state (hierarchy, history, stats). snapshot: get full instance tree structure. changes: get recent changes (added/removed/modified). viewport: get camera position, FOV, viewport size, selection bounds. clear_history: clear change history. metadata: get workspace metadata. scripts: get script list. selection_info: get selection info. clear_cache: clear state cache."},includeMetadata:{type:"boolean",description:"Include metadata (instance counts, timestamps). Used by: sync. Default: true."},limit:{type:"number",description:"Maximum number of changes to return. Used by: changes. Default: 20."},includeCameraInfo:{type:"boolean",description:"Include camera position and settings. Used by: viewport. Default: true."},includeSelectionBounds:{type:"boolean",description:"Include current selection bounds info. Used by: viewport. Default: true."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Dk={name:"manage_logs",description:"Output logs: get filtered logs, poll incrementally with sinceSeq cursor, clear buffer, get recent errors.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","clear","errors"],description:"Log action. get: retrieve logs with optional level/limit/since/sinceSeq filters. clear: clear internal log buffer without resetting seq. errors: quick access to recent errors only."},level:{type:"string",description:'Log level filter. Used by: get. Default: "all".',enum:["all","error","warning","info"]},limit:{type:"number",description:"Maximum entries to return. Used by: get (default: 100, max: 500), errors (default: 20, max: 100)."},pattern:{type:"string",description:"Text pattern to filter log messages. Used by: get."},since:{type:"number",description:"Unix timestamp in milliseconds. Only logs after this time. Used by: get."},sinceSeq:{type:"number",description:"Return only logs after this sequence number. Cursor mode returns logs oldest-to-newest and includes lastSeq/oldestSeq/hasMore/cursorStatus. Used by: get."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Nk={name:"system_info",description:"System info: ping, connection status, usage tier. [PRO] place info, services list, studio settings.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["ping","connection","usage","place_info","services","studio_settings"],description:"System action. Basic: ping (test connection, returns pong), connection (server/plugin connection info with session IDs), usage (current tier: basic/pro). [PRO]: place_info (place ID, name, game ID, creator), services (list all Roblox services), studio_settings (Studio preferences)."},message:{type:"string",description:"Optional message to echo back. Used by: ping."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var jk={name:"manage_studio",description:`Control Roblox Studio state for playtest lifecycle, automated test runs, and editor view/rendering QA workflows. Use it for state-changing playtest controls and Studio session-level View settings such as UI preview; it does not edit game UI objects or their properties.
|
|
141
|
+
`},targetPath:{type:"string",description:"Path to existing UI instance. Both `StarterGui.MyGui` and `game.StarterGui.MyGui` are accepted. Used by: update, delete (required)."},changes:{type:"object",description:"\uBD80\uBD84 \uBCC0\uACBD \uC2A4\uD399. {properties?: {...}, addChildren?: Tree[], removeChildren?: [string]}\nproperties\uB294 `Instance:SetPropertyValue` \uD638\uD658 \uD0A4\xB7\uAC12 \uC30D. \uAC12 \uC778\uCF54\uB529\uC740 tree \uC124\uBA85\uC758 Property \uAC12 \uC778\uCF54\uB529\uC744 \uB530\uB978\uB2E4.\n"},includeVisualAnalysis:{type:"boolean",description:"Opt-in only. Used by: check. When true, the server may read a saved preview snapshot PNG + visible GUI metadata and merge AI visual suggestions into check_results. Default false; no screenshot capture is triggered by check."},snapshotId:{type:"string",description:"Saved manage_ui.preview snapshot_id to use for visual analysis. Used by: check when includeVisualAnalysis=true. If omitted, the latest compatible saved snapshot is used when available."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"create_tree"}}},then:{required:["tree"]}},{if:{properties:{action:{const:"update"}}},then:{required:["targetPath","changes"]}},{if:{properties:{action:{const:"delete"}}},then:{required:["targetPath"]}}],required:["action"]}};var xk={name:"manage_lighting",description:"[PRO] Configure environment: lighting, atmosphere, sky, terrain properties, time of day.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["lighting","atmosphere","sky","terrain_props","time","mood"],description:"[PRO] Environment action. lighting: set Lighting service properties. atmosphere: set Atmosphere properties. sky: set Sky properties. terrain_props: set Terrain water/visual properties. time: set time of day. mood: apply a full environment mood preset with overrides."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},properties:{type:"object",description:"Dictionary of properties to set. Used by: lighting, atmosphere, sky, terrain_props. Supports Color3 {r,g,b} (0-255), numbers, booleans, Enum strings.",additionalProperties:!0},createIfMissing:{type:"boolean",description:"Create Atmosphere/Sky instance if missing. Used by: atmosphere, sky. Default: true."},time:{type:"string",description:'Time string in "HH:MM:SS" format (e.g., "14:30:00"). Used by: time. Provide this OR clockTime.'},clockTime:{type:"number",description:"Numeric time in 24-hour format (e.g., 14.5 for 2:30 PM). Used by: time. Provide this OR time."},preset:{type:"string",description:"Environment mood preset. Used by: mood. Applies Lighting + Atmosphere + Sky + post effects + Terrain water appearance in one call.",enum:["sunny_day","golden_hour","sunset","dawn","night","moonlit_night","overcast","foggy","stormy","eerie"]},overrides:{type:"object",description:"Per-section property overrides applied on top of the preset. Used by: mood. Sections: lighting, atmosphere, sky, effects, water. Values follow the same conversion rules as the properties param.",properties:{lighting:{type:"object",additionalProperties:!0},atmosphere:{type:"object",additionalProperties:!0},sky:{type:"object",additionalProperties:!0},effects:{type:"object",additionalProperties:!0},water:{type:"object",additionalProperties:!0}}},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"mood"}}},then:{required:["preset"]}}],required:["action"]}};var _k={name:"manage_selection",description:"Get, set, or clear selection. [PRO] context, details, add/remove items, watch changes.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set","clear","cached","context","details","add","remove","watch"],description:"Selection action. Basic: get (current selection), set (replace selection), clear (deselect all), cached (from cache without round-trip). [PRO]: context (detailed with source/properties), details (hierarchical with ancestors/descendants), add (add to selection), remove (remove from selection), watch (monitor changes)."},paths:{type:"array",description:"Array of instance paths. Used by: set (required), add (required), remove (required).",items:{type:"string"}},maxAge:{type:"number",description:"Maximum age of cached data in milliseconds. Used by: cached. Default: 30000. Set to 0 for any age."},maxDepth:{type:"number",description:"[PRO] Maximum depth for descendant tree traversal. Used by: details. Default: 1."},includeSource:{type:"boolean",description:"[PRO] Include script source code. Used by: context. Default: true."},includeProperties:{type:"boolean",description:"[PRO] Include all readable properties. Used by: context. Default: true."},includeChildren:{type:"boolean",description:"[PRO] Include immediate children. Used by: context. Default: false."},includeAncestors:{type:"boolean",description:"[PRO] Include full ancestor chain. Used by: details. Default: false."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"set"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"add"}}},then:{required:["paths"]}},{if:{properties:{action:{const:"remove"}}},then:{required:["paths"]}}],required:["action"]}};var Sk={name:"manage_camera",description:"Camera operations: get info, focus on instance/position, suggest view, capture Edit-mode viewport screenshot (Edit mode only; not usable during playtest).",inputSchema:{type:"object",properties:{action:{type:"string",enum:["info","focus_path","focus_position","suggest","screenshot"],description:'Camera action. info: get current camera position, rotation, FOV, viewport size. focus_path: move camera to focus on instance by path. focus_position: move camera to focus on world position. suggest: get suggested camera view for a target. [PRO] screenshot: **EDIT MODE ONLY \u2014 DO NOT call while a playtest is active.** Captures the current Studio Edit-mode viewport as a PNG image (returns MCP image content). If you are uncertain whether a playtest is running, call manage_studio.play_status first and only proceed when state == "edit"; otherwise the call returns an error. Requires "Allow Mesh / Image APIs" Studio setting (Game Settings > Security). Resolution capped by plugin setting screenshotMaxDimension (default 1024px on longest side; kept at full resolution by Claude while reducing token cost ~40% vs 1280). Play-mode capture is not supported in v1 because Roblox platform blocks converting CaptureService temporary contentId into EditableImage from any non-edit-DM context.'},path:{type:"string",description:"Instance path to focus on. Used by: focus_path (if not provided, focuses on selection), suggest (if not provided, uses selection)."},position:{type:"object",description:"World position to focus on as Vector3. Used by: focus_position (required).",required:["x","y","z"],properties:{x:{type:"number",description:"X coordinate"},y:{type:"number",description:"Y coordinate"},z:{type:"number",description:"Z coordinate"}}},distance:{type:"number",description:"Distance from target in studs. Used by: focus_path, focus_position. Auto-calculated if not provided."},duration:{type:"number",description:"Animation duration in seconds. Used by: focus_path, focus_position. Default: 0.5."},offset:{type:"object",description:"Camera offset direction from target (normalized and scaled by distance). Used by: focus_path, focus_position. Default: {x:1, y:0.5, z:1}.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},lookAt:{type:"object",description:"Point for camera to look at. Used by: focus_position.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},respectAutoFocusSetting:{type:"boolean",description:"If true, only focus when plugin Auto Focus setting is enabled. Used by: focus_path, focus_position. Default: false."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"focus_position"}}},then:{required:["position"]}}],required:["action"]}};var wk={name:"manage_tween",description:"[PRO] Tween service: create, play, pause, cancel tweens for smooth animations.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","play","pause","cancel"],description:"[PRO] Tween action. create: create a new tween with target properties. play: play a created tween. pause: pause a running tween. cancel: cancel a tween."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Instance path to tween. Used by: create (required)."},tweenInfo:{type:"object",description:"Tween configuration. Used by: create.",properties:{time:{type:"number",description:"Duration in seconds. Default: 1."},easingStyle:{type:"string",description:'Easing style (e.g., "Linear", "Quad", "Cubic", "Sine", "Bounce", "Elastic"). Default: "Quad".'},easingDirection:{type:"string",description:'Easing direction. Default: "Out".',enum:["In","Out","InOut"]},repeatCount:{type:"number",description:"Number of times to repeat. -1 for infinite. Default: 0."},reverses:{type:"boolean",description:"Whether the tween reverses on each repeat. Default: false."},delayTime:{type:"number",description:"Delay before tween starts in seconds. Default: 0."}}},properties:{type:"object",description:"Target property values to tween to. Used by: create. Supports Vector3, Color3, numbers, etc.",additionalProperties:!0},tweenId:{type:"string",description:"Tween identifier returned by create. Used by: play, pause, cancel."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"create"}}},then:{required:["path"]}}],required:["action"]}};var Ck={name:"manage_audio",description:"[PRO] Audio management: play, stop, pause, resume sounds. Set audio listener.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["play","stop","pause","resume","set_listener"],description:"[PRO] Audio action. play: play a sound (creates Sound if needed). stop: stop a playing sound. pause: pause a playing sound. resume: resume a paused sound. set_listener: set the audio listener type/target."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the Sound instance or parent to create Sound in. Used by: play, stop, pause, resume."},soundId:{type:"string",description:'Roblox sound asset ID (e.g., "rbxassetid://1234567"). Used by: play (if creating a new Sound).'},volume:{type:"number",description:"Sound volume (0-10). Used by: play. Default: 0.5."},looped:{type:"boolean",description:"Whether the sound loops. Used by: play. Default: false."},playbackSpeed:{type:"number",description:"Playback speed multiplier. Used by: play. Default: 1."},listenerType:{type:"string",description:"Listener type for SoundService. Used by: set_listener.",enum:["Camera","CFrame","ObjectPosition","ObjectCFrame"]},listenerPath:{type:"string",description:"Instance path for ObjectPosition/ObjectCFrame listener type. Used by: set_listener."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Ik={name:"manage_animation",description:"[PRO] Animation: load, play, stop animations. Get animation tracks from humanoid/controller.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["load","play","stop","get_tracks"],description:"[PRO] Animation action. load: load an animation on a Humanoid/AnimationController. play: play a loaded animation track. stop: stop a playing animation. get_tracks: list all loaded animation tracks."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the Humanoid, AnimationController, or Model containing one. Used by: load, play, stop, get_tracks."},animationId:{type:"string",description:'Roblox animation asset ID (e.g., "rbxassetid://1234567"). Used by: load.'},trackId:{type:"string",description:"Animation track identifier returned by load. Used by: play (required), stop (required)."},speed:{type:"number",description:"Playback speed multiplier. Used by: play. Default: 1."},fadeTime:{type:"number",description:"Fade time in seconds when starting/stopping. Used by: play, stop. Default: 0.1."},weight:{type:"number",description:"Animation weight (0-1) for blending. Used by: play. Default: 1."},priority:{type:"string",description:"Animation priority. Used by: play.",enum:["Core","Idle","Movement","Action","Action2","Action3","Action4"]},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"play"}}},then:{required:["trackId"]}},{if:{properties:{action:{const:"stop"}}},then:{required:["trackId"]}}],required:["action"]}};var kk={name:"manage_physics",description:"[PRO] Physics collision groups: register, set collidable between groups, list groups.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["register_group","set_collidable","get_groups"],description:"[PRO] Physics action. register_group: register a new collision group with PhysicsService. set_collidable: set whether two groups can collide. get_groups: list all registered collision groups."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},groupName:{type:"string",description:"Collision group name. Used by: register_group (required)."},group1:{type:"string",description:"First collision group name. Used by: set_collidable (required)."},group2:{type:"string",description:"Second collision group name. Used by: set_collidable (required)."},collidable:{type:"boolean",description:"Whether the two groups can collide. Used by: set_collidable (required)."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"register_group"}}},then:{required:["groupName"]}},{if:{properties:{action:{const:"set_collidable"}}},then:{required:["group1","group2","collidable"]}}],required:["action"]}};var Pk={name:"manage_effects",description:"[PRO] Particle effects: emit particles, clear all particles, toggle effect enabled state.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["emit","clear","toggle"],description:"[PRO] Effects action. emit: emit a burst of particles from a ParticleEmitter. clear: clear all particles from a ParticleEmitter or all emitters under an instance. toggle: enable or disable a ParticleEmitter, Beam, Trail, or other effect."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},path:{type:"string",description:"Path to the effect instance (ParticleEmitter, Beam, Trail) or parent containing effects. Used by: emit, clear, toggle."},count:{type:"number",description:"Number of particles to emit in a burst. Used by: emit. Default: 16."},enabled:{type:"boolean",description:"Enable or disable the effect. Used by: toggle."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Rk={name:"manage_terrain",description:"[PRO] Terrain operations: fill shapes, clear regions, replace materials, manage colors, read/write voxels, generate procedural terrain, smooth terrain.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["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"],description:"[PRO] Terrain action. fill_block/fill_ball/fill_cylinder/fill_wedge: fill shapes with material. clear_region/clear_bounds: clear terrain. replace_material: swap materials in region. colors_get/colors_set: manage material colors. read_voxel: single voxel. read_voxels/write_voxels: bulk voxels. generate: procedural terrain. smooth: smooth terrain."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},material:{type:"string",description:"Terrain material name (e.g., Grass, Rock, Water, Sand, Slate, Concrete). Used by: fill_*, replace_material, colors_get, colors_set."},center:{type:"object",description:"Center position as Vector3. Used by: fill_ball.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},position:{type:"object",description:"Position as Vector3. Used by: read_voxel.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},cframe:{type:"object",description:"Position and rotation for fill shapes. Used by: fill_block, fill_cylinder, fill_wedge.",required:["position"],properties:{position:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},rotation:{type:"object",description:"Optional rotation in degrees.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},size:{type:"object",description:"Size in studs. Used by: fill_block, fill_wedge.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},radius:{type:"number",description:"Radius in studs. Used by: fill_ball, fill_cylinder."},height:{type:"number",description:"Height in studs. Used by: fill_cylinder."},region:{type:"object",description:"Rectangular region with min/max corners. Used by: clear_region, replace_material, read_voxels, write_voxels, generate, smooth.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},min:{type:"object",description:"Minimum corner for bounds-based clear. Used by: clear_bounds.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",description:"Maximum corner for bounds-based clear. Used by: clear_bounds.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},sourceMaterial:{type:"string",description:"Material to replace. Used by: replace_material."},targetMaterial:{type:"string",description:"Replacement material. Used by: replace_material."},color:{type:"object",description:"RGB color (0-255). Used by: colors_set.",required:["r","g","b"],properties:{r:{type:"number",minimum:0,maximum:255},g:{type:"number",minimum:0,maximum:255},b:{type:"number",minimum:0,maximum:255}}},resolution:{type:"number",description:"Voxel resolution (studs per voxel). Used by: read_voxels, write_voxels. Default: 4."},materials:{type:"array",description:"3D array of material names [x][y][z]. Used by: write_voxels.",items:{type:"array",items:{type:"array",items:{type:"string"}}}},occupancy:{type:"array",description:"3D array of occupancy values [x][y][z] (0-1). Used by: write_voxels.",items:{type:"array",items:{type:"array",items:{type:"number",minimum:0,maximum:1}}}},baseHeight:{type:"number",description:"Base terrain height in studs. Used by: generate. Default: 32."},amplitude:{type:"number",description:"Height variation amplitude in studs. Used by: generate. Default: 24."},frequency:{type:"number",description:"Noise frequency (0.001-0.1). Used by: generate. Default: 0.01.",minimum:.001,maximum:.1},seed:{type:"number",description:"Random seed for terrain generation. Used by: generate."},layers:{type:"array",description:"Material layers by height. Used by: generate. Each: {material, maxHeight}.",items:{type:"object",required:["material","maxHeight"],properties:{material:{type:"string"},maxHeight:{type:"number"}}}},intensity:{type:"number",description:"Smoothing intensity (0-1). Used by: smooth. Default: 0.5.",minimum:0,maximum:1},preset:{type:"string",description:"Biome preset for natural terrain. Used by: generate. Explicit parameters override preset values.",enum:["mountains","hills","plains","dunes","islands","canyon"]},octaves:{type:"number",description:"fBm noise octave count (1-8). Used by: generate. Default: 4.",minimum:1,maximum:8},persistence:{type:"number",description:"Amplitude decay between octaves (0-1). Used by: generate. Default: 0.5.",minimum:0,maximum:1},waterLevel:{type:"number",description:"Absolute water surface height in studs. Used by: generate. Empty space below this level is filled with Water."},edgeBlend:{type:"object",description:"Blend generated heights into existing terrain at region borders. Used by: generate.",required:["enabled"],properties:{enabled:{type:"boolean"},width:{type:"number",description:"Blend falloff width in studs. Default: 32."}}},materialPalette:{type:"object",description:"Material palette override {surface, cliff, shore, underwater}. Used by: generate.",properties:{surface:{type:"string"},cliff:{type:"string"},shore:{type:"string"},underwater:{type:"string"}}},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"generate"}}},then:{required:["region"]}}],required:["action"]}};var Ek={name:"spatial_query",description:"[PRO] Spatial queries: raycast, find ground, check placement, multi-raycast, scan area, find flat areas, find spawn positions, analyze walkable, spatial map, find empty space, get bounds, snap to grid, check collision.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["raycast","find_ground","check_placement","multi_raycast","scan_area","find_flat","find_spawn","analyze_walkable","spatial_map","find_space","bounds","snap_grid","collision"],description:"[PRO] Spatial action. raycast: single ray. find_ground: ground below point. check_placement: collision-free placement check. multi_raycast: batch rays. scan_area: heightmap generation. find_flat: flat areas for building. find_spawn: spawn positions. analyze_walkable: walkability grid. spatial_map: all BasePart positions. find_space: empty space for object. bounds: bounding box. snap_grid: snap position to grid. collision: AABB collision check."},origin:{type:"object",description:"Ray origin as Vector3. Used by: raycast.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},direction:{type:"object",description:"Ray direction and length as Vector3. Used by: raycast.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},maxDistance:{type:"number",description:"Maximum distance for ground search. Used by: find_ground. Default: 1000."},position:{type:"object",description:"Position as Vector3. Used by: find_ground (cast from here), check_placement (center), collision (hypothetical position).",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},size:{type:"object",description:"Size as Vector3. Used by: check_placement (object size), find_space (required space size), scan_area (area X/Z dimensions).",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},filterType:{type:"string",description:'Raycast filter type. Used by: raycast, multi_raycast. Default: "Exclude".',enum:["Exclude","Include"]},filterList:{type:"array",description:"Instance paths to filter. Used by: raycast, multi_raycast, find_ground, check_placement, scan_area. Alias: filterInstances.",items:{type:"string"}},filterInstances:{type:"array",description:"Instance paths to filter (alias for filterList). Used by: raycast, multi_raycast, find_ground, check_placement, scan_area.",items:{type:"string"}},ignoreWater:{type:"boolean",description:"Ignore terrain water. Used by: raycast, multi_raycast. Default: false."},rays:{type:"array",description:"Array of ray specifications. Used by: multi_raycast. Max 50 rays.",maxItems:50,items:{type:"object",required:["origin","direction"],properties:{origin:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},direction:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}}},center:{type:"object",description:"Center point for area scan. Used by: scan_area.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},area:{type:"object",description:"Bounding box for analysis. Used by: analyze_walkable. Contains min/max.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},searchArea:{type:"object",description:"Bounding box for search. Used by: find_flat, find_spawn, find_space.",required:["min","max"],properties:{min:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},max:{type:"object",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}}}},minSize:{type:"object",description:"Minimum flat area size. Used by: find_flat.",required:["x","z"],properties:{x:{type:"number"},z:{type:"number"}}},maxSlope:{type:"number",description:"Maximum slope in degrees. Used by: find_flat (default: 10), analyze_walkable (default: 45)."},resolution:{type:"number",description:"Grid resolution in studs. Used by: scan_area, analyze_walkable. Default: 4."},gridSize:{type:"number",description:"Grid snap size in studs. Used by: snap_grid (default: 4), find_space (default: 4)."},path:{type:"string",description:"Instance path. Used by: bounds (optional), snap_grid (required), collision (required), spatial_map (rootPath alias)."},paths:{type:"array",description:"Multiple instance paths for batch bounds. Used by: bounds.",items:{type:"string"}},tolerance:{type:"number",description:"Height variation tolerance in studs. Used by: find_flat."},gridSnap:{type:"number",description:"Grid snap size. Alias for gridSize."},axes:{type:"array",description:'Axes to snap. Used by: snap_grid. Default: ["x","y","z"]. Use ["x","z"] for horizontal only.',items:{type:"string",enum:["x","y","z"]}},ignorePaths:{type:"array",description:"Instance paths to ignore in collision check. Used by: collision.",items:{type:"string"}},offset:{type:"number",description:"Vertical offset for ground position. Used by: find_ground. Default: 0."},rotation:{type:"object",description:"Rotation in degrees. Used by: check_placement.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},checkGround:{type:"boolean",description:"Verify ground support for placement. Used by: check_placement. Default: true."},spawnSize:{type:"object",description:"Size of spawning entity. Used by: find_spawn. Default: {x:4, y:5, z:4}.",properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},minSpacing:{type:"number",description:"Minimum distance between spawn positions. Used by: find_spawn. Default: 10."},preferOutdoor:{type:"boolean",description:"Prefer open sky positions. Used by: find_spawn. Default: false."},count:{type:"number",description:"Number of results to find. Used by: find_spawn. Default: 10."},characterHeight:{type:"number",description:"Character height for clearance checks. Used by: analyze_walkable. Default: 5."},maxStepHeight:{type:"number",description:"Maximum step height. Used by: analyze_walkable. Default: 2."},rootPath:{type:"string",description:'Root path for spatial map scan. Used by: spatial_map. Default: "game.Workspace".'},includeModels:{type:"boolean",description:"Include Model bounding boxes. Used by: spatial_map. Default: true."},maxResults:{type:"number",description:"Maximum results. Used by: spatial_map (default: 500), scan_area (default: 500), find_flat (default: 10)."},padding:{type:"number",description:"Minimum distance from other objects. Used by: find_space. Default: 1."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"snap_grid"}}},then:{required:["path"]}},{if:{properties:{action:{const:"collision"}}},then:{required:["path"]}}],required:["action"]}};var Tk={name:"manage_assets",description:"[PRO] Asset management: insert models by ID, get asset info, search creator store, insert free models/packages, export selection JSON, generate/review Roblox models, round-trip .rbxm files through Asset Library, and generate local thumbnails.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["insert","info","search","search_insert","insert_free","insert_package","export_selection_json","export_selection_rbxm","export_path_rbxm","review_model","generate_model","upload_asset","import_rbxm","generate_thumbnail"],description:"[PRO] Asset action. insert: insert model by asset ID. info: get asset metadata. search: search Creator Store. search_insert: search and insert first match. insert_free: insert free model. insert_package: insert package. export_selection_json: JSON snapshot of current selection. export_selection_rbxm/export_path_rbxm: save Studio content to Asset Library .rbxm. review_model: QA a selected/path model and optionally register it in Asset Library. generate_model: generate a Roblox model in Studio via GenerationService only. upload_asset: upload the selected Studio asset through Studio-local AssetService with automatic Model/Mesh/Image type selection. import_rbxm: import Asset Library .rbxm into Studio. generate_thumbnail: create or replace thumbnail.png for an Asset Library .rbxm."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},assetId:{type:"number",description:"Roblox asset ID. Used by: insert (required), info (required), insert_free (required), insert_package (required)."},parent:{type:"string",description:'Parent path for inserted asset. Used by: insert, search_insert, insert_free, insert_package. Default: "game.Workspace".'},name:{type:"string",description:"Optional name for inserted instance."},position:{type:"object",description:"Position to place the model. Used by: insert, insert_free.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},query:{type:"string",description:'Search keyword. Used by: search (required), search_insert (required). E.g., "monster", "tree", "car".'},maxResults:{type:"number",description:"Maximum search results. Used by: search. Default: 10."},category:{type:"string",description:"Asset category filter. Used by: search, export_selection_rbxm, export_path_rbxm, review_model, generate_model, import_rbxm, generate_thumbnail. upload_asset may omit this and use assetType/selection auto-detection."},sortType:{type:"string",description:"Sort order for search results. Used by: search."},format:{type:"string",description:"Export format. Used by: export_selection_json."},includeProperties:{type:"boolean",description:"Include all properties in export. Used by: export_selection_json. Default: false."},includeChildren:{type:"boolean",description:"Include children in export. Used by: export_selection_json. Default: false."},maxDepth:{type:"number",description:"Maximum depth for recursive child export. Used by: export_selection_json. Default: 5."},scope:{type:"string",description:"Asset Library scope. Used by: export_selection_rbxm, export_path_rbxm, review_model, import_rbxm, generate_thumbnail. Default: place.",enum:["place","shared"]},placeId:{type:"number",description:"Place ID for place-scoped Asset Library .rbxm round-trip operations. For other manage_assets Studio/plugin actions, this also acts as an optional Studio target selector."},assetLibraryAssetId:{type:"string",description:"Asset Library asset ID. Used by: import_rbxm, generate_thumbnail."},targetParent:{type:"string",description:"Studio parent path for imported/generated instances. Used by: import_rbxm, generate_model. Default: game.Workspace."},sourcePath:{type:"string",description:"Studio instance path to export, review, or upload. Used by: export_path_rbxm, review_model, upload_asset."},displayName:{type:"string",description:"Asset Library display name or Studio upload display name. Used by: export_selection_rbxm, export_path_rbxm, review_model, generate_model, upload_asset."},description:{type:"string",description:"Asset Library description or Studio upload description. Used by: export_selection_rbxm, export_path_rbxm, review_model, upload_asset."},assetType:{type:"string",description:"Roblox Studio-local upload asset type. Used by: upload_asset. Default: auto, which selects Model/Mesh/Image from the selected Studio object.",enum:["auto","model","mesh","image"]},thumbnailMode:{type:"string",description:"Thumbnail capture mode. Used by: export_selection_rbxm, export_path_rbxm, review_model. Default: none.",enum:["none","auto"]},uploadMode:{type:"string",description:"Studio-local upload behavior for .rbxm registration actions. auto uploads the selected object as a Roblox Model asset first, model requires that path, embeddedResources uploads only generated Mesh/Image resources, and localOnly skips Roblox upload. Used by: export_selection_rbxm, export_path_rbxm, review_model. Default: localOnly.",enum:["auto","model","embeddedResources","localOnly"]},uploadTemporaryAssets:{type:"boolean",description:"Explicit user approval for Studio-local CreateAssetAsync uploads before .rbxm registration. Used by: export_selection_rbxm, export_path_rbxm, review_model. Default: false; set true only after user approval."},creatorType:{type:"string",description:"Optional Roblox creator type for Studio-local temporary asset upload. Used with uploadTemporaryAssets by .rbxm registration actions. Omit to use the logged-in Studio user.",enum:["user","group"]},creatorId:{type:"string",description:"Optional Roblox user or group ID for Studio-local temporary asset upload. Used with uploadTemporaryAssets by .rbxm registration actions."},prompt:{type:"string",description:"Text prompt for Roblox GenerationService model generation. Used by: generate_model."},schemaMode:{type:"string",description:"Generation schema mode. Used by: generate_model. Default: predefined.",enum:["predefined","custom"]},predefinedSchema:{type:"string",description:"Roblox predefined model schema. Used by: generate_model when schemaMode=predefined. Default: Body1.",enum:["Body1","Car5"]},schemaGroups:{type:"array",description:"Custom schema group names for generated model segmentation. Used by: generate_model when schemaMode=custom.",items:{type:"string"}},size:{type:"object",description:"Requested approximate generated model bounds in studs. Used by: generate_model.",required:["x","y","z"],properties:{x:{type:"number"},y:{type:"number"},z:{type:"number"}}},maxTriangles:{type:"number",description:"Maximum triangle budget requested from Roblox GenerationService. Used by: generate_model."},generateTextures:{type:"boolean",description:"Whether Roblox GenerationService should generate textures. Used by: generate_model. Default: true."},review:{type:"boolean",description:"Whether to run post-generation/review QA. Used by: generate_model. Default: true."},exportToLibrary:{type:"boolean",description:"Whether to register the reviewed model as an Asset Library .rbxm asset. Used by: review_model. Default: false."},expectedUse:{type:"string",description:"Expected model use for QA heuristics. Used by: review_model, generate_model. Default: unknown.",enum:["decorative","interactive","vehicle","character","unknown"]},expectedGroups:{type:"array",description:"Expected child/group names for generated or reviewed model QA. Used by: review_model, generate_model.",items:{type:"string"}},maxDescendants:{type:"number",description:"Maximum descendants to inspect during model QA. Used by: review_model, generate_model. Default: 500."},readiness:{type:"string",description:"Optional readiness gate for Asset Library registration decisions. Used by: review_model, generate_model.",enum:["ready","review","blocked"]},anchorMode:{type:"string",description:"How to anchor generated BaseParts before review/export. Used by: generate_model. Default: all.",enum:["none","all"]},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},allOf:[{if:{properties:{action:{const:"insert"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"info"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"search"}}},then:{required:["query"]}},{if:{properties:{action:{const:"search_insert"}}},then:{required:["query"]}},{if:{properties:{action:{const:"insert_free"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"insert_package"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"export_selection_rbxm"}}},then:{required:["category"]}},{if:{properties:{action:{const:"export_path_rbxm"}}},then:{required:["category","sourcePath"]}},{if:{properties:{action:{const:"review_model"}}},then:{required:["category"]}},{if:{properties:{action:{const:"generate_model"}}},then:{required:["prompt"]}},{if:{properties:{action:{const:"import_rbxm"}}},then:{required:["category","assetLibraryAssetId"]}},{if:{properties:{action:{const:"generate_thumbnail"}}},then:{required:["category","assetLibraryAssetId"]}}],required:["action"]}};var Ak={name:"manage_open_cloud_assets",description:"[PRO] Roblox Open Cloud asset upload: credential status, category capabilities, upload local files, update assets, read metadata, and poll operation status. Does not expose delete/archive/restore actions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["credential_status","capabilities","upload","update","info","operation_status"],description:"[PRO] Open Cloud asset action. credential_status: check local API key status. capabilities: list supported upload categories. upload: create an asset from a local file. update: update an existing asset. info: read asset metadata. operation_status: check upload/update processing."},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},assetId:{type:"string",description:"Roblox asset ID. Used by: update (required), info (required)."},operationId:{type:"string",description:"Roblox Open Cloud operation ID or operations/{id} path. Used by: operation_status."},filePath:{type:"string",description:"Local file path on the MCP server machine. Used by: upload, update."},category:{type:"string",description:"WEPPY asset category. Used by: upload, update.",enum:["image","decal","audio","mesh","model","video","animation"]},displayName:{type:"string",description:"Roblox asset display name. Used by: upload, update."},description:{type:"string",description:"Roblox asset description. Used by: upload, update."},creatorType:{type:"string",description:"Asset creator owner type. Used by: upload, update. Defaults to saved credential metadata when available.",enum:["user","group"]},creatorId:{type:"string",description:"User ID or group ID for the asset creator. Used by: upload, update. Defaults to saved credential metadata when available."},expectedPrice:{type:"number",description:"Expected upload fee in Robux. Used by: upload, update when Roblox requires an expected price."},readMask:{type:"array",description:"Asset metadata fields to retrieve. Used by: info.",items:{type:"string"}},updateMask:{type:"array",description:"Metadata fields to update. Used by: update.",items:{type:"string"}},waitForOperation:{type:"boolean",description:"When true, poll the returned Open Cloud operation until done or timeout. Used by: upload, update."},operationPollTimeoutMs:{type:"number",description:"Maximum operation polling time in milliseconds. Used by: upload, update when waitForOperation is true."},operationPollIntervalMs:{type:"number",description:"Operation polling interval in milliseconds. Used by: upload, update when waitForOperation is true."}},allOf:[{if:{properties:{action:{const:"upload"}}},then:{required:["filePath","category","displayName"]}},{if:{properties:{action:{const:"update"}}},then:{required:["assetId","category"]}},{if:{properties:{action:{const:"info"}}},then:{required:["assetId"]}},{if:{properties:{action:{const:"operation_status"}}},then:{required:["operationId"]}}],required:["action"]}};var $k={name:"manage_sync",description:"[PRO] Project sync management: status, history, direction settings, read/write synced files.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["status_current_place","history","directions","read_file","write_file","progress"],description:"[PRO] Sync action. status_current_place: get sync status for the current connected place. history: get change history. directions: get per-type sync directions. read_file: read a synced file. write_file: write to a synced file. progress: get real-time sync progress and bandwidth."},placeId:{type:"number",description:"Place ID for sync operations. Used by: history, directions, read_file, write_file."},instancePath:{type:"string",description:"Instance path for file read/write. Used by: read_file, write_file."},content:{type:"string",description:"File content to write. Used by: write_file."},query:{type:"object",description:"Query parameters for history. Used by: history.",properties:{limit:{type:"number",description:"Maximum entries to return."},offset:{type:"number",description:"Number of entries to skip."}}}},allOf:[{if:{properties:{action:{const:"read_file"}}},then:{required:["placeId","instancePath"]}},{if:{properties:{action:{const:"write_file"}}},then:{required:["placeId","instancePath","content"]}}],required:["action"]}};var Ok={name:"workspace_state",description:"[PRO] Workspace state: full sync, snapshot, recent changes, viewport info, clear history, metadata, scripts, selection info, clear cache.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["sync","snapshot","changes","viewport","clear_history","metadata","scripts","selection_info","clear_cache"],description:"[PRO] State action. sync: fetch current Workspace state (hierarchy, history, stats). snapshot: get full instance tree structure. changes: get recent changes (added/removed/modified). viewport: get camera position, FOV, viewport size, selection bounds. clear_history: clear change history. metadata: get workspace metadata. scripts: get script list. selection_info: get selection info. clear_cache: clear state cache."},includeMetadata:{type:"boolean",description:"Include metadata (instance counts, timestamps). Used by: sync. Default: true."},limit:{type:"number",description:"Maximum number of changes to return. Used by: changes. Default: 20."},includeCameraInfo:{type:"boolean",description:"Include camera position and settings. Used by: viewport. Default: true."},includeSelectionBounds:{type:"boolean",description:"Include current selection bounds info. Used by: viewport. Default: true."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Dk={name:"manage_logs",description:"Output logs: get filtered logs, poll incrementally with sinceSeq cursor, clear buffer, get recent errors.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","clear","errors"],description:"Log action. get: retrieve logs with optional level/limit/since/sinceSeq filters. clear: clear internal log buffer without resetting seq. errors: quick access to recent errors only."},level:{type:"string",description:'Log level filter. Used by: get. Default: "all".',enum:["all","error","warning","info"]},limit:{type:"number",description:"Maximum entries to return. Used by: get (default: 100, max: 500), errors (default: 20, max: 100)."},pattern:{type:"string",description:"Text pattern to filter log messages. Used by: get."},since:{type:"number",description:"Unix timestamp in milliseconds. Only logs after this time. Used by: get."},sinceSeq:{type:"number",description:"Return only logs after this sequence number. Cursor mode returns logs oldest-to-newest and includes lastSeq/oldestSeq/hasMore/cursorStatus. Used by: get."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var Nk={name:"system_info",description:"System info: ping, connection status, usage tier. [PRO] place info, services list, studio settings.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["ping","connection","usage","place_info","services","studio_settings"],description:"System action. Basic: ping (test connection, returns pong), connection (server/plugin connection info with session IDs), usage (current tier: basic/pro). [PRO]: place_info (place ID, name, game ID, creator), services (list all Roblox services), studio_settings (Studio preferences)."},message:{type:"string",description:"Optional message to echo back. Used by: ping."},placeId:{type:"number",description:"Optional Studio target selector. When multiple Studio clients are connected, route this call to the active client for this Roblox placeId. If no matching active client exists, the call fails instead of falling back to another Place."},clientId:{type:"string",description:"Optional Studio target selector. Routes this call to the exact connected WEPPY Plugin client. Takes precedence over targetAlias and placeId."},targetAlias:{type:"string",description:"Optional Studio target selector. Routes this call to the connected WEPPY Studio target alias shown in Dashboard/Plugin, such as studio-1. Takes precedence over placeId."}},required:["action"]}};var jk={name:"manage_studio",description:`Control Roblox Studio state for playtest lifecycle, automated test runs, and editor view/rendering QA workflows. Use it for state-changing playtest controls and Studio session-level View settings such as UI preview; it does not edit game UI objects or their properties.
|
|
142
142
|
`,inputSchema:{type:"object",properties:{action:{type:"string",enum:["toggle_ui_preview","play_start","play_stop","play_pause","play_resume","play_status","run_test"],description:`Studio editor action. [PRO]: toggle_ui_preview (toggle StarterGui UI rendering in Edit mode through the Studio UI preview setting), play_start (start Play or Run mode), play_stop (stop active playtest), play_pause (pause active playtest), play_resume (resume paused playtest), play_status (get current playtest state), run_test (inject test script, run playtest, collect logs, and write local report files).
|
|
143
143
|
`},contextId:{type:"string",description:"Optional execution context identifier. Used to continue an existing context for mutating actions."},contextSummary:{type:"object",properties:{intent:{type:"string"},affectedAreas:{type:"array",items:{type:"object",required:["kind","target","label"],properties:{kind:{type:"string",enum:["script","instance","property","system","gameplay","ui","terrain","lighting","asset","other"]},target:{type:"string"},label:{type:"string"}}}},testScenario:{type:"string"},expectedBehavior:{type:"string"},observedBehavior:{type:"string"}},description:"Optional structured execution context attached to this tool call."},replayMetadata:{type:"object",properties:{mode:{type:"string"},timeout:{type:"number"},seed:{type:"number"},inputRefs:{type:"array",items:{type:"string"}},setupRefs:{type:"array",items:{type:"string"}},assertionRefs:{type:"array",items:{type:"string"}},artifactRefs:{type:"array",items:{type:"string"}}},description:"Optional replay-ready metadata attached to this tool call."},enabled:{type:"boolean",description:`Boolean value to set. Omit to toggle the current value.
|
|
144
144
|
Used by: toggle_ui_preview (optional).
|
|
@@ -501,7 +501,7 @@ Used by: toggle_ui_preview (optional).
|
|
|
501
501
|
`)}catch(i){y.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()},Afe),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 wt.relative(this.config.getSyncRoot(),e)}extractServiceName(e){return Kt(e)[0]??""}findTreeNode(e,n){let i=Kt(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=Kt(e);return n.length===0?null:n[n.length-1]??null}getParentPath(e){let n=Kt(e);return n.length<=1?null:`game.${n.slice(0,-1).join(".")}`}async copyDirectory(e,n){await this.ensureDir(n);let i=await st.readdir(e,{withFileTypes:!0});for(let r of i){let a=wt.join(e,r.name),o=wt.join(n,r.name);r.isDirectory()?await this.copyDirectory(a,o):await st.copyFile(a,o)}}async tryRename(e,n){try{return this.onWriteCallback?.(e),this.onWriteCallback?.(n),await st.rename(e,n),!0}catch{return!1}}};function IE(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)=>IE(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)&&IE(n[o],i[o]))}function Ofe(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;IE(a,o)||(n[r]={before:a,after:o})}return n}Sr();import Ve from"path";import{promises as ts}from"fs";ce();var dx=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){y.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=Ve.relative(this.placeRoot,a.fsPath);i.push({type:"instanceRemoved",instancePath:a.instancePath,fsPath:o,fileType:a.fileType,content:null,destructive:!0})}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=Ve.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=Ve.relative(this.placeRoot,o.fsPath),_={type:"instanceRemoved",instancePath:p,fsPath:x,fileType:"directory",content:null,destructive:!0};f&&(_.siblingIndex=f),n.push(_);continue}if(r.has(m)||this.isServiceInstance(p)||a.has(o.fsPath)||!await this.isContainerDirectory(o.fsPath))continue;let h=Ve.relative(this.placeRoot,o.fsPath),v={type:"containerCreated",instancePath:p,fsPath:h,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=Ve.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,destructive:!0};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){y.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(Ve.basename(e)==="_tree.json")return;let r=Ve.relative(n,e);if(r.startsWith(".."))return;let a=r.split(Ve.sep).filter(d=>d.length>0);if(a.length<2)return;let o=a[a.length-2],s=Ve.dirname(e),c=Ve.dirname(s),l=this.index.getOriginalInstance(c,o);return l?l.siblingIndex:Gr(o).siblingIndex}isForwardOnlyPath(e){return this.index.isPathUnderClass(e,cl)}logForwardOnlySkip(e,n){y.info("Skipped reverse change for forward-only path",{source:n,path:Ve.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=Ve.relative(n,e);if(i.startsWith("..")||i===""||Ve.isAbsolute(i))return null;let r=i.split(Ve.sep).filter(s=>s.length>0);if(r.length===0)return null;let a=["game"],o=n;for(let s of r){o=Ve.join(o,s);let c=Ve.dirname(o);a.push(this.index.getOriginalNameForDir(c,s))}return gt(a)}getSiblingIndexForDirectory(e){let n=Ve.basename(e),i=Ve.dirname(e),r=this.index.getOriginalInstance(i,n);return r?r.siblingIndex:Gr(n).siblingIndex}async isContainerDirectory(e){try{let n=await ts.readdir(e,{withFileTypes:!0});for(let i of n)if(i.isFile()&&jb.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 ts.readFile(e,"utf-8"),r=Ve.relative(this.placeRoot,e);return{type:"scriptSource",instancePath:n,fsPath:r,fileType:"script",content:i}}async readModifiedProps(e,n){let i=await ts.readFile(e,"utf-8"),r=JSON.parse(i),a=Ve.relative(this.placeRoot,e);return{type:"properties",instancePath:n,fsPath:a,fileType:"props",content:r}}async readModifiedValue(e,n){let i=await ts.readFile(e,"utf-8"),r=JSON.parse(i),a=Ve.relative(this.placeRoot,e);return{type:"valueChanged",instancePath:n,fsPath:a,fileType:"value",content:r}}async readNewScript(e,n){let i=await ts.readFile(e,"utf-8"),r=Ve.relative(this.placeRoot,e),a=Ve.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 ts.readFile(e,"utf-8"),r=JSON.parse(i),a=Ve.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 ts.readFile(e,"utf-8"),r=JSON.parse(i),a=Ve.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 St(e)}isServiceInstance(e){let n=Ei(e);return n.length!==2||n[0]!=="game"?!1:JR.has(n[1])}};ce();import Mfe from"path";ce();import qa from"path";import{createHash as F8}from"crypto";import{promises as PE}from"fs";Sr();var Dfe=500,kE=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`${qa.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=Dfe){this.explorerRoot=qa.resolve(e),this.syncIndex=n,this.scanIntervalMs=i}setDirectionChecker(e){this.directionChecker=e}setOnForwardViolation(e){this.onForwardViolation=e}suppressPath(e,n){let i=qa.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"),y.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=>{y.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){y.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),y.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=M8(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&&y.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=qa.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=qa.join(this.explorerRoot,r.relativePath),o=new Date().toISOString();if(await this.isSuppressedPath(a)||r.kind==="file"&&wE(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 PE.readFile(a,"utf-8"),l=F8("md5").update(c,"utf-8").digest("hex");if(s&&l===s){y.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}y.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;y.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,cl)?!0:this.directionChecker?this.directionChecker(e)==="forward":!1}async isSuppressedPath(e){let n=qa.resolve(e);for(let[i,r]of this.suppressedPaths){if(n===i||n.startsWith(`${i}${qa.sep}`))return r.mode==="generic"?!0:r.mode==="missing"?!await Nfe(n):await jfe(n)===r.hash;if(i.startsWith(`${n}${qa.sep}`))return r.mode==="generic"}return!1}};async function Nfe(t){try{return await PE.access(t),!0}catch{return!1}}async function jfe(t){try{let e=await PE.readFile(t,"utf-8");return F8("md5").update(e,"utf-8").digest("hex")}catch{return null}}var q8=kE;var ut="snapshot-scanner",px=class extends q8{placeId;detectorExplorerRoot;lifecycleGeneration=0;constructor(e,n,i={}){super(e,n,i.scanIntervalMs),this.placeId=i.placeId??null,this.detectorExplorerRoot=Mfe.resolve(e)}async start(){let e=++this.lifecycleGeneration;y.info("Reverse detector bootstrap scheduled",{placeId:this.placeId,mode:ut,explorerRoot:this.detectorExplorerRoot}),await super.start(),e===this.lifecycleGeneration&&y.info("Reverse detector bootstrap completed",{placeId:this.placeId,mode:ut})}async stop(e){this.lifecycleGeneration+=1,y.info("Reverse detector stopping",{placeId:this.placeId,mode:ut,reason:e??"unspecified"}),await super.stop(e)}beginFullSyncReplacement(){y.info("Reverse detector paused for full sync replacement",{placeId:this.placeId,mode:ut}),super.beginFullSyncReplacement()}async endFullSyncReplacement(){y.info("Reverse detector baseline refresh scheduled",{placeId:this.placeId,mode:ut}),await super.endFullSyncReplacement()}async rescan(){y.debug("Reverse detector manual rescan requested",{placeId:this.placeId,mode:ut});let e=await super.rescan();return y.info("Reverse detector manual rescan completed",{placeId:this.placeId,mode:ut,added:e,pendingCount:this.getPendingCount()}),e}};import Il from"path";import{promises as B8}from"fs";function ns(t,e,n,i,r=!1){if(i&&i>=1){let s=St(e);if(s){let c=t.getEffectiveDir(s,i);if(c){let l=lt(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 RE(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=Il.relative(s,a).split(Il.sep).filter(l=>l.length>0);return gt(["game",...c])}let o=e;if(n){let s=t.getResolvedName(e,n);if(s)o=sf(o,s);else if(r)throw new Error(`Missing collision mapping for ${e}#${n}`)}return o}function zfe(t,e){let n=Ei(t),i=Ei(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 H8(t,e){e=Lfe(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=ns(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&&zfe(a,s)){i.add(r);break}return i.size===0?e:e.filter((r,a)=>!i.has(a))}function Lfe(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=rs(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 rs(t,e,n,i=!1){if(n&&n>=1){let r=St(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 Ba(t,e,n,i,r){let a=Il.join(e,n),o=Il.join(e,i);try{(await B8.stat(a)).isDirectory()&&(r&&(r.suppressPath(a),r.suppressPath(o)),await B8.rename(a,o),t.renameHashKeysUnder(a,o),t.renameReverseNameMappingsUnder(a,o),t.renameInstanceDirMappingsUnder(a,o))}catch{return}}function RE(t,e,n){let i=Il.relative(t.getExplorerRoot(),e).split(Il.sep).filter(r=>r.length>0);return gt(["game",...i,n])}async function fx(t,e){let n=t.index.planCollisionReindexAfterBatchRemovals(e.instancePath,[...e.removedSiblingIndices],e.parentDir);for(let i of n.renames)await Ba(t.index,e.parentDir,i.from,i.to,t.fileWatcher),await kl(t.writer,t.index,e.parentDir,i.from,i.to);t.index.applyCollisionReindexAfterBatchRemovals(e.instancePath,e.parentDir,n)}async function kl(t,e,n,i,r){let a=RE(e,n,i),o=RE(e,n,r);await t.renameInTree(a,o,r)}import mx from"path";var Z8=5*60*1e3,V8=100;function EE(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function cf(t){return typeof t=="string"&&t.length>0}function gx(t,e){let n=mx.resolve(t),i=mx.resolve(e),r=mx.relative(n,i);return r===""||!r.startsWith("..")&&!mx.isAbsolute(r)}function lf(t){return t.pluginProcessToken?`process:${t.pluginProcessToken}`:t.pluginSessionId?`session:${t.pluginSessionId}`:t.pluginClientId?`client:${t.pluginClientId}`:null}function W8(t){if(!EE(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(!cf(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"}:cf(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 cf(t.serviceName)?cf(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 G8(t){if(!EE(t))return{success:!1,error:"Body must be an object"};if(!cf(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(!EE(i)||!e.has(i.type))return{success:!1,error:`changes[${n}]: invalid type '${String(i?.type)}'`}}return{success:!0,data:t}}import Ir from"path";import{promises as is}from"fs";Sr();ce();var hx=class{constructor(e){this.ctx=e}async processChangeForPlace(e,n,i){let r=C6(n.type);if(e.directions[r]==="reverse")return y.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=ns(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):y.warn("propertyChanged: missing both property and properties",{path:o});return null}case"instanceAdded":{let o=sl.has(n.className),s=n.path,c=n.name;{let d=rs(e.index,n.path,n.parentSiblingIndex,!0),{resolved:p,retroactiveRename:f}=e.index.registerCollision(n.path,n.siblingIndex,d);f&&(await Ba(e.index,d,f.from,f.to,e.fileWatcher),await kl(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(),h=Ir.relative(g,d).split(Ir.sep).filter(v=>v.length>0);s=gt(["game",...h,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=St(s)||n.parentPath;return await e.writer.addToTree(u,l),e.instanceCount++,o&&n.scriptSource!==void 0&&e.scriptCount++,null}case"instanceRemoved":{let o=ns(e.index,n.path,n.siblingIndex,n.parentSiblingIndex,!0),s=rs(e.index,n.path,n.parentSiblingIndex,!0);y.info("Processing instanceRemoved",{path:o}),await e.writer.removeInstance(o),this.removeOriginalClassMapping(e,n.path,o);let c=lt(o),l=St(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=St(o);if(u)try{let d=e.index.resolveChildrenDir(u);Ir.dirname(d)!==e.index.getExplorerRoot()&&(await is.readdir(d)).length===0&&await is.rmdir(d)}catch{return null}return null}case"instanceRenamed":{let o=ns(e.index,n.oldPath,n.siblingIndex,n.parentSiblingIndex,!0),s=St(n.oldPath)===St(n.newPath),c=s?rs(e.index,n.oldPath,n.parentSiblingIndex,!0):null,l=rs(e.index,n.newPath,n.parentSiblingIndex,!0),{resolved:u,retroactiveRename:d}=e.index.registerCollision(n.newPath,n.siblingIndex,l);d&&(await Ba(e.index,l,d.from,d.to,e.fileWatcher),await kl(e.writer,e.index,l,d.from,d.to));let p=u!==e.index.sanitizeName(n.newName)?sf(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 Ba(e.index,c,m.from,m.to,e.fileWatcher),await kl(e.writer,e.index,c,m.from,m.to);e.index.applyCollisionReindexAfterRemoval(n.oldPath,c,f)}return null}case"instanceMoved":{let o=ns(e.index,n.oldPath,n.siblingIndex,n.parentSiblingIndex,!0),s=rs(e.index,n.newPath,n.parentSiblingIndex,!0),{resolved:c,retroactiveRename:l}=e.index.registerCollision(n.newPath,n.siblingIndex,s);l&&(await Ba(e.index,s,l.from,l.to,e.fileWatcher),await kl(e.writer,e.index,s,l.from,l.to));let u=lt(n.newPath)||"",d=c!==e.index.sanitizeName(u)?sf(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=ns(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=Ir.join(this.ctx.config.getPlaceRoot(e.placeId),"explorer"),o=Ir.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=Ir.join(this.ctx.config.getPlaceRoot(e.placeId),"explorer"),a=Ir.relative(r,i);e.fileWatcher.injectPending({fsPath:i,relativePath:a,type:"change",detectedAt:new Date().toISOString()})}}catch(i){y.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 is.readFile(i,"utf-8"),a=JSON.parse(r);if(a.className&&sl.has(a.className))return a.className}catch{return"ModuleScript"}return"ModuleScript"}async cleanupStaleScriptFilesForPlace(e,n,i){let r=Db[i],a=Ir.join(this.ctx.config.getPlaceRoot(e.placeId),"explorer");for(let[o,s]of Object.entries(Db)){if(s===r)continue;let c=e.index.resolveScriptPath(n,o,!1);try{await is.unlink(c),e.index.removeHash(c),y.info("Cleaned up stale script file",{placeId:e.placeId,removed:Ir.relative(a,c),currentClassName:i})}catch(l){l.code!=="ENOENT"&&y.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 is.readFile(r,"utf-8")}catch{return null}return e.index.computeHash(o)===a?null:{fsPath:Ir.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 is.readFile(a,"utf-8")}catch{return null}return e.index.computeHash(s)===o?null:{fsPath:Ir.relative(this.ctx.config.getPlaceRoot(e.placeId),a),instancePath:n,fileType:"script",studioContent:i,fileContent:s}}catch{return null}}async applyDeferredCollisionBatchReindexForPlace(e,n){await fx(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 is.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??lt(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 K8 from"path";import{promises as yx}from"fs";Sr();ce();tr();var vx=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=K8.join(r,".sync-index.json"),o=!1;try{await yx.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=K8.join(r,"explorer"),c=new Fa(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),y.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)}typeof i.autoApplyDeletes=="boolean"&&(a.autoApplyDeletes=i.autoApplyDeletes),this.ctx.touchRuntimePlace(r),n.status(200).json({status:"updated",directions:a.directions,applyModes:a.applyModes,autoApplyDeletes:a.autoApplyDeletes})}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),y.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=wn(e.query.limit,50,1,200),a=wn(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 rf(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:{...Go},reverseDetectorActive:!1,reverseDetectorMode:ut,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:{...Go},reverseDetectorActive:!1,reverseDetectorMode:ut,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:ut,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 rf(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{...Wo};let i=this.ctx.places.get(n);return i?{...i.directions}:{...Wo}}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 yx.readFile(a,"utf-8"),path:a}}catch(s){if(s.code!=="ENOENT")throw s}for(let s of sl){let c=r.index.resolveScriptPath(n,s,!1);try{return{content:await yx.readFile(c,"utf-8"),path:c}}catch{continue}}let o=r.index.resolveValuePath(n);try{return{content:await yx.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:lt(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 Me from"path";import{createHash as Ufe,randomUUID as Ffe}from"crypto";import{promises as jn}from"fs";Sr();Lb();ce();function qfe(t){return Ufe("md5").update(t,"utf-8").digest("hex")}var bx=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&&(y.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=lf(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),y.info("Sync directions received",{placeId:e,directions:r.directions})}else r.directions={...Wo};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={...Go};r.autoApplyDeletes=n.autoApplyDeletes===!0,r.forwardRestoreQueue=[];let a=Ffe();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=Me.join(o,`explorer_tmp_${a}`);await jn.mkdir(s,{recursive:!0}),r.tmpIndex=new Fa(o,s),r.tmpWriter=new Cl(this.ctx.config,r.tmpIndex,e),r.collisionDirMap=new Map;let c=n.preserveLocalFiles;Array.isArray(c)&&c.length>0&&(this.setPreserveLocalFiles(a,c),y.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=Me.join(o,".sync-meta.json");await jn.mkdir(Me.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}`}),y.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??lf(n),h=this.getPreferredResolvedName(r,g,p),{resolved:v,retroactiveRename:x}=o.registerCollisionWithPreferredName(p.path,p.siblingIndex??void 0,m,h);x&&(await Ba(o,m,x.from,x.to),this.rewritePendingEffectivePaths(c,o.getExplorerRoot(),Me.join(m,x.from),Me.join(m,x.to)),o.updateSessionDebugMappingResolvedName(g,x.instancePath,x.siblingIndex,x.to));let _=o.resolveChildrenDir(p.path),I=Me.join(m,v);I!==_&&u.set(_,I);let w=o.sanitizeName(p.name),D=p;if(m!==f||v!==w){let G=o.getExplorerRoot(),K=Me.relative(G,m).split(Me.sep).filter(ht=>ht.length>0),Ce=gt(["game",...K,v]);D={...p,path:Ce}}let M=await s.writeInstance(D);o.setClassName(p.path,p.className,p.siblingIndex),this.recordSessionDebugMapping(r,g,p,v),l++,(M.propsWritten||M.valueWritten)&&r.instanceCount++,M.scriptWritten&&r.scriptCount++,c.instances.push({effectivePath:D.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++),y.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=Me.join(o,"explorer"),c=Me.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=Me.resolve(o,f);try{let g=await jn.readFile(m,"utf-8");d.set(f,g)}catch{p.push(f)}}y.info("Backed up local files for preservation",{placeId:e,requested:u.length,backed:d.size,deleted:p.length})}l&&l.beginFullSyncReplacement();try{try{await jn.rm(s,{recursive:!0,force:!0})}catch{}await jn.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=Me.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(),h=r.index.getExplorerRoot();for(let[v,x]of r.tmpIndex.getAllHashes()){let _=Me.relative(g,v),I=Me.resolve(h,_);r.index.updateHashByValue(I,x)}for(let[v,x]of r.tmpIndex.getAllFileHashes()){let _=Me.relative(g,v),I=Me.resolve(h,_);r.index.updateFileHashByValue(I,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,h]of d){let v=Me.resolve(o,g);try{await jn.mkdir(Me.dirname(v),{recursive:!0}),await jn.writeFile(v,h,"utf-8"),l?.suppressPath(v,qfe(h))}catch(x){y.warn("Failed to restore preserved file",{path:g,error:x instanceof Error?x.message:String(x)})}}y.info("Restored preserved local files",{placeId:e,count:d.size})}if(p.length>0){let g=0;for(let h of p){let v=Me.resolve(o,h);try{await jn.unlink(v),r.index.removeHash(v),l?.suppressPath(v,"missing"),g++}catch(x){x.code!=="ENOENT"&&y.warn("Failed to delete preserved-as-deleted file",{path:h,error:x instanceof Error?x.message:String(x)})}}g>0&&(await r.index.saveToDisk(),y.info("Deleted locally-removed files from new sync",{placeId:e,count:g}))}try{let g=this.ctx.config.getSyncRoot();await zb(g,o)}catch(g){y.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(),h={version:1,lastActivePlaceId:r.placeId,lastActivePlaceName:r.placeName??null,lastActiveAt:new Date().toISOString()},v=Me.join(g,".project-meta.json");await this.ctx.atomicWriteFile(v,JSON.stringify(h,null,2)+`
|
|
504
|
-
`),await ll(g)}catch(g){y.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=>{y.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}`}),y.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(y.warn("Incomplete sync TTL expired, cleaning up",{placeId:e.placeId,syncId:n}),e.incompleteSyncTimer=null,e.activeFullSyncSessionId===n&&e.syncInitRequestsInFlight>0){y.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=Me.join(r,`explorer_tmp_${n}`);try{await jn.rm(a,{recursive:!0,force:!0})}catch(o){y.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))},Z8);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=St(i.path),s=lt(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:St(i.path),originalName:lt(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=Kt(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?Kt(n).map(i=>e.tmpIndex.sanitizeName(i)):Kt(n)}rewritePendingEffectivePaths(e,n,i,r){let a=Me.relative(n,i).split(Me.sep).filter(l=>l.length>0),o=Me.relative(n,r).split(Me.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 jn.readdir(e,{withFileTypes:!0});for(let i of n)if(i.isDirectory()){if(i.name.startsWith("explorer_tmp_")){let r=Me.join(e,i.name);y.warn("Removing stale temp directory from crashed sync",{dir:i.name});try{await jn.rm(r,{recursive:!0,force:!0})}catch(a){y.error(`Failed to remove stale temp dir: ${i.name}`,a instanceof Error?a:new Error(String(a)))}}if(i.name.startsWith("place_")){let r=Me.join(e,i.name);try{let a=await jn.readdir(r,{withFileTypes:!0});for(let o of a)if(o.isDirectory()&&o.name.startsWith("explorer_tmp_")){let s=Me.join(r,o.name);y.warn("Removing stale temp directory from crashed sync",{dir:`${i.name}/${o.name}`});try{await jn.rm(s,{recursive:!0,force:!0})}catch(c){y.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;y.warn("Failed to scan for stale temp dirs",{error:n instanceof Error?n.message:String(n)})}}};import kr from"path";import{promises as xx}from"fs";Sr();ce();var _x=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=kr.resolve(s,u);if(!gx(s,d)){l.push({path:u,error:"Path is outside the place root"});continue}try{let p=await xx.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=lt(m),h=St(m);h&&g&&await o.writer.removeFromTree(h,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(!gx(o,kr.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=kr.resolve(c,r);if(!gx(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 xx.mkdir(kr.dirname(l),{recursive:!0});let p=i.studioContent,f=u.computeHash(p);s.fileWatcher?.suppressPath(l,f),await xx.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 xx.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),y.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=kr.relative(r,n);if(a.startsWith("..")||a===""||kr.isAbsolute(a))return null;let o=a.split(kr.sep).filter(f=>f.length>0);if(o.length<2)return null;let s=kr.basename(n),c=kr.dirname(n),l=e.getOriginalInstance(c,s);if(l)return l.instancePath;let u=s.toLowerCase();if(jb.some(f=>u.endsWith(f))||u==="_tree.json")return null;let d=["game"],p=r;for(let f of o){p=kr.join(p,f);let m=kr.dirname(p);d.push(e.getOriginalNameForDir(m,f))}return gt(d)}};Sr();Lb();ce();var Hfe=5;function J8(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 Zfe(t){return t.type==="instanceAdded"||t.type==="instanceRemoved"||t.type==="instanceRenamed"||t.type==="instanceMoved"||t.type==="scriptSourceChanged"}var Kr=class{config;places;apiHandler;changeProcessor;initHandler;reverseHandler;reverseDetectorFactory;activeFullSyncPlaceId=null;activeRuntimeSyncPlaceId=null;currentConnectedPlaceId=null;currentConnectedPlaceName=null;constructor(e,n={}){this.config=new $b(e,n),this.reverseDetectorFactory=n.reverseDetectorFactory??(i=>new px(i.explorerRoot,i.syncIndex,{placeId:i.placeId})),this.apiHandler=new vx(this),this.changeProcessor=new hx(this),this.initHandler=new bx(this),this.reverseHandler=new _x(this),this.places=new ux({max:Hfe,dispose:(i,r)=>{y.info("Disposing place context (LRU eviction)",{placeId:r}),this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),i.fileWatcher&&(y.info("Disposing place context: stopping reverse detector",{placeId:r,reason:"lru-dispose",mode:ut}),i.fileWatcher.stop("lru-dispose").catch(a=>{y.error("Error stopping reverse detector during dispose",a)}),i.fileWatcher=null),i.writer.stopChangeLogFlusher().catch(a=>{y.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=>{y.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&&(y.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=TE.join(r,"explorer");await Pl.mkdir(r,{recursive:!0}),await Pl.mkdir(a,{recursive:!0});let o=new Fa(r,a);await o.loadFromDisk();let s=new Cl(this.config,o,e),c=new dx(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:{...Wo},applyModes:{...Go},autoApplyDeletes:!1,forwardRestoreQueue:[],syncProgress:null,collisionDirMap:null,activeSyncIdentityScope:null},this.places.set(e,i),y.info("Created new place context",{placeId:e,placeRoot:r})}return i}async handleSyncInit(e,n){try{J8(e.body);let i=W8(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{J8(e.body);let i=G8(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=H8(o,r.changes);y.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++,Zfe(m)&&(d=!0))}catch(g){let h="path"in m?m.path:"oldPath"in m?m.oldPath:"unknown";c.push({path:h,error:g instanceof Error?g.message:String(g)})}for(let m of p.values())try{await fx(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 zb(m,g),await ll(m)}catch(m){y.warn("Failed to refresh sourcemaps after incremental sync update",{placeId:a,error:m instanceof Error?m.message:String(m)})}o.changesSinceLastSave+=u,o.changesSinceLastSave>=V8&&(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,autoApplyDeletes:!1,reverseDetectorActive:!1,reverseDetectorMode:ut,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,autoApplyDeletes:a.autoApplyDeletes,directions:a.directions,reverseDetectorActive:s,reverseDetectorMode:ut,fileWatcherActive:c,forwardOnlyClasses:[...cl]};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(),a=lf(i);if(y.info("handleSyncStop requested",{placeId:r,clientId:i.clientId??null,identityScope:a,reason:i.reason??"requested"}),r==null){n.status(200).json({status:"idle",state:"idle",placeId:null,message:"No active sync place"});return}let o=this.places.get(r);if(!o){y.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}let s=!!(i.clientId&&o.activeClientId&&i.clientId!==o.activeClientId),c=o.activeFullSyncSessionId!==null||o.state==="syncing"||o.state==="initializing",l=!!(a&&o.activeSyncIdentityScope&&a===o.activeSyncIdentityScope);if(s&&c&&!l){y.warn("handleSyncStop rejected due to active client mismatch",{placeId:r,requestedClientId:i.clientId,activeClientId:o.activeClientId,requestedIdentityScope:a,activeIdentityScope:o.activeSyncIdentityScope,state:o.state,activeFullSyncSessionId:o.activeFullSyncSessionId}),n.status(409).json({error:"Conflict",message:`This sync session belongs to client ${o.activeClientId}`});return}s&&l&&y.info("handleSyncStop accepted stale client cleanup by identity scope",{placeId:r,requestedClientId:i.clientId,activeClientId:o.activeClientId,identityScope:a,state:o.state});let u=o.activeFullSyncSessionId,d=o.state,p=o.fileWatcher!==null;if(u&&(this.initHandler.clearPreserveLocalFiles(u),this.initHandler.clearPendingServiceTrees(u)),o.fileWatcher&&(y.info("handleSyncStop suspending reverse detector",{placeId:r,state:o.state,activeClientId:o.activeClientId,mode:ut}),o.fileWatcher.beginFullSyncReplacement()),o.incompleteSyncTimer&&(clearTimeout(o.incompleteSyncTimer),o.incompleteSyncTimer=null),u){let f=this.config.getPlaceRoot(r),m=TE.join(f,`explorer_tmp_${u}`);await Pl.rm(m,{recursive:!0,force:!0}).catch(()=>{})}o.tmpWriter&&(o.tmpWriter.stopChangeLogFlusher(),o.tmpWriter=null),o.tmpIndex=null,o.collisionDirMap=null,o.activeSyncIdentityScope=null,o.syncInitRequestsInFlight=0,o.activeFullSyncSessionId=null,o.syncProgress=null,o.state="idle",o.activeClientId=null,o.instanceCount=0,o.scriptCount=0,o.forwardRestoreQueue=[],this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),this.clearRuntimePlaceIfMatch(r),y.info("handleSyncStop responding idle",{placeId:r,previousState:d,activeFullSyncSessionId:u,hadWatcher:p}),y.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(),y.info("SyncController initialized")}catch(e){y.error("SyncController initialization failed",e instanceof Error?e:new Error(String(e)))}}async shutdown(){try{y.info("SyncController shutdown: clearing place contexts",{placeCount:this.places.size}),this.places.clear(),y.info("SyncController shut down")}catch(e){y.error("SyncController shutdown error",e instanceof Error?e:new Error(String(e)))}}async atomicWriteFile(e,n){let i=e+".tmp."+Bfe().slice(0,8);try{await Pl.writeFile(i,n,"utf-8"),await Pl.rename(i,e)}catch(r){throw await Pl.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"){y.debug("Skipping reverse detector start - place not syncing",{placeId:e.placeId,state:e.state});return}if(e.fileWatcher){if(e.fileWatcher.isActivelyScanning()){y.info("startFileWatcherForPlace: reusing active reverse detector",{placeId:e.placeId,mode:ut});return}y.info("startFileWatcherForPlace: resuming paused reverse detector",{placeId:e.placeId,mode:ut}),e.fileWatcher.endFullSyncReplacement();return}let n=this.createReverseChangeDetector(e);this.configureReverseChangeDetector(e,n),e.fileWatcher=n,n.start().then(()=>{e.fileWatcher===n&&y.info("Reverse detector started for reverse sync",{placeId:e.placeId,mode:ut})}).catch(i=>{y.warn("Failed to start reverse detector",{placeId:e.placeId,mode:ut,error:i instanceof Error?i.message:String(i)}),e.fileWatcher===n&&(e.fileWatcher=null)})}createReverseChangeDetector(e){return this.reverseDetectorFactory({explorerRoot:TE.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=I6(i);return e.directions[r]}),n.setOnForwardViolation(i=>{e.forwardRestoreQueue.includes(i)||(e.forwardRestoreQueue.push(i),y.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"){y.warn(`SyncController.${i} disk error`,{code:a,message:r}),e.status(500).json({error:"Disk error",message:r,code:a,operation:i});return}y.error(`SyncController.${i} failed`,n instanceof Error?n:new Error(r)),e.status(500).json({error:"Internal error",message:`${i}: ${r}`})}};import{randomUUID as Vfe}from"crypto";function Y8(t,e){let n=Vfe(),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 X8=Pt(Ta(),1);ce();function Q8(t){let e=X8.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)=>{y.debug(`${n.method} ${n.path}`,{ip:n.ip}),r()})}xa();import{randomUUID as Yx}from"crypto";xa();ce();function Wfe(){let t=process.env.WEPPY_ROBLOX_MCP_VERSION?.trim();return t||null}var Xe=Wfe()??"2.10.2";wi();tr();ff();Da();fl();xa();Da();var aq="studio-",Kfe=/^studio-[1-9]\d*$/;function Ix(t){return Kfe.test(t)}function oq(t,e){let n=new Set;for(let i of t)e!==void 0&&i.clientId===e||i.targetAlias&&Ix(i.targetAlias)&&n.add(i.targetAlias);return n}function Jfe(t,e){let n=oq(t,e),i=1;for(;n.has(`${aq}${i}`);)i+=1;return`${aq}${i}`}function kx(t,e){let n=oq(t,e.clientId);return e.targetAlias&&Ix(e.targetAlias)&&!n.has(e.targetAlias)||(e.targetAlias=Jfe(t,e.clientId)),e.targetAlias}fl();function Px(t){for(let e of t)kx(t,e)}function Rx(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??Ze.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),t.studioState!==void 0&&(e.studioState=t.studioState),t.studioStateSource!==void 0&&(e.studioStateSource=t.studioStateSource),t.studioStateUpdatedAt!==void 0&&(e.studioStateUpdatedAt=t.studioStateUpdatedAt),t.playtestMode!==void 0&&(e.playtestMode=t.playtestMode),e}function ME(t){let e=Cn(t);return Px(e),ef(e.map(Rx),null)}function Ex(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 sq(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),y.debug("Removed stale MCP instance",{instanceId:i,lastSeen:r.lastSeen}))}function cq(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"){y.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}),y.debug("Selection cache updated",{count:r.count,clientId:a,timestamp:o}),n.json({status:"ok",timestamp:o})}catch(r){y.error("Error handling selection update",r),n.status(500).json({error:"Internal server error"})}}function lq(t,e,n){let i=parseInt(e.query.maxAge)||3e4,r=mf(t,i);r?n.json({cached:!0,...r}):n.json({cached:!1,message:"No cached selection available"})}function mf(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 zE(t,e){let n=t.pluginClients.get(e.clientId),i=Date.now(),r=[...t.pluginClients.values()].filter(c=>c.clientId===e.clientId||c.commandSessionState!==Ze.DISCONNECTED),a=n??{clientId:e.clientId,connectedAt:i,lastSeen:i,commandsProcessed:0,connectionType:"polling"},o=kx(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,studioState:n?.studioState,studioStateSource:n?.studioStateSource,studioStateUpdatedAt:n?.studioStateUpdatedAt,playtestMode:n?.playtestMode,...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)&&ex(t,s.placeId,s.placeName??null),t.analyticsManager&&(e.pluginVersion&&t.analyticsManager.setPluginVersion(e.pluginVersion),t.analyticsManager.trackPluginConnected()),y.info("Plugin client registered",{clientId:e.clientId,targetAlias:o,projectName:e.projectName,placeName:e.placeName,isReconnect:!!n}),{clientInfo:s,sessionId:t.sessionId,mcpVersion:Xe,mcpInstanceCount:t.mcpInstances.size+1,aiClientNames:Ex(t)}}function LE(t,e){let n=t.pluginClients.get(e),i=t.pluginClients.has(e),r=n?.commandSessionState===Ze.CONNECTED;if(t.pluginClients.delete(e),t.pendingCommands.delete(e),i&&pl(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&&tf(t,e,"disconnected",n),y.info("Plugin client unregistered",{clientId:e,existed:i}),i}function Tx(t,e,n){try{let i=e.body;if(!i.clientId){n.status(400).json({error:"Missing clientId"});return}let r=zE(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){y.error("Error registering plugin client",i),n.status(500).json({error:"Internal server error"})}}function Ax(t,e,n){let i=e.body?.clientId;if(!i){n.status(400).json({error:"Missing clientId"});return}let r=LE(t,i);n.json({status:"ok",existed:r})}function uq(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),rt(t,"mcp_status",{aiClientName:a.aiClientName??"Unknown",instanceId:i.instanceId,status:"registered"}),yl(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}:{}}),y.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:Xe,mcpInstanceCount:t.mcpInstances.size+1})}catch(i){y.error("Error registering MCP instance",i),n.status(500).json({error:"Internal server error"})}}function dq(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&&(rt(t,"mcp_status",{aiClientName:r?.aiClientName??"Unknown",instanceId:i,status:"unregistered"}),yl(t,{timestamp:new Date().toISOString(),type:"mcp",status:"unregistered",instanceId:i,message:`MCP unregistered \u2014 ${r?.aiClientName??i}`,...r?.aiClientName?{aiClientName:r.aiClientName}:{}})),y.info("MCP instance unregistered",{instanceId:i,existed:a}),n.json({status:"ok",existed:a})}function pq(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 fq(t){let e=3e4,n=Date.now(),i=_r({appDataDir:t.config.appDataDir});for(let[a,o]of t.pluginClients)n-o.lastSeen>e&&(t.pluginClients.delete(a),t.pendingCommands.delete(a),pl(t,a));sq(t);let r=Cn(t);return Px(r),{serverInstanceId:t.instanceId,sessionId:t.sessionId,mcpVersion:Xe,uptime:n-t.startTime,serverStartTime:t.startTime,serverExecutable:process.execPath,serverHost:t.config.httpHost,serverPort:t.config.httpPort,serverPid:process.pid,pluginClients:r.map(Rx),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 $x(t,e){e.json(fq(t))}function Ox(t,e,n){let i=e.query.instanceId;i&&t.mcpInstances.has(i)&&(t.mcpInstances.get(i).lastSeen=Date.now()),sq(t);let r=Cn(t);Px(r);let s={...{status:"online",connectedClients:r.length,queuedCommands:l8(t),uptime:Date.now()-t.startTime,version:Xe,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:Ex(t),pluginVersion:t.pluginVersion||void 0,dashboardSseClients:t.dashboardSseClients?.size??0,websocketClients:r.length,pluginClients:r.map(Rx),...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 mq(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")){y.warn("Shutdown request rejected from non-localhost",{ip:r}),n.status(403).json({error:"Forbidden: localhost only"});return}y.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(),y.info("Graceful shutdown completed"),process.exit(0)}catch(o){y.error("Error during graceful shutdown",o),process.exit(1)}},100)}async function Dx(t){if(t.isClientMode)try{let e=await fetch(`${t.baseUrl}/connection-info`);if(e.ok)return await e.json()}catch(e){y.warn("Failed to fetch connection info from server",{error:e})}return fq(t)}Da();var dt={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"}},Xfe=new Set([dt.canonical.runTest]),Qfe=new Set([dt.canonical.playStop]),q4e=new Set([dt.canonical.playStart,dt.canonical.playStop,dt.canonical.playPause,dt.canonical.playResume,dt.canonical.playStatus]);function Jr(t){return Xfe.has(t)}function gf(t){return Qfe.has(t)}var V4e=dt.canonical.playStop,gq=[5e3,15e3];fl();var eme=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm","manage_assets_review_model","manage_assets_generate_model","manage_assets_import_rbxm","manage_assets_generate_thumbnail"]),on=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 tme(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 on("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 on("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&&nme(e,t)){if(typeof a!="number"||!Number.isFinite(a))throw new on("invalid_target_selector","placeId target selector must be a finite number",{selectionMode:"placeId"});n.requestedPlaceId=a}return n}function Nx(t,e,n={},i){let r=tme(n,i),a=z6(e,t.studioRoutingMode==="pinned"?t.pinnedTargetClientId:null);if(r.requestedClientId!==void 0)return rme(a,r);if(r.requestedTargetAlias!==void 0)return ime(a,r);if(r.requestedPlaceId!==void 0)return ame(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:Pr("pinnedTarget",r,s)}}let o=a[0];return o?{targetClientId:o.clientId,routing:Pr("recentPriority",r,o)}:{routing:{selectionMode:"globalQueue"}}}function nme(t,e){return!t||!eme.has(t)?!0:e.scope==="shared"}function rme(t,e){let n=t.find(i=>i.clientId===e.requestedClientId);if(!n)throw new on("target_client_not_found",`Target client not found: ${e.requestedClientId}`,Pr("clientId",e));if(e.requestedTargetAlias!==void 0&&n.targetAlias!==e.requestedTargetAlias)throw new on("target_selector_mismatch",`Target client ${n.clientId} does not match targetAlias ${e.requestedTargetAlias}`,Pr("clientId",e,n));return hq("clientId",e,n),{targetClientId:n.clientId,routing:Pr("clientId",e,n)}}function ime(t,e){let n=t.find(i=>i.targetAlias!==void 0&&Ix(i.targetAlias)&&i.targetAlias===e.requestedTargetAlias);if(!n)throw new on("target_alias_not_found",`Target alias not found: ${e.requestedTargetAlias}`,Pr("targetAlias",e));return hq("targetAlias",e,n),{targetClientId:n.clientId,routing:Pr("targetAlias",e,n)}}function ame(t,e){let n=t.filter(r=>r.placeId===e.requestedPlaceId);if(n.length===0)throw new on("target_place_not_found",`Target place not found: ${e.requestedPlaceId}`,Pr("placeId",e));if(n.length>1)throw new on("target_place_ambiguous",`Target place is ambiguous: ${e.requestedPlaceId}`,Pr("placeId",e));let i=n[0];return{targetClientId:i.clientId,routing:Pr("placeId",e,i)}}function hq(t,e,n){if(e.requestedPlaceId!==void 0&&n.placeId!==e.requestedPlaceId)throw new on("target_selector_mismatch",`Target client ${n.clientId} is not connected to placeId ${e.requestedPlaceId}`,Pr(t,e,n))}function Pr(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}eE();ce();uf();var Tl={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","review_model","generate_model","upload_asset","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 ome={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 jx(t){return ome[t]||"plugin"}var yq=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_model","manage_assets_generate_thumbnail","manage_assets_import_rbxm","manage_assets_info","manage_assets_insert","manage_assets_insert_free","manage_assets_insert_package","manage_assets_review_model","manage_assets_search","manage_assets_search_insert","manage_assets_upload_asset","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"]),UE=new Set(["system_info_connection","system_info_ping","system_info_usage"]);function zn(t){return yq.has(t)?"pro":"basic"}ki();Mx();import{readFile as Ime}from"node:fs/promises";import kme from"node:path";import{createHash as xme,randomUUID as HE}from"node:crypto";import{mkdir as xf,readFile as Pq,readdir as Rq,rename as Eq,rm as _me,stat as Sme,writeFile as qx}from"node:fs/promises";import zt from"node:path";import{extname as ume}from"node:path";import{stat as dme}from"node:fs/promises";var pme=20*1024*1024,Iq=[{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"}}],fme=new Map(Iq.map(t=>[t.category,t]));function xq(t){if(!t)throw new Error("Open Cloud asset upload is disabled in WEPPY Dashboard settings.")}function zx(t,e){return t.split(e.apiKey).join("[redacted]")}function qE(t){let e=fme.get(t);if(!e)throw new Error(`Unsupported asset category: ${t}`);return e}function Lx(t){return qE(t)}function _q(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 Sq(t,e,n){let i=ume(e).toLowerCase(),r=t.contentTypes[i];if(!r)throw new Error(`Unsupported file extension ${i||"(none)"} for ${t.category}.`);if((await dme(e)).size>n)throw new Error(`Asset file is too large. Maximum size is ${n} bytes.`);return r}function wq(t){return typeof t.path=="string"&&t.path.startsWith("operations/")?t.path:null}function Cq(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 Al=class{client;credentialStore;isOpenCloudUploadEnabled;maxFileSizeBytes;constructor(e){this.client=e.client,this.credentialStore=e.credentialStore,this.isOpenCloudUploadEnabled=e.isOpenCloudUploadEnabled,this.maxFileSizeBytes=e.maxFileSizeBytes??pme}getCapabilities(){return Iq.map(({contentTypes:e,...n})=>n)}async uploadAsset(e){xq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=_q(e,n),r=qE(i.category),a=await Sq(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=wq(s);return c?await this.client.pollOperation(Cq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(zx(o instanceof Error?o.message:String(o),n))}}async updateAsset(e){xq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=_q(e,n),r=qE(i.category),a;if(i.filePath){if(!r.supportsContentUpdate)throw new Error(`${r.category} assets do not support content updates.`);a=await Sq(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=wq(s);return c?await this.client.pollOperation(Cq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(zx(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(zx(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(zx(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 kq from"node:fs";import Jt from"node:path";Ob();var mme=/^asset_(image|decal|audio|mesh|model|video|animation)_\d+_[a-z0-9]+$/;function gme(t){if(!Number.isInteger(t)||t<0)throw new Error(`Invalid place ID: ${t}`)}function hme(t,e){try{return kq.statSync(Jt.join(t,e,".sync-meta.json")).isFile()}catch{return!1}}function yme(t,e){gme(e.placeId);let n=`place_${e.placeId}`,i=e.placeName?ol(e.placeName):"",r=i?`${n}_${i}`:n,a=[];try{let o=new RegExp(`^place_${e.placeId}(?:_.*)?$`);a=kq.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=>hme(t,o))??(a.includes(r)?r:null)??a[0]??r}function BE(t){let e=Jt.resolve(t.projectSyncRoot),n=Lx(t.category).folder,i=t.scope.kind==="place"?Jt.join(e,yme(e,t.scope),"assets",n):Jt.join(e,"shared-assets",n);return{root:i,inbox:Jt.join(i,"inbox"),index:Jt.join(i,".asset-library-index.json")}}function vme(t){let e=mme.exec(t);return e?.[1]?e[1]:null}function yf(t,e){let n=vme(t);return n?e?n===e:!0:!1}function Ux(t,e){if(!yf(t,e))throw new Error(`Invalid asset ID: ${t}`)}function Yr(t,e){let n=Jt.relative(Jt.resolve(t),Jt.resolve(e));return n===""||!n.startsWith("..")&&!Jt.isAbsolute(n)}function bme(t){Ux(t.assetId,t.category);let e=BE(t),n=Jt.resolve(e.root,t.assetId);if(!Yr(e.root,n))throw new Error(`Invalid asset path for ${t.assetId}`);return n}function Fx(t){let e=bme(t),n=Jt.resolve(e,t.relativeFileName);if(!Yr(e,n))throw new Error(`Invalid asset file path for ${t.assetId}`);return n}function vf(t,e){return Jt.relative(Jt.resolve(t),Jt.resolve(e)).split(Jt.sep).join("/")}var Tq=20*1024*1024,wme=200;function Aq(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 $q(t,e){let n=zt.extname(t).toLowerCase(),i=Lx(e);if(!i.extensions.includes(n))return null;let r=i.contentTypes[n];return r?{canonicalExt:n,mimeType:r}:null}function ZE(t,e,n){if(e!=="image"&&e!=="decal")return!0;let i=zt.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 Oq(t){return xme("sha256").update(t).digest("hex")}function Bx(t){return t.now?.()??Date.now()}function Cme(t){return(t.randomId?.()??HE().replace(/-/g,"").slice(0,6)).toLowerCase().replace(/[^a-z0-9]/g,"").slice(0,12)||"asset"}function Dq(t,e){let n=Math.floor(Bx(t)/1e3);for(let i=0;i<20;i++){let r=Cme(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}_${HE().replace(/-/g,"").slice(0,10)}`}function Nq(t){let e=zt.parse(t).name.trim();return e.length>0?e:t}function jq(t){if(t.mimeType!=="image/png")throw new Error("Asset Library preview must be an image/png thumbnail");if(zt.basename(t.fileName).toLowerCase()!=="thumbnail.png")throw new Error("Asset Library preview file must be thumbnail.png");if(!ZE("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 VE(t,e){let n=`${t}.tmp.${HE().slice(0,8)}`;await qx(n,JSON.stringify(e,null,2),"utf8"),await Eq(n,t)}async function Mq(t,e){try{let n=await Pq(zt.join(e,"asset.json"),"utf8"),i=JSON.parse(n);return!yf(i.id,t.category)||i.category!==t.category||!Aq(i.scope,t.scope)?null:i}catch{return null}}async function bf(t,e){let n;try{n=await Rq(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()||!yf(r.name,t.category))continue;let a=zt.join(e.root,r.name),o=await Mq(t,a);o&&i.push(o)}return i.sort((r,a)=>a.createdAt.localeCompare(r.createdAt)||a.id.localeCompare(r.id))}async function $l(t,e,n){if(Ux(n.id,t.category),n.category!==t.category||!Aq(n.scope,t.scope))throw new Error(`Asset metadata does not match library scope/category: ${n.id}`);let i=zt.join(e.root,n.id);if(!Yr(e.root,i))throw new Error(`Invalid asset path for ${n.id}`);await xf(i,{recursive:!0}),await VE(zt.join(i,"asset.json"),n)}async function zq(t,e){await xf(t.root,{recursive:!0});let n={version:1,generatedAt:new Date().toISOString(),assets:e.map(i=>i.id)};await VE(t.index,n)}function Ti(t,e,n){return{fileName:t,reason:e,message:n}}async function Xr(t){let e=BE(t);return await xf(e.inbox,{recursive:!0}),e}async function Lq(t){let e=await Xr(t),n=await bf(t,e);return await zq(e,n),n}async function Lt(t,e){Ux(e,t.category);let n=await Xr(t),i=zt.join(n.root,e);if(!Yr(n.root,i))throw new Error(`Invalid asset path for ${e}`);let r=await Mq(t,i);if(!r)throw new Error(`Asset not found: ${e}`);return r}async function Ol(t){let e=await Xr(t),n=await bf(t,e),i={version:1,generatedAt:new Date().toISOString(),assets:n.map(r=>r.id)};return await VE(e.index,i),i}async function Uq(t){let e=await Xr(t),n=await bf(t,e),i=new Set(n.map(p=>p.id)),r=new Set(n.map(p=>p.file.sha256)),a=[],o=[],s=t.maxFileSizeBytes??Tq,c=t.maxFilesPerRescan??wme,l;try{l=await Rq(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(Ti(f.name,"maxFileCount","rescan file count limit exceeded"));continue}if(f.name.startsWith(".")){o.push(Ti(f.name,"hidden","hidden or system file"));continue}if(f.isSymbolicLink()){o.push(Ti(f.name,"symlink","symlink files are not followed"));continue}if(f.isDirectory()){o.push(Ti(f.name,"nestedDirectory","nested directories are not scanned"));continue}if(!f.isFile()){o.push(Ti(f.name,"unsupportedType","unsupported inbox entry type"));continue}let m=$q(f.name,t.category);if(!m){o.push(Ti(f.name,"unsupportedType",`unsupported ${t.category} extension`));continue}let g=zt.join(e.inbox,f.name),h=await Sme(g);if(h.size>s){o.push(Ti(f.name,"oversized","asset file is larger than the configured limit"));continue}let v=await Pq(g);if(!ZE(f.name,t.category,v)){o.push(Ti(f.name,"invalidSignature","file signature does not match the extension"));continue}let x=Oq(v);if(r.has(x)){o.push(Ti(f.name,"duplicate","asset content already exists in Asset Library"));continue}let _=Dq(t,i);i.add(_),r.add(x);let I=zt.join(e.root,_),w=`original${m.canonicalExt}`;await xf(I,{recursive:!0}),await Eq(g,zt.join(I,w));let D=new Date(Bx(t)).toISOString(),M={version:1,id:_,category:t.category,scope:t.scope,status:"localOnly",displayName:Nq(f.name),description:"",source:{kind:"generated",originalPath:vf(t.projectSyncRoot,g)},file:{original:w,preview:null,mimeType:m.mimeType,sha256:x,sizeBytes:h.size,width:null,height:null,durationMs:null},roblox:{uploaded:!1},usage:{lastScannedAt:null,scanSource:null,references:[]},createdAt:D,updatedAt:D};await $l(t,e,M),a.push(M)}let d=await bf(t,e);return await zq(e,d),{assets:d,adopted:a,skipped:o,adoptedCount:a.length,skippedCount:o.length}}async function Fq(t){let e=await Xr(t),n=$q(t.originalFileName,t.category);if(!n)throw new Error(`Unsupported ${t.category} extension for Asset Library export`);let i=t.maxFileSizeBytes??Tq;if(t.content.length>i)throw new Error("asset file is larger than the configured limit");if(!ZE(t.originalFileName,t.category,t.content))throw new Error("file signature does not match the extension");let r=await bf(t,e),a=Oq(t.content),o=r.find(h=>h.file.sha256===a);if(o)return{asset:o,deduplicated:!0};let s=new Set(r.map(h=>h.id)),c=Dq(t,s),l=zt.join(e.root,c);if(!Yr(e.root,l))throw new Error(`Invalid asset path for ${c}`);let u=`original${n.canonicalExt}`;await xf(l,{recursive:!0}),await qx(zt.join(l,u),t.content);let d=null;if(t.preview){let h=jq(t.preview);d=h.fileName,await qx(zt.join(l,h.fileName),h.content)}let p=new Date(Bx(t)).toISOString(),f=t.roblox??{uploaded:!1},m=f.uploaded&&f.assetId?"uploaded":"localOnly",g={version:1,id:c,category:t.category,scope:t.scope,status:m,displayName:t.displayName?.trim()||Nq(t.originalFileName),description:t.description??"",source:{...t.source,originalPath:vf(t.projectSyncRoot,zt.join(l,u))},file:{original:u,preview:d,mimeType:n.mimeType,sha256:a,sizeBytes:t.content.length,width:null,height:null,durationMs:null},roblox:f,usage:{lastScannedAt:null,scanSource:null,references:[]},...t.rbxm?{rbxm:t.rbxm}:{},createdAt:p,updatedAt:p};return await $l(t,e,g),await Ol(t),{asset:g,deduplicated:!1}}async function qq(t){let e=await Xr(t),n=await Lt(t,t.assetId),i=jq(t.preview),r=Fx({...t,relativeFileName:i.fileName});await qx(r,i.content);let a={...n,file:{...n.file,preview:i.fileName},...n.rbxm&&t.rbxmThumbnail?{rbxm:{...n.rbxm,thumbnail:t.rbxmThumbnail}}:{},updatedAt:new Date(Bx(t)).toISOString()};return await $l(t,e,a),await Ol(t),{asset:a}}async function Bq(t,e,n){let i=await Xr(t),r=await Lt(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 $l(t,i,a),await Ol(t),a}async function Hq(t,e,n){let i=await Xr(t),a={...await Lt(t,e),usage:n,updatedAt:new Date().toISOString()};return await $l(t,i,a),await Ol(t),a}async function Zq(t,e){let n=await Xr(t);await Lt(t,e);let i=zt.join(n.root,e);if(!Yr(n.root,i))throw new Error(`Invalid asset path for ${e}`);return await _me(i,{recursive:!0}),await Ol(t),{assetId:e,removed:1}}async function Ha(t){let e=await Xr(t);return await $l(t,e,t.asset),await Ol(t),t.asset}async function Dl(t){let e=await Lt(t,t.assetId);return Fx({...t,relativeFileName:e.file.original})}async function Vq(t){let e=await Lt(t,t.assetId);return Fx({...t,relativeFileName:e.file.preview??e.file.original})}var Pme="https://create.roblox.com/dashboard/creations/store",Rme="manage_assets_import_rbxm",GE="manage_assets_generate_thumbnail",Eme="manage_assets_review_model";var KE=new Set([Rme,GE]),JE=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm",Eme]),Tme=new Set(["model","animation"]);function Qe(t){return t&&typeof t=="object"?t:null}function Ame(t){if(typeof t!="string"||!Tme.has(t))throw new Error(`Unsupported Asset Library .rbxm round-trip category: ${String(t??"(missing)")}`);return t}function $me(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 Wq(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 YE(t,e){let n=mt(t.config.dataDir),i=Ame(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=$me(e.placeId),s=t.syncController?.getDefaultRuntimePlaceId()??null,c=o??s??Wq(t)?.placeId??null;if(c===null)throw new Error("No placeId is available for Asset Library .rbxm round-trip.");let l=Wq(t,c);return{projectSyncRoot:n,scope:{kind:"place",placeId:c,...l?.placeName?{placeName:l.placeName}:{}},category:i,...a?{assetId:a}:{}}}function Ome(t){if(kme.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 Dme(t,e){if(typeof t!="string"||t.trim().length===0)throw new Error(`${e} is missing`);return Buffer.from(t,"base64")}function Nme(t,e){let n=Qe(e),r={kind:n?.kind==="generation"||typeof t.prompt=="string"?"generated":"studioExport",originalPath:"studio:selection"};if(n){let a=typeof n.path=="string"?n.path:typeof n.kind=="string"?n.kind:void 0;a&&(r.originalPath=`studio:${a}`);let o=ge(n.prompt,1e3);o&&(r.prompt=o)}if(!r.prompt){let a=ge(t.prompt,1e3);a&&(r.prompt=a)}return typeof t.contextId=="string"&&(r.contextId=t.contextId),r}function Yq(t){let e=Qe(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=_f(e.attempts);return i.length>0&&(n.attempts=i),Object.keys(n).length>0?n:void 0}function ge(t,e){return typeof t!="string"?null:t.slice(0,e)}function jme(t){if(typeof t!="string")return null;let e=t.trim();return/^\d+$/.test(e)?e:null}function Gq(t){return`rbxassetid://${t}`}function Kq(t){return`${Pme}/${t}/configure`}function Jq(t){return`assets/${t}`}function rr(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Xq(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.name,256),r=ge(n.className,128),a=ge(n.path,512);return i===null||r===null||a===null?[]:[{name:i,className:r,path:a}]}):[]}function Mme(t){let e=Qe(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 zme(t){return Array.isArray(t)?t.slice(0,200).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.path,512),r=ge(n.property,128),a=ge(n.value,1024);if(i===null||r===null||a===null)return[];let o=ge(n.assetId,64);return[{path:i,property:r,value:a,...o?{assetId:o}:{}}]}):[]}function _f(t){return Array.isArray(t)?t.slice(0,8).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.method,80),r=n.status==="success"||n.status==="failed"||n.status==="skipped"?n.status:null;if(i===null||r===null)return[];let a=ge(n.message,512);return[{method:i,status:r,...a?{message:a}:{}}]}):[]}function Lme(t,e){let n=t.thumbnailMode==="auto"?"auto":"none";if(n==="none")return{mode:n,status:"skipped",message:"Thumbnail generation disabled"};let i=Yq(e),r=Qe(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=rr(i.width),c=rr(i.height),l=_f(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=_f(Qe(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 Ume(t,e){let n=Qe(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=ge(n.message,512),o=rr(n.width),s=rr(n.height),c=ge(n.source,128),l=_f(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 WE(t,e=0){if(e>3)return;if(typeof t=="string")return t.slice(0,512);if(typeof t=="boolean")return t;if(typeof t=="number")return Number.isFinite(t)?t:void 0;if(Array.isArray(t))return t.slice(0,50).flatMap(r=>{let a=WE(r,e+1);return a===void 0?[]:[a]});let n=Qe(t);if(!n)return;let i={};for(let[r,a]of Object.entries(n).slice(0,50)){let o=WE(a,e+1);o!==void 0&&(i[r.slice(0,128)]=o)}return i}function Fme(t){let e=Qe(t),n=rr(e?.x),i=rr(e?.y),r=rr(e?.z);if(!(n===void 0||i===void 0||r===void 0))return{x:n,y:i,z:r}}function qme(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=n.severity==="info"||n.severity==="warning"||n.severity==="error"?n.severity:null,r=ge(n.category,80),a=ge(n.code,120),o=ge(n.path,512),s=ge(n.message,512);if(!i||r===null||a===null||o===null||s===null)return[];let c=ge(n.suggestion,512);return[{severity:i,category:r,code:a,path:o,message:s,...c?{suggestion:c}:{}}]}):[]}function Bme(t){let e=Qe(t);if(!e)return;let n=e.readiness==="ready"||e.readiness==="review"||e.readiness==="blocked"?e.readiness:null;if(!n)return;let i=WE(e.summary),r=ge(e.reviewedAt,64),a=Xq(e.roots);return{readiness:n,...r?{reviewedAt:r}:{},...a.length>0?{roots:a}:{},summary:Qe(i)??{},findings:qme(e.findings)}}function Hme(t){let e=Qe(t);if(!e)return;let n={};for(let[i,r]of Object.entries(e).slice(0,16))typeof r=="string"&&(n[i.slice(0,128)]=r.slice(0,256)),typeof r=="number"&&Number.isFinite(r)&&(n[i.slice(0,128)]=r),typeof r=="boolean"&&(n[i.slice(0,128)]=r);return Object.keys(n).length>0?n:void 0}function Zme(t){let e=Qe(t);if(!e)return;let n=ge(e.provider,120);if(!n)return;let i=ge(e.generatedAt,64),r=ge(e.prompt,1e3),a=e.schemaMode==="predefined"||e.schemaMode==="custom"?e.schemaMode:void 0,o=e.predefinedSchema==="Body1"||e.predefinedSchema==="Car5"?e.predefinedSchema:void 0,s=Array.isArray(e.schemaGroups)?e.schemaGroups.slice(0,50).flatMap(f=>{let m=ge(f,120);return m?[m]:[]}):void 0,c=Fme(e.requestedSize),l=rr(e.maxTriangles),u=ge(e.targetParent,512),d=ge(e.path,512),p=Hme(e.metadata);return{provider:n,...i?{generatedAt:i}:{},...r?{prompt:r}:{},...a?{schemaMode:a}:{},...o?{predefinedSchema:o}:{},...s&&s.length>0?{schemaGroups:s}:{},...c?{requestedSize:c}:{},...l!==void 0?{maxTriangles:Math.floor(l)}:{},...typeof e.generateTextures=="boolean"?{generateTextures:e.generateTextures}:{},...u?{targetParent:u}:{},...d?{path:d}:{},...p?{metadata:p}:{}}}function Vme(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.path,512),r=n.assetType==="Mesh"||n.assetType==="Image"||n.assetType==="Model"?n.assetType:null,a=n.status==="uploaded"||n.status==="failed"?n.status:null;if(i===null||r===null||a===null)return[];let o=ge(n.assetId,64),s=ge(n.assetUri,128),c=n.creatorType==="user"||n.creatorType==="group"?n.creatorType:void 0,l=ge(n.creatorId,64),u=ge(n.sourceProperty,128),d=ge(n.uploadedAt,64),p=ge(n.message,512);return[{path:i,assetType:r,status:a,...o?{assetId:o}:{},...s?{assetUri:s}:{},...c?{creatorType:c}:{},...l?{creatorId:l}:{},...u?{sourceProperty:u}:{},...d?{uploadedAt:d}:{},...p?{message:p}:{}}]}):[]}function Wme(t){let e=Qe(t);if(!e||e.uploaded!==!0)return;let n=jme(e.assetId);if(!n)return;let i=ge(e.uploadedAt,64)??new Date().toISOString(),r=e.creatorType==="user"||e.creatorType==="group"?e.creatorType:void 0,a=ge(e.creatorId,64);return{uploaded:!0,assetId:n,assetUri:Gq(n),assetWebUrl:Kq(n),remotePath:Jq(n),uploadedAt:i,uploadAttempts:[{startedAt:i,finishedAt:i,status:"uploaded",assetRole:"primary",...r?{creatorType:r}:{},...a?{creatorId:a}:{},assetId:n,assetUri:Gq(n),assetWebUrl:Kq(n),remotePath:Jq(n)}]}}function Gme(t){let e=Qe(t.value),n=Xq(e?.roots),i=Mme(e?.classCounts),r=zme(e?.resourceReferences),a=Bme(e?.review),o=Zme(e?.generation),s=Vme(e?.studioUploads),c=rr(e?.exportedCount)??rr(t.exportedCount)??n.length;return{exportedCount:Math.max(0,Math.floor(c)),roots:n,classCounts:i,resourceReferences:r,thumbnail:Ume(e?.thumbnail,t.fallbackThumbnail),...a?{review:a}:{},...o?{generation:o}:{},...s.length>0?{studioUploads:s}:{}}}function Kme(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 Qq(t){let e=Qe(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(bq(e.base64Rgba,e.width,e.height),"base64")),!!n){if(!Kme(n))throw new Error("Thumbnail payload is not a valid PNG image.");return{fileName:"thumbnail.png",content:n,mimeType:"image/png"}}}function Jme(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 eB(t){if(!KE.has(t.command))return t.params;let e=YE(t.ctx,t.params);if(!e.assetId)throw new Error("assetLibraryAssetId is required for Asset Library .rbxm round-trip.");let n=await Lt(e,e.assetId);Ome(n);let i=await Dl({...e,assetId:n.id}),r=await Ime(i);return{...t.params,__assetLibraryRbxmBase64:r.toString("base64"),__assetLibraryOriginalFile:n.file.original}}async function tB(t){if(!JE.has(t.command)||!t.result.success)return t.result;let e=Qe(t.result.data);if(!e||typeof e.rbxmBase64!="string"||e.rbxmBase64.trim().length===0)return t.result;let n=YE(t.ctx,t.params),i=Dme(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=Qq(e.thumbnail)}catch(f){c=f,s=void 0}let l=Gme({value:e.rbxm,exportedCount:e.exportedCount,fallbackThumbnail:Lme(t.params,e.thumbnail)});c&&(l=Jme(l,c));let u=Wme(e.roblox),d=await Fq({projectSyncRoot:n.projectSyncRoot,scope:n.scope,category:n.category,originalFileName:o,content:i,...r!==void 0?{displayName:r}:{},...a!==void 0?{description:a}:{},source:Nme(t.params,e.source),...s?{preview:s}:{},rbxm:l,...u?{roblox:u}:{}}),p=Yq(e.thumbnail);return{...t.result,data:{asset:d.asset,deduplicated:d.deduplicated,...typeof e.byteLength=="number"?{byteLength:e.byteLength}:{},...typeof e.exportedCount=="number"?{exportedCount:e.exportedCount}:{},...e.source!==void 0?{source:e.source}:{},...p?{thumbnail:p}:{}}}}async function nB(t){if(!t.result.success)return t.result;let e=Qe(t.result.data),n=Qe(e?.thumbnail),i;try{i=Qq(n)}catch(d){return{...t.result,success:!1,error:d instanceof Error?d.message:String(d)}}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=rr(n.width),a=rr(n.height),o=ge(n.source,128),s=_f(n.attempts),c={mode:"auto",status:"generated",...r!==void 0?{width:r}:{},...a!==void 0?{height:a}:{},...o?{source:o}:{},...s.length>0?{attempts:s}:{}},l=YE(t.ctx,t.params);if(!l.assetId)throw new Error("assetLibraryAssetId is required for Asset Library thumbnail generation.");let u=await qq({projectSyncRoot:l.projectSyncRoot,scope:l.scope,category:l.category,assetId:l.assetId,preview:i,rbxmThumbnail:c});return{...t.result,data:{asset:u.asset,...r!==void 0?{width:r}:{},...a!==void 0?{height:a}:{},...o?{source:o}:{}}}}function Yme(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 Xme=/^Pro action '[^']+' is blocked in Basic mode\. Basic fallback '([^']+)' failed: (.*)$/s,Qme=/^Pro action '[^']+' is blocked in Basic mode\.(?! Basic fallback ')/,ege=/instance not found|not found in|parent not found/,tge=/is required|missing required/,nge=/unknown action|unknown command/,rge=/must be|invalid|cannot/;function ige(t){let e=Xme.exec(t);return e?{fallbackCommand:e[1],reason:e[2]}:null}function age(t){return Qme.test(t)}function oge(t){let e=t.toLowerCase();return ege.test(e)?"not_found":tge.test(e)?"missing_param":nge.test(e)?"unknown_action":rge.test(e)?"validation":"other"}function XE(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 Nl(t){if(t.resultSuccess){let e=Yme(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=ige(t.resultError);if(e)return{kind:"blocked_fallback_failed",fallbackCommand:e.fallbackCommand,blockedDetail:oge(e.reason)};if(age(t.resultError))return{kind:"blocked_unsupported"}}return t.failureClassification?{kind:XE(t.failureClassification)}:{kind:"error"}}function we(t,e,n,i,r={}){return{errorType:t,errorDetail:e,failureOrigin:n,recoverability:i,...r}}function sge(t){let e=t.toLowerCase();return/^\s*compilation error:/.test(e)?we("execution_failed","compile_error","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*result too large:/.test(e)?we("execution_failed","result_too_large","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*execution timed out after/.test(e)?we("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)?we("execution_failed","blocked_source","roblox_policy","code_fix",{validationStage:"plugin_handler"}):null}function rB(t){let e=t.toLowerCase();return/upstream_server_down/.test(e)?we("bridge_error","upstream_down","bridge","wait_connection"):/^http [45]\d\d/.test(e)?we("bridge_error","http_error","bridge","retry"):/duplicate request\s*id/.test(e)?we("bridge_error","duplicate_request_id","bridge","code_fix"):/timeout/.test(e)?we("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|econnreset|epipe|network/.test(e)?we("bridge_error","connection","bridge","wait_connection"):/abort/.test(e)?we("command_timeout","aborted","bridge","retry"):/runtime error|traceback|attempt to/.test(e)?we("plugin_runtime","runtime_error","plugin_runtime","code_fix"):/created instance, but failed to set \d+ propert/.test(e)?we("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler",partialSuccess:"true"}):/failed to set property/.test(e)?we("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler"}):/parent(?: instance)? not found/.test(e)?we("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)?we("execution_failed","not_found","user_project_state","fix_params",{validationStage:"plugin_handler"}):/is required|missing required/.test(e)?we("execution_failed","missing_param","agent_request","fix_params",{validationStage:"schema"}):/invalid classname|invalid class/.test(e)?we("execution_failed","invalid_class","agent_request","fix_params",{validationStage:"plugin_handler"}):/unknown action|unknown command/.test(e)?we("execution_failed","unknown_action","agent_request","fix_params",{validationStage:"dispatcher"}):/failed to insert asset/.test(e)?we("execution_failed","asset_error","roblox_policy","fix_params",{validationStage:"roblox_api"}):/failed to read property|property access denied/.test(e)?we("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)?we("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)?we("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)?we("execution_failed","unsupported_context","roblox_policy","no_retry",{validationStage:"preflight"}):/editableimage api is not enabled|allow mesh \/ image apis|allow http requests/.test(e)?we("execution_failed","feature_disabled","roblox_policy","no_retry",{validationStage:"preflight"}):/must be|invalid|cannot/.test(e)?we("execution_failed","validation","agent_request","fix_params",{validationStage:"plugin_handler"}):we("execution_failed","other","unknown","unknown")}function jl(t,e){if(t==="execute_luau"){let i=sge(e);if(i)return i}let n=rB(e);return t==="execute_luau"&&n.errorDetail==="runtime_error"&&/^\s*runtime error:/i.test(e)?we("execution_failed","runtime_error","agent_request","code_fix"):n}function iB(t){let n=(t instanceof Error?t.message:String(t)).toLowerCase();return/timeout/.test(n)?we("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|network|econnreset|epipe/.test(n)?we("bridge_error","connection","bridge","wait_connection"):/eaddrinuse/.test(n)?we("bridge_error","port_in_use","bridge","no_retry"):we("exception","unexpected","server_exception","code_fix")}Vx();import{randomBytes as fge}from"node:crypto";var mge=["manage_ui_create_tree","manage_ui_update","manage_ui_delete"],pB=["manage_ui_preview","manage_ui_check"],gge=["game_genre","ui_role","style_family","layout_family","device_policy","safe_area_policy","existing_ui_strategy"];function iT(t){return t&&typeof t=="object"?t:void 0}function nT(t){return typeof t=="number"&&Number.isFinite(t)?t:0}function Wx(t){let e=iT(t);if(!e)return;let n={};for(let i of gge){let r=e[i];typeof r=="string"&&r.trim().length>0&&(n[i]=r)}return Object.keys(n).length>0?n:void 0}function rT(t){let e=Wx(t.qualityPlanSummary);if(e)return e;let n=iT(t.contextSummary),i=Wx(n?.qualityPlanSummary);if(i)return i;let r=Wx(n?.qualityPlan);if(r)return r;let a=Wx(n?.quality_plan);if(a)return a}function fB(t,e){return e?{...t??{},...e}:t}function hge(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 mB(t,e,n,i,r){if(!e)return;let a=nT(e.priority_high),o=nT(e.priority_medium),s=nT(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 gB(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 yge(t){let e=iT(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 vge(){return{source:"unavailable",priority_high:0,priority_medium:0,priority_low:0,total:0}}function hB(t){let e=t.now??Date.now,n=null,i=null,r=u=>`${u}_${e()}_${fge(3).toString("hex")}`,a=()=>{i&&(clearTimeout(i),i=null)},o=()=>{a(),i=setTimeout(()=>{c("idle_timeout")},t.idleMs)},s=async u=>{try{return hge(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 h of d.affectedPaths)if(d.afterSnapshotsPathPolicy[h]==="skip")p[h]=null;else{let v=await s(h);p[h]=v.snapshotId,f=gB(f,mB("after_snapshot",v.designCheckSummary,h,v.snapshotId,v.capturedAt))}let m=f??d.latestDesignCheckSummary??vge(),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 lB(t.placeDir,g)},l=u=>({requestId:r("req"),contextId:u.contextId,label:yge(u.contextSummary),startedAtIso:new Date(e()).toISOString(),startedAtMs:e(),affectedPaths:new Set,beforeSnapshots:{},afterSnapshotsPathPolicy:{},childMutationIds:[],mutationCount:0,ok:!0,qualityPlanSummary:rT(u),latestDesignCheckSummary:void 0,pendingMutation:void 0});return{async beforeMutation(u){if(pB.includes(u.command)){if(n){let p=r("mut");n.qualityPlanSummary=fB(n.qualityPlanSummary,rT(u)),n.pendingMutation={mutationId:p,startedMs:e(),args:u}}return}if(!mge.includes(u.command))return;n&&n.contextId!==u.contextId?await c("context_change"):n&&a(),n||(n=l(u)),n.qualityPlanSummary=fB(n.qualityPlanSummary,rT(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 uB(t.placeDir,f),n.pendingMutation=void 0,pB.includes(p.command)){n.latestDesignCheckSummary=gB(n.latestDesignCheckSummary,mB("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 DB=100,Xge=12e4,Qge=15e3,NB=new Set(["manage_ui_create_tree","manage_ui_update","manage_ui_delete"]);function ehe(t,e){return`License required for internal command ${t}. ${e??"Activate Pro license to use this feature."}`}var the={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"}},nhe={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"},rhe=Object.entries(Tl).reduce((t,[e,n])=>{for(let i of n.validActions)t[`${e}_${i}`]=e;return t},{});function RB(t){return{toolName:rhe[t]||t,commandName:t}}function EB(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 Gx(t,e){if(t!=="manage_sync_status_current_place")return e;let{placeId:n,...i}=e;return i}function ihe(t,e){let n=e.routing;return{requestId:t,success:!1,error:e.message,errorCode:e.code,routing:n,data:{routing:n}}}async function ahe(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 ohe(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 she(t,e){let n=e.targetPath;if(typeof n=="string"&&n.length>0)return n;if(t==="manage_ui_create_tree")return ohe(e)}function che(t){let e=the[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 TB(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function lhe(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=TB(a,"before"),c=TB(a,"after");i.set(o,{...s&&{before:a.before},...c&&{after:a.after},hasBefore:s,hasAfter:c})}return i}function jB(t,e){let i=t.changes?.properties;if(!i||typeof i!="object")return;let r=lhe(e),a=Object.entries(i).map(([o,s])=>{let c=che(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 MB(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?`${nhe[r]} ${a}\uAC1C`:null}).filter(r=>r!==null);return i.length>0?`${i.join(", ")} \uBCC0\uACBD`:void 0}function AB(t,e){if(t==="manage_ui_update"){let n=e.changes,i=MB(jB(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 Af(t){return t&&typeof t=="object"?t:void 0}function Kx(t,e){let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:0}function zB(t){let e=Af(t),n=Af(e?.design_check_summary);if(n)return{priority_high:Kx(n,"priority_high"),priority_medium:Kx(n,"priority_medium"),priority_low:Kx(n,"priority_low"),total:Kx(n,"total"),...typeof n.scope=="string"&&{scope:n.scope},...typeof n.target=="string"&&{target:n.target}}}function LB(t){let n=Af(t)?.snapshot_id;return typeof n=="string"?n:null}function $B(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 UB(t){let e=Af(t),n=Af(e?.meta);return $B(n?.captured_at)??$B(n?.evaluated_at)}function uhe(t,e){let n=t.uiStudioRecorders.get(e);if(n)return n;let i=hB({placeDir:e,idleMs:Qge,capturePreview:async r=>{try{let a=await ir(t,"manage_ui_preview",{targetPath:r},Yx());if(!a.success||!a.data||typeof a.data!="object")return null;let o=zB(a.data),s=UB(a.data);return{snapshotId:LB(a.data),...o!==void 0&&{designCheckSummary:o},...s!==void 0&&{capturedAt:s}}}catch{return null}}});return t.uiStudioRecorders.set(e,i),i}async function dhe(t,e,n){if(!NB.has(e))return null;let i=await ahe(t,n);if(!i)return null;let r=uhe(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=she(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 y.debug("UI Studio recorder beforeMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:p}),null}}async function OB(t,e){if(t)try{let n=t.command==="manage_ui_update"?jB(t.params,e.data):void 0,i=t.command==="manage_ui_update"?MB(n)??AB(t.command,t.params):AB(t.command,t.params),r=zB(e.data),a=LB(e.data),o=UB(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){y.debug("UI Studio recorder afterMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:n})}}async function Jx(t,e,n,i,r,a){if(!t.historyManager)return;let o=!r.success&&r.error?jl(n,r.error):void 0,s=Nl({resultSuccess:r.success,resultData:r.data,resultError:r.error,tier:zn(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=Gx(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,Gx(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,Gx(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=Gx(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 cT(t,e,n){let i=t.pendingCommands.get(e)||[];i.length>=DB&&i.shift(),i.push(n),t.pendingCommands.set(e,i)}function phe(t,e){t.globalPendingCommands.length>=DB&&t.globalPendingCommands.shift(),t.globalPendingCommands.push(e)}function FB(t,e,n){let i=Yx(),r={requestId:i,command:e.command,params:e.params,timestamp:Date.now(),queueTimeoutMs:e.queueTimeoutMs,ackedTimeoutMs:e.ackedTimeoutMs,state:vn.QUEUED,targetClientId:n,resolve:()=>{},reject:a=>{y.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(()=>{Jb(t,r,r.queueTimeoutMs)},r.queueTimeoutMs),{event:"command",id:i,data:{command:r.command,requestId:i,params:r.params}}}function fhe(t,e,n,i){if(!gf(e.data.command))return;let r=t.commandQueue.get(e.data.requestId);if(!r)return;qB(t,r);let a=n.filter(o=>o.clientId!==i);for(let o of a){let s=FB(t,r,o.clientId);cT(t,o.clientId,s)}a.length>0&&y.info("Fan-out playtest stop command to active plugin clients",{requestId:e.data.requestId,primaryClientId:i,auxiliaryClientIds:a.map(o=>o.clientId)})}function qB(t,e,n){for(let i of gq)setTimeout(()=>{let a=n?[...new Set(n)]:[...new Set(Cn(t).map(o=>o.clientId))];for(let o of a){if(!t.pluginClients.get(o))continue;let c=FB(t,e,o);cT(t,o,c)}y.info("Retry playtest stop command to active plugin clients",{sourceRequestId:e.requestId,delayMs:i,targetClientIds:a}),hl(t)},i).unref?.()}function BB(t){return t==="clientId"||t==="targetAlias"||t==="placeId"}function mhe(t,e,n){if(!n||!gf(e.data.command))return!1;let i=t.commandQueue.get(e.data.requestId)?.routing?.selectionMode;return!BB(i)}function ghe(t,e,n){y.debug("Broadcasting command",{command:e.data.command,requestId:e.data.requestId,targetClientId:n||"all",activeWebsocketClients:Cn(t).length});let i=n;if(n){cT(t,n,e);let r=t.commandQueue.get(e.data.requestId),a=r?.routing?.selectionMode;if(r&&gf(e.data.command)&&BB(a))qB(t,r,[n]);else if(mhe(t,e,n)){let o=Cn(t).sort((s,c)=>c.lastSeen-s.lastSeen);fhe(t,e,o,n),i=void 0}}else phe(t,e);hl(t,i)}async function HB(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=RB(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(y.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=mf(t,m!==void 0?m:3e4),h=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,h,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,h,c.commandName),n.json({requestId:s,success:!0,data:x});return}if(r==="get_connection_info"){let m=await Dx(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(jx(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(zn(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 _=ehe(r,x.reason),I=Date.now()-i;t.historyManager&&await Jx(t,c.toolName,c.commandName,a,{success:!1,error:_},I),n.json({requestId:s,success:!1,error:_});return}}let m={...a,__sessionId:u},g=await t.internalCommandExecutor(r,m),h=Date.now()-i,v=EB(m,g.data);t.historyManager&&await Jx(t,c.toolName,c.commandName,v,{success:g.success,data:g.data,error:g.error||"Internal command failed"},h),n.json({requestId:s,...g});return}let d=await ir(t,r,a,s,l),p=Date.now()-i,f={...EB(a,d.data),__sessionId:u};t.historyManager&&await Jx(t,c.toolName,c.commandName,f,d,p),n.json(d)}catch(o){let s=Date.now()-i,c=Mn(o);if(t.historyManager&&r){let l=RB(r);await t.historyManager.recordFailure(l.toolName,a,c,s,"EXCEPTION",l.commandName)}y.error("Execute request failed",o),n.status(500).json({success:!1,error:c})}}async function ZB(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=Yx(),{action:l,...u}=r;try{t.serverLastCommandAt=Date.now();let d=await ir(t,s,u,c),p=Date.now()-i;t.historyManager&&await Jx(t,"manage_properties",s,u,d,p),n.json(d)}catch(d){let p=Date.now()-i,f=Mn(d);t.historyManager&&await t.historyManager.recordFailure("manage_properties",u,f,p,"EXCEPTION",s),y.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(y.debug("Executing command locally",{command:e,requestId:i}),Q6(t,i)){let d=`Duplicate requestId '${i}' for command '${e}'. Generate a unique requestId for each command.`;return y.warn("Duplicate execute request rejected",{command:e,requestId:i}),{requestId:i,success:!1,error:d}}let a;try{a=Nx(t,Cn(t),n,e)}catch(d){if(d instanceof on)return y.warn("Command target selection failed",{command:e,requestId:i,errorCode:d.code,routing:d.routing}),ihe(i,d);throw d}let o=NB.has(e)?await dhe(t,e,n):null,s=t.config.requestTimeout,c=r?.timeout??Math.max(t.config.requestTimeout,Xge),l=KE.has(e)?await eB({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:vn.QUEUED,...a.targetClientId?{targetClientId:a.targetClientId}:{},routing:a.routing,resolve:d,reject:p,timeoutId:null};t.commandQueue.set(i,m),Zb(t,a.targetClientId,f),m.timeoutId=setTimeout(()=>{Jb(t,m,s)},s)});return ghe(t,{event:"command",id:Yx(),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(()=>(sT(),oT)),g=await m(t,n),h=await f("manage_ui_preview",d.data,g);p={...d,data:h.data,...h.mcpContent?{mcpContent:h.mcpContent}:{}}}catch(f){y.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(()=>(sT(),oT)),{processCheckResult:m}=await Promise.resolve().then(()=>(PB(),kB)),g=await f(t,n),h=await m("manage_ui_check",d.data,g,n);p={...p,data:h.data}}catch(f){y.warn("check visual post-processing failed",{error:f instanceof Error?f.message:String(f)})}return JE.has(e)?p=await tB({ctx:t,command:e,params:n,result:p}):e===GE&&(p=await nB({ctx:t,params:n,result:p})),p}).then(async d=>(await OB(o,{success:d.success,...d.data!==void 0&&{data:d.data},...d.error!==void 0&&{error:d.error}}),d),async d=>{throw await OB(o,{success:!1,error:Mn(d)}),d})}ce();wi();function Xx(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),rt(t,"license",n)}function ti(t,e,n,i){t.status(e).json({success:!1,error:{code:n,message:i}})}function hhe(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();return e.length>0?e:void 0}function Qx(t,e){if(e==="plugin")return t;let n={...t};return delete n.sessionToken,n}function $f(t,e,n,i){let r=hhe(i??e.query.provider)??"auto";return t.licenseState?.supportsProvider(r)===!1?(ti(n,400,"LICENSE_PROVIDER_UNSUPPORTED",`provider "${r}" is not supported`),null):r}function Of(t,e){return t.licenseState?!0:(ti(e,503,"LICENSE_NOT_INITIALIZED","License system is not initialized"),!1)}function yhe(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 Df(t,e,n,i="plugin"){if(!Of(t,n))return;let r=e.body,a=typeof r?.licenseKey=="string"?r.licenseKey:"";if(!a.trim()){ti(n,400,"LICENSE_KEY_REQUIRED","licenseKey is required");return}let o=$f(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"),Xx(t,{provider:u.provider,tier:u.canUsePro?"pro":"basic",status:u.status,canUsePro:u.canUsePro}),n.json(Qx(u,i))}).catch(u=>{y.warn("License activate failed",{error:u instanceof Error?u.message:"unknown_error"}),ti(n,502,"LICENSE_ACTIVATE_FAILED",u instanceof Error?u.message:"License activation failed")})}function Nf(t,e,n,i="plugin"){if(!Of(t,n))return;let r=$f(t,e,n);if(r)try{let a=t.licenseState.getStatus(r);t.analyticsManager?.setTier(a.canUsePro?"pro":"basic"),n.json(Qx(a,i))}catch(a){y.warn("License status check failed",{error:a instanceof Error?a.message:"unknown_error"}),ti(n,502,"LICENSE_STATUS_FAILED",a instanceof Error?a.message:"License status check failed")}}function jf(t,e,n,i="plugin"){if(!Of(t,n))return;let r=e.body,a=$f(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"),Xx(t,{provider:s.provider,tier:s.canUsePro?"pro":"basic",status:s.status,canUsePro:s.canUsePro}),n.json(Qx(s,i))}).catch(s=>{y.warn("License refresh failed",{error:s instanceof Error?s.message:"unknown_error"}),ti(n,502,"LICENSE_REFRESH_FAILED",s instanceof Error?s.message:"License refresh failed")})}function Mf(t,e,n,i="plugin"){if(!Of(t,n))return;let r=e.body,a=$f(t,e,n,r?.provider);a&&t.licenseState.resetGateway({provider:a,clientType:i}).then(o=>{t.analyticsManager?.setTier("basic"),Xx(t,{provider:o.provider,tier:"basic",status:o.status,canUsePro:o.canUsePro,cleared:!0}),n.json(Qx(o,i))}).catch(o=>{y.warn("License reset failed",{error:o instanceof Error?o.message:"unknown_error"}),ti(n,502,"LICENSE_RESET_FAILED",o instanceof Error?o.message:"License reset failed")})}function lT(t,e,n){if(!Of(t,n))return;let i=e.body,r=$f(t,e,n,i?.provider);if(!r)return;if(i?.clientType!=="plugin"){ti(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=yhe(i?.snapshot)?i.snapshot:void 0;if(!o&&!a){ti(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"),Xx(t,{provider:c.provider,tier:c.canUsePro?"pro":"basic",status:c.status,canUsePro:c.canUsePro}),n.json({ok:!0})}).catch(c=>{y.warn("License bootstrap failed",{error:c instanceof Error?c.message:"unknown_error"}),ti(n,502,"LICENSE_BOOTSTRAP_FAILED",c instanceof Error?c.message:"License bootstrap failed")})}function VB(t){t.app.post("/license/bootstrap",(e,n)=>lT(t,e,n)),t.app.post("/license/activate",(e,n)=>Df(t,e,n,"plugin")),t.app.post("/license/refresh",(e,n)=>jf(t,e,n,"plugin")),t.app.post("/license/reset",(e,n)=>Mf(t,e,n,"plugin")),t.app.get("/license/status",(e,n)=>Nf(t,e,n,"plugin"))}ft();ce();import{promises as e_}from"fs";import uT from"path";function vhe(t){let e=t.config.appDataDir??ot();return uT.join(e,"observability","logs")}async function Fl(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)){y.warn("Invalid logs request",{body:r}),n.status(400).json({error:"Invalid request body"});return}let a=vhe(t);await e_.mkdir(a,{recursive:!0});let c=`plugin-${new Date().toISOString().split("T")[0]}.log`,l=uT.join(a,c),u=uT.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 ll(g)}catch(g){y.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=>{y.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}`}),y.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(y.warn("Incomplete sync TTL expired, cleaning up",{placeId:e.placeId,syncId:n}),e.incompleteSyncTimer=null,e.activeFullSyncSessionId===n&&e.syncInitRequestsInFlight>0){y.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=Me.join(r,`explorer_tmp_${n}`);try{await jn.rm(a,{recursive:!0,force:!0})}catch(o){y.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))},Z8);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=St(i.path),s=lt(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:St(i.path),originalName:lt(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=Kt(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?Kt(n).map(i=>e.tmpIndex.sanitizeName(i)):Kt(n)}rewritePendingEffectivePaths(e,n,i,r){let a=Me.relative(n,i).split(Me.sep).filter(l=>l.length>0),o=Me.relative(n,r).split(Me.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 jn.readdir(e,{withFileTypes:!0});for(let i of n)if(i.isDirectory()){if(i.name.startsWith("explorer_tmp_")){let r=Me.join(e,i.name);y.warn("Removing stale temp directory from crashed sync",{dir:i.name});try{await jn.rm(r,{recursive:!0,force:!0})}catch(a){y.error(`Failed to remove stale temp dir: ${i.name}`,a instanceof Error?a:new Error(String(a)))}}if(i.name.startsWith("place_")){let r=Me.join(e,i.name);try{let a=await jn.readdir(r,{withFileTypes:!0});for(let o of a)if(o.isDirectory()&&o.name.startsWith("explorer_tmp_")){let s=Me.join(r,o.name);y.warn("Removing stale temp directory from crashed sync",{dir:`${i.name}/${o.name}`});try{await jn.rm(s,{recursive:!0,force:!0})}catch(c){y.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;y.warn("Failed to scan for stale temp dirs",{error:n instanceof Error?n.message:String(n)})}}};import kr from"path";import{promises as xx}from"fs";Sr();ce();var _x=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=kr.resolve(s,u);if(!gx(s,d)){l.push({path:u,error:"Path is outside the place root"});continue}try{let p=await xx.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=lt(m),h=St(m);h&&g&&await o.writer.removeFromTree(h,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(!gx(o,kr.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=kr.resolve(c,r);if(!gx(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 xx.mkdir(kr.dirname(l),{recursive:!0});let p=i.studioContent,f=u.computeHash(p);s.fileWatcher?.suppressPath(l,f),await xx.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 xx.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),y.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=kr.relative(r,n);if(a.startsWith("..")||a===""||kr.isAbsolute(a))return null;let o=a.split(kr.sep).filter(f=>f.length>0);if(o.length<2)return null;let s=kr.basename(n),c=kr.dirname(n),l=e.getOriginalInstance(c,s);if(l)return l.instancePath;let u=s.toLowerCase();if(jb.some(f=>u.endsWith(f))||u==="_tree.json")return null;let d=["game"],p=r;for(let f of o){p=kr.join(p,f);let m=kr.dirname(p);d.push(e.getOriginalNameForDir(m,f))}return gt(d)}};Sr();Lb();ce();var Hfe=5;function J8(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 Zfe(t){return t.type==="instanceAdded"||t.type==="instanceRemoved"||t.type==="instanceRenamed"||t.type==="instanceMoved"||t.type==="scriptSourceChanged"}var Kr=class{config;places;apiHandler;changeProcessor;initHandler;reverseHandler;reverseDetectorFactory;activeFullSyncPlaceId=null;activeRuntimeSyncPlaceId=null;currentConnectedPlaceId=null;currentConnectedPlaceName=null;constructor(e,n={}){this.config=new $b(e,n),this.reverseDetectorFactory=n.reverseDetectorFactory??(i=>new px(i.explorerRoot,i.syncIndex,{placeId:i.placeId})),this.apiHandler=new vx(this),this.changeProcessor=new hx(this),this.initHandler=new bx(this),this.reverseHandler=new _x(this),this.places=new ux({max:Hfe,dispose:(i,r)=>{y.info("Disposing place context (LRU eviction)",{placeId:r}),this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),i.fileWatcher&&(y.info("Disposing place context: stopping reverse detector",{placeId:r,reason:"lru-dispose",mode:ut}),i.fileWatcher.stop("lru-dispose").catch(a=>{y.error("Error stopping reverse detector during dispose",a)}),i.fileWatcher=null),i.writer.stopChangeLogFlusher().catch(a=>{y.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=>{y.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&&(y.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=TE.join(r,"explorer");await Pl.mkdir(r,{recursive:!0}),await Pl.mkdir(a,{recursive:!0});let o=new Fa(r,a);await o.loadFromDisk();let s=new Cl(this.config,o,e),c=new dx(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:{...Wo},applyModes:{...Go},autoApplyDeletes:!1,forwardRestoreQueue:[],syncProgress:null,collisionDirMap:null,activeSyncIdentityScope:null},this.places.set(e,i),y.info("Created new place context",{placeId:e,placeRoot:r})}return i}async handleSyncInit(e,n){try{J8(e.body);let i=W8(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{J8(e.body);let i=G8(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=H8(o,r.changes);y.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++,Zfe(m)&&(d=!0))}catch(g){let h="path"in m?m.path:"oldPath"in m?m.oldPath:"unknown";c.push({path:h,error:g instanceof Error?g.message:String(g)})}for(let m of p.values())try{await fx(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 zb(m,g),await ll(m)}catch(m){y.warn("Failed to refresh sourcemaps after incremental sync update",{placeId:a,error:m instanceof Error?m.message:String(m)})}o.changesSinceLastSave+=u,o.changesSinceLastSave>=V8&&(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,autoApplyDeletes:!1,reverseDetectorActive:!1,reverseDetectorMode:ut,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,autoApplyDeletes:a.autoApplyDeletes,directions:a.directions,reverseDetectorActive:s,reverseDetectorMode:ut,fileWatcherActive:c,forwardOnlyClasses:[...cl]};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(),a=lf(i);if(y.info("handleSyncStop requested",{placeId:r,clientId:i.clientId??null,identityScope:a,reason:i.reason??"requested"}),r==null){n.status(200).json({status:"idle",state:"idle",placeId:null,message:"No active sync place"});return}let o=this.places.get(r);if(!o){y.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}let s=!!(i.clientId&&o.activeClientId&&i.clientId!==o.activeClientId),c=o.activeFullSyncSessionId!==null||o.state==="syncing"||o.state==="initializing",l=!!(a&&o.activeSyncIdentityScope&&a===o.activeSyncIdentityScope);if(s&&c&&!l){y.warn("handleSyncStop rejected due to active client mismatch",{placeId:r,requestedClientId:i.clientId,activeClientId:o.activeClientId,requestedIdentityScope:a,activeIdentityScope:o.activeSyncIdentityScope,state:o.state,activeFullSyncSessionId:o.activeFullSyncSessionId}),n.status(409).json({error:"Conflict",message:`This sync session belongs to client ${o.activeClientId}`});return}s&&l&&y.info("handleSyncStop accepted stale client cleanup by identity scope",{placeId:r,requestedClientId:i.clientId,activeClientId:o.activeClientId,identityScope:a,state:o.state});let u=o.activeFullSyncSessionId,d=o.state,p=o.fileWatcher!==null;if(u&&(this.initHandler.clearPreserveLocalFiles(u),this.initHandler.clearPendingServiceTrees(u)),o.fileWatcher&&(y.info("handleSyncStop suspending reverse detector",{placeId:r,state:o.state,activeClientId:o.activeClientId,mode:ut}),o.fileWatcher.beginFullSyncReplacement()),o.incompleteSyncTimer&&(clearTimeout(o.incompleteSyncTimer),o.incompleteSyncTimer=null),u){let f=this.config.getPlaceRoot(r),m=TE.join(f,`explorer_tmp_${u}`);await Pl.rm(m,{recursive:!0,force:!0}).catch(()=>{})}o.tmpWriter&&(o.tmpWriter.stopChangeLogFlusher(),o.tmpWriter=null),o.tmpIndex=null,o.collisionDirMap=null,o.activeSyncIdentityScope=null,o.syncInitRequestsInFlight=0,o.activeFullSyncSessionId=null,o.syncProgress=null,o.state="idle",o.activeClientId=null,o.instanceCount=0,o.scriptCount=0,o.forwardRestoreQueue=[],this.activeFullSyncPlaceId===r&&(this.activeFullSyncPlaceId=null),this.clearRuntimePlaceIfMatch(r),y.info("handleSyncStop responding idle",{placeId:r,previousState:d,activeFullSyncSessionId:u,hadWatcher:p}),y.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(),y.info("SyncController initialized")}catch(e){y.error("SyncController initialization failed",e instanceof Error?e:new Error(String(e)))}}async shutdown(){try{y.info("SyncController shutdown: clearing place contexts",{placeCount:this.places.size}),this.places.clear(),y.info("SyncController shut down")}catch(e){y.error("SyncController shutdown error",e instanceof Error?e:new Error(String(e)))}}async atomicWriteFile(e,n){let i=e+".tmp."+Bfe().slice(0,8);try{await Pl.writeFile(i,n,"utf-8"),await Pl.rename(i,e)}catch(r){throw await Pl.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"){y.debug("Skipping reverse detector start - place not syncing",{placeId:e.placeId,state:e.state});return}if(e.fileWatcher){if(e.fileWatcher.isActivelyScanning()){y.info("startFileWatcherForPlace: reusing active reverse detector",{placeId:e.placeId,mode:ut});return}y.info("startFileWatcherForPlace: resuming paused reverse detector",{placeId:e.placeId,mode:ut}),e.fileWatcher.endFullSyncReplacement();return}let n=this.createReverseChangeDetector(e);this.configureReverseChangeDetector(e,n),e.fileWatcher=n,n.start().then(()=>{e.fileWatcher===n&&y.info("Reverse detector started for reverse sync",{placeId:e.placeId,mode:ut})}).catch(i=>{y.warn("Failed to start reverse detector",{placeId:e.placeId,mode:ut,error:i instanceof Error?i.message:String(i)}),e.fileWatcher===n&&(e.fileWatcher=null)})}createReverseChangeDetector(e){return this.reverseDetectorFactory({explorerRoot:TE.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=I6(i);return e.directions[r]}),n.setOnForwardViolation(i=>{e.forwardRestoreQueue.includes(i)||(e.forwardRestoreQueue.push(i),y.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"){y.warn(`SyncController.${i} disk error`,{code:a,message:r}),e.status(500).json({error:"Disk error",message:r,code:a,operation:i});return}y.error(`SyncController.${i} failed`,n instanceof Error?n:new Error(r)),e.status(500).json({error:"Internal error",message:`${i}: ${r}`})}};import{randomUUID as Vfe}from"crypto";function Y8(t,e){let n=Vfe(),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 X8=Pt(Ta(),1);ce();function Q8(t){let e=X8.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)=>{y.debug(`${n.method} ${n.path}`,{ip:n.ip}),r()})}xa();import{randomUUID as Yx}from"crypto";xa();ce();function Wfe(){let t=process.env.WEPPY_ROBLOX_MCP_VERSION?.trim();return t||null}var Xe=Wfe()??"2.10.4";wi();tr();ff();Da();fl();xa();Da();var aq="studio-",Kfe=/^studio-[1-9]\d*$/;function Ix(t){return Kfe.test(t)}function oq(t,e){let n=new Set;for(let i of t)e!==void 0&&i.clientId===e||i.targetAlias&&Ix(i.targetAlias)&&n.add(i.targetAlias);return n}function Jfe(t,e){let n=oq(t,e),i=1;for(;n.has(`${aq}${i}`);)i+=1;return`${aq}${i}`}function kx(t,e){let n=oq(t,e.clientId);return e.targetAlias&&Ix(e.targetAlias)&&!n.has(e.targetAlias)||(e.targetAlias=Jfe(t,e.clientId)),e.targetAlias}fl();function Px(t){for(let e of t)kx(t,e)}function Rx(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??Ze.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),t.studioState!==void 0&&(e.studioState=t.studioState),t.studioStateSource!==void 0&&(e.studioStateSource=t.studioStateSource),t.studioStateUpdatedAt!==void 0&&(e.studioStateUpdatedAt=t.studioStateUpdatedAt),t.playtestMode!==void 0&&(e.playtestMode=t.playtestMode),e}function ME(t){let e=Cn(t);return Px(e),ef(e.map(Rx),null)}function Ex(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 sq(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),y.debug("Removed stale MCP instance",{instanceId:i,lastSeen:r.lastSeen}))}function cq(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"){y.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}),y.debug("Selection cache updated",{count:r.count,clientId:a,timestamp:o}),n.json({status:"ok",timestamp:o})}catch(r){y.error("Error handling selection update",r),n.status(500).json({error:"Internal server error"})}}function lq(t,e,n){let i=parseInt(e.query.maxAge)||3e4,r=mf(t,i);r?n.json({cached:!0,...r}):n.json({cached:!1,message:"No cached selection available"})}function mf(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 zE(t,e){let n=t.pluginClients.get(e.clientId),i=Date.now(),r=[...t.pluginClients.values()].filter(c=>c.clientId===e.clientId||c.commandSessionState!==Ze.DISCONNECTED),a=n??{clientId:e.clientId,connectedAt:i,lastSeen:i,commandsProcessed:0,connectionType:"polling"},o=kx(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,studioState:n?.studioState,studioStateSource:n?.studioStateSource,studioStateUpdatedAt:n?.studioStateUpdatedAt,playtestMode:n?.playtestMode,...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)&&ex(t,s.placeId,s.placeName??null),t.analyticsManager&&(e.pluginVersion&&t.analyticsManager.setPluginVersion(e.pluginVersion),t.analyticsManager.trackPluginConnected()),y.info("Plugin client registered",{clientId:e.clientId,targetAlias:o,projectName:e.projectName,placeName:e.placeName,isReconnect:!!n}),{clientInfo:s,sessionId:t.sessionId,mcpVersion:Xe,mcpInstanceCount:t.mcpInstances.size+1,aiClientNames:Ex(t)}}function LE(t,e){let n=t.pluginClients.get(e),i=t.pluginClients.has(e),r=n?.commandSessionState===Ze.CONNECTED;if(t.pluginClients.delete(e),t.pendingCommands.delete(e),i&&pl(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&&tf(t,e,"disconnected",n),y.info("Plugin client unregistered",{clientId:e,existed:i}),i}function Tx(t,e,n){try{let i=e.body;if(!i.clientId){n.status(400).json({error:"Missing clientId"});return}let r=zE(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){y.error("Error registering plugin client",i),n.status(500).json({error:"Internal server error"})}}function Ax(t,e,n){let i=e.body?.clientId;if(!i){n.status(400).json({error:"Missing clientId"});return}let r=LE(t,i);n.json({status:"ok",existed:r})}function uq(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),rt(t,"mcp_status",{aiClientName:a.aiClientName??"Unknown",instanceId:i.instanceId,status:"registered"}),yl(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}:{}}),y.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:Xe,mcpInstanceCount:t.mcpInstances.size+1})}catch(i){y.error("Error registering MCP instance",i),n.status(500).json({error:"Internal server error"})}}function dq(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&&(rt(t,"mcp_status",{aiClientName:r?.aiClientName??"Unknown",instanceId:i,status:"unregistered"}),yl(t,{timestamp:new Date().toISOString(),type:"mcp",status:"unregistered",instanceId:i,message:`MCP unregistered \u2014 ${r?.aiClientName??i}`,...r?.aiClientName?{aiClientName:r.aiClientName}:{}})),y.info("MCP instance unregistered",{instanceId:i,existed:a}),n.json({status:"ok",existed:a})}function pq(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 fq(t){let e=3e4,n=Date.now(),i=_r({appDataDir:t.config.appDataDir});for(let[a,o]of t.pluginClients)n-o.lastSeen>e&&(t.pluginClients.delete(a),t.pendingCommands.delete(a),pl(t,a));sq(t);let r=Cn(t);return Px(r),{serverInstanceId:t.instanceId,sessionId:t.sessionId,mcpVersion:Xe,uptime:n-t.startTime,serverStartTime:t.startTime,serverExecutable:process.execPath,serverHost:t.config.httpHost,serverPort:t.config.httpPort,serverPid:process.pid,pluginClients:r.map(Rx),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 $x(t,e){e.json(fq(t))}function Ox(t,e,n){let i=e.query.instanceId;i&&t.mcpInstances.has(i)&&(t.mcpInstances.get(i).lastSeen=Date.now()),sq(t);let r=Cn(t);Px(r);let s={...{status:"online",connectedClients:r.length,queuedCommands:l8(t),uptime:Date.now()-t.startTime,version:Xe,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:Ex(t),pluginVersion:t.pluginVersion||void 0,dashboardSseClients:t.dashboardSseClients?.size??0,websocketClients:r.length,pluginClients:r.map(Rx),...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 mq(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")){y.warn("Shutdown request rejected from non-localhost",{ip:r}),n.status(403).json({error:"Forbidden: localhost only"});return}y.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(),y.info("Graceful shutdown completed"),process.exit(0)}catch(o){y.error("Error during graceful shutdown",o),process.exit(1)}},100)}async function Dx(t){if(t.isClientMode)try{let e=await fetch(`${t.baseUrl}/connection-info`);if(e.ok)return await e.json()}catch(e){y.warn("Failed to fetch connection info from server",{error:e})}return fq(t)}Da();var dt={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"}},Xfe=new Set([dt.canonical.runTest]),Qfe=new Set([dt.canonical.playStop]),q4e=new Set([dt.canonical.playStart,dt.canonical.playStop,dt.canonical.playPause,dt.canonical.playResume,dt.canonical.playStatus]);function Jr(t){return Xfe.has(t)}function gf(t){return Qfe.has(t)}var V4e=dt.canonical.playStop,gq=[5e3,15e3];fl();var eme=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm","manage_assets_review_model","manage_assets_generate_model","manage_assets_import_rbxm","manage_assets_generate_thumbnail"]),on=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 tme(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 on("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 on("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&&nme(e,t)){if(typeof a!="number"||!Number.isFinite(a))throw new on("invalid_target_selector","placeId target selector must be a finite number",{selectionMode:"placeId"});n.requestedPlaceId=a}return n}function Nx(t,e,n={},i){let r=tme(n,i),a=z6(e,t.studioRoutingMode==="pinned"?t.pinnedTargetClientId:null);if(r.requestedClientId!==void 0)return rme(a,r);if(r.requestedTargetAlias!==void 0)return ime(a,r);if(r.requestedPlaceId!==void 0)return ame(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:Pr("pinnedTarget",r,s)}}let o=a[0];return o?{targetClientId:o.clientId,routing:Pr("recentPriority",r,o)}:{routing:{selectionMode:"globalQueue"}}}function nme(t,e){return!t||!eme.has(t)?!0:e.scope==="shared"}function rme(t,e){let n=t.find(i=>i.clientId===e.requestedClientId);if(!n)throw new on("target_client_not_found",`Target client not found: ${e.requestedClientId}`,Pr("clientId",e));if(e.requestedTargetAlias!==void 0&&n.targetAlias!==e.requestedTargetAlias)throw new on("target_selector_mismatch",`Target client ${n.clientId} does not match targetAlias ${e.requestedTargetAlias}`,Pr("clientId",e,n));return hq("clientId",e,n),{targetClientId:n.clientId,routing:Pr("clientId",e,n)}}function ime(t,e){let n=t.find(i=>i.targetAlias!==void 0&&Ix(i.targetAlias)&&i.targetAlias===e.requestedTargetAlias);if(!n)throw new on("target_alias_not_found",`Target alias not found: ${e.requestedTargetAlias}`,Pr("targetAlias",e));return hq("targetAlias",e,n),{targetClientId:n.clientId,routing:Pr("targetAlias",e,n)}}function ame(t,e){let n=t.filter(r=>r.placeId===e.requestedPlaceId);if(n.length===0)throw new on("target_place_not_found",`Target place not found: ${e.requestedPlaceId}`,Pr("placeId",e));if(n.length>1)throw new on("target_place_ambiguous",`Target place is ambiguous: ${e.requestedPlaceId}`,Pr("placeId",e));let i=n[0];return{targetClientId:i.clientId,routing:Pr("placeId",e,i)}}function hq(t,e,n){if(e.requestedPlaceId!==void 0&&n.placeId!==e.requestedPlaceId)throw new on("target_selector_mismatch",`Target client ${n.clientId} is not connected to placeId ${e.requestedPlaceId}`,Pr(t,e,n))}function Pr(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}eE();ce();uf();var Tl={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","scatter"]),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","mood"])},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","review_model","generate_model","upload_asset","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 ome={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 jx(t){return ome[t]||"plugin"}var yq=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_model","manage_assets_generate_thumbnail","manage_assets_import_rbxm","manage_assets_info","manage_assets_insert","manage_assets_insert_free","manage_assets_insert_package","manage_assets_review_model","manage_assets_search","manage_assets_search_insert","manage_assets_upload_asset","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_mood","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_scatter","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"]),UE=new Set(["system_info_connection","system_info_ping","system_info_usage"]);function zn(t){return yq.has(t)?"pro":"basic"}ki();Mx();import{readFile as Ime}from"node:fs/promises";import kme from"node:path";import{createHash as xme,randomUUID as HE}from"node:crypto";import{mkdir as xf,readFile as Pq,readdir as Rq,rename as Eq,rm as _me,stat as Sme,writeFile as qx}from"node:fs/promises";import zt from"node:path";import{extname as ume}from"node:path";import{stat as dme}from"node:fs/promises";var pme=20*1024*1024,Iq=[{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"}}],fme=new Map(Iq.map(t=>[t.category,t]));function xq(t){if(!t)throw new Error("Open Cloud asset upload is disabled in WEPPY Dashboard settings.")}function zx(t,e){return t.split(e.apiKey).join("[redacted]")}function qE(t){let e=fme.get(t);if(!e)throw new Error(`Unsupported asset category: ${t}`);return e}function Lx(t){return qE(t)}function _q(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 Sq(t,e,n){let i=ume(e).toLowerCase(),r=t.contentTypes[i];if(!r)throw new Error(`Unsupported file extension ${i||"(none)"} for ${t.category}.`);if((await dme(e)).size>n)throw new Error(`Asset file is too large. Maximum size is ${n} bytes.`);return r}function wq(t){return typeof t.path=="string"&&t.path.startsWith("operations/")?t.path:null}function Cq(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 Al=class{client;credentialStore;isOpenCloudUploadEnabled;maxFileSizeBytes;constructor(e){this.client=e.client,this.credentialStore=e.credentialStore,this.isOpenCloudUploadEnabled=e.isOpenCloudUploadEnabled,this.maxFileSizeBytes=e.maxFileSizeBytes??pme}getCapabilities(){return Iq.map(({contentTypes:e,...n})=>n)}async uploadAsset(e){xq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=_q(e,n),r=qE(i.category),a=await Sq(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=wq(s);return c?await this.client.pollOperation(Cq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(zx(o instanceof Error?o.message:String(o),n))}}async updateAsset(e){xq(this.isOpenCloudUploadEnabled());let n=await this.getRequiredCredential(),i=_q(e,n),r=qE(i.category),a;if(i.filePath){if(!r.supportsContentUpdate)throw new Error(`${r.category} assets do not support content updates.`);a=await Sq(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=wq(s);return c?await this.client.pollOperation(Cq(n,c,i.operationPollIntervalMs,i.operationPollTimeoutMs)):s}return s}catch(o){throw new Error(zx(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(zx(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(zx(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 kq from"node:fs";import Jt from"node:path";Ob();var mme=/^asset_(image|decal|audio|mesh|model|video|animation)_\d+_[a-z0-9]+$/;function gme(t){if(!Number.isInteger(t)||t<0)throw new Error(`Invalid place ID: ${t}`)}function hme(t,e){try{return kq.statSync(Jt.join(t,e,".sync-meta.json")).isFile()}catch{return!1}}function yme(t,e){gme(e.placeId);let n=`place_${e.placeId}`,i=e.placeName?ol(e.placeName):"",r=i?`${n}_${i}`:n,a=[];try{let o=new RegExp(`^place_${e.placeId}(?:_.*)?$`);a=kq.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=>hme(t,o))??(a.includes(r)?r:null)??a[0]??r}function BE(t){let e=Jt.resolve(t.projectSyncRoot),n=Lx(t.category).folder,i=t.scope.kind==="place"?Jt.join(e,yme(e,t.scope),"assets",n):Jt.join(e,"shared-assets",n);return{root:i,inbox:Jt.join(i,"inbox"),index:Jt.join(i,".asset-library-index.json")}}function vme(t){let e=mme.exec(t);return e?.[1]?e[1]:null}function yf(t,e){let n=vme(t);return n?e?n===e:!0:!1}function Ux(t,e){if(!yf(t,e))throw new Error(`Invalid asset ID: ${t}`)}function Yr(t,e){let n=Jt.relative(Jt.resolve(t),Jt.resolve(e));return n===""||!n.startsWith("..")&&!Jt.isAbsolute(n)}function bme(t){Ux(t.assetId,t.category);let e=BE(t),n=Jt.resolve(e.root,t.assetId);if(!Yr(e.root,n))throw new Error(`Invalid asset path for ${t.assetId}`);return n}function Fx(t){let e=bme(t),n=Jt.resolve(e,t.relativeFileName);if(!Yr(e,n))throw new Error(`Invalid asset file path for ${t.assetId}`);return n}function vf(t,e){return Jt.relative(Jt.resolve(t),Jt.resolve(e)).split(Jt.sep).join("/")}var Tq=20*1024*1024,wme=200;function Aq(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 $q(t,e){let n=zt.extname(t).toLowerCase(),i=Lx(e);if(!i.extensions.includes(n))return null;let r=i.contentTypes[n];return r?{canonicalExt:n,mimeType:r}:null}function ZE(t,e,n){if(e!=="image"&&e!=="decal")return!0;let i=zt.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 Oq(t){return xme("sha256").update(t).digest("hex")}function Bx(t){return t.now?.()??Date.now()}function Cme(t){return(t.randomId?.()??HE().replace(/-/g,"").slice(0,6)).toLowerCase().replace(/[^a-z0-9]/g,"").slice(0,12)||"asset"}function Dq(t,e){let n=Math.floor(Bx(t)/1e3);for(let i=0;i<20;i++){let r=Cme(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}_${HE().replace(/-/g,"").slice(0,10)}`}function Nq(t){let e=zt.parse(t).name.trim();return e.length>0?e:t}function jq(t){if(t.mimeType!=="image/png")throw new Error("Asset Library preview must be an image/png thumbnail");if(zt.basename(t.fileName).toLowerCase()!=="thumbnail.png")throw new Error("Asset Library preview file must be thumbnail.png");if(!ZE("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 VE(t,e){let n=`${t}.tmp.${HE().slice(0,8)}`;await qx(n,JSON.stringify(e,null,2),"utf8"),await Eq(n,t)}async function Mq(t,e){try{let n=await Pq(zt.join(e,"asset.json"),"utf8"),i=JSON.parse(n);return!yf(i.id,t.category)||i.category!==t.category||!Aq(i.scope,t.scope)?null:i}catch{return null}}async function bf(t,e){let n;try{n=await Rq(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()||!yf(r.name,t.category))continue;let a=zt.join(e.root,r.name),o=await Mq(t,a);o&&i.push(o)}return i.sort((r,a)=>a.createdAt.localeCompare(r.createdAt)||a.id.localeCompare(r.id))}async function $l(t,e,n){if(Ux(n.id,t.category),n.category!==t.category||!Aq(n.scope,t.scope))throw new Error(`Asset metadata does not match library scope/category: ${n.id}`);let i=zt.join(e.root,n.id);if(!Yr(e.root,i))throw new Error(`Invalid asset path for ${n.id}`);await xf(i,{recursive:!0}),await VE(zt.join(i,"asset.json"),n)}async function zq(t,e){await xf(t.root,{recursive:!0});let n={version:1,generatedAt:new Date().toISOString(),assets:e.map(i=>i.id)};await VE(t.index,n)}function Ti(t,e,n){return{fileName:t,reason:e,message:n}}async function Xr(t){let e=BE(t);return await xf(e.inbox,{recursive:!0}),e}async function Lq(t){let e=await Xr(t),n=await bf(t,e);return await zq(e,n),n}async function Lt(t,e){Ux(e,t.category);let n=await Xr(t),i=zt.join(n.root,e);if(!Yr(n.root,i))throw new Error(`Invalid asset path for ${e}`);let r=await Mq(t,i);if(!r)throw new Error(`Asset not found: ${e}`);return r}async function Ol(t){let e=await Xr(t),n=await bf(t,e),i={version:1,generatedAt:new Date().toISOString(),assets:n.map(r=>r.id)};return await VE(e.index,i),i}async function Uq(t){let e=await Xr(t),n=await bf(t,e),i=new Set(n.map(p=>p.id)),r=new Set(n.map(p=>p.file.sha256)),a=[],o=[],s=t.maxFileSizeBytes??Tq,c=t.maxFilesPerRescan??wme,l;try{l=await Rq(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(Ti(f.name,"maxFileCount","rescan file count limit exceeded"));continue}if(f.name.startsWith(".")){o.push(Ti(f.name,"hidden","hidden or system file"));continue}if(f.isSymbolicLink()){o.push(Ti(f.name,"symlink","symlink files are not followed"));continue}if(f.isDirectory()){o.push(Ti(f.name,"nestedDirectory","nested directories are not scanned"));continue}if(!f.isFile()){o.push(Ti(f.name,"unsupportedType","unsupported inbox entry type"));continue}let m=$q(f.name,t.category);if(!m){o.push(Ti(f.name,"unsupportedType",`unsupported ${t.category} extension`));continue}let g=zt.join(e.inbox,f.name),h=await Sme(g);if(h.size>s){o.push(Ti(f.name,"oversized","asset file is larger than the configured limit"));continue}let v=await Pq(g);if(!ZE(f.name,t.category,v)){o.push(Ti(f.name,"invalidSignature","file signature does not match the extension"));continue}let x=Oq(v);if(r.has(x)){o.push(Ti(f.name,"duplicate","asset content already exists in Asset Library"));continue}let _=Dq(t,i);i.add(_),r.add(x);let I=zt.join(e.root,_),w=`original${m.canonicalExt}`;await xf(I,{recursive:!0}),await Eq(g,zt.join(I,w));let D=new Date(Bx(t)).toISOString(),M={version:1,id:_,category:t.category,scope:t.scope,status:"localOnly",displayName:Nq(f.name),description:"",source:{kind:"generated",originalPath:vf(t.projectSyncRoot,g)},file:{original:w,preview:null,mimeType:m.mimeType,sha256:x,sizeBytes:h.size,width:null,height:null,durationMs:null},roblox:{uploaded:!1},usage:{lastScannedAt:null,scanSource:null,references:[]},createdAt:D,updatedAt:D};await $l(t,e,M),a.push(M)}let d=await bf(t,e);return await zq(e,d),{assets:d,adopted:a,skipped:o,adoptedCount:a.length,skippedCount:o.length}}async function Fq(t){let e=await Xr(t),n=$q(t.originalFileName,t.category);if(!n)throw new Error(`Unsupported ${t.category} extension for Asset Library export`);let i=t.maxFileSizeBytes??Tq;if(t.content.length>i)throw new Error("asset file is larger than the configured limit");if(!ZE(t.originalFileName,t.category,t.content))throw new Error("file signature does not match the extension");let r=await bf(t,e),a=Oq(t.content),o=r.find(h=>h.file.sha256===a);if(o)return{asset:o,deduplicated:!0};let s=new Set(r.map(h=>h.id)),c=Dq(t,s),l=zt.join(e.root,c);if(!Yr(e.root,l))throw new Error(`Invalid asset path for ${c}`);let u=`original${n.canonicalExt}`;await xf(l,{recursive:!0}),await qx(zt.join(l,u),t.content);let d=null;if(t.preview){let h=jq(t.preview);d=h.fileName,await qx(zt.join(l,h.fileName),h.content)}let p=new Date(Bx(t)).toISOString(),f=t.roblox??{uploaded:!1},m=f.uploaded&&f.assetId?"uploaded":"localOnly",g={version:1,id:c,category:t.category,scope:t.scope,status:m,displayName:t.displayName?.trim()||Nq(t.originalFileName),description:t.description??"",source:{...t.source,originalPath:vf(t.projectSyncRoot,zt.join(l,u))},file:{original:u,preview:d,mimeType:n.mimeType,sha256:a,sizeBytes:t.content.length,width:null,height:null,durationMs:null},roblox:f,usage:{lastScannedAt:null,scanSource:null,references:[]},...t.rbxm?{rbxm:t.rbxm}:{},createdAt:p,updatedAt:p};return await $l(t,e,g),await Ol(t),{asset:g,deduplicated:!1}}async function qq(t){let e=await Xr(t),n=await Lt(t,t.assetId),i=jq(t.preview),r=Fx({...t,relativeFileName:i.fileName});await qx(r,i.content);let a={...n,file:{...n.file,preview:i.fileName},...n.rbxm&&t.rbxmThumbnail?{rbxm:{...n.rbxm,thumbnail:t.rbxmThumbnail}}:{},updatedAt:new Date(Bx(t)).toISOString()};return await $l(t,e,a),await Ol(t),{asset:a}}async function Bq(t,e,n){let i=await Xr(t),r=await Lt(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 $l(t,i,a),await Ol(t),a}async function Hq(t,e,n){let i=await Xr(t),a={...await Lt(t,e),usage:n,updatedAt:new Date().toISOString()};return await $l(t,i,a),await Ol(t),a}async function Zq(t,e){let n=await Xr(t);await Lt(t,e);let i=zt.join(n.root,e);if(!Yr(n.root,i))throw new Error(`Invalid asset path for ${e}`);return await _me(i,{recursive:!0}),await Ol(t),{assetId:e,removed:1}}async function Ha(t){let e=await Xr(t);return await $l(t,e,t.asset),await Ol(t),t.asset}async function Dl(t){let e=await Lt(t,t.assetId);return Fx({...t,relativeFileName:e.file.original})}async function Vq(t){let e=await Lt(t,t.assetId);return Fx({...t,relativeFileName:e.file.preview??e.file.original})}var Pme="https://create.roblox.com/dashboard/creations/store",Rme="manage_assets_import_rbxm",GE="manage_assets_generate_thumbnail",Eme="manage_assets_review_model";var KE=new Set([Rme,GE]),JE=new Set(["manage_assets_export_selection_rbxm","manage_assets_export_path_rbxm",Eme]),Tme=new Set(["model","animation"]);function Qe(t){return t&&typeof t=="object"?t:null}function Ame(t){if(typeof t!="string"||!Tme.has(t))throw new Error(`Unsupported Asset Library .rbxm round-trip category: ${String(t??"(missing)")}`);return t}function $me(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 Wq(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 YE(t,e){let n=mt(t.config.dataDir),i=Ame(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=$me(e.placeId),s=t.syncController?.getDefaultRuntimePlaceId()??null,c=o??s??Wq(t)?.placeId??null;if(c===null)throw new Error("No placeId is available for Asset Library .rbxm round-trip.");let l=Wq(t,c);return{projectSyncRoot:n,scope:{kind:"place",placeId:c,...l?.placeName?{placeName:l.placeName}:{}},category:i,...a?{assetId:a}:{}}}function Ome(t){if(kme.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 Dme(t,e){if(typeof t!="string"||t.trim().length===0)throw new Error(`${e} is missing`);return Buffer.from(t,"base64")}function Nme(t,e){let n=Qe(e),r={kind:n?.kind==="generation"||typeof t.prompt=="string"?"generated":"studioExport",originalPath:"studio:selection"};if(n){let a=typeof n.path=="string"?n.path:typeof n.kind=="string"?n.kind:void 0;a&&(r.originalPath=`studio:${a}`);let o=ge(n.prompt,1e3);o&&(r.prompt=o)}if(!r.prompt){let a=ge(t.prompt,1e3);a&&(r.prompt=a)}return typeof t.contextId=="string"&&(r.contextId=t.contextId),r}function Yq(t){let e=Qe(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=_f(e.attempts);return i.length>0&&(n.attempts=i),Object.keys(n).length>0?n:void 0}function ge(t,e){return typeof t!="string"?null:t.slice(0,e)}function jme(t){if(typeof t!="string")return null;let e=t.trim();return/^\d+$/.test(e)?e:null}function Gq(t){return`rbxassetid://${t}`}function Kq(t){return`${Pme}/${t}/configure`}function Jq(t){return`assets/${t}`}function rr(t){return typeof t=="number"&&Number.isFinite(t)?t:void 0}function Xq(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.name,256),r=ge(n.className,128),a=ge(n.path,512);return i===null||r===null||a===null?[]:[{name:i,className:r,path:a}]}):[]}function Mme(t){let e=Qe(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 zme(t){return Array.isArray(t)?t.slice(0,200).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.path,512),r=ge(n.property,128),a=ge(n.value,1024);if(i===null||r===null||a===null)return[];let o=ge(n.assetId,64);return[{path:i,property:r,value:a,...o?{assetId:o}:{}}]}):[]}function _f(t){return Array.isArray(t)?t.slice(0,8).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.method,80),r=n.status==="success"||n.status==="failed"||n.status==="skipped"?n.status:null;if(i===null||r===null)return[];let a=ge(n.message,512);return[{method:i,status:r,...a?{message:a}:{}}]}):[]}function Lme(t,e){let n=t.thumbnailMode==="auto"?"auto":"none";if(n==="none")return{mode:n,status:"skipped",message:"Thumbnail generation disabled"};let i=Yq(e),r=Qe(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=rr(i.width),c=rr(i.height),l=_f(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=_f(Qe(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 Ume(t,e){let n=Qe(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=ge(n.message,512),o=rr(n.width),s=rr(n.height),c=ge(n.source,128),l=_f(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 WE(t,e=0){if(e>3)return;if(typeof t=="string")return t.slice(0,512);if(typeof t=="boolean")return t;if(typeof t=="number")return Number.isFinite(t)?t:void 0;if(Array.isArray(t))return t.slice(0,50).flatMap(r=>{let a=WE(r,e+1);return a===void 0?[]:[a]});let n=Qe(t);if(!n)return;let i={};for(let[r,a]of Object.entries(n).slice(0,50)){let o=WE(a,e+1);o!==void 0&&(i[r.slice(0,128)]=o)}return i}function Fme(t){let e=Qe(t),n=rr(e?.x),i=rr(e?.y),r=rr(e?.z);if(!(n===void 0||i===void 0||r===void 0))return{x:n,y:i,z:r}}function qme(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=n.severity==="info"||n.severity==="warning"||n.severity==="error"?n.severity:null,r=ge(n.category,80),a=ge(n.code,120),o=ge(n.path,512),s=ge(n.message,512);if(!i||r===null||a===null||o===null||s===null)return[];let c=ge(n.suggestion,512);return[{severity:i,category:r,code:a,path:o,message:s,...c?{suggestion:c}:{}}]}):[]}function Bme(t){let e=Qe(t);if(!e)return;let n=e.readiness==="ready"||e.readiness==="review"||e.readiness==="blocked"?e.readiness:null;if(!n)return;let i=WE(e.summary),r=ge(e.reviewedAt,64),a=Xq(e.roots);return{readiness:n,...r?{reviewedAt:r}:{},...a.length>0?{roots:a}:{},summary:Qe(i)??{},findings:qme(e.findings)}}function Hme(t){let e=Qe(t);if(!e)return;let n={};for(let[i,r]of Object.entries(e).slice(0,16))typeof r=="string"&&(n[i.slice(0,128)]=r.slice(0,256)),typeof r=="number"&&Number.isFinite(r)&&(n[i.slice(0,128)]=r),typeof r=="boolean"&&(n[i.slice(0,128)]=r);return Object.keys(n).length>0?n:void 0}function Zme(t){let e=Qe(t);if(!e)return;let n=ge(e.provider,120);if(!n)return;let i=ge(e.generatedAt,64),r=ge(e.prompt,1e3),a=e.schemaMode==="predefined"||e.schemaMode==="custom"?e.schemaMode:void 0,o=e.predefinedSchema==="Body1"||e.predefinedSchema==="Car5"?e.predefinedSchema:void 0,s=Array.isArray(e.schemaGroups)?e.schemaGroups.slice(0,50).flatMap(f=>{let m=ge(f,120);return m?[m]:[]}):void 0,c=Fme(e.requestedSize),l=rr(e.maxTriangles),u=ge(e.targetParent,512),d=ge(e.path,512),p=Hme(e.metadata);return{provider:n,...i?{generatedAt:i}:{},...r?{prompt:r}:{},...a?{schemaMode:a}:{},...o?{predefinedSchema:o}:{},...s&&s.length>0?{schemaGroups:s}:{},...c?{requestedSize:c}:{},...l!==void 0?{maxTriangles:Math.floor(l)}:{},...typeof e.generateTextures=="boolean"?{generateTextures:e.generateTextures}:{},...u?{targetParent:u}:{},...d?{path:d}:{},...p?{metadata:p}:{}}}function Vme(t){return Array.isArray(t)?t.slice(0,100).flatMap(e=>{let n=Qe(e);if(!n)return[];let i=ge(n.path,512),r=n.assetType==="Mesh"||n.assetType==="Image"||n.assetType==="Model"?n.assetType:null,a=n.status==="uploaded"||n.status==="failed"?n.status:null;if(i===null||r===null||a===null)return[];let o=ge(n.assetId,64),s=ge(n.assetUri,128),c=n.creatorType==="user"||n.creatorType==="group"?n.creatorType:void 0,l=ge(n.creatorId,64),u=ge(n.sourceProperty,128),d=ge(n.uploadedAt,64),p=ge(n.message,512);return[{path:i,assetType:r,status:a,...o?{assetId:o}:{},...s?{assetUri:s}:{},...c?{creatorType:c}:{},...l?{creatorId:l}:{},...u?{sourceProperty:u}:{},...d?{uploadedAt:d}:{},...p?{message:p}:{}}]}):[]}function Wme(t){let e=Qe(t);if(!e||e.uploaded!==!0)return;let n=jme(e.assetId);if(!n)return;let i=ge(e.uploadedAt,64)??new Date().toISOString(),r=e.creatorType==="user"||e.creatorType==="group"?e.creatorType:void 0,a=ge(e.creatorId,64);return{uploaded:!0,assetId:n,assetUri:Gq(n),assetWebUrl:Kq(n),remotePath:Jq(n),uploadedAt:i,uploadAttempts:[{startedAt:i,finishedAt:i,status:"uploaded",assetRole:"primary",...r?{creatorType:r}:{},...a?{creatorId:a}:{},assetId:n,assetUri:Gq(n),assetWebUrl:Kq(n),remotePath:Jq(n)}]}}function Gme(t){let e=Qe(t.value),n=Xq(e?.roots),i=Mme(e?.classCounts),r=zme(e?.resourceReferences),a=Bme(e?.review),o=Zme(e?.generation),s=Vme(e?.studioUploads),c=rr(e?.exportedCount)??rr(t.exportedCount)??n.length;return{exportedCount:Math.max(0,Math.floor(c)),roots:n,classCounts:i,resourceReferences:r,thumbnail:Ume(e?.thumbnail,t.fallbackThumbnail),...a?{review:a}:{},...o?{generation:o}:{},...s.length>0?{studioUploads:s}:{}}}function Kme(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 Qq(t){let e=Qe(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(bq(e.base64Rgba,e.width,e.height),"base64")),!!n){if(!Kme(n))throw new Error("Thumbnail payload is not a valid PNG image.");return{fileName:"thumbnail.png",content:n,mimeType:"image/png"}}}function Jme(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 eB(t){if(!KE.has(t.command))return t.params;let e=YE(t.ctx,t.params);if(!e.assetId)throw new Error("assetLibraryAssetId is required for Asset Library .rbxm round-trip.");let n=await Lt(e,e.assetId);Ome(n);let i=await Dl({...e,assetId:n.id}),r=await Ime(i);return{...t.params,__assetLibraryRbxmBase64:r.toString("base64"),__assetLibraryOriginalFile:n.file.original}}async function tB(t){if(!JE.has(t.command)||!t.result.success)return t.result;let e=Qe(t.result.data);if(!e||typeof e.rbxmBase64!="string"||e.rbxmBase64.trim().length===0)return t.result;let n=YE(t.ctx,t.params),i=Dme(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=Qq(e.thumbnail)}catch(f){c=f,s=void 0}let l=Gme({value:e.rbxm,exportedCount:e.exportedCount,fallbackThumbnail:Lme(t.params,e.thumbnail)});c&&(l=Jme(l,c));let u=Wme(e.roblox),d=await Fq({projectSyncRoot:n.projectSyncRoot,scope:n.scope,category:n.category,originalFileName:o,content:i,...r!==void 0?{displayName:r}:{},...a!==void 0?{description:a}:{},source:Nme(t.params,e.source),...s?{preview:s}:{},rbxm:l,...u?{roblox:u}:{}}),p=Yq(e.thumbnail);return{...t.result,data:{asset:d.asset,deduplicated:d.deduplicated,...typeof e.byteLength=="number"?{byteLength:e.byteLength}:{},...typeof e.exportedCount=="number"?{exportedCount:e.exportedCount}:{},...e.source!==void 0?{source:e.source}:{},...p?{thumbnail:p}:{}}}}async function nB(t){if(!t.result.success)return t.result;let e=Qe(t.result.data),n=Qe(e?.thumbnail),i;try{i=Qq(n)}catch(d){return{...t.result,success:!1,error:d instanceof Error?d.message:String(d)}}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=rr(n.width),a=rr(n.height),o=ge(n.source,128),s=_f(n.attempts),c={mode:"auto",status:"generated",...r!==void 0?{width:r}:{},...a!==void 0?{height:a}:{},...o?{source:o}:{},...s.length>0?{attempts:s}:{}},l=YE(t.ctx,t.params);if(!l.assetId)throw new Error("assetLibraryAssetId is required for Asset Library thumbnail generation.");let u=await qq({projectSyncRoot:l.projectSyncRoot,scope:l.scope,category:l.category,assetId:l.assetId,preview:i,rbxmThumbnail:c});return{...t.result,data:{asset:u.asset,...r!==void 0?{width:r}:{},...a!==void 0?{height:a}:{},...o?{source:o}:{}}}}function Yme(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 Xme=/^Pro action '[^']+' is blocked in Basic mode\. Basic fallback '([^']+)' failed: (.*)$/s,Qme=/^Pro action '[^']+' is blocked in Basic mode\.(?! Basic fallback ')/,ege=/instance not found|not found in|parent not found/,tge=/is required|missing required/,nge=/unknown action|unknown command/,rge=/must be|invalid|cannot/;function ige(t){let e=Xme.exec(t);return e?{fallbackCommand:e[1],reason:e[2]}:null}function age(t){return Qme.test(t)}function oge(t){let e=t.toLowerCase();return ege.test(e)?"not_found":tge.test(e)?"missing_param":nge.test(e)?"unknown_action":rge.test(e)?"validation":"other"}function XE(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 Nl(t){if(t.resultSuccess){let e=Yme(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=ige(t.resultError);if(e)return{kind:"blocked_fallback_failed",fallbackCommand:e.fallbackCommand,blockedDetail:oge(e.reason)};if(age(t.resultError))return{kind:"blocked_unsupported"}}return t.failureClassification?{kind:XE(t.failureClassification)}:{kind:"error"}}function we(t,e,n,i,r={}){return{errorType:t,errorDetail:e,failureOrigin:n,recoverability:i,...r}}function sge(t){let e=t.toLowerCase();return/^\s*compilation error:/.test(e)?we("execution_failed","compile_error","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*result too large:/.test(e)?we("execution_failed","result_too_large","agent_request","code_fix",{validationStage:"plugin_handler"}):/^\s*execution timed out after/.test(e)?we("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)?we("execution_failed","blocked_source","roblox_policy","code_fix",{validationStage:"plugin_handler"}):null}function rB(t){let e=t.toLowerCase();return/upstream_server_down/.test(e)?we("bridge_error","upstream_down","bridge","wait_connection"):/^http [45]\d\d/.test(e)?we("bridge_error","http_error","bridge","retry"):/duplicate request\s*id/.test(e)?we("bridge_error","duplicate_request_id","bridge","code_fix"):/timeout/.test(e)?we("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|econnreset|epipe|network/.test(e)?we("bridge_error","connection","bridge","wait_connection"):/abort/.test(e)?we("command_timeout","aborted","bridge","retry"):/runtime error|traceback|attempt to/.test(e)?we("plugin_runtime","runtime_error","plugin_runtime","code_fix"):/created instance, but failed to set \d+ propert/.test(e)?we("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler",partialSuccess:"true"}):/failed to set property/.test(e)?we("execution_failed","property_apply_failed","agent_request","fix_params",{validationStage:"plugin_handler"}):/parent(?: instance)? not found/.test(e)?we("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)?we("execution_failed","not_found","user_project_state","fix_params",{validationStage:"plugin_handler"}):/is required|missing required/.test(e)?we("execution_failed","missing_param","agent_request","fix_params",{validationStage:"schema"}):/invalid classname|invalid class/.test(e)?we("execution_failed","invalid_class","agent_request","fix_params",{validationStage:"plugin_handler"}):/unknown action|unknown command/.test(e)?we("execution_failed","unknown_action","agent_request","fix_params",{validationStage:"dispatcher"}):/failed to insert asset/.test(e)?we("execution_failed","asset_error","roblox_policy","fix_params",{validationStage:"roblox_api"}):/failed to read property|property access denied/.test(e)?we("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)?we("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)?we("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)?we("execution_failed","unsupported_context","roblox_policy","no_retry",{validationStage:"preflight"}):/editableimage api is not enabled|allow mesh \/ image apis|allow http requests/.test(e)?we("execution_failed","feature_disabled","roblox_policy","no_retry",{validationStage:"preflight"}):/must be|invalid|cannot/.test(e)?we("execution_failed","validation","agent_request","fix_params",{validationStage:"plugin_handler"}):we("execution_failed","other","unknown","unknown")}function jl(t,e){if(t==="execute_luau"){let i=sge(e);if(i)return i}let n=rB(e);return t==="execute_luau"&&n.errorDetail==="runtime_error"&&/^\s*runtime error:/i.test(e)?we("execution_failed","runtime_error","agent_request","code_fix"):n}function iB(t){let n=(t instanceof Error?t.message:String(t)).toLowerCase();return/timeout/.test(n)?we("command_timeout","timeout","bridge","retry"):/econnrefused|socket hang up|network|econnreset|epipe/.test(n)?we("bridge_error","connection","bridge","wait_connection"):/eaddrinuse/.test(n)?we("bridge_error","port_in_use","bridge","no_retry"):we("exception","unexpected","server_exception","code_fix")}Vx();import{randomBytes as fge}from"node:crypto";var mge=["manage_ui_create_tree","manage_ui_update","manage_ui_delete"],pB=["manage_ui_preview","manage_ui_check"],gge=["game_genre","ui_role","style_family","layout_family","device_policy","safe_area_policy","existing_ui_strategy"];function iT(t){return t&&typeof t=="object"?t:void 0}function nT(t){return typeof t=="number"&&Number.isFinite(t)?t:0}function Wx(t){let e=iT(t);if(!e)return;let n={};for(let i of gge){let r=e[i];typeof r=="string"&&r.trim().length>0&&(n[i]=r)}return Object.keys(n).length>0?n:void 0}function rT(t){let e=Wx(t.qualityPlanSummary);if(e)return e;let n=iT(t.contextSummary),i=Wx(n?.qualityPlanSummary);if(i)return i;let r=Wx(n?.qualityPlan);if(r)return r;let a=Wx(n?.quality_plan);if(a)return a}function fB(t,e){return e?{...t??{},...e}:t}function hge(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 mB(t,e,n,i,r){if(!e)return;let a=nT(e.priority_high),o=nT(e.priority_medium),s=nT(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 gB(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 yge(t){let e=iT(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 vge(){return{source:"unavailable",priority_high:0,priority_medium:0,priority_low:0,total:0}}function hB(t){let e=t.now??Date.now,n=null,i=null,r=u=>`${u}_${e()}_${fge(3).toString("hex")}`,a=()=>{i&&(clearTimeout(i),i=null)},o=()=>{a(),i=setTimeout(()=>{c("idle_timeout")},t.idleMs)},s=async u=>{try{return hge(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 h of d.affectedPaths)if(d.afterSnapshotsPathPolicy[h]==="skip")p[h]=null;else{let v=await s(h);p[h]=v.snapshotId,f=gB(f,mB("after_snapshot",v.designCheckSummary,h,v.snapshotId,v.capturedAt))}let m=f??d.latestDesignCheckSummary??vge(),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 lB(t.placeDir,g)},l=u=>({requestId:r("req"),contextId:u.contextId,label:yge(u.contextSummary),startedAtIso:new Date(e()).toISOString(),startedAtMs:e(),affectedPaths:new Set,beforeSnapshots:{},afterSnapshotsPathPolicy:{},childMutationIds:[],mutationCount:0,ok:!0,qualityPlanSummary:rT(u),latestDesignCheckSummary:void 0,pendingMutation:void 0});return{async beforeMutation(u){if(pB.includes(u.command)){if(n){let p=r("mut");n.qualityPlanSummary=fB(n.qualityPlanSummary,rT(u)),n.pendingMutation={mutationId:p,startedMs:e(),args:u}}return}if(!mge.includes(u.command))return;n&&n.contextId!==u.contextId?await c("context_change"):n&&a(),n||(n=l(u)),n.qualityPlanSummary=fB(n.qualityPlanSummary,rT(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 uB(t.placeDir,f),n.pendingMutation=void 0,pB.includes(p.command)){n.latestDesignCheckSummary=gB(n.latestDesignCheckSummary,mB("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 DB=100,Xge=12e4,Qge=15e3,NB=new Set(["manage_ui_create_tree","manage_ui_update","manage_ui_delete"]);function ehe(t,e){return`License required for internal command ${t}. ${e??"Activate Pro license to use this feature."}`}var the={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"}},nhe={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"},rhe=Object.entries(Tl).reduce((t,[e,n])=>{for(let i of n.validActions)t[`${e}_${i}`]=e;return t},{});function RB(t){return{toolName:rhe[t]||t,commandName:t}}function EB(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 Gx(t,e){if(t!=="manage_sync_status_current_place")return e;let{placeId:n,...i}=e;return i}function ihe(t,e){let n=e.routing;return{requestId:t,success:!1,error:e.message,errorCode:e.code,routing:n,data:{routing:n}}}async function ahe(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 ohe(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 she(t,e){let n=e.targetPath;if(typeof n=="string"&&n.length>0)return n;if(t==="manage_ui_create_tree")return ohe(e)}function che(t){let e=the[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 TB(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function lhe(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=TB(a,"before"),c=TB(a,"after");i.set(o,{...s&&{before:a.before},...c&&{after:a.after},hasBefore:s,hasAfter:c})}return i}function jB(t,e){let i=t.changes?.properties;if(!i||typeof i!="object")return;let r=lhe(e),a=Object.entries(i).map(([o,s])=>{let c=che(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 MB(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?`${nhe[r]} ${a}\uAC1C`:null}).filter(r=>r!==null);return i.length>0?`${i.join(", ")} \uBCC0\uACBD`:void 0}function AB(t,e){if(t==="manage_ui_update"){let n=e.changes,i=MB(jB(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 Af(t){return t&&typeof t=="object"?t:void 0}function Kx(t,e){let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:0}function zB(t){let e=Af(t),n=Af(e?.design_check_summary);if(n)return{priority_high:Kx(n,"priority_high"),priority_medium:Kx(n,"priority_medium"),priority_low:Kx(n,"priority_low"),total:Kx(n,"total"),...typeof n.scope=="string"&&{scope:n.scope},...typeof n.target=="string"&&{target:n.target}}}function LB(t){let n=Af(t)?.snapshot_id;return typeof n=="string"?n:null}function $B(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 UB(t){let e=Af(t),n=Af(e?.meta);return $B(n?.captured_at)??$B(n?.evaluated_at)}function uhe(t,e){let n=t.uiStudioRecorders.get(e);if(n)return n;let i=hB({placeDir:e,idleMs:Qge,capturePreview:async r=>{try{let a=await ir(t,"manage_ui_preview",{targetPath:r},Yx());if(!a.success||!a.data||typeof a.data!="object")return null;let o=zB(a.data),s=UB(a.data);return{snapshotId:LB(a.data),...o!==void 0&&{designCheckSummary:o},...s!==void 0&&{capturedAt:s}}}catch{return null}}});return t.uiStudioRecorders.set(e,i),i}async function dhe(t,e,n){if(!NB.has(e))return null;let i=await ahe(t,n);if(!i)return null;let r=uhe(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=she(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 y.debug("UI Studio recorder beforeMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:p}),null}}async function OB(t,e){if(t)try{let n=t.command==="manage_ui_update"?jB(t.params,e.data):void 0,i=t.command==="manage_ui_update"?MB(n)??AB(t.command,t.params):AB(t.command,t.params),r=zB(e.data),a=LB(e.data),o=UB(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){y.debug("UI Studio recorder afterMutation \uC2E4\uD328 (\uBB34\uC2DC)",{error:n})}}async function Jx(t,e,n,i,r,a){if(!t.historyManager)return;let o=!r.success&&r.error?jl(n,r.error):void 0,s=Nl({resultSuccess:r.success,resultData:r.data,resultError:r.error,tier:zn(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=Gx(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,Gx(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,Gx(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=Gx(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 cT(t,e,n){let i=t.pendingCommands.get(e)||[];i.length>=DB&&i.shift(),i.push(n),t.pendingCommands.set(e,i)}function phe(t,e){t.globalPendingCommands.length>=DB&&t.globalPendingCommands.shift(),t.globalPendingCommands.push(e)}function FB(t,e,n){let i=Yx(),r={requestId:i,command:e.command,params:e.params,timestamp:Date.now(),queueTimeoutMs:e.queueTimeoutMs,ackedTimeoutMs:e.ackedTimeoutMs,state:vn.QUEUED,targetClientId:n,resolve:()=>{},reject:a=>{y.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(()=>{Jb(t,r,r.queueTimeoutMs)},r.queueTimeoutMs),{event:"command",id:i,data:{command:r.command,requestId:i,params:r.params}}}function fhe(t,e,n,i){if(!gf(e.data.command))return;let r=t.commandQueue.get(e.data.requestId);if(!r)return;qB(t,r);let a=n.filter(o=>o.clientId!==i);for(let o of a){let s=FB(t,r,o.clientId);cT(t,o.clientId,s)}a.length>0&&y.info("Fan-out playtest stop command to active plugin clients",{requestId:e.data.requestId,primaryClientId:i,auxiliaryClientIds:a.map(o=>o.clientId)})}function qB(t,e,n){for(let i of gq)setTimeout(()=>{let a=n?[...new Set(n)]:[...new Set(Cn(t).map(o=>o.clientId))];for(let o of a){if(!t.pluginClients.get(o))continue;let c=FB(t,e,o);cT(t,o,c)}y.info("Retry playtest stop command to active plugin clients",{sourceRequestId:e.requestId,delayMs:i,targetClientIds:a}),hl(t)},i).unref?.()}function BB(t){return t==="clientId"||t==="targetAlias"||t==="placeId"}function mhe(t,e,n){if(!n||!gf(e.data.command))return!1;let i=t.commandQueue.get(e.data.requestId)?.routing?.selectionMode;return!BB(i)}function ghe(t,e,n){y.debug("Broadcasting command",{command:e.data.command,requestId:e.data.requestId,targetClientId:n||"all",activeWebsocketClients:Cn(t).length});let i=n;if(n){cT(t,n,e);let r=t.commandQueue.get(e.data.requestId),a=r?.routing?.selectionMode;if(r&&gf(e.data.command)&&BB(a))qB(t,r,[n]);else if(mhe(t,e,n)){let o=Cn(t).sort((s,c)=>c.lastSeen-s.lastSeen);fhe(t,e,o,n),i=void 0}}else phe(t,e);hl(t,i)}async function HB(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=RB(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(y.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=mf(t,m!==void 0?m:3e4),h=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,h,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,h,c.commandName),n.json({requestId:s,success:!0,data:x});return}if(r==="get_connection_info"){let m=await Dx(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(jx(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(zn(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 _=ehe(r,x.reason),I=Date.now()-i;t.historyManager&&await Jx(t,c.toolName,c.commandName,a,{success:!1,error:_},I),n.json({requestId:s,success:!1,error:_});return}}let m={...a,__sessionId:u},g=await t.internalCommandExecutor(r,m),h=Date.now()-i,v=EB(m,g.data);t.historyManager&&await Jx(t,c.toolName,c.commandName,v,{success:g.success,data:g.data,error:g.error||"Internal command failed"},h),n.json({requestId:s,...g});return}let d=await ir(t,r,a,s,l),p=Date.now()-i,f={...EB(a,d.data),__sessionId:u};t.historyManager&&await Jx(t,c.toolName,c.commandName,f,d,p),n.json(d)}catch(o){let s=Date.now()-i,c=Mn(o);if(t.historyManager&&r){let l=RB(r);await t.historyManager.recordFailure(l.toolName,a,c,s,"EXCEPTION",l.commandName)}y.error("Execute request failed",o),n.status(500).json({success:!1,error:c})}}async function ZB(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=Yx(),{action:l,...u}=r;try{t.serverLastCommandAt=Date.now();let d=await ir(t,s,u,c),p=Date.now()-i;t.historyManager&&await Jx(t,"manage_properties",s,u,d,p),n.json(d)}catch(d){let p=Date.now()-i,f=Mn(d);t.historyManager&&await t.historyManager.recordFailure("manage_properties",u,f,p,"EXCEPTION",s),y.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(y.debug("Executing command locally",{command:e,requestId:i}),Q6(t,i)){let d=`Duplicate requestId '${i}' for command '${e}'. Generate a unique requestId for each command.`;return y.warn("Duplicate execute request rejected",{command:e,requestId:i}),{requestId:i,success:!1,error:d}}let a;try{a=Nx(t,Cn(t),n,e)}catch(d){if(d instanceof on)return y.warn("Command target selection failed",{command:e,requestId:i,errorCode:d.code,routing:d.routing}),ihe(i,d);throw d}let o=NB.has(e)?await dhe(t,e,n):null,s=t.config.requestTimeout,c=r?.timeout??Math.max(t.config.requestTimeout,Xge),l=KE.has(e)?await eB({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:vn.QUEUED,...a.targetClientId?{targetClientId:a.targetClientId}:{},routing:a.routing,resolve:d,reject:p,timeoutId:null};t.commandQueue.set(i,m),Zb(t,a.targetClientId,f),m.timeoutId=setTimeout(()=>{Jb(t,m,s)},s)});return ghe(t,{event:"command",id:Yx(),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(()=>(sT(),oT)),g=await m(t,n),h=await f("manage_ui_preview",d.data,g);p={...d,data:h.data,...h.mcpContent?{mcpContent:h.mcpContent}:{}}}catch(f){y.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(()=>(sT(),oT)),{processCheckResult:m}=await Promise.resolve().then(()=>(PB(),kB)),g=await f(t,n),h=await m("manage_ui_check",d.data,g,n);p={...p,data:h.data}}catch(f){y.warn("check visual post-processing failed",{error:f instanceof Error?f.message:String(f)})}return JE.has(e)?p=await tB({ctx:t,command:e,params:n,result:p}):e===GE&&(p=await nB({ctx:t,params:n,result:p})),p}).then(async d=>(await OB(o,{success:d.success,...d.data!==void 0&&{data:d.data},...d.error!==void 0&&{error:d.error}}),d),async d=>{throw await OB(o,{success:!1,error:Mn(d)}),d})}ce();wi();function Xx(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),rt(t,"license",n)}function ti(t,e,n,i){t.status(e).json({success:!1,error:{code:n,message:i}})}function hhe(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();return e.length>0?e:void 0}function Qx(t,e){if(e==="plugin")return t;let n={...t};return delete n.sessionToken,n}function $f(t,e,n,i){let r=hhe(i??e.query.provider)??"auto";return t.licenseState?.supportsProvider(r)===!1?(ti(n,400,"LICENSE_PROVIDER_UNSUPPORTED",`provider "${r}" is not supported`),null):r}function Of(t,e){return t.licenseState?!0:(ti(e,503,"LICENSE_NOT_INITIALIZED","License system is not initialized"),!1)}function yhe(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 Df(t,e,n,i="plugin"){if(!Of(t,n))return;let r=e.body,a=typeof r?.licenseKey=="string"?r.licenseKey:"";if(!a.trim()){ti(n,400,"LICENSE_KEY_REQUIRED","licenseKey is required");return}let o=$f(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"),Xx(t,{provider:u.provider,tier:u.canUsePro?"pro":"basic",status:u.status,canUsePro:u.canUsePro}),n.json(Qx(u,i))}).catch(u=>{y.warn("License activate failed",{error:u instanceof Error?u.message:"unknown_error"}),ti(n,502,"LICENSE_ACTIVATE_FAILED",u instanceof Error?u.message:"License activation failed")})}function Nf(t,e,n,i="plugin"){if(!Of(t,n))return;let r=$f(t,e,n);if(r)try{let a=t.licenseState.getStatus(r);t.analyticsManager?.setTier(a.canUsePro?"pro":"basic"),n.json(Qx(a,i))}catch(a){y.warn("License status check failed",{error:a instanceof Error?a.message:"unknown_error"}),ti(n,502,"LICENSE_STATUS_FAILED",a instanceof Error?a.message:"License status check failed")}}function jf(t,e,n,i="plugin"){if(!Of(t,n))return;let r=e.body,a=$f(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"),Xx(t,{provider:s.provider,tier:s.canUsePro?"pro":"basic",status:s.status,canUsePro:s.canUsePro}),n.json(Qx(s,i))}).catch(s=>{y.warn("License refresh failed",{error:s instanceof Error?s.message:"unknown_error"}),ti(n,502,"LICENSE_REFRESH_FAILED",s instanceof Error?s.message:"License refresh failed")})}function Mf(t,e,n,i="plugin"){if(!Of(t,n))return;let r=e.body,a=$f(t,e,n,r?.provider);a&&t.licenseState.resetGateway({provider:a,clientType:i}).then(o=>{t.analyticsManager?.setTier("basic"),Xx(t,{provider:o.provider,tier:"basic",status:o.status,canUsePro:o.canUsePro,cleared:!0}),n.json(Qx(o,i))}).catch(o=>{y.warn("License reset failed",{error:o instanceof Error?o.message:"unknown_error"}),ti(n,502,"LICENSE_RESET_FAILED",o instanceof Error?o.message:"License reset failed")})}function lT(t,e,n){if(!Of(t,n))return;let i=e.body,r=$f(t,e,n,i?.provider);if(!r)return;if(i?.clientType!=="plugin"){ti(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=yhe(i?.snapshot)?i.snapshot:void 0;if(!o&&!a){ti(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"),Xx(t,{provider:c.provider,tier:c.canUsePro?"pro":"basic",status:c.status,canUsePro:c.canUsePro}),n.json({ok:!0})}).catch(c=>{y.warn("License bootstrap failed",{error:c instanceof Error?c.message:"unknown_error"}),ti(n,502,"LICENSE_BOOTSTRAP_FAILED",c instanceof Error?c.message:"License bootstrap failed")})}function VB(t){t.app.post("/license/bootstrap",(e,n)=>lT(t,e,n)),t.app.post("/license/activate",(e,n)=>Df(t,e,n,"plugin")),t.app.post("/license/refresh",(e,n)=>jf(t,e,n,"plugin")),t.app.post("/license/reset",(e,n)=>Mf(t,e,n,"plugin")),t.app.get("/license/status",(e,n)=>Nf(t,e,n,"plugin"))}ft();ce();import{promises as e_}from"fs";import uT from"path";function vhe(t){let e=t.config.appDataDir??ot();return uT.join(e,"observability","logs")}async function Fl(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)){y.warn("Invalid logs request",{body:r}),n.status(400).json({error:"Invalid request body"});return}let a=vhe(t);await e_.mkdir(a,{recursive:!0});let c=`plugin-${new Date().toISOString().split("T")[0]}.log`,l=uT.join(a,c),u=uT.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 e_.appendFile(l,d,"utf-8");try{let p="";try{p=await e_.readFile(u,"utf-8")}catch{}let m=(p+d).split(`
|
|
507
507
|
`).slice(-500).join(`
|