@weppy/roblox-mcp 2.17.14 → 2.17.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dashboard/dist/assets/{AiPromptExamples-B3Uy68MJ.js → AiPromptExamples-Cwfw0ZqC.js} +1 -1
  3. package/dashboard/dist/assets/{AssetsPage-DGSoVLnO.js → AssetsPage-Cd1Ir_6o.js} +1 -1
  4. package/dashboard/dist/assets/{ChangelogPage-B9dCtQOo.js → ChangelogPage-BPP9_53U.js} +1 -1
  5. package/dashboard/dist/assets/{ConfirmModal-B6ovGUld.js → ConfirmModal-CdZW4-sk.js} +1 -1
  6. package/dashboard/dist/assets/{ConnectionPage-B3NzHXCM.js → ConnectionPage-j6oGLSEC.js} +1 -1
  7. package/dashboard/dist/assets/{ControlsPage-dQj67_QM.js → ControlsPage-CkU_Xz6W.js} +1 -1
  8. package/dashboard/dist/assets/{GameChangeDetail-BfltcON0.js → GameChangeDetail-BVanxiU-.js} +1 -1
  9. package/dashboard/dist/assets/{InfoLabel-CUAC4KaS.js → InfoLabel-DuNAxesz.js} +1 -1
  10. package/dashboard/dist/assets/OverviewPage-DaR6Zf4N.js +1 -0
  11. package/dashboard/dist/assets/{PageHeader-BbXDD7J9.js → PageHeader-C8RSD2wK.js} +1 -1
  12. package/dashboard/dist/assets/{PlaceSelectOptions-CoWR0lUt.js → PlaceSelectOptions-B-hh23M4.js} +1 -1
  13. package/dashboard/dist/assets/{PlaytestAiPromptExamples-CNzT1Zzl.js → PlaytestAiPromptExamples-CVThXrz5.js} +1 -1
  14. package/dashboard/dist/assets/{PlaytestPage-DoyKVZGe.js → PlaytestPage-BoKMpsGY.js} +1 -1
  15. package/dashboard/dist/assets/{SettingsPage-DmuhCaCs.js → SettingsPage-Cgnm6p8V.js} +1 -1
  16. package/dashboard/dist/assets/SyncPage-CZ3NhJOo.js +1 -0
  17. package/dashboard/dist/assets/{Tabs-CI7QBRFn.js → Tabs-Br8Zgvmi.js} +1 -1
  18. package/dashboard/dist/assets/{TierPromoPanel-BcWyr5ni.js → TierPromoPanel-BYdwzdxN.js} +1 -1
  19. package/dashboard/dist/assets/{ToolsPage-BYlAjTDF.js → ToolsPage-DC8hKMbq.js} +1 -1
  20. package/dashboard/dist/assets/{TooltipText-C8S8B8k6.js → TooltipText-DudXe1Qy.js} +1 -1
  21. package/dashboard/dist/assets/{UiStudioPage-Sg9Sc7dA.js → UiStudioPage-DZUmNIp2.js} +1 -1
  22. package/dashboard/dist/assets/{WhatsNewPage-Xu9jN9ei.js → WhatsNewPage-EVjYD3ti.js} +1 -1
  23. package/dashboard/dist/assets/{bot-GYHFrFjr.js → bot-Cud9Il_O.js} +1 -1
  24. package/dashboard/dist/assets/{check-CK84xvEL.js → check-CsYm1hvL.js} +1 -1
  25. package/dashboard/dist/assets/{copy-Dagqdoq_.js → copy-yeY7HS26.js} +1 -1
  26. package/dashboard/dist/assets/{index-Dryjq9a5.js → index-CbTOKOZ5.js} +11 -11
  27. package/dashboard/dist/assets/{rotate-ccw-BhctsB9r.js → rotate-ccw-CzAWuBD5.js} +1 -1
  28. package/dashboard/dist/assets/{sample-requests-B6Kd_Wul.js → sample-requests-Ctlw72Az.js} +1 -1
  29. package/dashboard/dist/assets/{trash-2-BkWSghui.js → trash-2-BAenJavG.js} +1 -1
  30. package/dashboard/dist/assets/{useLiveUptime-C0rFrLl1.js → useLiveUptime-Dyb_GmdN.js} +1 -1
  31. package/dashboard/dist/assets/{useSettings-CyIbYDSy.js → useSettings-fppB8ls5.js} +1 -1
  32. package/dashboard/dist/index.html +1 -1
  33. package/dist/index.js +244 -160
  34. package/package.json +1 -1
  35. package/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
  36. package/dashboard/dist/assets/OverviewPage-DAHV_J9P.js +0 -1
  37. package/dashboard/dist/assets/SyncPage-DTwGdjCc.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weppy/roblox-mcp",
3
- "version": "2.17.14",
3
+ "version": "2.17.15",
4
4
  "description": "MCP (Model Context Protocol) server for Roblox Studio integration - enables AI coding agents to interact with Roblox Studio in real-time",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
Binary file
@@ -1 +0,0 @@
1
- import{j as s,u as R,r as h,d as L,e as F,b as M,D as V}from"./index-Dryjq9a5.js";import{I as A}from"./InfoLabel-CUAC4KaS.js";import{P as U}from"./PageHeader-BbXDD7J9.js";import{u as z,f as O,S as X}from"./useLiveUptime-C0rFrLl1.js";import{T as q}from"./TooltipText-C8S8B8k6.js";import{G as J}from"./GameChangeDetail-BfltcON0.js";const K="_page_amwos_2",Q="_card_amwos_10",W="_cardHeader_amwos_17",Y="_disconnectCard_amwos_28",Z="_disconnectIcon_amwos_36",ee="_disconnectTitle_amwos_41",se="_disconnectMessage_amwos_48",te="_reconnectGuide_amwos_55",ne="_guideStep_amwos_64",ie="_stepNumber_amwos_72",ae="_reconnectIndicator_amwos_88",ce="_reconnectDot_amwos_98",re="_pulse_amwos_1",oe="_disconnectActions_amwos_112",le="_btn_amwos_118",de="_btnSecondary_amwos_134",me="_metricRow_amwos_152",ue="_metricGrid_amwos_158",ve="_metricCard_amwos_164",ge="_metric_ok_amwos_174",_e="_metric_warn_amwos_179",he="_metric_error_amwos_184",pe="_metricHeader_amwos_189",we="_metricIcon_amwos_200",fe="_metricTitle_amwos_204",xe="_metricValue_amwos_208",Ce="_metricSubtitle_amwos_215",je="_guideCard_amwos_225",Ne="_guideTitle_amwos_232",ye="_checklist_amwos_239",Te="_feedEmpty_amwos_263",Se="_feedList_amwos_270",Ie="_feedItem_amwos_278",be="_feedTime_amwos_291",ke="_feedIcon_amwos_298",Me="_feedSummary_amwos_304",De="_feedText_amwos_313",Be="_feedContext_amwos_321",He="_feedItemClickable_amwos_330",Ee="_feedChevron_amwos_338",Pe="_feedDetail_amwos_347",$e="_feedDetailPre_amwos_356",Re="_feedDetailText_amwos_365",Ge="_changelogSummary_amwos_372",Le="_changeTag_amwos_381",Fe="_tierBar_amwos_393",Ve="_tierBarTrack_amwos_399",Ae="_tierBarFillBasic_amwos_407",Ue="_tierBarFillPro_amwos_412",ze="_tierLabels_amwos_417",t={page:K,card:Q,cardHeader:W,disconnectCard:Y,disconnectIcon:Z,disconnectTitle:ee,disconnectMessage:se,reconnectGuide:te,guideStep:ne,stepNumber:ie,reconnectIndicator:ae,reconnectDot:ce,pulse:re,disconnectActions:oe,btn:le,btnSecondary:de,metricRow:me,metricGrid:ue,metricCard:ve,metric_ok:ge,metric_warn:_e,metric_error:he,metricHeader:pe,metricIcon:we,metricTitle:fe,metricValue:xe,metricSubtitle:Ce,guideCard:je,guideTitle:Ne,checklist:ye,feedEmpty:Te,feedList:Se,feedItem:Ie,feedTime:be,feedIcon:ke,feedSummary:Me,feedText:De,feedContext:Be,feedItemClickable:He,feedChevron:Ee,feedDetail:Pe,feedDetailPre:$e,feedDetailText:Re,changelogSummary:Ge,changeTag:Le,tierBar:Fe,tierBarTrack:Ve,tierBarFillBasic:Ae,tierBarFillPro:Ue,tierLabels:ze};function N({title:e,value:i,icon:a,subtitle:c,status:r,children:n}){const l=r?t[`metric_${r}`]:"";return s.jsxs("div",{className:`${t.metricCard} ${l}`,children:[s.jsxs("div",{className:t.metricHeader,children:[a&&s.jsx("span",{className:t.metricIcon,children:a}),s.jsx("span",{className:t.metricTitle,children:e})]}),s.jsx("div",{className:t.metricValue,children:i}),c&&s.jsx("div",{className:t.metricSubtitle,children:c}),n]})}function Oe(e){var a,c;const i=e==null?void 0:e.contextSummary;return(i==null?void 0:i.intent)??((c=(a=i==null?void 0:i.affectedAreas)==null?void 0:a[0])==null?void 0:c.label)??(i==null?void 0:i.testScenario)??null}function H({changes:e}){const{t:i}=R(),[a,c]=h.useState(null);return e.length===0?s.jsx("div",{className:t.feedEmpty,children:i("overview.feed.empty")}):s.jsx("div",{className:t.feedList,children:e.map((r,n)=>{const l=a===n,m=r.raw,u=m&&(m.before!=null||m.after!=null||m.details!=null),p=Oe(m);return s.jsxs("div",{children:[s.jsxs("div",{className:`${t.feedItem} ${u?t.feedItemClickable:""}`,onClick:()=>u&&c(l?null:n),children:[s.jsx("span",{className:t.feedTime,children:r.timestamp}),s.jsx("span",{className:t.feedIcon,children:r.icon}),s.jsxs("span",{className:t.feedText,children:[s.jsx("span",{className:t.feedSummary,children:r.summary}),p&&s.jsx("span",{className:t.feedContext,children:p})]}),u&&s.jsx("span",{className:t.feedChevron,children:l?"▴":"▾"})]}),l&&m&&s.jsx("div",{className:t.feedDetail,children:s.jsx(J,{change:m})})]},n)})})}const E=20;function G(e){return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function P(){return G(new Date)}function $(e){switch(e){case"script":return"📝";case"instance":return"🧱";case"property":return"🎨";case"lighting":return"💡";case"terrain":return"⛰️";case"asset":return"📦";default:return"🔧"}}function Xe(){const{level:e,status:i}=L(),a=F(),[c,r]=h.useState(null),[n,l]=h.useState(null),[m,u]=h.useState(null),[p,v]=h.useState([]),y=h.useRef(null),T=h.useCallback(async()=>{try{const o=await M.get("/connection-info");r(o)}catch{r(null)}},[]),S=h.useCallback(async()=>{try{const o=await M.get("/api/dashboard/changelog/active");if(u(o),o.recentChanges&&o.recentChanges.length>0){const w=o.recentChanges.map(g=>({timestamp:g.timestamp?G(new Date(g.timestamp)):P(),icon:$(g.category),summary:g.summary,category:g.category,raw:g}));v(w)}}catch{u(null)}},[]),f=h.useCallback(async()=>{try{const o=await M.get("/sync/status");l(o)}catch{l(null)}},[]);return h.useEffect(()=>{e!=="disconnected"?(T(),S(),f()):(r(null),l(null),u(null));const o=new V;y.current=o,o.connect();const w=o.on("game_change",x=>{const _=x,C={timestamp:P(),icon:$(_.category),summary:_.summary,category:_.category};v(k=>{const j=[C,...k];return j.length>E?j.slice(0,E):j}),S()}),g=o.on("sync",x=>{const _=x;l(C=>({...C,state:_.status,..._.placeId?{placeId:_.placeId}:{}}))});return()=>{w(),g(),o.disconnect(),y.current=null}},[e,T,S,f]),{level:e,status:i,connectionInfo:c,syncStatus:n,changeSummary:m,recentChanges:p,tier:a}}function D(e){return e.scriptsModified+e.scriptsCreated+e.instancesCreated+e.instancesDeleted+e.instancesMoved+e.propertiesChanged+e.assetsInserted+(e.lightingChanged?1:0)+(e.terrainChanged?1:0)}function qe(e,i){switch(e){case"syncing":return i("status.syncing","Syncing");case"initializing":return i("status.initializing","Initializing");case"error":return i("status.error","Error");default:return i("status.idle","Idle")}}function Je(e){switch(e){case"syncing":return"ok";case"initializing":return"warn";case"error":return"error";default:return"ok"}}function b(e,i,a,c){return s.jsxs("div",{className:e.metricSubtitle,children:[s.jsx(A,{label:i,tooltip:a}),": ",c]},i)}function d(e,i){return s.jsx(q,{text:i,children:e})}function ss(){var j,B;const{t:e}=R(),{level:i,status:a,connectionInfo:c,syncStatus:r,changeSummary:n,recentChanges:l}=Xe(),m=z(a==null?void 0:a.uptime),u=s.jsx(U,{title:e("page.overview.title","Overview"),description:e("page.overview.description","Check server, plugin, agent, sync, and recent game-change status in one place."),helpTopicId:"overview",helpState:{connectionLevel:i}});if(i==="disconnected")return s.jsxs("div",{className:t.page,children:[u,s.jsxs("div",{className:t.disconnectCard,children:[s.jsx("div",{className:t.disconnectIcon,children:"⚠️"}),s.jsx("h2",{className:t.disconnectTitle,children:e("overview.l0.title")}),s.jsx("p",{className:t.disconnectMessage,children:e("overview.l0.message")}),s.jsxs("div",{className:t.reconnectGuide,children:[s.jsxs("div",{className:t.guideStep,children:[s.jsx("span",{className:t.stepNumber,children:"1"}),s.jsx("span",{children:e("overview.l0.step1")})]}),s.jsxs("div",{className:t.guideStep,children:[s.jsx("span",{className:t.stepNumber,children:"2"}),s.jsx("span",{children:e("overview.l0.step2")})]})]}),s.jsxs("div",{className:t.reconnectIndicator,children:[s.jsx("span",{className:t.reconnectDot}),e("overview.l0.reconnecting")]}),s.jsxs("div",{className:t.disconnectActions,children:[s.jsx("button",{className:t.btn,onClick:()=>window.location.reload(),children:e("overview.l0.reconnectBtn")}),s.jsx("button",{className:t.btnSecondary,onClick:()=>{window.location.hash="#/settings"},children:e("overview.l0.settingsBtn")})]})]})]});const p=(c==null?void 0:c.mcpInstanceCount)??0,v=((j=c==null?void 0:c.mcpInstances)==null?void 0:j.find(I=>!I.isServer&&I.aiClientName))??((B=c==null?void 0:c.mcpInstances)==null?void 0:B.find(I=>!!I.aiClientName))??null,y=(a==null?void 0:a.pluginClients)??[],T=y.length>0,S=(a==null?void 0:a.sessionId)??(c==null?void 0:c.sessionId)??"-",f=e("overview.metric.server.tooltip","MCP server runtime and process status"),o=e("overview.metric.plugin.tooltip","Roblox Studio plugin connection and version status"),w=e("overview.metric.agent.tooltip","Connected AI coding agents and their runtime state"),g=e("overview.metric.sync.tooltip","Current Studio to local sync activity"),x=a?[b(t,e("overview.meta.version","Version"),e("overview.meta.version.tooltip","Installed MCP server version"),`v${a.version}`),b(t,e("overview.meta.session","Session"),e("overview.meta.session.tooltip","Current MCP session identifier"),S),b(t,e("overview.meta.pid","PID"),e("overview.meta.pid.tooltip","Operating system process identifier"),String(a.pid??"-")),b(t,e("overview.meta.uptime","Uptime"),e("overview.meta.uptime.tooltip","Time elapsed since the MCP server started"),O(m??a.uptime))]:[];if(i==="serverOnly")return s.jsxs("div",{className:t.page,children:[u,s.jsxs("div",{className:t.metricRow,children:[s.jsx(N,{title:d(e("overview.metric.server"),f),value:d(e("status.online"),f),icon:"🖥️",status:"ok",children:s.jsxs(s.Fragment,{children:[x,s.jsx(X,{status:"online"})]})}),s.jsx(N,{title:d(e("overview.metric.agent"),w),value:d((v==null?void 0:v.aiClientName)??e("overview.metric.noAgent"),w),icon:"🤖",subtitle:p>1?`${p} ${e("overview.metric.agent.instancesUnit","instances")}`:void 0,status:v?"ok":"warn"})]}),s.jsxs("div",{className:t.guideCard,children:[s.jsx("h3",{className:t.guideTitle,children:e("overview.l1.pluginGuide")}),s.jsxs("ul",{className:t.checklist,children:[s.jsx("li",{children:e("overview.l1.check1")}),s.jsx("li",{children:e("overview.l1.check2")})]})]}),s.jsxs("div",{className:t.card,children:[s.jsx("div",{className:t.cardHeader,children:e("overview.feed.title")}),l.length>0?s.jsx(H,{changes:l}):s.jsx("div",{className:t.feedEmpty,children:e("overview.l1.feedHint")})]}),n&&D(n)>0&&s.jsxs("div",{className:t.card,children:[s.jsx("div",{className:t.cardHeader,children:e("overview.changelog.title")}),s.jsxs("div",{className:t.changelogSummary,children:[s.jsxs("span",{children:[e("overview.changelog.entries","Entries"),": ",D(n)]}),n.scriptsModified>0&&s.jsxs("span",{className:t.changeTag,children:["📝"," ",n.scriptsModified," ",e("overview.changelog.scripts")]}),n.instancesCreated>0&&s.jsxs("span",{className:t.changeTag,children:["🧱"," ",n.instancesCreated," ",e("overview.changelog.instances")]}),n.propertiesChanged>0&&s.jsxs("span",{className:t.changeTag,children:["🎨"," ",n.propertiesChanged," ",e("overview.changelog.properties")]}),n.assetsInserted>0&&s.jsxs("span",{className:t.changeTag,children:["📦"," ",n.assetsInserted," ",e("overview.changelog.assets")]})]})]})]});const _=y[0],C=n?D(n):0,k=!!n&&C>0;return s.jsxs("div",{className:t.page,children:[u,s.jsxs("div",{className:t.metricGrid,children:[s.jsx(N,{title:d(e("overview.metric.server"),f),value:d(e("status.online"),f),icon:"🖥️",status:"ok",children:s.jsx(s.Fragment,{children:x})}),s.jsx(N,{title:d(e("overview.metric.plugin"),o),value:d(e(T?"status.online":"status.offline"),o),icon:"🔌",subtitle:_?`${_.placeName??"-"} / v${_.pluginVersion??"-"}`:void 0,status:T?"ok":"error"}),s.jsx(N,{title:d(e("overview.metric.agent"),w),value:d((v==null?void 0:v.aiClientName)??e("overview.metric.noAgent"),w),icon:"🤖",subtitle:p>1?`${p} ${e("overview.metric.agent.instancesUnit","instances")}`:void 0,status:v?"ok":"warn"}),s.jsx(N,{title:d(e("overview.metric.sync"),g),value:d(qe(r==null?void 0:r.state,e),g),icon:"🔄",status:Je(r==null?void 0:r.state)})]}),s.jsxs("div",{className:t.card,children:[s.jsx("div",{className:t.cardHeader,children:e("overview.feed.title")}),s.jsx(H,{changes:l})]}),k&&s.jsxs("div",{className:t.card,children:[s.jsx("div",{className:t.cardHeader,children:e("overview.changelog.title")}),s.jsxs("div",{className:t.changelogSummary,children:[s.jsxs("span",{children:[e("overview.changelog.entries","Entries"),": ",C]}),n.scriptsModified>0&&s.jsxs("span",{className:t.changeTag,children:["📝"," ",n.scriptsModified," ",e("overview.changelog.scripts")]}),n.instancesCreated>0&&s.jsxs("span",{className:t.changeTag,children:["🧱"," ",n.instancesCreated," ",e("overview.changelog.instances")]}),n.propertiesChanged>0&&s.jsxs("span",{className:t.changeTag,children:["🎨"," ",n.propertiesChanged," ",e("overview.changelog.properties")]}),n.assetsInserted>0&&s.jsxs("span",{className:t.changeTag,children:["📦"," ",n.assetsInserted," ",e("overview.changelog.assets")]})]})]})]})}export{ss as Component};
@@ -1 +0,0 @@
1
- import{r as d,b as q,h as ee,D as le,u as ie,j as e,a as de,d as pe,e as ye,k as ue,T as ge}from"./index-Dryjq9a5.js";import{B as A,a as te,P as me}from"./PageHeader-BbXDD7J9.js";import{I as G}from"./InfoLabel-CUAC4KaS.js";import{T as D}from"./TooltipText-C8S8B8k6.js";import{C as oe}from"./ConfirmModal-B6ovGUld.js";import{T as he}from"./TierPromoPanel-BcWyr5ni.js";import"./ConfirmModal.module-DJksQHBd.js";const fe=5e3,T={report:null,loading:!1,applying:!1,error:null};function _e(t,i){if(i===null)return null;const m=t.filter(c=>c.placeId===i);return m.length===1?m[0]:i===0?null:m.find(c=>c.folderStatus==="canonical")??null}function ce(t,i){if(i===null||!Number.isSafeInteger(i)||i<0)return!1;const m=t.filter(c=>c.placeId===i);return i===0?m.length===1:m.length===0||m.some(c=>c.folderStatus==="canonical")}function X(t,i){return i.placeId<=0||!Number.isSafeInteger(i.placeId)?!1:ce(t,i.placeId)&&(i.folderStatus==="canonical"||t.filter(m=>m.placeId===i.placeId).length===1)}function Se(){const[t,i]=d.useState([]),[m,c]=d.useState(null),[r,n]=d.useState(null),[f,j]=d.useState(!0),[L,M]=d.useState(null),[h,E]=d.useState([]),[J,O]=d.useState(!1),[Q,H]=d.useState(null),[u,p]=d.useState(T),R=d.useRef(0),l=d.useRef(0),k=d.useRef(null),$=d.useRef(!1),x=d.useRef(null),b=d.useRef(new Set),P=d.useCallback(async()=>{const a=++R.current;try{const[g,y]=await Promise.all([q.get("/api/dashboard/sync/targets"),q.get("/api/dashboard/place-summary")]);if(a!==R.current)return;i(g.targets??[]),c(y),M(null)}catch(g){if(a!==R.current)return;i([]),c(null),M(g instanceof Error?g.message:String(g))}finally{a===R.current&&j(!1)}},[]),w=d.useMemo(()=>(m==null?void 0:m.places)??[],[m]),Y=d.useMemo(()=>new Set(t.map(a=>a.placeId).filter(a=>typeof a=="number")),[t]),B=d.useMemo(()=>w.filter(a=>a.placeId===0||!Y.has(a.placeId)),[Y,w]);d.useEffect(()=>{f||L||n(a=>{if((a==null?void 0:a.kind)==="target"&&t.some(y=>y.clientId===a.clientId)||(a==null?void 0:a.kind)==="stored"&&B.some(y=>y.placeId===a.placeId&&y.placeDirName===a.placeDirName&&X(w,y)))return a;if(t[0])return{kind:"target",clientId:t[0].clientId};const g=B.find(y=>X(w,y));return g?{kind:"stored",placeId:g.placeId,placeDirName:g.placeDirName}:null})},[f,w,L,B,t]);const U=(r==null?void 0:r.kind)==="target"?t.find(a=>a.clientId===r.clientId)??null:null,_=(U==null?void 0:U.placeId)??((r==null?void 0:r.kind)==="stored"?r.placeId:null),V=(r==null?void 0:r.kind)==="stored"?B.find(a=>a.placeId===r.placeId&&a.placeDirName===r.placeDirName)??null:_e(w,_),N=(r==null?void 0:r.kind)==="stored"?V!==null&&X(w,V):ce(w,_),W=(r==null?void 0:r.kind)==="target"?`target:${r.clientId}:${_??"none"}`:(r==null?void 0:r.kind)==="stored"?`stored:${r.placeDirName}`:null;k.current=_,$.current=N,x.current=W;const C=d.useCallback(async(a,g,y=!1)=>{if(a===null){p(T);return}if(!(y&&x.current!==null&&b.current.has(x.current))){y||p({...T,loading:!0});try{const S=await q.get("/api/sync/migration",{placeId:String(a)});if(g!==l.current||x.current!==null&&b.current.has(x.current))return;p({...T,report:S,applying:x.current!==null&&b.current.has(x.current),error:S.status==="blocked"?"migration_blocked":null})}catch(S){if(g!==l.current||x.current!==null&&b.current.has(x.current))return;S instanceof ee&&(S.status===404||S.status===503)?p(T):p({...T,error:"unknown"})}}},[]),I=d.useCallback(async(a,g,y=!1)=>{const S=++l.current;if(y||(E([]),H(null),p(T)),a===null||!g){O(!1);return}y||O(!0);const Z=q.get("/api/dashboard/sync/history",{placeId:String(a),limit:"30"}).then(K=>{S===l.current&&(E(K.entries??[]),H(null))}).catch(K=>{S===l.current&&H(K instanceof Error?K.message:String(K))}).finally(()=>{S===l.current&&O(!1)});await Promise.all([Z,C(a,S,y)])},[C]);d.useEffect(()=>(I(_,N),()=>{l.current+=1}),[I,_,N,(r==null?void 0:r.kind)==="target"?r.clientId:r==null?void 0:r.placeDirName]);const o=d.useCallback(()=>{P(),I(_,N)},[I,P,_,N]),v=d.useCallback(async()=>{N&&await C(_,l.current)},[C,_,N]),F=d.useCallback(async()=>{const a=u.report;if(!a||a.status!=="ready"||u.applying||!N||a.placeId!==_)return;const g=x.current;if(!(g===null||b.current.has(g))){b.current.add(g),p(y=>({...y,applying:!0,error:null}));try{const y=await q.post("/api/sync/migration",{placeId:a.placeId,fromVersion:2,previewFingerprint:a.previewFingerprint,apply:!0});if(b.current.delete(g),x.current!==g||k.current!==a.placeId)return;p({...T,report:y}),P()}catch(y){if(b.current.delete(g),x.current!==g||k.current!==a.placeId)return;if(y instanceof ee&&y.status===409&&(y.error==="preview_stale"||y.error==="migration_blocked")){if(await C(a.placeId,l.current),x.current!==g||k.current!==a.placeId)return;p(S=>({...S,applying:!1,error:y.error}))}else p(S=>({...S,applying:!1,error:"unknown"}))}}},[C,P,u,_,N]),z=d.useCallback(async a=>{if((await q.post(`/api/dashboard/sync/history/clear?placeId=${encodeURIComponent(String(a))}`)).placeId!==a)throw new Error("Cleared Place differs from the confirmed Place.");k.current===a&&$.current&&I(a,!0)},[I]);d.useEffect(()=>{P();const a=()=>{P(),k.current!==null&&$.current&&I(k.current,!0,!0)},g=setInterval(a,fe),y=new le;y.connect();const S=y.on("sync",a),Z=y.on("connection",a);return()=>{clearInterval(g),S(),Z(),y.disconnect(),R.current+=1}},[I,P]);const re=u.report&&u.report.placeId!==_?T:{...u,applying:u.applying||W!==null&&b.current.has(W)};return{targets:t,places:w,selection:r,selectedTarget:U,selectedPlace:V,selectedPlaceId:_,storageSafe:N,history:h,historyLoading:J,historyError:Q,loading:f,snapshotError:L,migration:re,selectTarget:a=>n({kind:"target",clientId:a}),selectStored:a=>n({kind:"stored",placeId:a.placeId,placeDirName:a.placeDirName}),refresh:o,refreshMigration:v,applyMigration:F,clearHistory:z}}const xe="_page_188sy_2",je="_detailsStack_188sy_9",we="_refreshButton_188sy_15",Ne="_targetRow_188sy_29",ve="_storedRow_188sy_30",be="_storedDisclosure_188sy_31",Ie="_targetList_188sy_33",Re="_storedList_188sy_33",ke="_targetRowSelected_188sy_53",De="_targetIdentity_188sy_54",Le="_targetStudio_188sy_54",Pe="_targetState_188sy_54",Ce="_stateNote_188sy_57",Te="_selectedScope_188sy_94",Ae="_sharedNote_188sy_109",Ee="_emptyMessage_188sy_109",Be="_errorMessage_188sy_110",Me="_card_188sy_113",Oe="_cardHeader_188sy_120",$e="_clearButton_188sy_132",Fe="_statusRow_188sy_158",He="_metaItem_188sy_165",Ue="_statusGrid_188sy_171",Ve="_forwardStatusReason_188sy_191",We="_migrationPanel_188sy_199",qe="_migrationHeader_188sy_206",Ke="_migrationTitle_188sy_213",Ge="_migrationDescription_188sy_222",Ye="_migrationLedger_188sy_230",ze="_migrationLedgerItem_188sy_237",Xe="_migrationLedgerBlocked_188sy_262",Je="_migrationSection_188sy_266",Qe="_migrationList_188sy_280",Ze="_migrationRow_188sy_290",et="_migrationOperation_188sy_303",tt="_migrationRowBody_188sy_308",st="_migrationNotice_188sy_329",nt="_migrationActions_188sy_336",at="_migrationButton_188sy_342",it="_policySummary_188sy_379",ot="_policySummaryItem_188sy_390",ct="_policyPrimaryValue_188sy_415",rt="_policyReviewNotice_188sy_421",lt="_policyApplySection_188sy_432",dt="_policyApplyHeader_188sy_436",pt="_policyApplyTitle_188sy_440",yt="_policyApplyDescription_188sy_448",ut="_policyInfoLabel_188sy_456",gt="_policySafetyRow_188sy_467",mt="_policySafetyLabel_188sy_479",ht="_policySafetyBadge_188sy_485",ft="_policyDisclosure_188sy_489",_t="_policyDisclosureIcon_188sy_521",St="_policyDisclosureIconOpen_188sy_528",xt="_policyScopeList_188sy_532",jt="_policyScopeRow_188sy_539",wt="_policyScopeName_188sy_553",Nt="_policyDirectionRail_188sy_565",vt="_policyDirectionEndpoint_188sy_581",bt="_policyDirectionEndpointStudio_188sy_588",It="_policyDirectionArrow_188sy_592",Rt="_forwardBadge_188sy_635",kt="_logContainer_188sy_650",Dt="_logEntry_188sy_657",Lt="_logTime_188sy_669",Pt="_logType_188sy_675",Ct="_logTypeWrite_188sy_684",Tt="_logTypeUpdate_188sy_688",At="_logTypeDelete_188sy_692",Et="_logTypeIdle_188sy_696",Bt="_logPath_188sy_700",Mt="_logEmpty_188sy_707",s={page:xe,detailsStack:je,refreshButton:we,targetRow:Ne,storedRow:ve,storedDisclosure:be,targetList:Ie,storedList:Re,targetRowSelected:ke,targetIdentity:De,targetStudio:Le,targetState:Pe,stateNote:Ce,selectedScope:Te,sharedNote:Ae,emptyMessage:Ee,errorMessage:Be,card:Me,cardHeader:Oe,clearButton:$e,statusRow:Fe,metaItem:He,statusGrid:Ue,forwardStatusReason:Ve,migrationPanel:We,migrationHeader:qe,migrationTitle:Ke,migrationDescription:Ge,migrationLedger:Ye,migrationLedgerItem:ze,migrationLedgerBlocked:Xe,migrationSection:Je,migrationList:Qe,migrationRow:Ze,migrationOperation:et,migrationRowBody:tt,migrationNotice:st,migrationActions:nt,migrationButton:at,policySummary:it,policySummaryItem:ot,policyPrimaryValue:ct,policyReviewNotice:rt,policyApplySection:lt,policyApplyHeader:dt,policyApplyTitle:pt,policyApplyDescription:yt,policyInfoLabel:ut,policySafetyRow:gt,policySafetyLabel:mt,policySafetyBadge:ht,policyDisclosure:ft,policyDisclosureIcon:_t,policyDisclosureIconOpen:St,policyScopeList:xt,policyScopeRow:jt,policyScopeName:wt,policyDirectionRail:Nt,policyDirectionEndpoint:vt,policyDirectionEndpointStudio:bt,policyDirectionArrow:It,forwardBadge:Rt,logContainer:kt,logEntry:Dt,logTime:Lt,logType:Pt,logTypeWrite:Ct,logTypeUpdate:Tt,logTypeDelete:At,logTypeIdle:Et,logPath:Bt,logEmpty:Mt};function Ot(t){return t==="add"?"success":t==="delete"?"danger":"accent"}function $t(t){return`sync.migration.reason.${t}`}function Ft(t){return`sync.migration.reason.${t}`}function Ht({migration:t,onRefresh:i,onApply:m}){const{t:c}=ie(),[r,n]=d.useState(!1),f=t==null?void 0:t.report;if(!t||!f||f.status==="not_required")return null;const j=f.status==="blocked",L=f.status==="ready"&&!t.loading&&!t.applying,M=async()=>{await m(),n(!1)};return e.jsxs("section",{className:`${s.card} ${s.migrationPanel}`,"aria-labelledby":"sync-migration-title",children:[e.jsxs("div",{className:s.migrationHeader,children:[e.jsxs("div",{children:[e.jsx("h2",{id:"sync-migration-title",className:s.migrationTitle,children:c("sync.migration.title","Sync format update available")}),e.jsx("p",{className:s.migrationDescription,children:c("sync.migration.description","Review the metadata changes before updating this place from sync format v2 to v3.")})]}),e.jsx(A,{variant:j?"warning":"accent",children:j?c("sync.migration.status.blocked","Blocked"):c("sync.migration.status.ready","Ready to review")})]}),e.jsxs("div",{className:s.migrationLedger,"aria-label":c("sync.migration.preview","Review changes"),children:[e.jsxs("div",{className:s.migrationLedgerItem,children:[e.jsx("span",{children:c("sync.migration.summary.add","Add")}),e.jsx("strong",{children:f.summary.add})]}),e.jsxs("div",{className:s.migrationLedgerItem,children:[e.jsx("span",{children:c("sync.migration.summary.modify","Modify")}),e.jsx("strong",{children:f.summary.modify})]}),e.jsxs("div",{className:s.migrationLedgerItem,children:[e.jsx("span",{children:c("sync.migration.summary.delete","Delete")}),e.jsx("strong",{children:f.summary.delete})]}),e.jsxs("div",{className:`${s.migrationLedgerItem} ${j?s.migrationLedgerBlocked:""}`,children:[e.jsx("span",{children:c("sync.migration.summary.blocked","Blocked")}),e.jsx("strong",{children:f.summary.blocked})]})]}),f.changes.length>0&&e.jsxs("div",{className:s.migrationSection,children:[e.jsx("h3",{children:c("sync.migration.changes","Metadata changes")}),e.jsx("ul",{className:s.migrationList,children:f.changes.map(h=>e.jsxs("li",{className:s.migrationRow,children:[e.jsx(A,{variant:Ot(h.operation),className:s.migrationOperation,children:c(`sync.migration.operation.${h.operation}`,h.operation)}),e.jsxs("div",{className:s.migrationRowBody,children:[e.jsx("code",{children:h.path}),e.jsx("span",{children:c($t(h.reason),h.reason.replace(/_/g," "))})]})]},`${h.operation}:${h.path}`))})]}),f.blockers.length>0&&e.jsxs("div",{className:s.migrationSection,children:[e.jsx("h3",{children:c("sync.migration.blockers","Items to resolve")}),e.jsx("ul",{className:s.migrationList,children:f.blockers.map((h,E)=>e.jsxs("li",{className:s.migrationRow,children:[e.jsx(A,{variant:"warning",className:s.migrationOperation,children:c("sync.migration.summary.blocked","Blocked")}),e.jsxs("div",{className:s.migrationRowBody,children:[h.path&&e.jsx("code",{children:h.path}),e.jsx("span",{children:c(Ft(h.reason),h.reason.replace(/_/g," "))})]})]},`${h.reason}:${h.path??E}`))})]}),e.jsxs("div",{className:s.migrationNotice,"aria-live":"polite",children:[(j||t.error==="migration_blocked")&&e.jsx("span",{children:c("sync.migration.blocked","Resolve sync conflicts before updating")}),t.error==="preview_stale"&&e.jsx("span",{children:c("sync.migration.stale","Preview changed. Review the latest diff.")}),t.error==="unknown"&&e.jsx("span",{children:c("sync.migration.error","Could not update the sync format. Try again.")})]}),e.jsxs("div",{className:s.migrationActions,children:[e.jsx(te,{variant:"secondary",className:s.migrationButton,disabled:t.loading||t.applying,onClick:()=>void i(),children:t.loading?c("sync.migration.refreshing","Refreshing…"):c("sync.migration.refresh","Refresh preview")}),e.jsx(te,{variant:"primary",className:s.migrationButton,disabled:!L,onClick:()=>n(!0),children:t.applying?c("sync.migration.applying","Applying…"):c("sync.migration.apply","Apply update")})]}),e.jsx(oe,{open:r,title:c("sync.migration.confirm.title","Apply sync format update?"),message:c("sync.migration.confirm.message","Back up and update the listed sync metadata. Your Luau source files will not change."),cancelLabel:c("common.cancel","Cancel"),confirmLabel:c("sync.migration.apply","Apply update"),loading:t.applying,onCancel:()=>!t.applying&&n(!1),onConfirm:()=>void M()})]})}const Ut=["scriptSource","properties","structure","serviceProperties"];function Vt(t){const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}`}function Wt(t){switch(t){case"write":return s.logTypeWrite;case"update":return s.logTypeUpdate;case"delete":return s.logTypeDelete;default:return s.logTypeIdle}}const se={unknown:"neutral",off:"neutral",idle:"neutral",initializing:"info",syncing:"success",paused:"warning",error:"error"},ne={unknown:"Unknown",off:"Sync OFF",idle:"Waiting",initializing:"Initializing",syncing:"Syncing",paused:"Paused",error:"Error"},qt={inactive:"Change sending off",active:"Change sending enabled",paused_play:"Paused for Play",reconciling:"Checking Edit changes",blocked:"Changes need attention",unknown:"Sending status unknown"},Kt={inactive:"neutral",active:"success",paused_play:"warning",reconciling:"info",blocked:"error",unknown:"neutral"};function Gt(t,i){switch(i){case"conflict_review":case"manual_review":return t("sync.forwardStatus.reason.review","Review changes in the Studio Plugin.");case"edit_changed_during_reconciliation":return t("sync.forwardStatus.reason.editChanged","Edit changed during the check. Inspect Sync in the Studio Plugin.");case"pre_check_failed":case"reverse_apply_failed":case"reconciliation_failed":case"sync_error":case"update_failed":case"acknowledgement_missing":case"ACK_EXPIRED":case"ACK_ID_REUSED":case"SYNC_DIRECTION_REVERSE":return t("sync.forwardStatus.reason.failed","Changes could not be confirmed. Inspect Sync in the Studio Plugin.");default:return t("sync.forwardStatus.reason.fallback","Check the Studio Plugin for details.")}}function Yt(t,i){const m={studio_first:"Studio First",bidirectional_review:"Bidirectional",local_code_studio_world:"Local Code, Studio World",custom:"Custom"};return t(`sync.policy.preset.${i}`,m[i])}function ae(t,i){return i==="auto"?t("sync.policy.apply.auto","Auto apply"):t("sync.policy.apply.manual","Review first")}function zt(t,i){const m={forward:"Studio → Local",reverse:"Local → Studio",bidirectional:"Both ways"};return t(`sync.policy.direction.${i}`,m[i])}function Xt(t){return{forward:"←",reverse:"→",bidirectional:"⇄"}[t]}function Jt(t,i){const m={forward:"Studio changes are written to local files.",reverse:"Local file changes are applied to Studio.",bidirectional:"Changes can move from Studio to local files and from local files to Studio."};return t(`sync.policy.direction.${i}.tooltip`,m[i])}function Qt(t,i){return i?t("sync.policy.safety.auto","Auto delete to Studio"):t("sync.policy.safety.review","Review before delete")}function Zt(t,i){return i?t("sync.policy.safety.auto.tooltip","Deleting local files may automatically remove matching Studio instances. This is separate from UI Studio automatic cleanup."):t("sync.policy.safety.review.tooltip","Local file deletions wait for review before matching Studio instances are removed. This is separate from UI Studio automatic cleanup.")}function es(t,i){switch(i){case"write":return t("sync.log.type.write","WRITE");case"update":return t("sync.log.type.update","UPDATE");case"delete":return t("sync.log.type.delete","DELETE");default:return t("sync.log.type.idle","IDLE")}}function ts(t,i){switch(i){case"write":return t("sync.log.type.write.tooltip","A new sync output was written to disk.");case"update":return t("sync.log.type.update.tooltip","An existing synced file or instance was updated.");case"delete":return t("sync.log.type.delete.tooltip","A synced file or instance was removed.");default:return t("sync.log.type.idle.tooltip","A sync event was recorded without a file mutation.")}}function ls(){var _,V,N,W,C,I;const{t}=ie(),{trackEvent:i}=de(),{level:m}=pe(),{tier:c,loading:r}=ye(),n=Se(),{show:f}=ue(),[j,L]=d.useState(null),[M,h]=d.useState(!1),[E,J]=d.useState(!1),[O,Q]=d.useState(!1),H=!r&&c==="basic",u=n.selectedTarget,p=u==null?void 0:u.sync,R=(p==null?void 0:p.forwardSyncStatus)??"unknown",l=u?{...u.sync.status,syncEnabled:u.sync.syncEnabled,policy:u.sync.policy,policyCapabilities:u.sync.policyCapabilities,policyReviewRequired:u.sync.policyReviewRequired}:null,k=(u==null?void 0:u.placeName)??((_=n.selectedPlace)==null?void 0:_.placeName)??t("sync.targets.unknownPlace","Unknown place"),$=n.selectedPlaceId===null?k:k+" · "+n.selectedPlaceId,x=n.storageSafe?(l==null?void 0:l.instanceCount)??((V=n.selectedPlace)==null?void 0:V.instanceCount):null,b=n.storageSafe?(l==null?void 0:l.scriptCount)??((N=n.selectedPlace)==null?void 0:N.scriptCount):null,P=new Set(n.targets.map(o=>o.placeId)),w=n.places.filter(o=>o.placeId===0||!P.has(o.placeId)),Y=e.jsx(me,{title:t("page.sync.title","Sync"),description:t("page.sync.description","Monitor Studio to local sync status, direction, apply mode, and recent sync logs."),helpTopicId:"sync",helpState:{connectionLevel:m,tier:c}}),B=n.history,U=async()=>{if(j){h(!0);try{await n.clearHistory(j.placeId),f(t("toast.clearSuccess","Cleared successfully"),"success"),L(null)}catch{f(t("toast.clearFailed","Failed to clear data"),"error")}finally{h(!1)}}};return e.jsxs("div",{className:s.page,children:[Y,e.jsxs("section",{className:s.card,"aria-label":t("sync.targets.title","Connected Studios"),children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsxs("span",{children:[t("sync.targets.title","Connected Studios")," (",n.targets.length,")"]}),e.jsx("button",{type:"button",className:s.refreshButton,onClick:n.refresh,children:t("sync.targets.refresh","Refresh")})]}),n.loading?e.jsx("p",{className:s.emptyMessage,children:t("sync.targets.loading","Loading Studio Sync status…")}):n.snapshotError?e.jsxs("p",{className:s.errorMessage,role:"alert",children:[t("sync.targets.unavailable","Studio Sync status is unavailable. Retry to check the current state.")," ",n.snapshotError]}):n.targets.length===0?e.jsx("p",{className:s.emptyMessage,children:t("sync.targets.empty","No Studio is connected. Connect the WEPPY Plugin to see live Sync status.")}):e.jsx("div",{className:s.targetList,children:n.targets.map(o=>{var F;const v=((F=n.selection)==null?void 0:F.kind)==="target"&&n.selection.clientId===o.clientId;return e.jsxs("button",{type:"button",className:`${s.targetRow} ${v?s.targetRowSelected:""}`,"aria-pressed":v,onClick:()=>n.selectTarget(o.clientId),children:[e.jsxs("span",{className:s.targetIdentity,children:[e.jsx(D,{text:o.placeName||t("sync.targets.unknownPlace","Unknown place"),children:e.jsx("strong",{children:o.placeName||t("sync.targets.unknownPlace","Unknown place")})}),e.jsxs("span",{children:[t("sync.targets.placeId","Place ID"),": ",o.placeId??"—"]})]}),e.jsxs("span",{className:s.targetStudio,children:[e.jsx(D,{text:o.clientId,children:e.jsxs("span",{children:[t("sync.targets.studioId","Studio ID"),": ",o.targetAlias]})}),e.jsx("span",{children:t("sync.targets.connected","Connected")})]}),e.jsxs("span",{className:s.targetState,children:[e.jsx(A,{variant:se[o.sync.state],shape:"pill",children:t("sync.targets.state."+o.sync.state,ne[o.sync.state])}),o.sync.syncEnabled===null&&e.jsx("span",{className:s.stateNote,children:t("sync.targets.notReported","Not reported yet")})]})]},o.clientId)})})]}),w.length>0&&e.jsxs("section",{className:s.card,"aria-label":t("sync.stored.title","Stored places"),children:[e.jsxs("button",{type:"button",className:s.storedDisclosure,"aria-expanded":O,onClick:()=>Q(o=>!o),children:[e.jsxs("span",{children:[t("sync.stored.title","Stored places")," (",w.length,")"]}),e.jsx("span",{"aria-hidden":"true",children:O?"⌃":"⌄"})]}),O&&e.jsx("div",{className:s.storedList,children:w.map(o=>{var z;const v=X(n.places,o),F=((z=n.selection)==null?void 0:z.kind)==="stored"&&n.selection.placeDirName===o.placeDirName;return e.jsxs("button",{type:"button",className:`${s.storedRow} ${F?s.targetRowSelected:""}`,disabled:!v,"aria-pressed":F,onClick:()=>n.selectStored(o),children:[e.jsxs("span",{children:[o.placeName," · ",o.placeId]}),e.jsx("span",{children:v?t("sync.stored.data","Stored data"):t("sync.stored.ambiguous","Storage location unconfirmed")})]},o.placeDirName)})})]}),n.selection&&!n.snapshotError&&e.jsxs("div",{className:s.selectedScope,children:[e.jsx("span",{children:t("sync.detail.scope","Viewing Sync details for")}),e.jsx("strong",{children:$}),u&&e.jsxs("span",{children:[t("sync.targets.studioId","Studio ID"),": ",u.targetAlias]}),e.jsx("span",{children:t("sync.detail.readOnly","Viewing details does not change Studio routing.")})]}),!n.selection&&!n.loading&&!n.snapshotError&&e.jsx("p",{className:s.emptyMessage,children:t("sync.detail.empty","Select a connected Studio or stored place to view details.")}),n.selection&&!n.snapshotError&&e.jsxs("div",{className:s.detailsStack,children:[e.jsxs("div",{className:s.card,children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsx(D,{text:t("sync.status.title.tooltip","Current Studio and local file sync status for this place."),children:t("sync.status.title","Sync Status")}),H&&e.jsx(D,{text:t("sync.status.forwardOnly.tooltip","Basic tier allows Studio to local forward sync only."),children:e.jsx("span",{className:s.forwardBadge,children:t("sync.status.forwardOnly","Forward Only")})})]}),e.jsxs("div",{className:s.statusRow,children:[p?e.jsx(A,{variant:se[p.state],shape:"pill",children:t("sync.targets.state."+p.state,ne[p.state])}):e.jsx(A,{variant:"neutral",shape:"pill",children:t("sync.stored.data","Stored data")}),e.jsx("span",{className:s.metaItem,children:$})]}),(p==null?void 0:p.state)==="unknown"&&e.jsx("p",{className:s.emptyMessage,children:t("sync.detail.unknown","This Studio has not reported its Sync state yet.")}),(p==null?void 0:p.state)==="error"&&e.jsx("p",{className:s.errorMessage,role:"alert",children:t("sync.detail.error","Sync reported an error. Check the Studio Plugin for details.")}),e.jsxs("dl",{className:s.statusGrid,children:[u&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(G,{label:t("sync.forwardStatus.label","Change sending"),tooltip:t("sync.forwardStatus.tooltip","This reports whether Edit changes can be sent. Enabled does not confirm every local file is current.")})}),e.jsxs("dd",{children:[e.jsx(A,{variant:Kt[R],shape:"pill",children:t("sync.forwardStatus."+R,qt[R])}),R==="blocked"&&e.jsx("span",{className:s.forwardStatusReason,children:Gt(t,p==null?void 0:p.forwardSyncReason)})]}),(p==null?void 0:p.forwardSyncObservedAt)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:t("sync.forwardStatus.observedAt","Observed")}),e.jsx("dd",{children:new Date(p.forwardSyncObservedAt).toLocaleString()})]})]}),u&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:t("sync.targets.studioId","Studio ID")}),e.jsx("dd",{children:u.targetAlias}),e.jsx("dt",{children:t("sync.targets.connectionId","Connection ID")}),e.jsx("dd",{children:u.clientId})]}),(l==null?void 0:l.syncRoot)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(G,{label:t("sync.status.path","Place Root"),tooltip:t("sync.status.path.tooltip","Local filesystem root currently used for this place sync output.")})}),e.jsx("dd",{children:l.syncRoot})]}),((W=n.selectedPlace)==null?void 0:W.placeDirName)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(G,{label:t("sync.detail.placeFolder","Place folder"),tooltip:t("sync.detail.placeFolder.tooltip","The stored folder shared by Studios opening this Place.")})}),e.jsx("dd",{children:n.selectedPlace.placeDirName})]}),x!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(G,{label:t("sync.status.instances","Instances"),tooltip:t("sync.status.instances.tooltip","Total synced Roblox instances tracked in the local mirror.")})}),e.jsx("dd",{children:x})]}),b!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(G,{label:t("sync.status.scripts","Scripts"),tooltip:t("sync.status.scripts.tooltip","Total synced script files currently indexed for this place.")})}),e.jsx("dd",{children:b})]})]}),e.jsx("p",{className:s.sharedNote,children:t("sync.detail.sharedData","Path, counts, and log belong to the Place and are shared by Studios opening it.")})]}),n.storageSafe&&e.jsx(Ht,{migration:n.migration,onRefresh:n.refreshMigration,onApply:n.applyMigration},[n.selection.kind==="target"?n.selection.clientId:n.selection.placeDirName,n.selectedPlaceId,(I=(C=n.migration)==null?void 0:C.report)==null?void 0:I.previewFingerprint].join(":")),(l==null?void 0:l.policy)&&e.jsxs("div",{className:s.card,children:[e.jsx("div",{className:s.cardHeader,children:e.jsx(D,{text:t("sync.policy.title.tooltip","Effective Sync policy reported by the connected Studio plugin."),children:t("sync.policy.title","Sync Policy")})}),e.jsxs("dl",{className:s.policySummary,children:[e.jsxs("div",{className:s.policySummaryItem,children:[e.jsx("dt",{children:t("sync.policy.activation","Activation")}),e.jsx("dd",{children:e.jsx(A,{variant:l.syncEnabled?"success":"neutral",children:l.syncEnabled?t("sync.policy.activation.on","Sync ON"):t("sync.policy.activation.off","Sync OFF")})})]}),e.jsxs("div",{className:s.policySummaryItem,children:[e.jsx("dt",{children:t("sync.policy.preset","Workflow")}),e.jsx("dd",{className:s.policyPrimaryValue,children:Yt(t,l.policy.preset)})]})]}),l.policyReviewRequired&&e.jsx("div",{className:s.policyReviewNotice,role:"status",children:t("sync.policy.reviewRequired","Review this policy in the Studio plugin before starting Sync.")}),e.jsxs("section",{className:s.policyApplySection,"aria-labelledby":"sync-policy-apply-title",children:[e.jsxs("div",{className:s.policyApplyHeader,children:[e.jsx("h3",{id:"sync-policy-apply-title",className:s.policyApplyTitle,children:t("sync.policy.apply.title","How local changes apply to Studio")}),e.jsx("p",{className:s.policyApplyDescription,children:t("sync.policy.apply.description","Shows whether changes made locally are reviewed first or applied to Studio automatically.")})]}),e.jsxs("dl",{className:s.policySummary,children:[e.jsxs("div",{className:s.policySummaryItem,children:[e.jsx("dt",{children:e.jsx(D,{text:t("sync.policy.apply.content.tooltip","Script Source, property, and Service property changes made locally. Instance creation, deletion, renaming, and moves are Structure changes."),children:e.jsx("span",{className:s.policyInfoLabel,tabIndex:0,children:t("sync.policy.apply.content","Content changes")})})}),e.jsx("dd",{children:ae(t,l.policy.apply.contentChanges)})]}),e.jsxs("div",{className:s.policySummaryItem,children:[e.jsx("dt",{children:e.jsx(D,{text:t("sync.policy.apply.structure.tooltip","Instance creation, deletion, renaming, and moves made locally. Automatic local deletion additionally requires the separate delete option below."),children:e.jsx("span",{className:s.policyInfoLabel,tabIndex:0,children:t("sync.policy.apply.structure","Structure changes")})})}),e.jsx("dd",{children:ae(t,l.policy.apply.structureChanges)})]})]}),e.jsxs("div",{className:s.policySafetyRow,children:[e.jsx("span",{className:s.policySafetyLabel,children:t("sync.policy.safety.localDeletes","Local delete → Studio instance removal")}),e.jsx(D,{text:Zt(t,l.policy.autoApplyLocalDeletesToStudio),children:e.jsx(A,{variant:l.policy.autoApplyLocalDeletesToStudio?"warning":"neutral",className:s.policySafetyBadge,tabIndex:0,children:Qt(t,l.policy.autoApplyLocalDeletesToStudio)})})]})]}),e.jsxs("button",{type:"button",className:s.policyDisclosure,"aria-expanded":E,"aria-controls":"sync-policy-scope-panel",onClick:()=>J(o=>!o),children:[e.jsx("span",{children:t("sync.policy.scope.disclosure","Scope directions")}),e.jsx("span",{"aria-hidden":"true",className:`${s.policyDisclosureIcon} ${E?s.policyDisclosureIconOpen:""}`,children:"⌄"})]}),E&&e.jsx("div",{id:"sync-policy-scope-panel",className:s.policyScopeList,children:Ut.map(o=>{const v=l.policy.directions[o];return e.jsxs("div",{className:s.policyScopeRow,"data-testid":"sync-policy-scope-row",children:[e.jsx("span",{className:s.policyScopeName,children:t(`sync.policy.scope.${o}`,o)}),e.jsx(D,{text:Jt(t,v),children:e.jsxs("span",{className:s.policyDirectionRail,"data-testid":"sync-policy-direction-rail",role:"img","aria-label":zt(t,v),tabIndex:0,children:[e.jsx("span",{className:s.policyDirectionEndpoint,children:t("sync.policy.endpoint.local","Local")}),e.jsx("span",{className:s.policyDirectionArrow,"aria-hidden":"true",children:Xt(v)}),e.jsx("span",{className:`${s.policyDirectionEndpoint} ${s.policyDirectionEndpointStudio}`,children:t("sync.policy.endpoint.studio","Studio")})]})})]},o)})})]}),e.jsxs("div",{className:s.card,children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsxs("span",{children:[t("sync.log.title","Sync Log")," · ",t("sync.log.shared","Shared Place log")]}),e.jsx("button",{className:s.clearButton,type:"button",disabled:!n.storageSafe||n.selectedPlaceId===null,onClick:()=>{n.selectedPlaceId!==null&&(i("dashboard_click_event",{click_target:"sync_clear_log",page:"sync"}),L({placeId:n.selectedPlaceId,label:$}))},children:t("common.clear","Clear")})]}),e.jsx("div",{className:s.logContainer,children:n.storageSafe?n.historyError?e.jsxs("div",{className:s.errorMessage,role:"alert",children:[t("sync.log.unavailable","The Place log could not be loaded. Retry to check it.")," ",n.historyError]}):n.historyLoading&&B.length===0?e.jsx("div",{className:s.logEmpty,children:t("sync.log.loading","Loading Place log…")}):B.length===0?e.jsx("div",{className:s.logEmpty,children:t("sync.log.empty","No sync events yet")}):B.map((o,v)=>e.jsxs("div",{className:s.logEntry,children:[e.jsx("span",{className:s.logTime,children:Vt(o.timestamp)}),e.jsx(D,{text:ts(t,o.type),children:e.jsx("span",{className:`${s.logType} ${Wt(o.type)}`,children:es(t,o.type)})}),e.jsxs("span",{className:s.logPath,children:[o.path,o.details?` — ${o.details}`:""]})]},v)):e.jsx("div",{className:s.logEmpty,children:t("sync.log.unsafe","This Place has no confirmed storage location for log access.")})})]}),H&&e.jsx(he,{title:t("sync.upgrade.title","Explore Full Sync with Pro"),description:t("tier.banner.save","Save AI tokens with Pro!"),benefits:[t("sync.upgrade.benefit1","Bidirectional sync — edit files, auto-apply to Studio"),t("sync.upgrade.benefit2","Reverse sync — push file changes back to Studio"),t("sync.upgrade.benefit3","Full sync history and detailed change log")],upgradeLabel:t("sync.upgrade.buy","View Pro"),upgradeHref:ge.sync})]}),e.jsx(oe,{open:j!==null,title:t("sync.clear.title","Clear sync log?"),message:t("sync.clear.selectedMessage","This permanently removes the shared Sync log for {place}.").replace("{place}",(j==null?void 0:j.label)??""),cancelLabel:t("common.cancel","Cancel"),confirmLabel:t("common.clear","Clear"),loading:M,onCancel:()=>!M&&L(null),onConfirm:U})]})}export{ls as Component};