@weppy/roblox-mcp 2.17.0 → 2.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dashboard/dist/assets/{AssetsPage-FecplRby.js → AssetsPage-ClzgrkC_.js} +1 -1
- package/dashboard/dist/assets/{ChangelogPage-DXZxXvJY.js → ChangelogPage-CRXXHovV.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-CQhMb2gs.js → ConfirmModal-Dz7mVKLZ.js} +1 -1
- package/dashboard/dist/assets/{ConnectionPage-Bk4HeU0-.js → ConnectionPage-CKKn3lt0.js} +2 -7
- package/dashboard/dist/assets/{ControlsPage-jEHyFrVc.js → ControlsPage-Ch6He2CV.js} +1 -1
- package/dashboard/dist/assets/{CurrentPlaceScope-B60o8hpn.js → CurrentPlaceScope-DhPCqaMU.js} +1 -1
- package/dashboard/dist/assets/{GameChangeDetail-B5X_6M-R.js → GameChangeDetail-CZuYgFvS.js} +1 -1
- package/dashboard/dist/assets/{InfoLabel-csGVLmJ3.js → InfoLabel-BGeOUBIl.js} +1 -1
- package/dashboard/dist/assets/{OverviewPage-B2_8B6fs.js → OverviewPage-B-CtTLEP.js} +1 -1
- package/dashboard/dist/assets/{PageHeader-B42Je0MJ.js → PageHeader-CYbeZdtL.js} +1 -1
- package/dashboard/dist/assets/PlaytestAiPromptExamples-DHVX0Ljy.css +1 -0
- package/dashboard/dist/assets/PlaytestAiPromptExamples-flhav1EU.js +1 -0
- package/dashboard/dist/assets/PlaytestPage-C092tN-C.js +127 -0
- package/dashboard/dist/assets/PlaytestPage-C3Vjgtlg.css +1 -0
- package/dashboard/dist/assets/{SettingsPage-eLuRrn1E.js → SettingsPage-bEHQn_8W.js} +1 -1
- package/dashboard/dist/assets/{StatusBadge-Ct9C2L71.js → StatusBadge-BmR5_DsF.js} +1 -1
- package/dashboard/dist/assets/{SyncPage-CKbsNp8O.js → SyncPage-BFz_XQ40.js} +1 -1
- package/dashboard/dist/assets/{Tabs-Dos9flTe.js → Tabs-C7TenrZD.js} +1 -1
- package/dashboard/dist/assets/{TierPromoPanel-Ci_piK2n.js → TierPromoPanel-C02VRkHz.js} +1 -1
- package/dashboard/dist/assets/{ToolsPage-mfcba-cj.js → ToolsPage-CJeoFakm.js} +1 -1
- package/dashboard/dist/assets/{TooltipText-EK4_jbu2.js → TooltipText-sb-BSgUg.js} +1 -1
- package/dashboard/dist/assets/{UiStudioPage-Y2PR7h_q.js → UiStudioPage-C5dYQMax.js} +1 -1
- package/dashboard/dist/assets/WhatsNewPage-C_z4g3oa.js +1 -0
- package/dashboard/dist/assets/WhatsNewPage-WMbbAUsL.css +1 -0
- package/dashboard/dist/assets/bot-oMwejCZF.js +6 -0
- package/dashboard/dist/assets/{check-BgcyMSc_.js → check-EdHXSSef.js} +1 -1
- package/dashboard/dist/assets/{copy-BJc7IQHD.js → copy-CePVq0VI.js} +1 -1
- package/dashboard/dist/assets/{index-89-Xnii6.js → index-DchewB5y.js} +54 -54
- package/dashboard/dist/assets/{sample-requests-DOteSh1j.js → sample-requests-CQvn7a4-.js} +1 -1
- package/dashboard/dist/assets/{trash-2-CeZRGbl-.js → trash-2-8V3SCC8q.js} +1 -1
- package/dashboard/dist/assets/{useLiveUptime-BX-d0MHY.js → useLiveUptime-BeZ9TLyF.js} +1 -1
- package/dashboard/dist/assets/{useSettings-B45j17ns.js → useSettings-D5XHMODc.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dist/index.js +136 -136
- package/package.json +1 -1
- package/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
- package/dashboard/dist/assets/PlaytestPage-B89cLi76.css +0 -1
- package/dashboard/dist/assets/PlaytestPage-Cww1uTQ8.js +0 -122
- package/dashboard/dist/assets/WhatsNewPage-BsVZv6D8.css +0 -1
- package/dashboard/dist/assets/WhatsNewPage-uAPdDJaM.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -46,6 +46,20 @@ All notable changes to this project will be documented in this file.
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## [2.17.1] - 2026-09-10
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
- **Start Playtest from an empty Dashboard** — Empty Test Values and Automated Test Results now show copyable AI request examples. Test Values also explains how to select an object in Studio and add a supported property, Attribute, or Value directly.
|
|
56
|
+
|
|
57
|
+
### Bug Fixes
|
|
58
|
+
|
|
59
|
+
- **Fix missing Playtest profile deletion in the Dashboard** — Test profiles can now be deleted from the profile editor after reviewing what will be removed. Profiles currently in use remain protected until Play or Run stops, and deleting a profile does not remove game objects, scripts, test connection code, other profiles, or saved automated test results.
|
|
60
|
+
- **Release Playtest profiles when a session ends** — Stopping a profile-started Play, returning Studio to Edit, or disconnecting Studio now closes the matching control session, releases the profile for editing or deletion, and marks its Watch values unavailable instead of leaving old values looking current.
|
|
61
|
+
- **Keep profile revision requirements visible to AI clients** — Profile update and deletion requests now explain when the current revision is required, helping AI agents avoid stale changes and retry with the latest profile when another edit has already occurred.
|
|
62
|
+
- **Close MCP Adapter sessions cleanly when input ends** — A normal AI client shutdown now finishes Adapter cleanup without forcing an immediate process exit, while the existing timeout fallback still handles leaked resources. This avoids abrupt shutdown behavior on Windows and keeps the shared Studio connection lifecycle separate.
|
|
49
63
|
|
|
50
64
|
## [2.17.0] - 2026-09-10
|
|
51
65
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{f as oe,b as O,l as Ne,u as me,j as s,P as As,I as Is,r as c,F as Ps,m as ks,R as hs,X as Ke,E as ws,n as ms,g as Rs,a as $s,e as Ls}from"./index-
|
|
1
|
+
import{f as oe,b as O,l as Ne,u as me,j as s,P as As,I as Is,r as c,F as Ps,m as ks,R as hs,X as Ke,E as ws,n as ms,g as Rs,a as $s,e as Ls}from"./index-DchewB5y.js";import{C as bs}from"./ConfirmModal-Dz7mVKLZ.js";import{B as De,C as Bs,D as Ye,b as Us,P as Ts}from"./PageHeader-CYbeZdtL.js";import{T as Z}from"./TooltipText-sb-BSgUg.js";import{T as Es}from"./trash-2-8V3SCC8q.js";import{C as xs}from"./copy-CePVq0VI.js";import"./ConfirmModal.module-DJksQHBd.js";/**
|
|
2
2
|
* @license lucide-react v1.8.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as o,b as P,D as Q,u as q,j as e,X as W,a as X,o as Y,c as J,e as ee,i as te,T as ae}from"./index-89-Xnii6.js";import{B as ne,P as se}from"./PageHeader-B42Je0MJ.js";import{C as ie}from"./ConfirmModal-CQhMb2gs.js";import{C as ce}from"./CurrentPlaceScope-B60o8hpn.js";import{T as O}from"./TooltipText-EK4_jbu2.js";import{C as oe,T as re}from"./Tabs-Dos9flTe.js";import{I as le}from"./InfoLabel-csGVLmJ3.js";import{G as de}from"./GameChangeDetail-B5X_6M-R.js";import"./ConfirmModal.module-DJksQHBd.js";const ge=10;function me(t,i){return typeof i!="number"?t:`${t}?placeId=${encodeURIComponent(String(i))}`}function he(t){const i=(t==null?void 0:t.placeId)??null,[m,c]=o.useState([]),[n,s]=o.useState(0),[u,p]=o.useState(!1),[r,T]=o.useState(!0),[C,E]=o.useState(0),[f,z]=o.useState("all"),B=o.useRef(null),S=o.useCallback(async(y,v)=>{T(!0);try{const k={limit:String(ge),offset:String(y)};v!=="all"&&(k.status=v),typeof i=="number"&&(k.placeId=String(i));const w=await P.get("/api/dashboard/changelog",k);c(w.entries),s(w.total),p(w.hasMore)}catch{c([]),s(0),p(!1)}finally{T(!1)}},[i]),I=o.useCallback(()=>{S(C,f)},[S,C,f]),$=o.useCallback(async()=>{await P.post(me("/api/dashboard/changelog/clear",i)),c([]),s(0),p(!1)},[i]);return o.useEffect(()=>{S(C,f)},[S,C,f]),o.useEffect(()=>{const y=new Q;B.current=y,y.connect();const v=y.on("command",()=>{S(C,f)});return()=>{v(),y.disconnect(),B.current=null}},[S,C,f]),{entries:m,total:n,hasMore:u,loading:r,offset:C,statusFilter:f,setOffset:E,setStatusFilter:z,refresh:I,clear:$}}const ue="_card_qniob_2",pe="_header_qniob_27",fe="_statusBadge_qniob_34",ye="_statusDot_qniob_45",xe="_active_qniob_51",_e="_completed_qniob_60",be="_timeRange_qniob_68",Ce="_summaryList_qniob_75",Se="_summaryItem_qniob_81",ve="_summaryIcon_qniob_90",je="_summaryText_qniob_96",Ne="_progressBar_qniob_101",Te="_progressFill_qniob_110",Ie="_emptySummary_qniob_124",ke="_contextBlock_qniob_132",we="_contextLabel_qniob_141",$e="_contextValue_qniob_149",h={card:ue,header:pe,statusBadge:fe,statusDot:ye,active:xe,completed:_e,timeRange:be,summaryList:Ce,summaryItem:Se,summaryIcon:ve,summaryText:je,progressBar:Ne,progressFill:Te,emptySummary:Ie,contextBlock:ke,contextLabel:we,contextValue:$e};function H(t){if(!t)return"--:--";const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}`}function Be({entry:t,onClick:i,buttonRef:m}){var v,k,w,L,A,R,d,_,D,M;const{t:c}=q(),n=t.changeSummary,s=t.status==="active",u=t.isBootstrapOnly===!0,p=[],r=n.scriptsModified+n.scriptsCreated;if(r>0){const g=[];n.scriptsModified>0&&g.push(`${n.scriptsModified} ${c("changelog.card.modified","modified")}`),n.scriptsCreated>0&&g.push(`${n.scriptsCreated} ${c("changelog.card.created","created")}`);const x=`${r} ${c("changelog.card.scripts","scripts")} ${g.join(", ")}`;p.push({icon:"📝",text:x,tooltip:c("changelog.card.scripts.tooltip","Script changes made in this session.")})}const T=n.instancesCreated+n.instancesDeleted+n.instancesMoved;if(T>0){const g=[];n.instancesCreated>0&&g.push(`${n.instancesCreated} ${c("changelog.card.created","created")}`),n.instancesDeleted>0&&g.push(`${n.instancesDeleted} ${c("changelog.card.deleted","deleted")}`),n.instancesMoved>0&&g.push(`${n.instancesMoved} ${c("changelog.card.moved","moved")}`);const x=`${T} ${c("changelog.card.instances","instances")} ${g.join(", ")}`;p.push({icon:"🧱",text:x,tooltip:c("changelog.card.instances.tooltip","Instance create, delete, move, or clone changes in this session.")})}n.propertiesChanged>0&&p.push({icon:"🎨",text:`${n.propertiesChanged} ${c("changelog.card.propertiesChanged","properties changed")}`,tooltip:c("changelog.card.propertiesChanged.tooltip","Property value changes recorded for this session.")}),n.lightingChanged&&p.push({icon:"🌅",text:c("changelog.card.lightingConfigured","Lighting configured"),tooltip:c("changelog.card.lightingConfigured.tooltip","Lighting or atmosphere settings changed in this session.")}),n.terrainChanged&&p.push({icon:"⛰️",text:c("changelog.card.terrainConfigured","Terrain configured"),tooltip:c("changelog.card.terrainConfigured.tooltip","Terrain data or terrain settings changed in this session.")}),n.assetsInserted>0&&p.push({icon:"📦",text:`${n.assetsInserted} ${c("changelog.card.assetsInserted","assets inserted")}`,tooltip:c("changelog.card.assetsInserted.tooltip","Assets inserted into the place during this session.")});const C=H(t.startTime),E=s?c("changelog.card.inProgress","in progress"):t.endTime?H(t.endTime):"--:--",f=u?c("changelog.card.bootstrapStatus","Bootstrap"):s?c("changelog.card.active","Active"):c("changelog.card.completed","Completed"),z=u?c("changelog.card.bootstrapStatus.tooltip","This session only contains the initial sync bootstrap snapshot."):s?c("changelog.card.active.tooltip","This session is still receiving new game changes."):c("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),B=u?c("changelog.card.bootstrapSummary","Initial sync snapshot"):c("changelog.card.noChanges","No changes yet"),S=u?c("changelog.card.bootstrapSummary.tooltip","Initial file sync writes are collapsed into a single bootstrap snapshot row."):c("changelog.card.noChanges.tooltip","No game changes have been extracted for this session yet."),I=(k=(v=t.contextSummary)==null?void 0:v.intent)==null?void 0:k.trim(),$=((R=(A=(L=(w=t.contextSummary)==null?void 0:w.affectedAreas)==null?void 0:L[0])==null?void 0:A.label)==null?void 0:R.trim())||((_=(d=t.contextSummary)==null?void 0:d.testScenario)==null?void 0:_.trim()),y=(M=(D=t.verificationSummary)==null?void 0:D.label)==null?void 0:M.trim();return e.jsxs("button",{ref:m,className:h.card,type:"button",onClick:g=>i(g.currentTarget),children:[e.jsxs("span",{className:h.header,children:[e.jsx(O,{text:z,children:e.jsxs("span",{className:`${h.statusBadge} ${s?h.active:h.completed}`,children:[e.jsx("span",{className:h.statusDot}),f]})}),e.jsxs("span",{className:h.timeRange,children:[C,"~",E]})]}),e.jsx("span",{className:h.summaryList,children:p.length>0?p.map((g,x)=>e.jsxs("span",{className:h.summaryItem,children:[e.jsx("span",{className:h.summaryIcon,children:g.icon}),e.jsx(O,{text:g.tooltip,children:e.jsx("span",{className:h.summaryText,children:g.text})})]},x)):e.jsx(O,{text:S,children:e.jsx("span",{className:h.emptySummary,style:{display:"block"},children:B})})}),I&&e.jsxs("span",{className:h.contextBlock,children:[e.jsx("span",{className:h.contextLabel,children:c("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:h.contextValue,children:I})]}),!I&&$&&e.jsxs("span",{className:h.contextBlock,children:[e.jsx("span",{className:h.contextLabel,children:c("changelog.card.representativeArea","Representative area")}),e.jsx("span",{className:h.contextValue,children:$})]}),y&&e.jsxs("span",{className:h.contextBlock,children:[e.jsx("span",{className:h.contextLabel,children:c("changelog.card.verification","Verification")}),e.jsx("span",{className:h.contextValue,children:y})]}),s&&e.jsx("span",{className:h.progressBar,children:e.jsx("span",{className:h.progressFill})})]})}function ze(t){const i={scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0};for(const m of t)switch(m.category){case"script":m.changeType==="create"?i.scriptsCreated++:i.scriptsModified++;break;case"instance":m.changeType==="create"?i.instancesCreated++:m.changeType==="delete"?i.instancesDeleted++:m.changeType==="move"&&i.instancesMoved++;break;case"property":i.propertiesChanged++;break;case"lighting":i.lightingChanged=!0;break;case"terrain":i.terrainChanged=!0;break;case"asset":i.assetsInserted++;break}return i}function Ee(t){if(typeof t=="number")return{placeId:String(t)}}function Le(t,i){const[m,c]=o.useState(""),[n,s]=o.useState(""),[u,p]=o.useState(),[r,T]=o.useState("completed"),[C,E]=o.useState([]),[f,z]=o.useState([]),[B,S]=o.useState([]),[I,$]=o.useState(),[y,v]=o.useState(),[k,w]=o.useState(),[L,A]=o.useState({scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0}),[R,d]=o.useState(!0),[_,D]=o.useState(null),M=o.useCallback(async()=>{if(t){d(!0),D(null);try{const g=Ee(i),[x,G]=await Promise.all([g?P.get(`/api/dashboard/changelog/${t}`,g):P.get(`/api/dashboard/changelog/${t}`),g?P.get(`/api/dashboard/changelog/${t}/changes`,g):P.get(`/api/dashboard/changelog/${t}/changes`)]);c(x.entryId),s(x.startTime),p(x.endTime),T(x.status),E(x.entries),z(x.failures),$(x.contextSummary),v(x.replayMetadata),w(x.verificationSummary),S(G.changes),A(ze(G.changes))}catch(g){D(g instanceof Error?g.message:"Failed to load changelog detail")}finally{d(!1)}}},[t,i]);return o.useEffect(()=>{M()},[M]),{entryId:m,startTime:n,endTime:u,status:r,entries:C,failures:f,changes:B,changeSummary:L,contextSummary:I,replayMetadata:y,verificationSummary:k,loading:R,error:_,refresh:M}}const Ae={script:"📝",instance:"🧱",property:"🎨",lighting:"🌅",terrain:"⛰️",asset:"📦"};function Re(t){return Ae[t]??"❓"}const Me="_dialogContent_197zf_2",Oe="_dialogHeader_197zf_10",De="_dialogTitleGroup_197zf_20",Fe="_dialogTitle_197zf_20",Pe="_dialogMeta_197zf_36",Ge="_dialogClose_197zf_43",Ke="_dialogBody_197zf_68",Ve="_page_197zf_77",qe="_headerTime_197zf_84",Ue="_dialogActions_197zf_90",He="_retryButton_197zf_96",Ze="_statusActive_197zf_129",Qe="_statusCompleted_197zf_134",We="_section_197zf_139",Xe="_sectionTitle_197zf_146",Ye="_summaryGrid_197zf_159",Je="_summaryCard_197zf_165",et="_summaryCardActive_197zf_188",tt="_summaryIcon_197zf_193",at="_summaryCount_197zf_199",nt="_summaryLabel_197zf_207",st="_contextGrid_197zf_217",it="_contextRow_197zf_223",ct="_contextKey_197zf_229",ot="_contextValue_197zf_237",rt="_timelineFilter_197zf_245",lt="_filterLabel_197zf_253",dt="_filterSelect_197zf_259",gt="_ownershipToggle_197zf_269",mt="_timeline_197zf_245",ht="_timelineEntry_197zf_297",ut="_timelineTime_197zf_326",pt="_timelineIcon_197zf_334",ft="_timelineBody_197zf_339",yt="_timelineSummary_197zf_345",xt="_timelineTarget_197zf_353",_t="_timelineConfidence_197zf_361",bt="_ownershipBadge_197zf_370",Ct="_confidenceExact_197zf_378",St="_confidencePartial_197zf_383",vt="_confidenceAfterOnly_197zf_388",jt="_confidenceIntentOnly_197zf_393",Nt="_confidenceUnknown_197zf_398",Tt="_timelineExpanded_197zf_404",It="_empty_197zf_413",kt="_loading_197zf_422",wt="_error_197zf_431",a={dialogContent:Me,dialogHeader:Oe,dialogTitleGroup:De,dialogTitle:Fe,dialogMeta:Pe,dialogClose:Ge,dialogBody:Ke,page:Ve,headerTime:qe,dialogActions:Ue,retryButton:He,statusActive:Ze,statusCompleted:Qe,section:We,sectionTitle:Xe,summaryGrid:Ye,summaryCard:Je,summaryCardActive:et,summaryIcon:tt,summaryCount:at,summaryLabel:nt,contextGrid:st,contextRow:it,contextKey:ct,contextValue:ot,timelineFilter:rt,filterLabel:lt,filterSelect:dt,ownershipToggle:gt,timeline:mt,timelineEntry:ht,timelineTime:ut,timelineIcon:pt,timelineBody:ft,timelineSummary:yt,timelineTarget:xt,timelineConfidence:_t,ownershipBadge:bt,confidenceExact:Ct,confidencePartial:St,confidenceAfterOnly:vt,confidenceIntentOnly:jt,confidenceUnknown:Nt,timelineExpanded:Tt,empty:It,loading:kt,error:wt},Z=[{key:"script",icon:"📝",labelKey:"changelog.category.script"},{key:"instance",icon:"🧱",labelKey:"changelog.category.instance"},{key:"property",icon:"🎨",labelKey:"changelog.category.property"},{key:"lighting",icon:"🌅",labelKey:"changelog.category.lighting"},{key:"terrain",icon:"⛰️",labelKey:"changelog.category.terrain"},{key:"asset",icon:"📦",labelKey:"changelog.category.asset"}];function V(t){if(!t)return"--:--";const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}`}function $t(t){if(!t)return"--:--:--";const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}:${String(i.getSeconds()).padStart(2,"0")}`}function Bt(t,i){if(!t||!i)return"";const m=new Date(i).getTime()-new Date(t).getTime();return m<0?"":`${Math.round(m/6e4)}min`}function zt(t){switch(t){case"exact":return a.confidenceExact;case"partial":return a.confidencePartial;case"after-only":return a.confidenceAfterOnly;case"intent-only":return a.confidenceIntentOnly;default:return a.confidenceUnknown}}function Et(t,i){switch(i){case"exact":return t("changelog.detail.confidence.exact","Exact");case"partial":return t("changelog.detail.confidence.partial","Partial");case"after-only":return t("changelog.detail.confidence.afterOnly","After only");case"intent-only":return t("changelog.detail.confidence.intentOnly","Intent only");default:return t("changelog.detail.confidence.unknown","Unknown")}}function Lt(t,i){switch(i){case"exact":return t("changelog.detail.confidence.exact.tooltip","Both the before and after state were confirmed for this change.");case"partial":return t("changelog.detail.confidence.partial.tooltip","Only part of the before and after state could be confirmed for this change.");case"after-only":return t("changelog.detail.confidence.afterOnly.tooltip","Only the resulting state after the change could be confirmed.");case"intent-only":return t("changelog.detail.confidence.intentOnly.tooltip","Only the requested action was recorded, not the resulting state.");default:return t("changelog.detail.confidence.unknown.tooltip","This change could not be confidently classified from the available data.")}}function At(t,i){switch(i){case"user_source":return t("changelog.ownership.userSource","User source");case"canonical_mirror":return t("changelog.ownership.canonicalMirror","Mirror metadata");case"generated":return t("changelog.ownership.generated","Generated");default:return null}}function Rt({entryId:t,placeId:i,onClose:m,returnFocusTo:c=null}){var v,k,w,L,A,R,d,_,D,M,g,x,G,U;const{t:n}=q(),s=Le(t,i),[u,p]=o.useState("all"),[r,T]=o.useState(!0),[C,E]=o.useState(null),f=o.useMemo(()=>{const l=r?s.changes:s.changes.filter(b=>b.artifactOwnership!=="generated");return[...u==="all"?l:l.filter(b=>b.category===u)].reverse()},[s.changes,u,r]),z=s.changes.some(l=>l.artifactOwnership==="generated"),B=Bt(s.startTime,s.endTime),S=s.endTime?`${V(s.startTime)} → ${V(s.endTime)} (${B})`:`${V(s.startTime)} → ${n("changelog.card.inProgress","in progress")}`,I=!!((v=s.contextSummary)!=null&&v.intent||(k=s.contextSummary)!=null&&k.testScenario||(w=s.contextSummary)!=null&&w.expectedBehavior||(L=s.contextSummary)!=null&&L.observedBehavior),$=!!((A=s.verificationSummary)!=null&&A.label||(R=s.verificationSummary)!=null&&R.status||(d=s.verificationSummary)!=null&&d.testTimestamp),y=n("changelog.detail.dialogLabel","Changelog detail");return e.jsx(oe,{open:!0,ariaLabel:y,onClose:m,returnFocusTo:c,testId:"changelog-detail-backdrop",children:e.jsxs("div",{className:a.dialogContent,children:[e.jsxs("div",{className:a.dialogHeader,children:[e.jsxs("div",{className:a.dialogTitleGroup,children:[e.jsx("h2",{className:a.dialogTitle,children:y}),!s.loading&&!s.error&&e.jsxs("div",{className:a.dialogMeta,children:[e.jsx("span",{className:a.headerTime,children:S}),e.jsx(O,{text:s.status==="active"?n("changelog.card.active.tooltip","This session is still receiving new game changes."):n("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),children:e.jsx("span",{className:s.status==="active"?a.statusActive:a.statusCompleted,children:s.status==="active"?n("changelog.card.active","Active"):n("changelog.card.completed","Completed")})})]})]}),e.jsx("button",{className:a.dialogClose,type:"button","aria-label":n("common.close","Close"),onClick:m,children:e.jsx(W,{size:18,"aria-hidden":"true"})})]}),e.jsxs("div",{className:a.dialogBody,children:[s.loading&&e.jsx("div",{className:a.loading,children:n("common.loading","Loading...")}),s.error&&e.jsxs("div",{className:a.error,children:[e.jsx("span",{children:s.error}),e.jsxs("div",{className:a.dialogActions,children:[e.jsx("button",{className:a.retryButton,type:"button",onClick:s.refresh,children:n("common.retry","Retry")}),e.jsx("button",{className:a.retryButton,type:"button",onClick:m,children:n("common.close","Close")})]})]}),!s.loading&&!s.error&&e.jsxs("div",{className:a.page,children:[e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.changeSummary.tooltip","Counts of extracted game changes grouped by category for this session."),children:e.jsx("span",{children:n("changelog.detail.changeSummary","Change Summary")})})}),e.jsx("div",{className:a.summaryGrid,children:Z.map(l=>{const j=s.changeSummary;let b;switch(l.key){case"script":b=j.scriptsModified+j.scriptsCreated;break;case"instance":b=j.instancesCreated+j.instancesDeleted+j.instancesMoved;break;case"property":b=j.propertiesChanged;break;case"lighting":b=j.lightingChanged?1:0;break;case"terrain":b=j.terrainChanged?1:0;break;case"asset":b=j.assetsInserted;break;default:b=0}const F=u===l.key;return e.jsxs("button",{type:"button",className:`${a.summaryCard} ${F?a.summaryCardActive:""}`,"aria-label":`${n(l.labelKey,l.key)}: ${b}`,"aria-pressed":F,onClick:()=>p(F?"all":l.key),children:[e.jsx("span",{className:a.summaryIcon,children:l.icon}),e.jsx("span",{className:a.summaryCount,children:b}),e.jsx("span",{className:a.summaryLabel,children:n(l.labelKey,l.key)})]},l.key)})})]}),I&&e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.context.tooltip","Structured execution context captured for this changelog session."),children:e.jsx("span",{children:n("changelog.detail.context.title","Context Summary")})})}),e.jsxs("div",{className:a.contextGrid,children:[((_=s.contextSummary)==null?void 0:_.intent)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.intent})]}),((D=s.contextSummary)==null?void 0:D.testScenario)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("playtest.context.why","Why this test ran")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.testScenario})]}),((M=s.contextSummary)==null?void 0:M.expectedBehavior)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("playtest.context.expected","Expected")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.expectedBehavior})]}),((g=s.contextSummary)==null?void 0:g.observedBehavior)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("playtest.context.observed","Observed")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.observedBehavior})]})]})]}),$&&e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.verification.tooltip","Verification signals linked to this changelog session."),children:e.jsx("span",{children:n("changelog.detail.verification.title","Verification")})})}),e.jsxs("div",{className:a.contextGrid,children:[((x=s.verificationSummary)==null?void 0:x.label)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.detail.verification.label","Result")}),e.jsx("span",{className:a.contextValue,children:s.verificationSummary.label})]}),((G=s.verificationSummary)==null?void 0:G.status)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.detail.verification.status","Status")}),e.jsx("span",{className:a.contextValue,children:s.verificationSummary.status})]}),((U=s.verificationSummary)==null?void 0:U.testTimestamp)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.detail.verification.timestamp","Recorded at")}),e.jsx("span",{className:a.contextValue,children:s.verificationSummary.testTimestamp})]})]})]}),e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.changeTimeline.tooltip","Chronological list of extracted game changes for this session."),children:e.jsx("span",{children:n("changelog.detail.changeTimeline","Change Timeline")})})}),e.jsxs("div",{className:a.timelineFilter,children:[e.jsx("span",{className:a.filterLabel,children:e.jsx(le,{label:`${n("changelog.detail.filterCategory","Category")}:`,tooltip:n("changelog.detail.filterCategory.tooltip","Filter the timeline to a single change category.")})}),e.jsxs("select",{className:a.filterSelect,value:u,onChange:l=>p(l.target.value),children:[e.jsx("option",{value:"all",children:n("tools.filter.all","All")}),Z.map(l=>e.jsxs("option",{value:l.key,children:[l.icon," ",n(l.labelKey,l.key)]},l.key))]}),z&&e.jsxs("label",{className:a.ownershipToggle,children:[e.jsx("input",{type:"checkbox",checked:r,onChange:l=>T(l.target.checked)}),n("changelog.ownership.showGenerated","Show generated metadata")]})]}),f.length===0?e.jsx("div",{className:a.empty,children:n("changelog.detail.noChanges","No changes in this category")}):e.jsx("div",{className:a.timeline,children:f.map((l,j)=>{const b=C===j,F=At(n,l.artifactOwnership);return e.jsxs("div",{children:[e.jsxs("button",{type:"button",className:a.timelineEntry,"aria-expanded":b,onClick:()=>E(b?null:j),children:[e.jsx("span",{className:a.timelineTime,children:$t(l.timestamp)}),e.jsx("span",{className:a.timelineIcon,children:Re(l.category)}),e.jsxs("span",{className:a.timelineBody,children:[e.jsxs("span",{className:a.timelineSummary,children:[l.summary,F&&e.jsx(ne,{variant:l.artifactOwnership==="generated"?"neutral":"accent",className:a.ownershipBadge,children:F}),e.jsx(O,{text:Lt(n,l.confidence),children:e.jsx("span",{className:`${a.timelineConfidence} ${zt(l.confidence)}`,children:Et(n,l.confidence)})})]}),e.jsx("span",{className:a.timelineTarget,children:l.target})]})]}),b&&e.jsx("div",{className:a.timelineExpanded,children:e.jsx(de,{change:l})})]},j)})})]})]})]})]})})}const Mt="_page_1tggr_2",Ot="_limitNotice_1tggr_9",Dt="_limitNoticeContent_1tggr_23",Ft="_limitNoticeTitle_1tggr_28",Pt="_limitNoticeText_1tggr_35",Gt="_primaryAction_1tggr_41",Kt="_clearButton_1tggr_67",Vt="_list_1tggr_88",qt="_empty_1tggr_95",Ut="_loading_1tggr_104",Ht="_pagination_1tggr_113",Zt="_pageInfo_1tggr_121",Qt="_btn_1tggr_127",N={page:Mt,limitNotice:Ot,limitNoticeContent:Dt,limitNoticeTitle:Ft,limitNoticeText:Pt,primaryAction:Gt,clearButton:Kt,list:Vt,empty:qt,loading:Ut,pagination:Ht,pageInfo:Zt,btn:Qt},K=10;function Wt(t,i){return typeof i!="number"?`/changelog/${t}`:`/changelog/${t}?placeId=${encodeURIComponent(String(i))}`}function Xt(t){const i=/^\/changelog\/([^/]+)$/.exec(t);if(!i)return null;try{return decodeURIComponent(i[1])}catch{return i[1]}}function Yt(t){const i=new URLSearchParams(t).get("placeId");if(!i)return null;const m=Number.parseInt(i,10);return Number.isInteger(m)&&m>=0?m:null}const Jt=[{key:"all",labelKey:"changelog.filter.all"},{key:"active",labelKey:"changelog.filter.active"},{key:"completed",labelKey:"changelog.filter.completed"}];function la(){const{t}=q(),{trackEvent:i,trackPageView:m}=X(),c=Y(),n=J(),s=Xt(n.pathname),[u,p]=o.useState(()=>Yt(n.search)),r=he({placeId:u}),T=ee(),{show:C}=te(),[E,f]=o.useState(!1),[z,B]=o.useState(!1),[S,I]=o.useState(null),$=o.useRef(null),y=s??S,v=!T.loading&&T.tier==="basic",k=v?r.entries.slice(0,3):r.entries,w=!v&&r.total>K;o.useEffect(()=>{s&&s===S&&I(null)},[S,s]);const L=async()=>{B(!0);try{await r.clear(),C(t("toast.clearSuccess","Cleared successfully"),"success"),f(!1)}catch{C(t("toast.clearFailed","Failed to clear data"),"error")}finally{B(!1)}},A=(d,_)=>{$.current=_,I(d),c(Wt(d,u))},R=()=>{I(null),c("/changelog",{replace:!0})};return e.jsxs("div",{className:N.page,children:[e.jsx(se,{title:t("page.changelog.title","Changelog"),description:t("page.changelog.description","Review game-change sessions captured from AI actions and sync events."),helpTopicId:"changelog",helpState:{tier:T.tier}}),e.jsx(ce,{surface:"changelog",selectable:!0,selectedPlaceId:u,onSelectedPlaceIdChange:d=>{p(d),r.setOffset(0)}}),e.jsx(re,{items:Jt.map(d=>({key:d.key,label:t(d.labelKey,d.key.charAt(0).toUpperCase()+d.key.slice(1))})),value:r.statusFilter,onChange:d=>{const _=`changelog_${d}`;i("dashboard_click_event",{click_target:`changelog_tab_${d}`,page:"changelog",tab:_}),m({page:"changelog",tab:_}),r.setStatusFilter(d),r.setOffset(0)},rightActions:e.jsx("button",{className:N.clearButton,onClick:()=>{i("dashboard_click_event",{click_target:"changelog_clear",page:"changelog",tab:`changelog_${r.statusFilter}`}),f(!0)},children:t("common.clear","Clear")})}),r.loading&&r.entries.length===0&&e.jsx("div",{className:N.loading,children:t("common.loading","Loading...")}),!r.loading&&r.entries.length===0?e.jsx("div",{className:N.empty,children:t("changelog.empty","No changelog entries for the current place yet")}):e.jsx("div",{className:N.list,children:k.map(d=>e.jsx(Be,{entry:d,onClick:_=>A(d.entryId,_),buttonRef:_=>{d.entryId===y&&_&&($.current=_)}},d.entryId))}),w&&e.jsxs("div",{className:N.pagination,children:[e.jsx("button",{className:N.btn,disabled:r.offset===0,onClick:()=>r.setOffset(Math.max(0,r.offset-K)),children:t("tools.page.prev","Prev")}),e.jsxs("span",{className:N.pageInfo,children:[r.offset+1,"–",Math.min(r.offset+K,r.total)," / ",r.total]}),e.jsx("button",{className:N.btn,disabled:!r.hasMore,onClick:()=>r.setOffset(r.offset+K),children:t("tools.page.next","Next")})]}),v&&e.jsx(e.Fragment,{children:e.jsxs("div",{className:N.limitNotice,children:[e.jsxs("div",{className:N.limitNoticeContent,children:[e.jsx("div",{className:N.limitNoticeTitle,children:t("changelog.basic.limit.title","Basic preview shows the latest 3 sessions")}),e.jsx("div",{className:N.limitNoticeText,children:t("changelog.basic.limit.body","Full changelog timeline browsing is available with Pro.")})]}),e.jsx("a",{className:N.primaryAction,href:ae.changelog,target:"_blank",rel:"noreferrer",onClick:()=>i("dashboard_click_event",{click_target:"upgrade_cta",placement:"changelog_limit_notice",page:"changelog",tab:`changelog_${r.statusFilter}`}),children:t("tier.upgrade","View Pro")})]})}),e.jsx(ie,{open:E,title:t("changelog.clear.title","Clear changelog?"),message:t("changelog.clear.message","This permanently removes the stored changelog for the current place."),cancelLabel:t("common.cancel","Cancel"),confirmLabel:t("common.clear","Clear"),loading:z,onCancel:()=>!z&&f(!1),onConfirm:L}),y&&e.jsx(Rt,{entryId:y,placeId:u,onClose:R,returnFocusTo:$.current})]})}export{la as Component};
|
|
1
|
+
import{r as o,b as P,D as Q,u as q,j as e,X as W,a as X,o as Y,c as J,e as ee,i as te,T as ae}from"./index-DchewB5y.js";import{B as ne,P as se}from"./PageHeader-CYbeZdtL.js";import{C as ie}from"./ConfirmModal-Dz7mVKLZ.js";import{C as ce}from"./CurrentPlaceScope-DhPCqaMU.js";import{T as O}from"./TooltipText-sb-BSgUg.js";import{C as oe,T as re}from"./Tabs-C7TenrZD.js";import{I as le}from"./InfoLabel-BGeOUBIl.js";import{G as de}from"./GameChangeDetail-CZuYgFvS.js";import"./ConfirmModal.module-DJksQHBd.js";const ge=10;function me(t,i){return typeof i!="number"?t:`${t}?placeId=${encodeURIComponent(String(i))}`}function he(t){const i=(t==null?void 0:t.placeId)??null,[m,c]=o.useState([]),[n,s]=o.useState(0),[u,p]=o.useState(!1),[r,T]=o.useState(!0),[C,E]=o.useState(0),[f,z]=o.useState("all"),B=o.useRef(null),S=o.useCallback(async(y,v)=>{T(!0);try{const k={limit:String(ge),offset:String(y)};v!=="all"&&(k.status=v),typeof i=="number"&&(k.placeId=String(i));const w=await P.get("/api/dashboard/changelog",k);c(w.entries),s(w.total),p(w.hasMore)}catch{c([]),s(0),p(!1)}finally{T(!1)}},[i]),I=o.useCallback(()=>{S(C,f)},[S,C,f]),$=o.useCallback(async()=>{await P.post(me("/api/dashboard/changelog/clear",i)),c([]),s(0),p(!1)},[i]);return o.useEffect(()=>{S(C,f)},[S,C,f]),o.useEffect(()=>{const y=new Q;B.current=y,y.connect();const v=y.on("command",()=>{S(C,f)});return()=>{v(),y.disconnect(),B.current=null}},[S,C,f]),{entries:m,total:n,hasMore:u,loading:r,offset:C,statusFilter:f,setOffset:E,setStatusFilter:z,refresh:I,clear:$}}const ue="_card_qniob_2",pe="_header_qniob_27",fe="_statusBadge_qniob_34",ye="_statusDot_qniob_45",xe="_active_qniob_51",_e="_completed_qniob_60",be="_timeRange_qniob_68",Ce="_summaryList_qniob_75",Se="_summaryItem_qniob_81",ve="_summaryIcon_qniob_90",je="_summaryText_qniob_96",Ne="_progressBar_qniob_101",Te="_progressFill_qniob_110",Ie="_emptySummary_qniob_124",ke="_contextBlock_qniob_132",we="_contextLabel_qniob_141",$e="_contextValue_qniob_149",h={card:ue,header:pe,statusBadge:fe,statusDot:ye,active:xe,completed:_e,timeRange:be,summaryList:Ce,summaryItem:Se,summaryIcon:ve,summaryText:je,progressBar:Ne,progressFill:Te,emptySummary:Ie,contextBlock:ke,contextLabel:we,contextValue:$e};function H(t){if(!t)return"--:--";const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}`}function Be({entry:t,onClick:i,buttonRef:m}){var v,k,w,L,A,R,d,_,D,M;const{t:c}=q(),n=t.changeSummary,s=t.status==="active",u=t.isBootstrapOnly===!0,p=[],r=n.scriptsModified+n.scriptsCreated;if(r>0){const g=[];n.scriptsModified>0&&g.push(`${n.scriptsModified} ${c("changelog.card.modified","modified")}`),n.scriptsCreated>0&&g.push(`${n.scriptsCreated} ${c("changelog.card.created","created")}`);const x=`${r} ${c("changelog.card.scripts","scripts")} ${g.join(", ")}`;p.push({icon:"📝",text:x,tooltip:c("changelog.card.scripts.tooltip","Script changes made in this session.")})}const T=n.instancesCreated+n.instancesDeleted+n.instancesMoved;if(T>0){const g=[];n.instancesCreated>0&&g.push(`${n.instancesCreated} ${c("changelog.card.created","created")}`),n.instancesDeleted>0&&g.push(`${n.instancesDeleted} ${c("changelog.card.deleted","deleted")}`),n.instancesMoved>0&&g.push(`${n.instancesMoved} ${c("changelog.card.moved","moved")}`);const x=`${T} ${c("changelog.card.instances","instances")} ${g.join(", ")}`;p.push({icon:"🧱",text:x,tooltip:c("changelog.card.instances.tooltip","Instance create, delete, move, or clone changes in this session.")})}n.propertiesChanged>0&&p.push({icon:"🎨",text:`${n.propertiesChanged} ${c("changelog.card.propertiesChanged","properties changed")}`,tooltip:c("changelog.card.propertiesChanged.tooltip","Property value changes recorded for this session.")}),n.lightingChanged&&p.push({icon:"🌅",text:c("changelog.card.lightingConfigured","Lighting configured"),tooltip:c("changelog.card.lightingConfigured.tooltip","Lighting or atmosphere settings changed in this session.")}),n.terrainChanged&&p.push({icon:"⛰️",text:c("changelog.card.terrainConfigured","Terrain configured"),tooltip:c("changelog.card.terrainConfigured.tooltip","Terrain data or terrain settings changed in this session.")}),n.assetsInserted>0&&p.push({icon:"📦",text:`${n.assetsInserted} ${c("changelog.card.assetsInserted","assets inserted")}`,tooltip:c("changelog.card.assetsInserted.tooltip","Assets inserted into the place during this session.")});const C=H(t.startTime),E=s?c("changelog.card.inProgress","in progress"):t.endTime?H(t.endTime):"--:--",f=u?c("changelog.card.bootstrapStatus","Bootstrap"):s?c("changelog.card.active","Active"):c("changelog.card.completed","Completed"),z=u?c("changelog.card.bootstrapStatus.tooltip","This session only contains the initial sync bootstrap snapshot."):s?c("changelog.card.active.tooltip","This session is still receiving new game changes."):c("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),B=u?c("changelog.card.bootstrapSummary","Initial sync snapshot"):c("changelog.card.noChanges","No changes yet"),S=u?c("changelog.card.bootstrapSummary.tooltip","Initial file sync writes are collapsed into a single bootstrap snapshot row."):c("changelog.card.noChanges.tooltip","No game changes have been extracted for this session yet."),I=(k=(v=t.contextSummary)==null?void 0:v.intent)==null?void 0:k.trim(),$=((R=(A=(L=(w=t.contextSummary)==null?void 0:w.affectedAreas)==null?void 0:L[0])==null?void 0:A.label)==null?void 0:R.trim())||((_=(d=t.contextSummary)==null?void 0:d.testScenario)==null?void 0:_.trim()),y=(M=(D=t.verificationSummary)==null?void 0:D.label)==null?void 0:M.trim();return e.jsxs("button",{ref:m,className:h.card,type:"button",onClick:g=>i(g.currentTarget),children:[e.jsxs("span",{className:h.header,children:[e.jsx(O,{text:z,children:e.jsxs("span",{className:`${h.statusBadge} ${s?h.active:h.completed}`,children:[e.jsx("span",{className:h.statusDot}),f]})}),e.jsxs("span",{className:h.timeRange,children:[C,"~",E]})]}),e.jsx("span",{className:h.summaryList,children:p.length>0?p.map((g,x)=>e.jsxs("span",{className:h.summaryItem,children:[e.jsx("span",{className:h.summaryIcon,children:g.icon}),e.jsx(O,{text:g.tooltip,children:e.jsx("span",{className:h.summaryText,children:g.text})})]},x)):e.jsx(O,{text:S,children:e.jsx("span",{className:h.emptySummary,style:{display:"block"},children:B})})}),I&&e.jsxs("span",{className:h.contextBlock,children:[e.jsx("span",{className:h.contextLabel,children:c("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:h.contextValue,children:I})]}),!I&&$&&e.jsxs("span",{className:h.contextBlock,children:[e.jsx("span",{className:h.contextLabel,children:c("changelog.card.representativeArea","Representative area")}),e.jsx("span",{className:h.contextValue,children:$})]}),y&&e.jsxs("span",{className:h.contextBlock,children:[e.jsx("span",{className:h.contextLabel,children:c("changelog.card.verification","Verification")}),e.jsx("span",{className:h.contextValue,children:y})]}),s&&e.jsx("span",{className:h.progressBar,children:e.jsx("span",{className:h.progressFill})})]})}function ze(t){const i={scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0};for(const m of t)switch(m.category){case"script":m.changeType==="create"?i.scriptsCreated++:i.scriptsModified++;break;case"instance":m.changeType==="create"?i.instancesCreated++:m.changeType==="delete"?i.instancesDeleted++:m.changeType==="move"&&i.instancesMoved++;break;case"property":i.propertiesChanged++;break;case"lighting":i.lightingChanged=!0;break;case"terrain":i.terrainChanged=!0;break;case"asset":i.assetsInserted++;break}return i}function Ee(t){if(typeof t=="number")return{placeId:String(t)}}function Le(t,i){const[m,c]=o.useState(""),[n,s]=o.useState(""),[u,p]=o.useState(),[r,T]=o.useState("completed"),[C,E]=o.useState([]),[f,z]=o.useState([]),[B,S]=o.useState([]),[I,$]=o.useState(),[y,v]=o.useState(),[k,w]=o.useState(),[L,A]=o.useState({scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0}),[R,d]=o.useState(!0),[_,D]=o.useState(null),M=o.useCallback(async()=>{if(t){d(!0),D(null);try{const g=Ee(i),[x,G]=await Promise.all([g?P.get(`/api/dashboard/changelog/${t}`,g):P.get(`/api/dashboard/changelog/${t}`),g?P.get(`/api/dashboard/changelog/${t}/changes`,g):P.get(`/api/dashboard/changelog/${t}/changes`)]);c(x.entryId),s(x.startTime),p(x.endTime),T(x.status),E(x.entries),z(x.failures),$(x.contextSummary),v(x.replayMetadata),w(x.verificationSummary),S(G.changes),A(ze(G.changes))}catch(g){D(g instanceof Error?g.message:"Failed to load changelog detail")}finally{d(!1)}}},[t,i]);return o.useEffect(()=>{M()},[M]),{entryId:m,startTime:n,endTime:u,status:r,entries:C,failures:f,changes:B,changeSummary:L,contextSummary:I,replayMetadata:y,verificationSummary:k,loading:R,error:_,refresh:M}}const Ae={script:"📝",instance:"🧱",property:"🎨",lighting:"🌅",terrain:"⛰️",asset:"📦"};function Re(t){return Ae[t]??"❓"}const Me="_dialogContent_197zf_2",Oe="_dialogHeader_197zf_10",De="_dialogTitleGroup_197zf_20",Fe="_dialogTitle_197zf_20",Pe="_dialogMeta_197zf_36",Ge="_dialogClose_197zf_43",Ke="_dialogBody_197zf_68",Ve="_page_197zf_77",qe="_headerTime_197zf_84",Ue="_dialogActions_197zf_90",He="_retryButton_197zf_96",Ze="_statusActive_197zf_129",Qe="_statusCompleted_197zf_134",We="_section_197zf_139",Xe="_sectionTitle_197zf_146",Ye="_summaryGrid_197zf_159",Je="_summaryCard_197zf_165",et="_summaryCardActive_197zf_188",tt="_summaryIcon_197zf_193",at="_summaryCount_197zf_199",nt="_summaryLabel_197zf_207",st="_contextGrid_197zf_217",it="_contextRow_197zf_223",ct="_contextKey_197zf_229",ot="_contextValue_197zf_237",rt="_timelineFilter_197zf_245",lt="_filterLabel_197zf_253",dt="_filterSelect_197zf_259",gt="_ownershipToggle_197zf_269",mt="_timeline_197zf_245",ht="_timelineEntry_197zf_297",ut="_timelineTime_197zf_326",pt="_timelineIcon_197zf_334",ft="_timelineBody_197zf_339",yt="_timelineSummary_197zf_345",xt="_timelineTarget_197zf_353",_t="_timelineConfidence_197zf_361",bt="_ownershipBadge_197zf_370",Ct="_confidenceExact_197zf_378",St="_confidencePartial_197zf_383",vt="_confidenceAfterOnly_197zf_388",jt="_confidenceIntentOnly_197zf_393",Nt="_confidenceUnknown_197zf_398",Tt="_timelineExpanded_197zf_404",It="_empty_197zf_413",kt="_loading_197zf_422",wt="_error_197zf_431",a={dialogContent:Me,dialogHeader:Oe,dialogTitleGroup:De,dialogTitle:Fe,dialogMeta:Pe,dialogClose:Ge,dialogBody:Ke,page:Ve,headerTime:qe,dialogActions:Ue,retryButton:He,statusActive:Ze,statusCompleted:Qe,section:We,sectionTitle:Xe,summaryGrid:Ye,summaryCard:Je,summaryCardActive:et,summaryIcon:tt,summaryCount:at,summaryLabel:nt,contextGrid:st,contextRow:it,contextKey:ct,contextValue:ot,timelineFilter:rt,filterLabel:lt,filterSelect:dt,ownershipToggle:gt,timeline:mt,timelineEntry:ht,timelineTime:ut,timelineIcon:pt,timelineBody:ft,timelineSummary:yt,timelineTarget:xt,timelineConfidence:_t,ownershipBadge:bt,confidenceExact:Ct,confidencePartial:St,confidenceAfterOnly:vt,confidenceIntentOnly:jt,confidenceUnknown:Nt,timelineExpanded:Tt,empty:It,loading:kt,error:wt},Z=[{key:"script",icon:"📝",labelKey:"changelog.category.script"},{key:"instance",icon:"🧱",labelKey:"changelog.category.instance"},{key:"property",icon:"🎨",labelKey:"changelog.category.property"},{key:"lighting",icon:"🌅",labelKey:"changelog.category.lighting"},{key:"terrain",icon:"⛰️",labelKey:"changelog.category.terrain"},{key:"asset",icon:"📦",labelKey:"changelog.category.asset"}];function V(t){if(!t)return"--:--";const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}`}function $t(t){if(!t)return"--:--:--";const i=new Date(t);return`${String(i.getHours()).padStart(2,"0")}:${String(i.getMinutes()).padStart(2,"0")}:${String(i.getSeconds()).padStart(2,"0")}`}function Bt(t,i){if(!t||!i)return"";const m=new Date(i).getTime()-new Date(t).getTime();return m<0?"":`${Math.round(m/6e4)}min`}function zt(t){switch(t){case"exact":return a.confidenceExact;case"partial":return a.confidencePartial;case"after-only":return a.confidenceAfterOnly;case"intent-only":return a.confidenceIntentOnly;default:return a.confidenceUnknown}}function Et(t,i){switch(i){case"exact":return t("changelog.detail.confidence.exact","Exact");case"partial":return t("changelog.detail.confidence.partial","Partial");case"after-only":return t("changelog.detail.confidence.afterOnly","After only");case"intent-only":return t("changelog.detail.confidence.intentOnly","Intent only");default:return t("changelog.detail.confidence.unknown","Unknown")}}function Lt(t,i){switch(i){case"exact":return t("changelog.detail.confidence.exact.tooltip","Both the before and after state were confirmed for this change.");case"partial":return t("changelog.detail.confidence.partial.tooltip","Only part of the before and after state could be confirmed for this change.");case"after-only":return t("changelog.detail.confidence.afterOnly.tooltip","Only the resulting state after the change could be confirmed.");case"intent-only":return t("changelog.detail.confidence.intentOnly.tooltip","Only the requested action was recorded, not the resulting state.");default:return t("changelog.detail.confidence.unknown.tooltip","This change could not be confidently classified from the available data.")}}function At(t,i){switch(i){case"user_source":return t("changelog.ownership.userSource","User source");case"canonical_mirror":return t("changelog.ownership.canonicalMirror","Mirror metadata");case"generated":return t("changelog.ownership.generated","Generated");default:return null}}function Rt({entryId:t,placeId:i,onClose:m,returnFocusTo:c=null}){var v,k,w,L,A,R,d,_,D,M,g,x,G,U;const{t:n}=q(),s=Le(t,i),[u,p]=o.useState("all"),[r,T]=o.useState(!0),[C,E]=o.useState(null),f=o.useMemo(()=>{const l=r?s.changes:s.changes.filter(b=>b.artifactOwnership!=="generated");return[...u==="all"?l:l.filter(b=>b.category===u)].reverse()},[s.changes,u,r]),z=s.changes.some(l=>l.artifactOwnership==="generated"),B=Bt(s.startTime,s.endTime),S=s.endTime?`${V(s.startTime)} → ${V(s.endTime)} (${B})`:`${V(s.startTime)} → ${n("changelog.card.inProgress","in progress")}`,I=!!((v=s.contextSummary)!=null&&v.intent||(k=s.contextSummary)!=null&&k.testScenario||(w=s.contextSummary)!=null&&w.expectedBehavior||(L=s.contextSummary)!=null&&L.observedBehavior),$=!!((A=s.verificationSummary)!=null&&A.label||(R=s.verificationSummary)!=null&&R.status||(d=s.verificationSummary)!=null&&d.testTimestamp),y=n("changelog.detail.dialogLabel","Changelog detail");return e.jsx(oe,{open:!0,ariaLabel:y,onClose:m,returnFocusTo:c,testId:"changelog-detail-backdrop",children:e.jsxs("div",{className:a.dialogContent,children:[e.jsxs("div",{className:a.dialogHeader,children:[e.jsxs("div",{className:a.dialogTitleGroup,children:[e.jsx("h2",{className:a.dialogTitle,children:y}),!s.loading&&!s.error&&e.jsxs("div",{className:a.dialogMeta,children:[e.jsx("span",{className:a.headerTime,children:S}),e.jsx(O,{text:s.status==="active"?n("changelog.card.active.tooltip","This session is still receiving new game changes."):n("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),children:e.jsx("span",{className:s.status==="active"?a.statusActive:a.statusCompleted,children:s.status==="active"?n("changelog.card.active","Active"):n("changelog.card.completed","Completed")})})]})]}),e.jsx("button",{className:a.dialogClose,type:"button","aria-label":n("common.close","Close"),onClick:m,children:e.jsx(W,{size:18,"aria-hidden":"true"})})]}),e.jsxs("div",{className:a.dialogBody,children:[s.loading&&e.jsx("div",{className:a.loading,children:n("common.loading","Loading...")}),s.error&&e.jsxs("div",{className:a.error,children:[e.jsx("span",{children:s.error}),e.jsxs("div",{className:a.dialogActions,children:[e.jsx("button",{className:a.retryButton,type:"button",onClick:s.refresh,children:n("common.retry","Retry")}),e.jsx("button",{className:a.retryButton,type:"button",onClick:m,children:n("common.close","Close")})]})]}),!s.loading&&!s.error&&e.jsxs("div",{className:a.page,children:[e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.changeSummary.tooltip","Counts of extracted game changes grouped by category for this session."),children:e.jsx("span",{children:n("changelog.detail.changeSummary","Change Summary")})})}),e.jsx("div",{className:a.summaryGrid,children:Z.map(l=>{const j=s.changeSummary;let b;switch(l.key){case"script":b=j.scriptsModified+j.scriptsCreated;break;case"instance":b=j.instancesCreated+j.instancesDeleted+j.instancesMoved;break;case"property":b=j.propertiesChanged;break;case"lighting":b=j.lightingChanged?1:0;break;case"terrain":b=j.terrainChanged?1:0;break;case"asset":b=j.assetsInserted;break;default:b=0}const F=u===l.key;return e.jsxs("button",{type:"button",className:`${a.summaryCard} ${F?a.summaryCardActive:""}`,"aria-label":`${n(l.labelKey,l.key)}: ${b}`,"aria-pressed":F,onClick:()=>p(F?"all":l.key),children:[e.jsx("span",{className:a.summaryIcon,children:l.icon}),e.jsx("span",{className:a.summaryCount,children:b}),e.jsx("span",{className:a.summaryLabel,children:n(l.labelKey,l.key)})]},l.key)})})]}),I&&e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.context.tooltip","Structured execution context captured for this changelog session."),children:e.jsx("span",{children:n("changelog.detail.context.title","Context Summary")})})}),e.jsxs("div",{className:a.contextGrid,children:[((_=s.contextSummary)==null?void 0:_.intent)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.intent})]}),((D=s.contextSummary)==null?void 0:D.testScenario)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("playtest.context.why","Why this test ran")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.testScenario})]}),((M=s.contextSummary)==null?void 0:M.expectedBehavior)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("playtest.context.expected","Expected")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.expectedBehavior})]}),((g=s.contextSummary)==null?void 0:g.observedBehavior)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("playtest.context.observed","Observed")}),e.jsx("span",{className:a.contextValue,children:s.contextSummary.observedBehavior})]})]})]}),$&&e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.verification.tooltip","Verification signals linked to this changelog session."),children:e.jsx("span",{children:n("changelog.detail.verification.title","Verification")})})}),e.jsxs("div",{className:a.contextGrid,children:[((x=s.verificationSummary)==null?void 0:x.label)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.detail.verification.label","Result")}),e.jsx("span",{className:a.contextValue,children:s.verificationSummary.label})]}),((G=s.verificationSummary)==null?void 0:G.status)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.detail.verification.status","Status")}),e.jsx("span",{className:a.contextValue,children:s.verificationSummary.status})]}),((U=s.verificationSummary)==null?void 0:U.testTimestamp)&&e.jsxs("div",{className:a.contextRow,children:[e.jsx("span",{className:a.contextKey,children:n("changelog.detail.verification.timestamp","Recorded at")}),e.jsx("span",{className:a.contextValue,children:s.verificationSummary.testTimestamp})]})]})]}),e.jsxs("div",{className:a.section,children:[e.jsx("div",{className:a.sectionTitle,children:e.jsx(O,{text:n("changelog.detail.changeTimeline.tooltip","Chronological list of extracted game changes for this session."),children:e.jsx("span",{children:n("changelog.detail.changeTimeline","Change Timeline")})})}),e.jsxs("div",{className:a.timelineFilter,children:[e.jsx("span",{className:a.filterLabel,children:e.jsx(le,{label:`${n("changelog.detail.filterCategory","Category")}:`,tooltip:n("changelog.detail.filterCategory.tooltip","Filter the timeline to a single change category.")})}),e.jsxs("select",{className:a.filterSelect,value:u,onChange:l=>p(l.target.value),children:[e.jsx("option",{value:"all",children:n("tools.filter.all","All")}),Z.map(l=>e.jsxs("option",{value:l.key,children:[l.icon," ",n(l.labelKey,l.key)]},l.key))]}),z&&e.jsxs("label",{className:a.ownershipToggle,children:[e.jsx("input",{type:"checkbox",checked:r,onChange:l=>T(l.target.checked)}),n("changelog.ownership.showGenerated","Show generated metadata")]})]}),f.length===0?e.jsx("div",{className:a.empty,children:n("changelog.detail.noChanges","No changes in this category")}):e.jsx("div",{className:a.timeline,children:f.map((l,j)=>{const b=C===j,F=At(n,l.artifactOwnership);return e.jsxs("div",{children:[e.jsxs("button",{type:"button",className:a.timelineEntry,"aria-expanded":b,onClick:()=>E(b?null:j),children:[e.jsx("span",{className:a.timelineTime,children:$t(l.timestamp)}),e.jsx("span",{className:a.timelineIcon,children:Re(l.category)}),e.jsxs("span",{className:a.timelineBody,children:[e.jsxs("span",{className:a.timelineSummary,children:[l.summary,F&&e.jsx(ne,{variant:l.artifactOwnership==="generated"?"neutral":"accent",className:a.ownershipBadge,children:F}),e.jsx(O,{text:Lt(n,l.confidence),children:e.jsx("span",{className:`${a.timelineConfidence} ${zt(l.confidence)}`,children:Et(n,l.confidence)})})]}),e.jsx("span",{className:a.timelineTarget,children:l.target})]})]}),b&&e.jsx("div",{className:a.timelineExpanded,children:e.jsx(de,{change:l})})]},j)})})]})]})]})]})})}const Mt="_page_1tggr_2",Ot="_limitNotice_1tggr_9",Dt="_limitNoticeContent_1tggr_23",Ft="_limitNoticeTitle_1tggr_28",Pt="_limitNoticeText_1tggr_35",Gt="_primaryAction_1tggr_41",Kt="_clearButton_1tggr_67",Vt="_list_1tggr_88",qt="_empty_1tggr_95",Ut="_loading_1tggr_104",Ht="_pagination_1tggr_113",Zt="_pageInfo_1tggr_121",Qt="_btn_1tggr_127",N={page:Mt,limitNotice:Ot,limitNoticeContent:Dt,limitNoticeTitle:Ft,limitNoticeText:Pt,primaryAction:Gt,clearButton:Kt,list:Vt,empty:qt,loading:Ut,pagination:Ht,pageInfo:Zt,btn:Qt},K=10;function Wt(t,i){return typeof i!="number"?`/changelog/${t}`:`/changelog/${t}?placeId=${encodeURIComponent(String(i))}`}function Xt(t){const i=/^\/changelog\/([^/]+)$/.exec(t);if(!i)return null;try{return decodeURIComponent(i[1])}catch{return i[1]}}function Yt(t){const i=new URLSearchParams(t).get("placeId");if(!i)return null;const m=Number.parseInt(i,10);return Number.isInteger(m)&&m>=0?m:null}const Jt=[{key:"all",labelKey:"changelog.filter.all"},{key:"active",labelKey:"changelog.filter.active"},{key:"completed",labelKey:"changelog.filter.completed"}];function la(){const{t}=q(),{trackEvent:i,trackPageView:m}=X(),c=Y(),n=J(),s=Xt(n.pathname),[u,p]=o.useState(()=>Yt(n.search)),r=he({placeId:u}),T=ee(),{show:C}=te(),[E,f]=o.useState(!1),[z,B]=o.useState(!1),[S,I]=o.useState(null),$=o.useRef(null),y=s??S,v=!T.loading&&T.tier==="basic",k=v?r.entries.slice(0,3):r.entries,w=!v&&r.total>K;o.useEffect(()=>{s&&s===S&&I(null)},[S,s]);const L=async()=>{B(!0);try{await r.clear(),C(t("toast.clearSuccess","Cleared successfully"),"success"),f(!1)}catch{C(t("toast.clearFailed","Failed to clear data"),"error")}finally{B(!1)}},A=(d,_)=>{$.current=_,I(d),c(Wt(d,u))},R=()=>{I(null),c("/changelog",{replace:!0})};return e.jsxs("div",{className:N.page,children:[e.jsx(se,{title:t("page.changelog.title","Changelog"),description:t("page.changelog.description","Review game-change sessions captured from AI actions and sync events."),helpTopicId:"changelog",helpState:{tier:T.tier}}),e.jsx(ce,{surface:"changelog",selectable:!0,selectedPlaceId:u,onSelectedPlaceIdChange:d=>{p(d),r.setOffset(0)}}),e.jsx(re,{items:Jt.map(d=>({key:d.key,label:t(d.labelKey,d.key.charAt(0).toUpperCase()+d.key.slice(1))})),value:r.statusFilter,onChange:d=>{const _=`changelog_${d}`;i("dashboard_click_event",{click_target:`changelog_tab_${d}`,page:"changelog",tab:_}),m({page:"changelog",tab:_}),r.setStatusFilter(d),r.setOffset(0)},rightActions:e.jsx("button",{className:N.clearButton,onClick:()=>{i("dashboard_click_event",{click_target:"changelog_clear",page:"changelog",tab:`changelog_${r.statusFilter}`}),f(!0)},children:t("common.clear","Clear")})}),r.loading&&r.entries.length===0&&e.jsx("div",{className:N.loading,children:t("common.loading","Loading...")}),!r.loading&&r.entries.length===0?e.jsx("div",{className:N.empty,children:t("changelog.empty","No changelog entries for the current place yet")}):e.jsx("div",{className:N.list,children:k.map(d=>e.jsx(Be,{entry:d,onClick:_=>A(d.entryId,_),buttonRef:_=>{d.entryId===y&&_&&($.current=_)}},d.entryId))}),w&&e.jsxs("div",{className:N.pagination,children:[e.jsx("button",{className:N.btn,disabled:r.offset===0,onClick:()=>r.setOffset(Math.max(0,r.offset-K)),children:t("tools.page.prev","Prev")}),e.jsxs("span",{className:N.pageInfo,children:[r.offset+1,"–",Math.min(r.offset+K,r.total)," / ",r.total]}),e.jsx("button",{className:N.btn,disabled:!r.hasMore,onClick:()=>r.setOffset(r.offset+K),children:t("tools.page.next","Next")})]}),v&&e.jsx(e.Fragment,{children:e.jsxs("div",{className:N.limitNotice,children:[e.jsxs("div",{className:N.limitNoticeContent,children:[e.jsx("div",{className:N.limitNoticeTitle,children:t("changelog.basic.limit.title","Basic preview shows the latest 3 sessions")}),e.jsx("div",{className:N.limitNoticeText,children:t("changelog.basic.limit.body","Full changelog timeline browsing is available with Pro.")})]}),e.jsx("a",{className:N.primaryAction,href:ae.changelog,target:"_blank",rel:"noreferrer",onClick:()=>i("dashboard_click_event",{click_target:"upgrade_cta",placement:"changelog_limit_notice",page:"changelog",tab:`changelog_${r.statusFilter}`}),children:t("tier.upgrade","View Pro")})]})}),e.jsx(ie,{open:E,title:t("changelog.clear.title","Clear changelog?"),message:t("changelog.clear.message","This permanently removes the stored changelog for the current place."),cancelLabel:t("common.cancel","Cancel"),confirmLabel:t("common.clear","Clear"),loading:z,onCancel:()=>!z&&f(!1),onConfirm:L}),y&&e.jsx(Rt,{entryId:y,placeId:u,onClose:R,returnFocusTo:$.current})]})}export{la as Component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as t,j as s}from"./index-
|
|
1
|
+
import{r as t,j as s}from"./index-DchewB5y.js";import{s as r}from"./ConfirmModal.module-DJksQHBd.js";function D({open:a,title:y,message:E,cancelLabel:R,confirmLabel:j,loading:n=!1,onCancel:c,onConfirm:k}){const i=t.useId(),o=t.useRef(null),f=t.useRef(null),d=t.useRef(null),m=t.useRef(c),h=t.useRef(n);return m.current=c,h.current=n,t.useEffect(()=>{var b;if(!a)return;d.current=document.activeElement instanceof HTMLElement?document.activeElement:null,(b=f.current)==null||b.focus();const l=e=>{if(e.key==="Escape"){e.preventDefault(),h.current||m.current();return}if(e.key!=="Tab"||!o.current)return;const u=Array.from(o.current.querySelectorAll("button:not([disabled])"));if(u.length===0){e.preventDefault(),o.current.focus();return}const p=u[0],x=u[u.length-1];e.shiftKey&&document.activeElement===p?(e.preventDefault(),x.focus()):!e.shiftKey&&document.activeElement===x&&(e.preventDefault(),p.focus())};return document.addEventListener("keydown",l),()=>{document.removeEventListener("keydown",l);const e=d.current;e&&document.contains(e)&&e.focus()}},[a]),a?s.jsx("div",{className:r.backdrop,onClick:n?void 0:c,children:s.jsxs("div",{ref:o,className:r.modal,role:"dialog","aria-modal":"true","aria-labelledby":i,tabIndex:-1,onClick:l=>l.stopPropagation(),children:[s.jsx("h2",{id:i,className:r.title,children:y}),s.jsx("p",{className:r.message,children:E}),s.jsxs("div",{className:r.actions,children:[s.jsx("button",{ref:f,className:r.cancelButton,onClick:c,disabled:n,children:R}),s.jsx("button",{className:r.confirmButton,onClick:k,disabled:n,children:n?"...":j})]})]})}):null}export{D as C};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import{f as
|
|
1
|
+
import{f as so,u as eo,r as d,j as o,d as co,b as U,D as io,L as lo,M as ao,h as Y,a as ro,i as po,s as go}from"./index-DchewB5y.js";import{I as u}from"./InfoLabel-BGeOUBIl.js";import{P as uo}from"./PageHeader-CYbeZdtL.js";import{S as to}from"./StatusBadge-BmR5_DsF.js";import{T as X}from"./TooltipText-sb-BSgUg.js";import{C as J}from"./ConfirmModal-Dz7mVKLZ.js";import{f as no,u as ho}from"./useLiveUptime-BeZ9TLyF.js";import{B as yo}from"./bot-oMwejCZF.js";import{C as V}from"./copy-CePVq0VI.js";import"./ConfirmModal.module-DJksQHBd.js";/**
|
|
2
2
|
* @license lucide-react v1.8.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const yo=[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]],mo=eo("bot",yo);/**
|
|
7
|
-
* @license lucide-react v1.8.0 - ISC
|
|
8
|
-
*
|
|
9
|
-
* This source code is licensed under the ISC license.
|
|
10
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/const xo=[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]],_o=eo("server",xo),So="_container_1h084_2",jo="_entry_1h084_14",vo="_timestamp_1h084_21",fo="_message_1h084_27",bo="_warn_1h084_34",Co="_error_1h084_39",No="_empty_1h084_44",O={container:So,entry:jo,timestamp:vo,message:fo,warn:bo,error:Co,empty:No};function wo(e){const s=new Date(e);return Number.isNaN(s.getTime())?e:`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}`}function ko({entries:e}){const{t:s}=to(),n=d.useRef(null);return d.useEffect(()=>{const l=n.current;l&&(l.scrollTop=l.scrollHeight)},[e.length]),o.jsx("div",{ref:n,className:O.container,children:e.length===0?o.jsx("div",{className:O.empty,children:s("connection.log.empty","No events yet")}):e.map((l,c)=>o.jsxs("div",{className:`${O.entry} ${l.type?O[l.type]:""}`,children:[o.jsx("span",{className:O.timestamp,children:wo(l.timestamp)}),o.jsx("span",{className:O.message,children:l.message})]},c))})}const Q=50;function Io(){const e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function Lo(){const{level:e,status:s,error:n}=co(),[l,c]=d.useState(null),[y,p]=d.useState(null),[i,k]=d.useState([]),C=d.useRef(null),z=d.useCallback((g,j)=>{k(w=>{const S=[...w,{timestamp:Io(),message:g,type:j}];return S.length>Q?S.slice(-Q):S})},[]),m=d.useCallback(async()=>{try{const g=await U.get("/connection-info");c(g)}catch{c(null)}},[]),A=d.useCallback(async()=>{try{const g=await U.get("/api/dashboard/studio-routing");p(g)}catch{p(null)}},[]),I=d.useCallback(async g=>{const j=await U.patch("/api/dashboard/studio-routing",g);return p(j),await m(),j},[m]),B=d.useCallback(async()=>{try{const g=await U.get("/api/dashboard/connection-log");k(g.entries??[])}catch{k([])}},[]),E=d.useCallback(async()=>{await U.post("/api/dashboard/connection-log/clear"),k([])},[]),N=d.useCallback(async g=>{await U.post("/api/dashboard/kill-agent",{instanceId:g}),await m()},[m]);return d.useEffect(()=>{e!=="disconnected"&&s?(m(),A()):p(null),B()},[e,s,m,B,A]),d.useEffect(()=>{const g=new io;C.current=g,g.connect();const j=g.on("connection",S=>{const h=S;h.status!=="updated"&&h.clientId&&z(`Plugin ${h.status} — ${h.clientId}`,h.status==="disconnected"?"warn":"info"),m(),A()}),w=g.on("mcp_status",S=>{const h=S,F=h.status==="registered"?"registered":"unregistered";z(`MCP ${F} — ${h.aiClientName}`,h.status==="registered"?"info":"warn"),m(),A()});return()=>{j(),w(),g.disconnect(),C.current=null}},[z,m,A]),{status:s,connectionInfo:l,studioRouting:y,connectionLog:i,level:e,error:n,clearConnectionLog:E,killAgent:N,updateStudioRouting:I}}const zo="_page_cozq1_2",Ao="_card_cozq1_11",Po="_topologyCard_cozq1_19",qo="_topologyDisconnected_cozq1_26",Bo="_topologyHeader_cozq1_30",$o="_topologyIntro_cozq1_38",Mo="_topologyNetwork_cozq1_45",Eo="_topologyLinks_cozq1_49",To="_topologyLink_cozq1_49",Ho="_topologyLink_agent_cozq1_66",Do="_topologyLink_studio_cozq1_70",Uo="_topologyGrid_cozq1_74",Oo="_topologyColumn_cozq1_83",Fo="_topologyColumnHeader_cozq1_90",Wo="_topologyColumnHeaderSpacer_cozq1_101",Yo="_topologyCount_cozq1_105",Vo="_topologyList_cozq1_120",Go="_topologyListCentered_cozq1_128",Ro="_topologyNode_cozq1_132",Ko="_topologyNodeTitle_cozq1_140",Xo="_topologyNodeMeta_cozq1_156",Jo="_topologyNodeSubtle_cozq1_157",Qo="_topologyState_cozq1_170",Zo="_topologyEmpty_cozq1_183",oe="_topologyOverflow_cozq1_198",ee="_topologyOverflowButton_cozq1_213",te="_topologyServerColumn_cozq1_236",ne="_topologyServer_cozq1_236",se="_topologyServerIcon_cozq1_254",ce="_topologyServerBody_cozq1_267",ie="_topologyServerTitle_cozq1_276",le="_topologyServerMeta_cozq1_283",ae="_routingSummaryCompact_cozq1_290",re="_disabled_cozq1_298",de="_cardHeader_cozq1_304",pe="_cardHint_cozq1_317",ge="_clearButton_cozq1_324",ue="_serverGrid_cozq1_348",he="_statusRow_cozq1_366",ye="_metaItem_cozq1_373",me="_table_cozq1_380",xe="_tableWrap_cozq1_400",_e="_routingSummary_cozq1_290",Se="_manageLink_cozq1_416",je="_segment_cozq1_442",ve="_segmentActive_cozq1_443",fe="_targetPrimary_cozq1_477",be="_monoMuted_cozq1_481",Ce="_copyIconButton_cozq1_485",Ne="_routingBadge_cozq1_510",we="_studioStateBadge_cozq1_524",ke="_studioState_running_cozq1_539",Ie="_studioState_paused_cozq1_545",Le="_studioState_edit_cozq1_551",ze="_studioState_unknown_cozq1_557",Ae="_toggleBtn_cozq1_564",Pe="_disconnected_cozq1_579",qe="_disconnectedActions_cozq1_596",Be="_btn_cozq1_603",$e="_activity_active_cozq1_621",Me="_activity_stale_cozq1_622",Ee="_activity_unknown_cozq1_623",Te="_killBtn_cozq1_647",He="_emptyRow_cozq1_671",t={page:zo,card:Ao,topologyCard:Po,topologyDisconnected:qo,topologyHeader:Bo,topologyIntro:$o,topologyNetwork:Mo,topologyLinks:Eo,topologyLink:To,topologyLink_agent:Ho,topologyLink_studio:Do,topologyGrid:Uo,topologyColumn:Oo,topologyColumnHeader:Fo,topologyColumnHeaderSpacer:Wo,topologyCount:Yo,topologyList:Vo,topologyListCentered:Go,topologyNode:Ro,topologyNodeTitle:Ko,topologyNodeMeta:Xo,topologyNodeSubtle:Jo,topologyState:Qo,topologyEmpty:Zo,topologyOverflow:oe,topologyOverflowButton:ee,topologyServerColumn:te,topologyServer:ne,topologyServerIcon:se,topologyServerBody:ce,topologyServerTitle:ie,topologyServerMeta:le,routingSummaryCompact:ae,disabled:re,cardHeader:de,cardHint:pe,clearButton:ge,serverGrid:ue,statusRow:he,metaItem:ye,table:me,tableWrap:xe,routingSummary:_e,manageLink:Se,segment:je,segmentActive:ve,targetPrimary:fe,monoMuted:be,copyIconButton:Ce,routingBadge:Ne,studioStateBadge:we,studioState_running:ke,studioState_paused:Ie,studioState_edit:Le,studioState_unknown:ze,toggleBtn:Ae,disconnected:Pe,disconnectedActions:qe,btn:Be,activity_active:$e,activity_stale:Me,activity_unknown:Ee,killBtn:Te,emptyRow:He},V=5;function De(e){return e?Date.now()-e<3e4?"active":"stale":"unknown"}function Ue(e,s){return e==="active"?s("connection.topology.active","Active"):e==="stale"?s("connection.topology.stale","Stale"):s("connection.topology.unknown","Unknown")}function Z(e){return e.length>10?e.slice(0,10):e}function oo(e,s){return e.replace("{count}",String(s))}function Oe(e,s,n){const l=e.studioState??"unknown",c={edit:s("connection.targets.studioState.edit","Edit"),running:s("connection.targets.studioState.running","Running"),paused:s("connection.targets.studioState.paused","Paused"),unknown:s("connection.targets.studioState.unknown","Unknown")},y=e.studioStateSource==="thread"?s("connection.targets.studioState.source.thread","WEPPY play command"):e.studioStateSource==="pluginConnection"?s("connection.targets.studioState.source.pluginConnection","Studio Play/Test connection"):e.studioStateSource==="runService"?s("connection.targets.studioState.source.runService","Studio RunService"):s("connection.targets.studioState.source.unknown","Unknown source"),p=e.studioStateUpdatedAt?n(e.studioStateUpdatedAt):s("connection.targets.studioState.updatedUnknown","not reported");return{state:l,label:c[l],tooltip:`${y} · ${p}`}}function Fe(e,s){return e.length!==s.length?!1:e.every((n,l)=>{const c=s[l];return c!==void 0&&n.id===c.id&&n.side===c.side&&Math.abs(n.x1-c.x1)<.5&&Math.abs(n.y1-c.y1)<.5&&Math.abs(n.x2-c.x2)<.5&&Math.abs(n.y2-c.y2)<.5})}function b(e,s,n){return{x:s-e.left,y:n-e.top}}function We(e,s,n,l){if(s.right<=n.left){const p=b(l,s.right,s.top+s.height/2),i=b(l,n.left,n.top+n.height/2);return{id:e,side:"agent",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}if(s.bottom<=n.top){const p=b(l,s.left+s.width/2,s.bottom),i=b(l,n.left+n.width/2,n.top);return{id:e,side:"agent",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}const c=b(l,s.left+s.width/2,s.top),y=b(l,n.left+n.width/2,n.bottom);return{id:e,side:"agent",x1:c.x,y1:c.y,x2:y.x,y2:y.y}}function Ye(e,s,n,l){if(n.right<=s.left){const p=b(l,s.left,s.top+s.height/2),i=b(l,n.right,n.top+n.height/2);return{id:e,side:"studio",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}if(n.bottom<=s.top){const p=b(l,s.left+s.width/2,s.top),i=b(l,n.left+n.width/2,n.bottom);return{id:e,side:"studio",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}const c=b(l,s.left+s.width/2,s.bottom),y=b(l,n.left+n.width/2,n.top);return{id:e,side:"studio",x1:c.x,y1:c.y,x2:y.x,y2:y.y}}function Ve({agents:e,isDisconnected:s,pinnedTargetClientId:n,priorityTarget:l,status:c,studioRoutingMode:y,studioTargets:p,t:i,timeAgo:k,onCopySelector:C,onManageRouting:z}){const[m,A]=d.useState(!1),[I,B]=d.useState(!1),[E,N]=d.useState([]),g=d.useRef(null),j=d.useRef(null),w=d.useRef(new Map),S=d.useRef(new Map),h=y==="pinned"?i("connection.routing.pinned","Manual: Pinned Studio"):i("connection.routing.recentPriority","Automatic: Recent priority"),F=s?"offline":"online",f=d.useMemo(()=>m?e:e.slice(0,V),[e,m]),T=Math.max(0,e.length-f.length),v=d.useMemo(()=>I?p:p.slice(0,V),[p,I]),$=Math.max(0,p.length-v.length),R=[t.topologyList,f.length<=1?t.topologyListCentered:""].filter(Boolean).join(" "),K=[t.topologyList,v.length<=1?t.topologyListCentered:""].filter(Boolean).join(" "),H=d.useCallback(a=>x=>{if(x){w.current.set(a,x);return}w.current.delete(a)},[]),r=d.useCallback(a=>x=>{if(x){S.current.set(a,x);return}S.current.delete(a)},[]),L=d.useCallback(()=>{const a=g.current,x=j.current;if(!a||!x){N([]);return}const _=a.getBoundingClientRect(),P=x.getBoundingClientRect(),D=[];f.forEach(q=>{const W=w.current.get(q.instanceId);W&&D.push(We(`agent-${q.instanceId}`,W.getBoundingClientRect(),P,_))}),v.forEach(q=>{const W=S.current.get(q.clientId);W&&D.push(Ye(`studio-${q.clientId}`,W.getBoundingClientRect(),P,_))}),N(q=>Fe(q,D)?q:D)},[f,v]);return d.useLayoutEffect(()=>{L();const a=[g.current,j.current,...f.map(_=>w.current.get(_.instanceId)),...v.map(_=>S.current.get(_.clientId))].filter(_=>_!=null);if(window.addEventListener("resize",L),typeof ResizeObserver>"u")return()=>{window.removeEventListener("resize",L)};const x=new ResizeObserver(L);return a.forEach(_=>x.observe(_)),()=>{window.removeEventListener("resize",L),x.disconnect()}},[L,f,v]),o.jsxs("section",{className:`${t.topologyCard} ${s?t.topologyDisconnected:""}`,"aria-label":i("connection.topology.ariaLabel","Connection topology"),children:[o.jsxs("div",{className:t.topologyHeader,children:[o.jsxs("div",{children:[o.jsx("div",{className:t.cardHeader,children:i("connection.topology.title","Connection topology")}),o.jsx("p",{className:t.topologyIntro,children:i("connection.topology.description","Each AI agent connects through its own MCP Adapter to one shared WEPPY Bridge, which keeps Roblox Studio connected.")})]}),o.jsx(lo,{to:"/controls?section=studio-routing",className:t.manageLink,onClick:z,children:i("connection.routing.manage","Manage routing")})]}),o.jsxs("div",{className:t.topologyNetwork,ref:g,children:[o.jsx("svg",{"aria-hidden":"true",className:t.topologyLinks,"data-testid":"topology-connection-lines",focusable:"false",children:E.map(a=>o.jsx("line",{className:`${t.topologyLink} ${t[`topologyLink_${a.side}`]}`,"data-side":a.side,vectorEffect:"non-scaling-stroke",x1:a.x1,x2:a.x2,y1:a.y1,y2:a.y2},a.id))}),o.jsxs("div",{className:t.topologyGrid,children:[o.jsxs("div",{className:t.topologyColumn,children:[o.jsxs("div",{className:t.topologyColumnHeader,children:[o.jsx(mo,{size:15,"aria-hidden":"true"}),o.jsx("span",{children:i("connection.agents.title","AI Agents")}),o.jsx("span",{className:t.topologyCount,children:e.length})]}),o.jsxs("div",{className:R,children:[e.length>0?f.map(a=>{const x=De(a.lastSeen),_=a.aiClientName??Z(a.instanceId),P=a.lastSeen??a.lastCommandAt??a.connectedAt,D=a.mcpVersion?`${i("connection.topology.adapterRole","MCP Adapter")} v${a.mcpVersion}`:i("connection.topology.adapterRole","MCP Adapter");return o.jsxs("div",{className:t.topologyNode,ref:H(a.instanceId),children:[o.jsxs("div",{className:t.topologyNodeTitle,children:[o.jsx("span",{className:t[`activity_${x}`]}),o.jsx("strong",{children:_}),o.jsx("span",{className:t.topologyState,children:Ue(x,i)})]}),o.jsxs("div",{className:t.topologyNodeMeta,children:[o.jsx("span",{children:D})," ·"," ",i("connection.server.session","Session")," ",Z(a.instanceId)," ·"," ",P?`${i("connection.topology.lastActivity","Last activity")} ${k(P)}`:i("connection.topology.noActivity","No recent activity")]})]},a.instanceId)}):o.jsx("div",{className:t.topologyEmpty,children:i("connection.agents.none","No agents connected")}),e.length>V?o.jsxs("div",{className:t.topologyOverflow,children:[T>0?o.jsx("span",{children:oo(i("connection.topology.moreAgents","+{count} more agents"),T)}):o.jsx("span",{children:i("connection.topology.allAgentsVisible","All agents visible")}),o.jsx("button",{type:"button",className:t.topologyOverflowButton,"aria-label":m?i("connection.topology.showLessAgents","Show less AI agents"):i("connection.topology.showAllAgents","Show all AI agents"),onClick:()=>A(a=>!a),children:m?i("connection.topology.showLess","Show less"):i("connection.topology.showAll","Show all")})]}):null]})]}),o.jsxs("div",{className:t.topologyServerColumn,children:[o.jsx("div",{className:t.topologyColumnHeaderSpacer,"aria-hidden":"true"}),o.jsxs("div",{className:`${t.topologyNode} ${t.topologyServer}`,ref:j,children:[o.jsx("div",{className:t.topologyServerIcon,children:o.jsx(_o,{size:18,"aria-hidden":"true"})}),o.jsxs("div",{className:t.topologyServerBody,children:[o.jsx("div",{className:t.topologyServerTitle,children:i("connection.topology.serverTitle","WEPPY Bridge")}),o.jsx(no,{status:F}),o.jsxs("div",{className:t.topologyServerMeta,children:[c!=null&&c.version?`v${c.version}`:i("connection.topology.versionUnknown","Version unknown"),c!=null&&c.sessionId?` · ${i("connection.server.session","Session")} ${c.sessionId.slice(0,8)}`:""]}),(c==null?void 0:c.pid)!=null||(c==null?void 0:c.uptime)!=null?o.jsxs("div",{className:t.topologyNodeSubtle,children:[(c==null?void 0:c.pid)!=null?o.jsx("span",{children:`${i("connection.server.pid","PID")} ${c.pid}`}):null,(c==null?void 0:c.pid)!=null&&(c==null?void 0:c.uptime)!=null?" · ":"",(c==null?void 0:c.uptime)!=null?o.jsx("span",{children:`${i("connection.server.uptime","Uptime")} ${so(c.uptime)}`}):null]}):null,o.jsx("div",{className:t.routingSummaryCompact,children:o.jsx("span",{className:t.routingBadge,children:h})})]})]})]}),o.jsxs("div",{className:t.topologyColumn,children:[o.jsxs("div",{className:t.topologyColumnHeader,children:[o.jsx(ao,{size:15,"aria-hidden":"true"}),o.jsx("span",{children:i("connection.targets.title","Studio Targets")}),o.jsx("span",{className:t.topologyCount,children:p.length})]}),o.jsxs("div",{className:K,children:[p.length>0?v.map(a=>{const x=y==="pinned"&&n===a.clientId,_=y==="recentPriority"&&(l==null?void 0:l.clientId)===a.clientId,P=Oe(a,i,k);return o.jsxs("div",{className:t.topologyNode,ref:r(a.clientId),children:[o.jsxs("div",{className:t.topologyNodeTitle,children:[o.jsx("span",{className:t.targetPrimary,children:a.targetAlias}),o.jsx(Y,{text:i("connection.targets.copyTargetAlias","Copy Studio ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":i("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>C(a.targetAlias,"target_alias"),children:o.jsx(G,{size:13,"aria-hidden":"true"})})}),x?o.jsx("span",{className:t.routingBadge,children:i("connection.routing.pinnedBadge","Pinned")}):_?o.jsx("span",{className:t.routingBadge,children:i("connection.routing.priorityBadge","Priority")}):null,o.jsx(Y,{text:P.tooltip,children:o.jsx("span",{className:`${t.studioStateBadge} ${t[`studioState_${P.state}`]}`,children:P.label})})]}),o.jsxs("div",{className:t.topologyNodeMeta,children:[o.jsx("span",{children:a.placeName??i("connection.topology.placeUnknown","Place unknown")}),a.placeId!==void 0?` · ${a.placeId}`:""]}),o.jsxs("div",{className:t.topologyNodeSubtle,children:[a.connectionState," · ",i("connection.targets.lastSeen","Last Seen")," ",k(a.lastSeen)]})]},a.clientId)}):o.jsx("div",{className:t.topologyEmpty,children:i("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")}),p.length>V?o.jsxs("div",{className:t.topologyOverflow,children:[$>0?o.jsx("span",{children:oo(i("connection.topology.moreStudios","+{count} more studios"),$)}):o.jsx("span",{children:i("connection.topology.allStudiosVisible","All studios visible")}),o.jsx("button",{type:"button",className:t.topologyOverflowButton,"aria-label":I?i("connection.topology.showLessStudios","Show less Studio targets"):i("connection.topology.showAllStudios","Show all Studio targets"),onClick:()=>B(a=>!a),children:I?i("connection.topology.showLess","Show less"):i("connection.topology.showAll","Show all")})]}):null]})]})]})]})]})}function M(e,s){const n=Math.max(0,Math.floor((Date.now()-e)/1e3));return n<60?`${n}${s("connection.time.secondsAgo","s ago")}`:n<3600?`${Math.floor(n/60)}${s("connection.time.minutesAgo","m ago")}`:`${Math.floor(n/3600)}${s("connection.time.hoursAgo","h ago")}`}function Ge(e){return e?Date.now()-e<3e4?"active":"stale":"unknown"}function Re(e,s){const n=e.studioState??"unknown",l={edit:s("connection.targets.studioState.edit","Edit"),running:s("connection.targets.studioState.running","Running"),paused:s("connection.targets.studioState.paused","Paused"),unknown:s("connection.targets.studioState.unknown","Unknown")},c=e.studioStateSource==="thread"?s("connection.targets.studioState.source.thread","WEPPY play command"):e.studioStateSource==="pluginConnection"?s("connection.targets.studioState.source.pluginConnection","Studio Play/Test connection"):e.studioStateSource==="runService"?s("connection.targets.studioState.source.runService","Studio RunService"):s("connection.targets.studioState.source.unknown","Unknown source"),y=e.studioStateUpdatedAt?M(e.studioStateUpdatedAt,s):s("connection.targets.studioState.updatedUnknown","not reported"),p=e.playtestMode&&e.playtestMode!=="unknown"?` · ${e.playtestMode}`:"";return{state:n,label:`${l[n]}${p}`,tooltip:`${c} · ${y}`}}function st(){const{t:e}=to(),{trackEvent:s}=ro(),{status:n,connectionInfo:l,studioRouting:c,connectionLog:y,level:p,clearConnectionLog:i,killAgent:k}=Lo(),{show:C}=po(),[z,m]=d.useState(!0),[A,I]=d.useState(!1),[B,E]=d.useState(!1),[N,g]=d.useState(null),[j,w]=d.useState(!1),S=ho(n==null?void 0:n.uptime),h=p==="disconnected",F=h?"offline":"online",f=(c==null?void 0:c.studioRoutingMode)??(n==null?void 0:n.studioRoutingMode)??"recentPriority",T=(c==null?void 0:c.pinnedTargetClientId)??(n==null?void 0:n.pinnedTargetClientId)??null,v=go((c==null?void 0:c.targets)??(n==null?void 0:n.pluginClients)??[],f,T),$=(c==null?void 0:c.priorityTarget)??v[0],R=async()=>{if(N){w(!0);try{await k(N.instanceId),C(e("connection.agents.killed","Agent killed"),"success"),g(null)}catch{C(e("connection.agents.killFailed","Failed to kill agent"),"error")}finally{w(!1)}}},K=async()=>{E(!0);try{await i(),C(e("toast.clearSuccess","Cleared successfully"),"success"),I(!1)}catch{C(e("toast.clearFailed","Failed to clear data"),"error")}finally{E(!1)}},H=async(r,L)=>{try{await navigator.clipboard.writeText(r),C(e("connection.targets.copied","Copied value"),"success"),s("dashboard_click_event",{click_target:`connection_copy_${L}`,page:"connection"})}catch{C(e("connection.targets.copyFailed","Failed to copy value"),"error")}};return o.jsxs("div",{className:t.page,children:[o.jsx(uo,{title:e("page.connection.title","Connection"),description:e("page.connection.description","Inspect WEPPY Bridge, MCP Adapter, Studio Plugin, and connection log status."),helpTopicId:"connection",helpState:{connectionLevel:p}}),o.jsx(Ve,{agents:(l==null?void 0:l.mcpInstances)??[],isDisconnected:h,pinnedTargetClientId:T,priorityTarget:$,status:n??null,studioRoutingMode:f,studioTargets:v,t:e,timeAgo:r=>M(r,e),onCopySelector:H,onManageRouting:()=>s("dashboard_click_event",{click_target:"connection_manage_routing",page:"connection"})}),o.jsxs("div",{className:t.card,children:[o.jsx("div",{className:t.cardHeader,children:e("connection.server.title","Bridge Status")}),h?o.jsxs("div",{className:t.disconnected,children:[o.jsx("h3",{children:e("level.l0.title")}),o.jsx("p",{children:e("level.l0.message")}),o.jsx("p",{children:e("common.reconnecting")}),o.jsxs("div",{className:t.disconnectedActions,children:[o.jsx("button",{className:t.btn,onClick:()=>window.location.reload(),children:e("connection.reconnect","Reconnect")}),o.jsx("button",{className:t.btn,onClick:()=>{window.location.hash="#/settings"},children:e("connection.checkSettings","Check Settings")})]})]}):o.jsxs(o.Fragment,{children:[o.jsx("div",{className:t.statusRow,children:o.jsx(no,{status:F})}),o.jsxs("dl",{className:t.serverGrid,children:[(n==null?void 0:n.version)&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.version","Version"),tooltip:e("connection.server.version.tooltip","WEPPY Bridge runtime version")})}),o.jsx("dd",{children:o.jsx(X,{text:e("connection.server.version.tooltip","WEPPY Bridge runtime version"),children:`v${n.version}`})})]}),(n==null?void 0:n.pid)!=null&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.pid","PID"),tooltip:e("connection.server.pid.tooltip","Operating system process identifier")})}),o.jsx("dd",{children:n.pid})]}),(n==null?void 0:n.uptime)!=null&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.uptime","Uptime"),tooltip:e("connection.server.uptime.tooltip","Time elapsed since the WEPPY Bridge started")})}),o.jsx("dd",{children:so(S??n.uptime)})]}),(n==null?void 0:n.sessionId)&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.session","Session"),tooltip:e("connection.server.session.tooltip","Current WEPPY Bridge session identifier")})}),o.jsx("dd",{children:n.sessionId.slice(0,8)})]}),(l==null?void 0:l.serverExecutable)&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.exec","Exec"),tooltip:e("connection.server.exec.tooltip","Executable path used to launch the WEPPY Bridge")})}),o.jsx("dd",{children:l.serverExecutable})]})]})]})]}),o.jsxs("div",{className:`${t.card} ${h?t.disabled:""}`,children:[o.jsxs("div",{className:t.cardHeader,children:[o.jsxs("span",{children:[e("connection.agents.title","AI Agents")," ","(",(l==null?void 0:l.mcpInstanceCount)??0,")"]}),o.jsx("button",{className:t.toggleBtn,onClick:()=>m(r=>!r),"aria-label":z?e("common.collapse","Collapse"):e("common.expand","Expand"),children:z?"▾":"▸"})]}),z&&o.jsxs("table",{className:t.table,children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:e("connection.agents.name","Agent")}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.version","Version"),tooltip:e("connection.agents.version.tooltip","MCP Adapter package version for this agent session")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.server.pid","PID"),tooltip:e("connection.server.pid.tooltip","Operating system process identifier")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.projectRoot","Project Root"),tooltip:e("connection.agents.projectRoot.tooltip","Authoritative project root for sync ownership")})}),o.jsx("th",{children:e("connection.agents.connected","Connected")}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.lastSeen","Last Seen"),tooltip:e("connection.agents.lastSeen.tooltip","Most recent heartbeat or activity from this agent")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.lastCommand","Last Command"),tooltip:e("connection.agents.lastCommand.tooltip","Most recent tool call executed by this agent")})}),o.jsx("th",{})]})}),o.jsx("tbody",{children:l!=null&&l.mcpInstances&&l.mcpInstances.length>0?l.mcpInstances.map(r=>o.jsxs("tr",{children:[o.jsxs("td",{children:[o.jsx("span",{className:t[`activity_${Ge(r.lastSeen)}`]}),r.aiClientName??e("connection.agents.unknown","Unknown")]}),o.jsx("td",{children:r.mcpVersion??"-"}),o.jsx("td",{children:r.pid}),o.jsx("td",{children:r.projectRoot??r.cwd??e("connection.agents.projectRoot.unresolved","Unresolved")}),o.jsx("td",{children:M(r.connectedAt,e)}),o.jsx("td",{children:r.lastSeen?M(r.lastSeen,e):"-"}),o.jsx("td",{children:r.lastCommandAt?M(r.lastCommandAt,e):"-"}),o.jsx("td",{children:!r.isServer&&o.jsx("button",{className:t.killBtn,onClick:()=>{s("dashboard_click_event",{click_target:"connection_kill_agent",page:"connection"}),g({instanceId:r.instanceId,name:r.aiClientName??r.instanceId.slice(0,8)})},children:e("connection.agents.kill","Kill")})})]},r.instanceId)):o.jsx("tr",{children:o.jsx("td",{colSpan:8,className:t.emptyRow,children:e("connection.agents.none","No agents connected")})})})]})]}),o.jsxs("div",{className:`${t.card} ${h?t.disabled:""}`,children:[o.jsxs("div",{className:t.cardHeader,children:[e("connection.targets.title","Studio Targets")," ","(",v.length,")"]}),o.jsx("p",{className:t.cardHint,children:e("connection.targets.help","When multiple Studio windows are connected, tell the agent to use Studio ID studio-1 to choose one.")}),o.jsx("div",{className:t.tableWrap,children:o.jsxs("table",{className:t.table,children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.target","Studio ID"),tooltip:e("connection.targets.target.tooltip","Short name for this Roblox Studio window")})}),o.jsx("th",{children:e("connection.targets.place","Place")}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.placeId","Place ID"),tooltip:e("connection.targets.placeId.tooltip","Roblox Place ID for this Studio window")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.clientId","Connection ID"),tooltip:e("connection.targets.clientId.tooltip","Full connection ID for diagnostics. Usually use Studio ID instead.")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.studioState","Studio State"),tooltip:e("connection.targets.studioState.tooltip","Current edit/play runtime state reported by this Studio window")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.session","Session"),tooltip:e("connection.targets.session.tooltip","Command channel state for this Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.lastUsed","Last Used"),tooltip:e("connection.targets.lastUsed.tooltip","Most recent plugin-route request routed to this Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.lastSeen","Last Seen"),tooltip:e("connection.targets.lastSeen.tooltip","Most recent heartbeat received from this Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.version","Version"),tooltip:e("connection.targets.version.tooltip","Installed plugin version reported by Studio")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.routing","Routing"),tooltip:e("connection.targets.routing.tooltip","Routing priority for requests without a named Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.inFlight","In Flight"),tooltip:e("connection.targets.inFlight.tooltip","Active command request currently routed to this Studio target")})})]})}),o.jsx("tbody",{children:v.length>0?v.map(r=>{const L=r.clientId.slice(0,10),a=Re(r,e);return o.jsxs("tr",{children:[o.jsxs("td",{children:[o.jsx("span",{className:t.monoMuted,title:r.clientId,children:r.targetAlias}),o.jsx(Y,{text:e("connection.targets.copyTargetAlias","Copy Studio ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":e("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>H(r.targetAlias,"target_alias"),children:o.jsx(G,{size:13,"aria-hidden":"true"})})})]}),o.jsx("td",{children:o.jsx("span",{className:t.targetPrimary,children:r.placeName??"-"})}),o.jsxs("td",{children:[r.placeId??"-",r.placeId!==void 0?o.jsx(Y,{text:e("connection.targets.copyPlaceId","Copy Place ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":e("connection.targets.copyPlaceId","Copy Place ID"),onClick:()=>H(String(r.placeId),"place_id"),children:o.jsx(G,{size:13,"aria-hidden":"true"})})}):null]}),o.jsxs("td",{children:[o.jsx("span",{className:t.monoMuted,title:r.clientId,children:L}),o.jsx(Y,{text:e("connection.targets.copyClientId","Copy Connection ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":e("connection.targets.copyClientId","Copy Connection ID"),onClick:()=>H(r.clientId,"client_id"),children:o.jsx(G,{size:13,"aria-hidden":"true"})})})]}),o.jsx("td",{children:o.jsx(X,{text:a.tooltip,children:o.jsx("span",{className:`${t.studioStateBadge} ${t[`studioState_${a.state}`]}`,children:a.label})})}),o.jsx("td",{children:r.connectionState}),o.jsx("td",{children:r.lastRoutedAt?M(r.lastRoutedAt,e):"-"}),o.jsx("td",{children:M(r.lastSeen,e)}),o.jsx("td",{children:r.pluginVersion??"-"}),o.jsx("td",{children:f==="pinned"&&T===r.clientId?o.jsx("span",{className:t.routingBadge,children:e("connection.routing.pinnedBadge","Pinned")}):f==="recentPriority"&&($==null?void 0:$.clientId)===r.clientId?o.jsx("span",{className:t.routingBadge,children:e("connection.routing.priorityBadge","Priority")}):o.jsx("span",{className:t.monoMuted,children:"-"})}),o.jsx("td",{children:r.inFlightRequestId?r.inFlightRequestId.slice(0,8):"-"})]},r.clientId)}):o.jsx("tr",{children:o.jsx("td",{colSpan:11,className:t.emptyRow,children:e("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")})})})]})})]}),o.jsxs("div",{className:`${t.card} ${h?t.disabled:""}`,children:[o.jsxs("div",{className:t.cardHeader,children:[o.jsx("span",{children:e("connection.log.title","Connection Log")}),o.jsx("button",{className:t.clearButton,onClick:()=>{s("dashboard_click_event",{click_target:"connection_clear_log",page:"connection"}),I(!0)},children:e("common.clear","Clear")})]}),o.jsx(ko,{entries:y})]}),o.jsx(J,{open:A,title:e("connection.clear.title","Clear connection log?"),message:e("connection.clear.message","This permanently removes the stored connection log for the current project."),cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("common.clear","Clear"),loading:B,onCancel:()=>!B&&I(!1),onConfirm:K}),o.jsx(J,{open:!!N,title:e("connection.agents.kill.title","Kill agent?"),message:`"${N==null?void 0:N.name}" 프로세스를 강제 종료합니다. 해당 에이전트의 진행 중인 작업이 중단됩니다.`,cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("connection.agents.kill","Kill"),loading:j,onCancel:()=>!j&&g(null),onConfirm:R})]})}export{st as Component};
|
|
6
|
+
*/const mo=[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]],xo=so("server",mo),_o="_container_1h084_2",So="_entry_1h084_14",jo="_timestamp_1h084_21",vo="_message_1h084_27",fo="_warn_1h084_34",bo="_error_1h084_39",Co="_empty_1h084_44",O={container:_o,entry:So,timestamp:jo,message:vo,warn:fo,error:bo,empty:Co};function No(e){const s=new Date(e);return Number.isNaN(s.getTime())?e:`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}`}function wo({entries:e}){const{t:s}=eo(),n=d.useRef(null);return d.useEffect(()=>{const l=n.current;l&&(l.scrollTop=l.scrollHeight)},[e.length]),o.jsx("div",{ref:n,className:O.container,children:e.length===0?o.jsx("div",{className:O.empty,children:s("connection.log.empty","No events yet")}):e.map((l,c)=>o.jsxs("div",{className:`${O.entry} ${l.type?O[l.type]:""}`,children:[o.jsx("span",{className:O.timestamp,children:No(l.timestamp)}),o.jsx("span",{className:O.message,children:l.message})]},c))})}const Q=50;function ko(){const e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function Io(){const{level:e,status:s,error:n}=co(),[l,c]=d.useState(null),[y,p]=d.useState(null),[i,k]=d.useState([]),C=d.useRef(null),z=d.useCallback((g,j)=>{k(w=>{const S=[...w,{timestamp:ko(),message:g,type:j}];return S.length>Q?S.slice(-Q):S})},[]),m=d.useCallback(async()=>{try{const g=await U.get("/connection-info");c(g)}catch{c(null)}},[]),A=d.useCallback(async()=>{try{const g=await U.get("/api/dashboard/studio-routing");p(g)}catch{p(null)}},[]),I=d.useCallback(async g=>{const j=await U.patch("/api/dashboard/studio-routing",g);return p(j),await m(),j},[m]),B=d.useCallback(async()=>{try{const g=await U.get("/api/dashboard/connection-log");k(g.entries??[])}catch{k([])}},[]),E=d.useCallback(async()=>{await U.post("/api/dashboard/connection-log/clear"),k([])},[]),N=d.useCallback(async g=>{await U.post("/api/dashboard/kill-agent",{instanceId:g}),await m()},[m]);return d.useEffect(()=>{e!=="disconnected"&&s?(m(),A()):p(null),B()},[e,s,m,B,A]),d.useEffect(()=>{const g=new io;C.current=g,g.connect();const j=g.on("connection",S=>{const h=S;h.status!=="updated"&&h.clientId&&z(`Plugin ${h.status} — ${h.clientId}`,h.status==="disconnected"?"warn":"info"),m(),A()}),w=g.on("mcp_status",S=>{const h=S,F=h.status==="registered"?"registered":"unregistered";z(`MCP ${F} — ${h.aiClientName}`,h.status==="registered"?"info":"warn"),m(),A()});return()=>{j(),w(),g.disconnect(),C.current=null}},[z,m,A]),{status:s,connectionInfo:l,studioRouting:y,connectionLog:i,level:e,error:n,clearConnectionLog:E,killAgent:N,updateStudioRouting:I}}const Lo="_page_cozq1_2",zo="_card_cozq1_11",Ao="_topologyCard_cozq1_19",Po="_topologyDisconnected_cozq1_26",qo="_topologyHeader_cozq1_30",Bo="_topologyIntro_cozq1_38",$o="_topologyNetwork_cozq1_45",Mo="_topologyLinks_cozq1_49",Eo="_topologyLink_cozq1_49",To="_topologyLink_agent_cozq1_66",Do="_topologyLink_studio_cozq1_70",Ho="_topologyGrid_cozq1_74",Uo="_topologyColumn_cozq1_83",Oo="_topologyColumnHeader_cozq1_90",Fo="_topologyColumnHeaderSpacer_cozq1_101",Wo="_topologyCount_cozq1_105",Yo="_topologyList_cozq1_120",Go="_topologyListCentered_cozq1_128",Vo="_topologyNode_cozq1_132",Ro="_topologyNodeTitle_cozq1_140",Ko="_topologyNodeMeta_cozq1_156",Xo="_topologyNodeSubtle_cozq1_157",Jo="_topologyState_cozq1_170",Qo="_topologyEmpty_cozq1_183",Zo="_topologyOverflow_cozq1_198",oe="_topologyOverflowButton_cozq1_213",ee="_topologyServerColumn_cozq1_236",te="_topologyServer_cozq1_236",ne="_topologyServerIcon_cozq1_254",se="_topologyServerBody_cozq1_267",ce="_topologyServerTitle_cozq1_276",ie="_topologyServerMeta_cozq1_283",le="_routingSummaryCompact_cozq1_290",ae="_disabled_cozq1_298",re="_cardHeader_cozq1_304",de="_cardHint_cozq1_317",pe="_clearButton_cozq1_324",ge="_serverGrid_cozq1_348",ue="_statusRow_cozq1_366",he="_metaItem_cozq1_373",ye="_table_cozq1_380",me="_tableWrap_cozq1_400",xe="_routingSummary_cozq1_290",_e="_manageLink_cozq1_416",Se="_segment_cozq1_442",je="_segmentActive_cozq1_443",ve="_targetPrimary_cozq1_477",fe="_monoMuted_cozq1_481",be="_copyIconButton_cozq1_485",Ce="_routingBadge_cozq1_510",Ne="_studioStateBadge_cozq1_524",we="_studioState_running_cozq1_539",ke="_studioState_paused_cozq1_545",Ie="_studioState_edit_cozq1_551",Le="_studioState_unknown_cozq1_557",ze="_toggleBtn_cozq1_564",Ae="_disconnected_cozq1_579",Pe="_disconnectedActions_cozq1_596",qe="_btn_cozq1_603",Be="_activity_active_cozq1_621",$e="_activity_stale_cozq1_622",Me="_activity_unknown_cozq1_623",Ee="_killBtn_cozq1_647",Te="_emptyRow_cozq1_671",t={page:Lo,card:zo,topologyCard:Ao,topologyDisconnected:Po,topologyHeader:qo,topologyIntro:Bo,topologyNetwork:$o,topologyLinks:Mo,topologyLink:Eo,topologyLink_agent:To,topologyLink_studio:Do,topologyGrid:Ho,topologyColumn:Uo,topologyColumnHeader:Oo,topologyColumnHeaderSpacer:Fo,topologyCount:Wo,topologyList:Yo,topologyListCentered:Go,topologyNode:Vo,topologyNodeTitle:Ro,topologyNodeMeta:Ko,topologyNodeSubtle:Xo,topologyState:Jo,topologyEmpty:Qo,topologyOverflow:Zo,topologyOverflowButton:oe,topologyServerColumn:ee,topologyServer:te,topologyServerIcon:ne,topologyServerBody:se,topologyServerTitle:ce,topologyServerMeta:ie,routingSummaryCompact:le,disabled:ae,cardHeader:re,cardHint:de,clearButton:pe,serverGrid:ge,statusRow:ue,metaItem:he,table:ye,tableWrap:me,routingSummary:xe,manageLink:_e,segment:Se,segmentActive:je,targetPrimary:ve,monoMuted:fe,copyIconButton:be,routingBadge:Ce,studioStateBadge:Ne,studioState_running:we,studioState_paused:ke,studioState_edit:Ie,studioState_unknown:Le,toggleBtn:ze,disconnected:Ae,disconnectedActions:Pe,btn:qe,activity_active:Be,activity_stale:$e,activity_unknown:Me,killBtn:Ee,emptyRow:Te},G=5;function De(e){return e?Date.now()-e<3e4?"active":"stale":"unknown"}function He(e,s){return e==="active"?s("connection.topology.active","Active"):e==="stale"?s("connection.topology.stale","Stale"):s("connection.topology.unknown","Unknown")}function Z(e){return e.length>10?e.slice(0,10):e}function oo(e,s){return e.replace("{count}",String(s))}function Ue(e,s,n){const l=e.studioState??"unknown",c={edit:s("connection.targets.studioState.edit","Edit"),running:s("connection.targets.studioState.running","Running"),paused:s("connection.targets.studioState.paused","Paused"),unknown:s("connection.targets.studioState.unknown","Unknown")},y=e.studioStateSource==="thread"?s("connection.targets.studioState.source.thread","WEPPY play command"):e.studioStateSource==="pluginConnection"?s("connection.targets.studioState.source.pluginConnection","Studio Play/Test connection"):e.studioStateSource==="runService"?s("connection.targets.studioState.source.runService","Studio RunService"):s("connection.targets.studioState.source.unknown","Unknown source"),p=e.studioStateUpdatedAt?n(e.studioStateUpdatedAt):s("connection.targets.studioState.updatedUnknown","not reported");return{state:l,label:c[l],tooltip:`${y} · ${p}`}}function Oe(e,s){return e.length!==s.length?!1:e.every((n,l)=>{const c=s[l];return c!==void 0&&n.id===c.id&&n.side===c.side&&Math.abs(n.x1-c.x1)<.5&&Math.abs(n.y1-c.y1)<.5&&Math.abs(n.x2-c.x2)<.5&&Math.abs(n.y2-c.y2)<.5})}function b(e,s,n){return{x:s-e.left,y:n-e.top}}function Fe(e,s,n,l){if(s.right<=n.left){const p=b(l,s.right,s.top+s.height/2),i=b(l,n.left,n.top+n.height/2);return{id:e,side:"agent",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}if(s.bottom<=n.top){const p=b(l,s.left+s.width/2,s.bottom),i=b(l,n.left+n.width/2,n.top);return{id:e,side:"agent",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}const c=b(l,s.left+s.width/2,s.top),y=b(l,n.left+n.width/2,n.bottom);return{id:e,side:"agent",x1:c.x,y1:c.y,x2:y.x,y2:y.y}}function We(e,s,n,l){if(n.right<=s.left){const p=b(l,s.left,s.top+s.height/2),i=b(l,n.right,n.top+n.height/2);return{id:e,side:"studio",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}if(n.bottom<=s.top){const p=b(l,s.left+s.width/2,s.top),i=b(l,n.left+n.width/2,n.bottom);return{id:e,side:"studio",x1:p.x,y1:p.y,x2:i.x,y2:i.y}}const c=b(l,s.left+s.width/2,s.bottom),y=b(l,n.left+n.width/2,n.top);return{id:e,side:"studio",x1:c.x,y1:c.y,x2:y.x,y2:y.y}}function Ye({agents:e,isDisconnected:s,pinnedTargetClientId:n,priorityTarget:l,status:c,studioRoutingMode:y,studioTargets:p,t:i,timeAgo:k,onCopySelector:C,onManageRouting:z}){const[m,A]=d.useState(!1),[I,B]=d.useState(!1),[E,N]=d.useState([]),g=d.useRef(null),j=d.useRef(null),w=d.useRef(new Map),S=d.useRef(new Map),h=y==="pinned"?i("connection.routing.pinned","Manual: Pinned Studio"):i("connection.routing.recentPriority","Automatic: Recent priority"),F=s?"offline":"online",f=d.useMemo(()=>m?e:e.slice(0,G),[e,m]),T=Math.max(0,e.length-f.length),v=d.useMemo(()=>I?p:p.slice(0,G),[p,I]),$=Math.max(0,p.length-v.length),R=[t.topologyList,f.length<=1?t.topologyListCentered:""].filter(Boolean).join(" "),K=[t.topologyList,v.length<=1?t.topologyListCentered:""].filter(Boolean).join(" "),D=d.useCallback(a=>x=>{if(x){w.current.set(a,x);return}w.current.delete(a)},[]),r=d.useCallback(a=>x=>{if(x){S.current.set(a,x);return}S.current.delete(a)},[]),L=d.useCallback(()=>{const a=g.current,x=j.current;if(!a||!x){N([]);return}const _=a.getBoundingClientRect(),P=x.getBoundingClientRect(),H=[];f.forEach(q=>{const W=w.current.get(q.instanceId);W&&H.push(Fe(`agent-${q.instanceId}`,W.getBoundingClientRect(),P,_))}),v.forEach(q=>{const W=S.current.get(q.clientId);W&&H.push(We(`studio-${q.clientId}`,W.getBoundingClientRect(),P,_))}),N(q=>Oe(q,H)?q:H)},[f,v]);return d.useLayoutEffect(()=>{L();const a=[g.current,j.current,...f.map(_=>w.current.get(_.instanceId)),...v.map(_=>S.current.get(_.clientId))].filter(_=>_!=null);if(window.addEventListener("resize",L),typeof ResizeObserver>"u")return()=>{window.removeEventListener("resize",L)};const x=new ResizeObserver(L);return a.forEach(_=>x.observe(_)),()=>{window.removeEventListener("resize",L),x.disconnect()}},[L,f,v]),o.jsxs("section",{className:`${t.topologyCard} ${s?t.topologyDisconnected:""}`,"aria-label":i("connection.topology.ariaLabel","Connection topology"),children:[o.jsxs("div",{className:t.topologyHeader,children:[o.jsxs("div",{children:[o.jsx("div",{className:t.cardHeader,children:i("connection.topology.title","Connection topology")}),o.jsx("p",{className:t.topologyIntro,children:i("connection.topology.description","Each AI agent connects through its own MCP Adapter to one shared WEPPY Bridge, which keeps Roblox Studio connected.")})]}),o.jsx(lo,{to:"/controls?section=studio-routing",className:t.manageLink,onClick:z,children:i("connection.routing.manage","Manage routing")})]}),o.jsxs("div",{className:t.topologyNetwork,ref:g,children:[o.jsx("svg",{"aria-hidden":"true",className:t.topologyLinks,"data-testid":"topology-connection-lines",focusable:"false",children:E.map(a=>o.jsx("line",{className:`${t.topologyLink} ${t[`topologyLink_${a.side}`]}`,"data-side":a.side,vectorEffect:"non-scaling-stroke",x1:a.x1,x2:a.x2,y1:a.y1,y2:a.y2},a.id))}),o.jsxs("div",{className:t.topologyGrid,children:[o.jsxs("div",{className:t.topologyColumn,children:[o.jsxs("div",{className:t.topologyColumnHeader,children:[o.jsx(yo,{size:15,"aria-hidden":"true"}),o.jsx("span",{children:i("connection.agents.title","AI Agents")}),o.jsx("span",{className:t.topologyCount,children:e.length})]}),o.jsxs("div",{className:R,children:[e.length>0?f.map(a=>{const x=De(a.lastSeen),_=a.aiClientName??Z(a.instanceId),P=a.lastSeen??a.lastCommandAt??a.connectedAt,H=a.mcpVersion?`${i("connection.topology.adapterRole","MCP Adapter")} v${a.mcpVersion}`:i("connection.topology.adapterRole","MCP Adapter");return o.jsxs("div",{className:t.topologyNode,ref:D(a.instanceId),children:[o.jsxs("div",{className:t.topologyNodeTitle,children:[o.jsx("span",{className:t[`activity_${x}`]}),o.jsx("strong",{children:_}),o.jsx("span",{className:t.topologyState,children:He(x,i)})]}),o.jsxs("div",{className:t.topologyNodeMeta,children:[o.jsx("span",{children:H})," ·"," ",i("connection.server.session","Session")," ",Z(a.instanceId)," ·"," ",P?`${i("connection.topology.lastActivity","Last activity")} ${k(P)}`:i("connection.topology.noActivity","No recent activity")]})]},a.instanceId)}):o.jsx("div",{className:t.topologyEmpty,children:i("connection.agents.none","No agents connected")}),e.length>G?o.jsxs("div",{className:t.topologyOverflow,children:[T>0?o.jsx("span",{children:oo(i("connection.topology.moreAgents","+{count} more agents"),T)}):o.jsx("span",{children:i("connection.topology.allAgentsVisible","All agents visible")}),o.jsx("button",{type:"button",className:t.topologyOverflowButton,"aria-label":m?i("connection.topology.showLessAgents","Show less AI agents"):i("connection.topology.showAllAgents","Show all AI agents"),onClick:()=>A(a=>!a),children:m?i("connection.topology.showLess","Show less"):i("connection.topology.showAll","Show all")})]}):null]})]}),o.jsxs("div",{className:t.topologyServerColumn,children:[o.jsx("div",{className:t.topologyColumnHeaderSpacer,"aria-hidden":"true"}),o.jsxs("div",{className:`${t.topologyNode} ${t.topologyServer}`,ref:j,children:[o.jsx("div",{className:t.topologyServerIcon,children:o.jsx(xo,{size:18,"aria-hidden":"true"})}),o.jsxs("div",{className:t.topologyServerBody,children:[o.jsx("div",{className:t.topologyServerTitle,children:i("connection.topology.serverTitle","WEPPY Bridge")}),o.jsx(to,{status:F}),o.jsxs("div",{className:t.topologyServerMeta,children:[c!=null&&c.version?`v${c.version}`:i("connection.topology.versionUnknown","Version unknown"),c!=null&&c.sessionId?` · ${i("connection.server.session","Session")} ${c.sessionId.slice(0,8)}`:""]}),(c==null?void 0:c.pid)!=null||(c==null?void 0:c.uptime)!=null?o.jsxs("div",{className:t.topologyNodeSubtle,children:[(c==null?void 0:c.pid)!=null?o.jsx("span",{children:`${i("connection.server.pid","PID")} ${c.pid}`}):null,(c==null?void 0:c.pid)!=null&&(c==null?void 0:c.uptime)!=null?" · ":"",(c==null?void 0:c.uptime)!=null?o.jsx("span",{children:`${i("connection.server.uptime","Uptime")} ${no(c.uptime)}`}):null]}):null,o.jsx("div",{className:t.routingSummaryCompact,children:o.jsx("span",{className:t.routingBadge,children:h})})]})]})]}),o.jsxs("div",{className:t.topologyColumn,children:[o.jsxs("div",{className:t.topologyColumnHeader,children:[o.jsx(ao,{size:15,"aria-hidden":"true"}),o.jsx("span",{children:i("connection.targets.title","Studio Targets")}),o.jsx("span",{className:t.topologyCount,children:p.length})]}),o.jsxs("div",{className:K,children:[p.length>0?v.map(a=>{const x=y==="pinned"&&n===a.clientId,_=y==="recentPriority"&&(l==null?void 0:l.clientId)===a.clientId,P=Ue(a,i,k);return o.jsxs("div",{className:t.topologyNode,ref:r(a.clientId),children:[o.jsxs("div",{className:t.topologyNodeTitle,children:[o.jsx("span",{className:t.targetPrimary,children:a.targetAlias}),o.jsx(Y,{text:i("connection.targets.copyTargetAlias","Copy Studio ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":i("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>C(a.targetAlias,"target_alias"),children:o.jsx(V,{size:13,"aria-hidden":"true"})})}),x?o.jsx("span",{className:t.routingBadge,children:i("connection.routing.pinnedBadge","Pinned")}):_?o.jsx("span",{className:t.routingBadge,children:i("connection.routing.priorityBadge","Priority")}):null,o.jsx(Y,{text:P.tooltip,children:o.jsx("span",{className:`${t.studioStateBadge} ${t[`studioState_${P.state}`]}`,children:P.label})})]}),o.jsxs("div",{className:t.topologyNodeMeta,children:[o.jsx("span",{children:a.placeName??i("connection.topology.placeUnknown","Place unknown")}),a.placeId!==void 0?` · ${a.placeId}`:""]}),o.jsxs("div",{className:t.topologyNodeSubtle,children:[a.connectionState," · ",i("connection.targets.lastSeen","Last Seen")," ",k(a.lastSeen)]})]},a.clientId)}):o.jsx("div",{className:t.topologyEmpty,children:i("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")}),p.length>G?o.jsxs("div",{className:t.topologyOverflow,children:[$>0?o.jsx("span",{children:oo(i("connection.topology.moreStudios","+{count} more studios"),$)}):o.jsx("span",{children:i("connection.topology.allStudiosVisible","All studios visible")}),o.jsx("button",{type:"button",className:t.topologyOverflowButton,"aria-label":I?i("connection.topology.showLessStudios","Show less Studio targets"):i("connection.topology.showAllStudios","Show all Studio targets"),onClick:()=>B(a=>!a),children:I?i("connection.topology.showLess","Show less"):i("connection.topology.showAll","Show all")})]}):null]})]})]})]})]})}function M(e,s){const n=Math.max(0,Math.floor((Date.now()-e)/1e3));return n<60?`${n}${s("connection.time.secondsAgo","s ago")}`:n<3600?`${Math.floor(n/60)}${s("connection.time.minutesAgo","m ago")}`:`${Math.floor(n/3600)}${s("connection.time.hoursAgo","h ago")}`}function Ge(e){return e?Date.now()-e<3e4?"active":"stale":"unknown"}function Ve(e,s){const n=e.studioState??"unknown",l={edit:s("connection.targets.studioState.edit","Edit"),running:s("connection.targets.studioState.running","Running"),paused:s("connection.targets.studioState.paused","Paused"),unknown:s("connection.targets.studioState.unknown","Unknown")},c=e.studioStateSource==="thread"?s("connection.targets.studioState.source.thread","WEPPY play command"):e.studioStateSource==="pluginConnection"?s("connection.targets.studioState.source.pluginConnection","Studio Play/Test connection"):e.studioStateSource==="runService"?s("connection.targets.studioState.source.runService","Studio RunService"):s("connection.targets.studioState.source.unknown","Unknown source"),y=e.studioStateUpdatedAt?M(e.studioStateUpdatedAt,s):s("connection.targets.studioState.updatedUnknown","not reported"),p=e.playtestMode&&e.playtestMode!=="unknown"?` · ${e.playtestMode}`:"";return{state:n,label:`${l[n]}${p}`,tooltip:`${c} · ${y}`}}function st(){const{t:e}=eo(),{trackEvent:s}=ro(),{status:n,connectionInfo:l,studioRouting:c,connectionLog:y,level:p,clearConnectionLog:i,killAgent:k}=Io(),{show:C}=po(),[z,m]=d.useState(!0),[A,I]=d.useState(!1),[B,E]=d.useState(!1),[N,g]=d.useState(null),[j,w]=d.useState(!1),S=ho(n==null?void 0:n.uptime),h=p==="disconnected",F=h?"offline":"online",f=(c==null?void 0:c.studioRoutingMode)??(n==null?void 0:n.studioRoutingMode)??"recentPriority",T=(c==null?void 0:c.pinnedTargetClientId)??(n==null?void 0:n.pinnedTargetClientId)??null,v=go((c==null?void 0:c.targets)??(n==null?void 0:n.pluginClients)??[],f,T),$=(c==null?void 0:c.priorityTarget)??v[0],R=async()=>{if(N){w(!0);try{await k(N.instanceId),C(e("connection.agents.killed","Agent killed"),"success"),g(null)}catch{C(e("connection.agents.killFailed","Failed to kill agent"),"error")}finally{w(!1)}}},K=async()=>{E(!0);try{await i(),C(e("toast.clearSuccess","Cleared successfully"),"success"),I(!1)}catch{C(e("toast.clearFailed","Failed to clear data"),"error")}finally{E(!1)}},D=async(r,L)=>{try{await navigator.clipboard.writeText(r),C(e("connection.targets.copied","Copied value"),"success"),s("dashboard_click_event",{click_target:`connection_copy_${L}`,page:"connection"})}catch{C(e("connection.targets.copyFailed","Failed to copy value"),"error")}};return o.jsxs("div",{className:t.page,children:[o.jsx(uo,{title:e("page.connection.title","Connection"),description:e("page.connection.description","Inspect WEPPY Bridge, MCP Adapter, Studio Plugin, and connection log status."),helpTopicId:"connection",helpState:{connectionLevel:p}}),o.jsx(Ye,{agents:(l==null?void 0:l.mcpInstances)??[],isDisconnected:h,pinnedTargetClientId:T,priorityTarget:$,status:n??null,studioRoutingMode:f,studioTargets:v,t:e,timeAgo:r=>M(r,e),onCopySelector:D,onManageRouting:()=>s("dashboard_click_event",{click_target:"connection_manage_routing",page:"connection"})}),o.jsxs("div",{className:t.card,children:[o.jsx("div",{className:t.cardHeader,children:e("connection.server.title","Bridge Status")}),h?o.jsxs("div",{className:t.disconnected,children:[o.jsx("h3",{children:e("level.l0.title")}),o.jsx("p",{children:e("level.l0.message")}),o.jsx("p",{children:e("common.reconnecting")}),o.jsxs("div",{className:t.disconnectedActions,children:[o.jsx("button",{className:t.btn,onClick:()=>window.location.reload(),children:e("connection.reconnect","Reconnect")}),o.jsx("button",{className:t.btn,onClick:()=>{window.location.hash="#/settings"},children:e("connection.checkSettings","Check Settings")})]})]}):o.jsxs(o.Fragment,{children:[o.jsx("div",{className:t.statusRow,children:o.jsx(to,{status:F})}),o.jsxs("dl",{className:t.serverGrid,children:[(n==null?void 0:n.version)&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.version","Version"),tooltip:e("connection.server.version.tooltip","WEPPY Bridge runtime version")})}),o.jsx("dd",{children:o.jsx(X,{text:e("connection.server.version.tooltip","WEPPY Bridge runtime version"),children:`v${n.version}`})})]}),(n==null?void 0:n.pid)!=null&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.pid","PID"),tooltip:e("connection.server.pid.tooltip","Operating system process identifier")})}),o.jsx("dd",{children:n.pid})]}),(n==null?void 0:n.uptime)!=null&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.uptime","Uptime"),tooltip:e("connection.server.uptime.tooltip","Time elapsed since the WEPPY Bridge started")})}),o.jsx("dd",{children:no(S??n.uptime)})]}),(n==null?void 0:n.sessionId)&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.session","Session"),tooltip:e("connection.server.session.tooltip","Current WEPPY Bridge session identifier")})}),o.jsx("dd",{children:n.sessionId.slice(0,8)})]}),(l==null?void 0:l.serverExecutable)&&o.jsxs(o.Fragment,{children:[o.jsx("dt",{children:o.jsx(u,{label:e("connection.server.exec","Exec"),tooltip:e("connection.server.exec.tooltip","Executable path used to launch the WEPPY Bridge")})}),o.jsx("dd",{children:l.serverExecutable})]})]})]})]}),o.jsxs("div",{className:`${t.card} ${h?t.disabled:""}`,children:[o.jsxs("div",{className:t.cardHeader,children:[o.jsxs("span",{children:[e("connection.agents.title","AI Agents")," ","(",(l==null?void 0:l.mcpInstanceCount)??0,")"]}),o.jsx("button",{className:t.toggleBtn,onClick:()=>m(r=>!r),"aria-label":z?e("common.collapse","Collapse"):e("common.expand","Expand"),children:z?"▾":"▸"})]}),z&&o.jsxs("table",{className:t.table,children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:e("connection.agents.name","Agent")}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.version","Version"),tooltip:e("connection.agents.version.tooltip","MCP Adapter package version for this agent session")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.server.pid","PID"),tooltip:e("connection.server.pid.tooltip","Operating system process identifier")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.projectRoot","Project Root"),tooltip:e("connection.agents.projectRoot.tooltip","Authoritative project root for sync ownership")})}),o.jsx("th",{children:e("connection.agents.connected","Connected")}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.lastSeen","Last Seen"),tooltip:e("connection.agents.lastSeen.tooltip","Most recent heartbeat or activity from this agent")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.agents.lastCommand","Last Command"),tooltip:e("connection.agents.lastCommand.tooltip","Most recent tool call executed by this agent")})}),o.jsx("th",{})]})}),o.jsx("tbody",{children:l!=null&&l.mcpInstances&&l.mcpInstances.length>0?l.mcpInstances.map(r=>o.jsxs("tr",{children:[o.jsxs("td",{children:[o.jsx("span",{className:t[`activity_${Ge(r.lastSeen)}`]}),r.aiClientName??e("connection.agents.unknown","Unknown")]}),o.jsx("td",{children:r.mcpVersion??"-"}),o.jsx("td",{children:r.pid}),o.jsx("td",{children:r.projectRoot??r.cwd??e("connection.agents.projectRoot.unresolved","Unresolved")}),o.jsx("td",{children:M(r.connectedAt,e)}),o.jsx("td",{children:r.lastSeen?M(r.lastSeen,e):"-"}),o.jsx("td",{children:r.lastCommandAt?M(r.lastCommandAt,e):"-"}),o.jsx("td",{children:!r.isServer&&o.jsx("button",{className:t.killBtn,onClick:()=>{s("dashboard_click_event",{click_target:"connection_kill_agent",page:"connection"}),g({instanceId:r.instanceId,name:r.aiClientName??r.instanceId.slice(0,8)})},children:e("connection.agents.kill","Kill")})})]},r.instanceId)):o.jsx("tr",{children:o.jsx("td",{colSpan:8,className:t.emptyRow,children:e("connection.agents.none","No agents connected")})})})]})]}),o.jsxs("div",{className:`${t.card} ${h?t.disabled:""}`,children:[o.jsxs("div",{className:t.cardHeader,children:[e("connection.targets.title","Studio Targets")," ","(",v.length,")"]}),o.jsx("p",{className:t.cardHint,children:e("connection.targets.help","When multiple Studio windows are connected, tell the agent to use Studio ID studio-1 to choose one.")}),o.jsx("div",{className:t.tableWrap,children:o.jsxs("table",{className:t.table,children:[o.jsx("thead",{children:o.jsxs("tr",{children:[o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.target","Studio ID"),tooltip:e("connection.targets.target.tooltip","Short name for this Roblox Studio window")})}),o.jsx("th",{children:e("connection.targets.place","Place")}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.placeId","Place ID"),tooltip:e("connection.targets.placeId.tooltip","Roblox Place ID for this Studio window")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.clientId","Connection ID"),tooltip:e("connection.targets.clientId.tooltip","Full connection ID for diagnostics. Usually use Studio ID instead.")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.studioState","Studio State"),tooltip:e("connection.targets.studioState.tooltip","Current edit/play runtime state reported by this Studio window")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.session","Session"),tooltip:e("connection.targets.session.tooltip","Command channel state for this Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.lastUsed","Last Used"),tooltip:e("connection.targets.lastUsed.tooltip","Most recent plugin-route request routed to this Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.lastSeen","Last Seen"),tooltip:e("connection.targets.lastSeen.tooltip","Most recent heartbeat received from this Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.version","Version"),tooltip:e("connection.targets.version.tooltip","Installed plugin version reported by Studio")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.routing","Routing"),tooltip:e("connection.targets.routing.tooltip","Routing priority for requests without a named Studio target")})}),o.jsx("th",{children:o.jsx(u,{label:e("connection.targets.inFlight","In Flight"),tooltip:e("connection.targets.inFlight.tooltip","Active command request currently routed to this Studio target")})})]})}),o.jsx("tbody",{children:v.length>0?v.map(r=>{const L=r.clientId.slice(0,10),a=Ve(r,e);return o.jsxs("tr",{children:[o.jsxs("td",{children:[o.jsx("span",{className:t.monoMuted,title:r.clientId,children:r.targetAlias}),o.jsx(Y,{text:e("connection.targets.copyTargetAlias","Copy Studio ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":e("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>D(r.targetAlias,"target_alias"),children:o.jsx(V,{size:13,"aria-hidden":"true"})})})]}),o.jsx("td",{children:o.jsx("span",{className:t.targetPrimary,children:r.placeName??"-"})}),o.jsxs("td",{children:[r.placeId??"-",r.placeId!==void 0?o.jsx(Y,{text:e("connection.targets.copyPlaceId","Copy Place ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":e("connection.targets.copyPlaceId","Copy Place ID"),onClick:()=>D(String(r.placeId),"place_id"),children:o.jsx(V,{size:13,"aria-hidden":"true"})})}):null]}),o.jsxs("td",{children:[o.jsx("span",{className:t.monoMuted,title:r.clientId,children:L}),o.jsx(Y,{text:e("connection.targets.copyClientId","Copy Connection ID"),children:o.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":e("connection.targets.copyClientId","Copy Connection ID"),onClick:()=>D(r.clientId,"client_id"),children:o.jsx(V,{size:13,"aria-hidden":"true"})})})]}),o.jsx("td",{children:o.jsx(X,{text:a.tooltip,children:o.jsx("span",{className:`${t.studioStateBadge} ${t[`studioState_${a.state}`]}`,children:a.label})})}),o.jsx("td",{children:r.connectionState}),o.jsx("td",{children:r.lastRoutedAt?M(r.lastRoutedAt,e):"-"}),o.jsx("td",{children:M(r.lastSeen,e)}),o.jsx("td",{children:r.pluginVersion??"-"}),o.jsx("td",{children:f==="pinned"&&T===r.clientId?o.jsx("span",{className:t.routingBadge,children:e("connection.routing.pinnedBadge","Pinned")}):f==="recentPriority"&&($==null?void 0:$.clientId)===r.clientId?o.jsx("span",{className:t.routingBadge,children:e("connection.routing.priorityBadge","Priority")}):o.jsx("span",{className:t.monoMuted,children:"-"})}),o.jsx("td",{children:r.inFlightRequestId?r.inFlightRequestId.slice(0,8):"-"})]},r.clientId)}):o.jsx("tr",{children:o.jsx("td",{colSpan:11,className:t.emptyRow,children:e("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")})})})]})})]}),o.jsxs("div",{className:`${t.card} ${h?t.disabled:""}`,children:[o.jsxs("div",{className:t.cardHeader,children:[o.jsx("span",{children:e("connection.log.title","Connection Log")}),o.jsx("button",{className:t.clearButton,onClick:()=>{s("dashboard_click_event",{click_target:"connection_clear_log",page:"connection"}),I(!0)},children:e("common.clear","Clear")})]}),o.jsx(wo,{entries:y})]}),o.jsx(J,{open:A,title:e("connection.clear.title","Clear connection log?"),message:e("connection.clear.message","This permanently removes the stored connection log for the current project."),cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("common.clear","Clear"),loading:B,onCancel:()=>!B&&I(!1),onConfirm:K}),o.jsx(J,{open:!!N,title:e("connection.agents.kill.title","Kill agent?"),message:`"${N==null?void 0:N.name}" 프로세스를 강제 종료합니다. 해당 에이전트의 진행 중인 작업이 중단됩니다.`,cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("connection.agents.kill","Kill"),loading:j,onCancel:()=>!j&&g(null),onConfirm:R})]})}export{st as Component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as P,j as e,d as q,i as z,c as k,r as l,v as K,w as Z,x as J,b as U,s as ee,y as te,h as D,N as ne}from"./index-89-Xnii6.js";import{D as Q,P as oe}from"./PageHeader-B42Je0MJ.js";import{I as T}from"./InfoLabel-csGVLmJ3.js";import{s as j}from"./ConfirmModal.module-DJksQHBd.js";import{T as F}from"./TooltipText-EK4_jbu2.js";import{s as t,u as ae}from"./useSettings-B45j17ns.js";import{C as B}from"./check-BgcyMSc_.js";import{C as _}from"./copy-BJc7IQHD.js";function H(o,s){return e.jsxs("div",{className:j.pathBlock,children:[e.jsx("span",{className:j.pathLabel,children:o}),e.jsx("code",{className:j.pathCode,children:s})]})}function ie(o){const n=/^[A-Z]:\\/i.test(o)||o.includes("\\")?"\\":"/";return`${o.replace(/[\\/]+$/,"")}${n}weppy-project-sync`}function se({open:o,step:s,selectedProjectRoot:n,studioConnected:d,loading:p=!1,errorMessage:h=null,onClose:a,onPick:c,onApply:g}){const{t:r}=P();if(!o)return null;const y=n?ie(n):"";return e.jsx("div",{className:j.backdrop,onClick:p?void 0:a,role:"presentation",children:e.jsxs("div",{className:j.modal,onClick:x=>x.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"project-root-change-modal-title",children:[e.jsx("h2",{id:"project-root-change-modal-title",className:j.title,children:s==="initial"?r("header.projectRootModal.initial.title","Change project root"):r("header.projectRootModal.confirm.title","Confirm new project root")}),e.jsx("p",{className:j.message,children:s==="initial"?d?r("header.projectRootModal.initial.body.connected","MCP will switch to the new project root and resync current Studio contents into the new target."):r("header.projectRootModal.initial.body.disconnected","MCP will switch to the new project root and use the new folder as the next sync target."):r("header.projectRootModal.confirm.body","Review the selected project folder before applying.")}),e.jsxs("div",{className:j.bodyGrid,children:[s==="initial"?e.jsxs(e.Fragment,{children:[H(r("header.projectRootModal.initial.nextSyncRoot","New sync target after selection"),r("header.projectRootModal.initial.nextSyncRoot.placeholder","<selected project folder>/weppy-project-sync")),e.jsxs("ul",{className:j.warningList,children:[d?e.jsxs(e.Fragment,{children:[e.jsx("li",{children:r("header.projectRootModal.initial.warningStop","Current sync stops immediately.")}),e.jsx("li",{children:r("header.projectRootModal.initial.warningFreshSync","The current Studio contents will be used to build a fresh full sync in the new target.")})]}):e.jsx("li",{children:r("header.projectRootModal.initial.warningDeferredSync","If Studio is not connected, full resync starts the next time the plugin connects.")}),e.jsx("li",{children:r("header.projectRootModal.initial.warningNoMove","Old sync folders are not moved automatically.")})]})]}):e.jsxs(e.Fragment,{children:[H(r("header.projectRootModal.confirm.projectRoot","Selected project folder"),n??""),H(r("header.projectRootModal.confirm.syncRoot","New sync target"),y),e.jsx("p",{className:j.message,children:r("header.projectRootModal.confirm.warningNoMove","Existing sync folders are not moved automatically.")})]}),h?e.jsx("p",{className:`${j.message} ${j.errorMessage}`,children:h}):null]}),e.jsxs("div",{className:j.actions,children:[e.jsx("button",{className:j.cancelButton,onClick:a,disabled:p,children:r("header.projectRootModal.cancel","Cancel")}),s==="initial"?e.jsx("button",{className:j.confirmButton,onClick:c,disabled:p,children:p?"...":r("header.projectRootModal.pick","Choose folder")}):e.jsx("button",{className:j.confirmButton,onClick:g,disabled:p||!n,children:p?"...":r("header.projectRootModal.apply","Apply change")})]})]})})}function W(o,s){if(o&&typeof o=="object"&&"message"in o&&typeof o.message=="string"){const n=o.message.trim();if(n.length>0)return n}return s}function le(){const{level:o,status:s}=q(),{t:n}=P(),{show:d}=z(),{search:p}=k(),h=l.useRef(null),[a,c]=l.useState(null),[g,r]=l.useState(!1),[y,x]=l.useState(null),[b,N]=l.useState(null),[S,u]=l.useState(!1),[f,v]=l.useState(!1),[L,C]=l.useState(null),M=l.useMemo(()=>new URLSearchParams(p).get("section")==="project-root",[p]),w=l.useCallback(async()=>{if(o==="disconnected"){c(null),r(!1);return}r(!1);try{const m=await K();c(m)}catch{c(null),r(!0)}},[o]);l.useEffect(()=>{w()},[w,s==null?void 0:s.connectedClients,s==null?void 0:s.sessionId]),l.useEffect(()=>{var m,E,V;M&&((E=(m=h.current)==null?void 0:m.scrollIntoView)==null||E.call(m,{block:"start",behavior:"smooth"}),(V=h.current)==null||V.focus())},[M]);const R=(m=!1)=>{!m&&(S||f)||(x(null),N(null),C(null))},i=()=>{o==="disconnected"||!a||(C(null),N(null),x("initial"))},I=async()=>{u(!0),C(null);try{const m=await J();if(m.cancelled||!m.projectRoot){R(!0);return}N(m.projectRoot),x("confirm")}catch(m){C(W(m,n("header.projectRootModal.error","Failed to change project root")))}finally{u(!1)}},A=async()=>{if(b){v(!0),C(null);try{const m=await Z(b);c(m),r(!1),R(!0)}catch(m){const E=W(m,n("header.projectRootModal.error","Failed to change project root"));C(E),d(E,"error")}finally{v(!1)}}},$=g?n("controls.projectRoot.unavailable","Project root unavailable"):n("common.loading","Loading..."),X=o==="disconnected"||!a;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{id:"controls-project-root",ref:h,tabIndex:-1,className:t.card,children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsx(T,{label:n("controls.projectRoot.title","Project Root"),tooltip:n("controls.projectRoot.title.tooltip","Authoritative project root and sync target used by MCP.")}),e.jsx(F,{text:n("controls.projectRoot.live.tooltip","Changing this updates MCP runtime state immediately after confirmation."),children:e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:n("settings.general.liveApply","Live Apply")})})]}),e.jsxs("dl",{className:t.controlGrid,children:[e.jsx("dt",{children:n("controls.projectRoot.projectRoot","Project Root")}),e.jsx("dd",{children:(a==null?void 0:a.projectRoot)??$}),e.jsx("dt",{children:n("controls.projectRoot.syncRoot","Sync Root")}),e.jsx("dd",{children:(a==null?void 0:a.projectSyncRoot)??$})]}),e.jsx("p",{className:t.controlHint,children:n("controls.projectRoot.hint","Use this only when MCP should write sync data under a different project folder. Existing sync folders are not moved automatically.")}),e.jsx("button",{type:"button",className:t.actionBtn,disabled:X,onClick:i,children:n("header.changeProjectRoot","Change Project Root")})]}),e.jsx(se,{open:y!==null,step:y??"initial",selectedProjectRoot:b,studioConnected:o==="studioConnected",loading:S||f,errorMessage:L,onClose:R,onPick:I,onApply:A})]})}function ce(o){if(!o)return null;const s=o.placeName?o.placeId!==void 0?`${o.placeName} · ${o.placeId}`:o.placeName:o.placeId!==void 0?String(o.placeId):null;return s?`${o.targetAlias} · ${s}`:o.targetAlias}function G(o,s){const n=Math.max(0,Math.floor((Date.now()-o)/1e3));return n<60?`${n}${s("connection.time.secondsAgo","s ago")}`:n<3600?`${Math.floor(n/60)}${s("connection.time.minutesAgo","m ago")}`:`${Math.floor(n/3600)}${s("connection.time.hoursAgo","h ago")}`}function re(){const{status:o,level:s}=q(),{t:n}=P(),{show:d}=z(),{search:p}=k(),h=l.useRef(null),a=l.useRef(null),[c,g]=l.useState(null),[r,y]=l.useState(null),[x,b]=l.useState("idle"),N=l.useMemo(()=>new URLSearchParams(p).get("section")==="studio-routing",[p]),S=l.useCallback(async()=>{if(s==="disconnected"){g(null);return}try{const i=await U.get("/api/dashboard/studio-routing");g(i)}catch{g(null)}},[s]);l.useEffect(()=>{S()},[S,o==null?void 0:o.connectedClients,o==null?void 0:o.sessionId]),l.useEffect(()=>{var i,I,A;N&&((I=(i=h.current)==null?void 0:i.scrollIntoView)==null||I.call(i,{block:"start",behavior:"smooth"}),(A=h.current)==null||A.focus())},[N]),l.useEffect(()=>()=>{a.current&&clearTimeout(a.current)},[]);const u=(c==null?void 0:c.studioRoutingMode)??(o==null?void 0:o.studioRoutingMode)??"recentPriority",f=(c==null?void 0:c.pinnedTargetClientId)??(o==null?void 0:o.pinnedTargetClientId)??null,v=ee((c==null?void 0:c.targets)??(o==null?void 0:o.pluginClients)??[],u,f),L=(c==null?void 0:c.priorityTarget)??te(v,u,f),C=ce(L),M=new Set(v.filter(i=>i.placeId!==void 0).map(i=>i.placeId).filter((i,I,A)=>A.filter($=>$===i).length>1)),w=async i=>{y(i.studioRoutingMode==="pinned"?i.pinnedTargetClientId??"pinned":"recentPriority"),b("idle"),a.current&&(clearTimeout(a.current),a.current=null);try{const I=await U.patch("/api/dashboard/studio-routing",i);g(I),b("applied"),a.current=setTimeout(()=>{b("idle"),a.current=null},2e3)}catch{b("failed"),d(n("connection.routing.updateFailed","Failed to update routing target"),"error")}finally{y(null)}},R=async i=>{try{await navigator.clipboard.writeText(i),d(n("connection.targets.copied","Copied value"),"success")}catch{d(n("connection.targets.copyFailed","Failed to copy value"),"error")}};return e.jsxs("div",{id:"controls-studio-routing",ref:h,tabIndex:-1,className:t.card,children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsxs("div",{className:t.cardHeaderTitleGroup,children:[e.jsx("span",{children:n("controls.studioRouting.title","Studio Routing")}),e.jsx(Q,{topicId:"studioRouting",variant:"field",tooltip:n("controls.studioRouting.helpButton","How does it work?"),triggerClassName:`${t.cardHelpButton} ${t.touchTarget44}`})]}),e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:n("settings.general.liveApply","Live Apply")})]}),e.jsxs("div",{className:t.routingOverview,children:[e.jsxs("div",{className:t.routingOverviewCopy,children:[e.jsx("span",{className:t.routingEyebrow,children:n("controls.studioRouting.priorityTitle","Priority for requests without a named Studio target")}),e.jsx("strong",{children:u==="pinned"?n("connection.routing.pinned","Manual: Pinned Studio"):n("connection.routing.recentPriority","Automatic: Recent priority")}),e.jsx("p",{children:n("controls.studioRouting.priorityDescription","Explicit Studio ID, Connection ID, or Place ID requests bypass this priority setting and route to the named Studio.")})]}),e.jsxs("div",{className:t.priorityTargetSummary,children:[e.jsx("span",{children:n("controls.studioRouting.state.currentTarget","Current priority target")}),e.jsx("strong",{children:C??n("controls.studioRouting.noPriorityTarget","No connected Studio target")}),e.jsx("span",{className:`${t.savedIndicator} ${t.routingFeedback} ${x==="failed"?t.savedIndicatorFailed:""} ${r===null&&x==="idle"?t.savedIndicatorHidden:""}`,"aria-live":"polite","data-testid":"studio-routing-save-feedback",children:r!==null?n("controls.studioRouting.saving","Applying…"):x==="applied"?n("controls.studioRouting.applied","Applied"):x==="failed"?n("controls.studioRouting.failed","Failed to apply"):null})]})]}),e.jsxs("div",{className:t.studioRoutingChoiceControl,role:"group","aria-label":n("connection.routing.priorityControl","Priority mode for requests without a named Studio target"),children:[e.jsxs("button",{type:"button",className:u==="recentPriority"?t.segmentActive:t.segment,disabled:r!==null,"aria-pressed":u==="recentPriority","aria-label":n("controls.studioRouting.mode.auto","Automatic"),onClick:()=>w({studioRoutingMode:"recentPriority"}),children:[e.jsx("span",{className:t.segmentIndicator,"aria-hidden":"true",children:u==="recentPriority"?e.jsx(B,{size:16}):null}),e.jsxs("span",{className:t.segmentCopy,children:[e.jsx("span",{className:t.segmentLabel,children:n("connection.routing.recentPriority","Automatic: Recent priority")}),e.jsx("small",{className:t.segmentDescription,children:n("controls.studioRouting.help.auto","Automatic uses the highest-priority active Studio, based on recent routed commands and connection order.")})]})]}),e.jsxs("button",{type:"button",className:u==="pinned"?t.segmentActive:t.segment,disabled:!v.length||r!==null,"aria-pressed":u==="pinned","aria-label":n("controls.studioRouting.mode.pinned","Studio fixed"),onClick:()=>w({studioRoutingMode:"pinned"}),children:[e.jsx("span",{className:t.segmentIndicator,"aria-hidden":"true",children:u==="pinned"?e.jsx(B,{size:16}):null}),e.jsxs("span",{className:t.segmentCopy,children:[e.jsx("span",{className:t.segmentLabel,children:n("connection.routing.pinned","Manual: Pinned Studio")}),e.jsx("small",{className:t.segmentDescription,children:n("controls.studioRouting.help.pinned","Studio fixed uses the selected Studio unless the request names a Studio ID, Connection ID, or Place ID.")})]})]})]}),v.length?null:e.jsx("p",{className:t.routingDisabledReason,children:n("controls.studioRouting.pinnedUnavailable","Connect a Studio target to use Studio fixed mode.")}),M.size>0?e.jsx("p",{className:t.routingWarning,children:n("controls.studioRouting.duplicatePlaceWarning","More than one connected Studio window has the same Place ID. Ask the AI agent to use Studio ID for that place.")}):null,e.jsx("div",{className:t.tableWrap,role:u==="pinned"?"radiogroup":void 0,"aria-label":u==="pinned"?n("controls.studioRouting.targetGroupLabel","Studio fixed target"):void 0,children:e.jsxs("table",{className:`${t.table} ${t.routingTargetsTable}`,children:[e.jsxs("colgroup",{children:[e.jsx("col",{className:t.routingActionColumn}),e.jsx("col",{span:6})]}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:n("connection.targets.routing","Routing")}),e.jsx("th",{children:n("connection.targets.target","Studio ID")}),e.jsx("th",{children:n("connection.targets.place","Place")}),e.jsx("th",{children:n("connection.targets.placeId","Place ID")}),e.jsx("th",{children:n("connection.targets.lastUsed","Last Used")}),e.jsx("th",{children:n("connection.targets.lastSeen","Last Seen")}),e.jsx("th",{children:n("connection.targets.clientId","Connection ID")})]})}),e.jsx("tbody",{children:v.length>0?v.map(i=>e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx("div",{className:t.routingActionSlot,children:u==="pinned"?e.jsxs("button",{type:"button",role:"radio","aria-checked":f===i.clientId,"aria-label":`${n("controls.studioRouting.selectTarget","Select fixed Studio")}: ${i.targetAlias}`,className:`${t.routingTargetRadio} ${f===i.clientId?t.routingTargetRadioActive:""}`,disabled:r!==null,onClick:()=>{f!==i.clientId&&w({studioRoutingMode:"pinned",pinnedTargetClientId:i.clientId})},children:[e.jsx("span",{className:t.routingRadioIndicator,"aria-hidden":"true",children:f===i.clientId?e.jsx(B,{size:12}):null}),e.jsx("span",{children:f===i.clientId?n("connection.routing.pinnedBadge","Pinned"):n("controls.studioRouting.select","Select")})]}):(L==null?void 0:L.clientId)===i.clientId?e.jsx("span",{className:t.routingBadge,children:n("connection.routing.priorityBadge","Priority")}):null})}),e.jsxs("td",{children:[e.jsx("span",{className:t.monoMuted,title:i.clientId,children:i.targetAlias}),e.jsx(D,{text:n("connection.targets.copyTargetAlias","Copy Studio ID"),children:e.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":n("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>R(i.targetAlias),children:e.jsx(_,{size:13,"aria-hidden":"true"})})})]}),e.jsx("td",{children:i.placeName??"-"}),e.jsxs("td",{children:[i.placeId??"-",i.placeId!==void 0?e.jsx(D,{text:n("connection.targets.copyPlaceId","Copy Place ID"),children:e.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":n("connection.targets.copyPlaceId","Copy Place ID"),onClick:()=>R(String(i.placeId)),children:e.jsx(_,{size:13,"aria-hidden":"true"})})}):null]}),e.jsx("td",{children:i.lastRoutedAt?G(i.lastRoutedAt,n):"-"}),e.jsx("td",{children:G(i.lastSeen,n)}),e.jsxs("td",{children:[e.jsx("span",{className:t.monoMuted,title:i.clientId,children:i.clientId.slice(0,10)}),e.jsx(D,{text:n("connection.targets.copyClientId","Copy Connection ID"),children:e.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":n("connection.targets.copyClientId","Copy Connection ID"),onClick:()=>R(i.clientId),children:e.jsx(_,{size:13,"aria-hidden":"true"})})})]})]},i.clientId)):e.jsx("tr",{children:e.jsx("td",{colSpan:7,className:t.emptyRow,children:n("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")})})})]})})]})}const Y=["debug","info","warn","error"];function O({checked:o,onChange:s,testId:n,ariaLabel:d}){return e.jsxs("label",{className:t.toggleSwitch,"data-testid":n,children:[e.jsx("input",{type:"checkbox",className:t.toggleInput,checked:o,"aria-label":d,onChange:p=>s(p.target.checked)}),e.jsx("span",{className:t.toggleTrack,"aria-hidden":"true",children:e.jsx("span",{className:t.toggleThumb})})]})}function de({settings:o,updateHotSetting:s}){const{t:n}=P(),[d,p]=l.useState(null),h=l.useCallback(async(a,c)=>{try{await s(a,c),p(a),setTimeout(()=>p(g=>g===a?null:g),2e3)}catch{p(g=>g===a?null:g)}},[s]);return e.jsxs("div",{className:t.card,children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsx(T,{label:n("settings.general.title","General Settings"),tooltip:n("settings.general.title.tooltip","Hot settings that apply immediately when changed.")}),e.jsx(F,{text:n("settings.general.liveApply.tooltip","Changes in this section are applied immediately without a separate save button."),children:e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:n("settings.general.liveApply","Live Apply")})})]}),o?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.logLevel","Log Level"),tooltip:n("settings.general.logLevel.tooltip","Sets how much detail WEPPY Dashboard writes to its logs.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("select",{className:t.select,value:o.hot.LOG_LEVEL,onChange:a=>{const c=Y.find(g=>g===a.target.value);c&&h("LOG_LEVEL",c)},children:Y.map(a=>e.jsx("option",{value:a,children:a},a))}),d==="LOG_LEVEL"&&e.jsx("span",{className:t.savedIndicator,children:n("settings.general.applied")})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.localHistory","Tool History Recording"),tooltip:n("settings.general.localHistory.tooltip","Stores local tool execution history for the WEPPY Dashboard history views.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${d==="ENABLE_LOCAL_HISTORY"?"":t.savedIndicatorHidden}`,children:n("settings.general.applied","Applied")}),e.jsx(O,{checked:o.hot.ENABLE_LOCAL_HISTORY,ariaLabel:n("settings.general.localHistory","Tool History Recording"),testId:"settings-toggle-enable-local-history",onChange:a=>h("ENABLE_LOCAL_HISTORY",a)})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.localStatistics","Tool Statistics Collection"),tooltip:n("settings.general.localStatistics.tooltip","Aggregates local usage statistics for WEPPY Dashboard reporting.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${d==="ENABLE_LOCAL_STATISTICS"?"":t.savedIndicatorHidden}`,children:n("settings.general.applied","Applied")}),e.jsx(O,{checked:o.hot.ENABLE_LOCAL_STATISTICS,ariaLabel:n("settings.general.localStatistics","Tool Statistics Collection"),testId:"settings-toggle-enable-local-statistics",onChange:a=>h("ENABLE_LOCAL_STATISTICS",a)})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.contextCapture","Context Capture"),tooltip:n("settings.general.contextCapture.tooltip","When enabled, WEPPY Dashboard records structured execution context for changelog and playtest views.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${d==="ENABLE_CONTEXT_CAPTURE"?"":t.savedIndicatorHidden}`,children:n("settings.general.applied","Applied")}),e.jsx(O,{checked:o.hot.ENABLE_CONTEXT_CAPTURE,ariaLabel:n("settings.general.contextCapture","Context Capture"),testId:"settings-toggle-enable-context-capture",onChange:a=>h("ENABLE_CONTEXT_CAPTURE",a)})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.requestTimeout","Action Timeout"),tooltip:n("settings.general.requestTimeout.tooltip","Maximum time WEPPY Dashboard waits for an action before it fails.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("input",{type:"number",className:t.numberInput,value:o.hot.REQUEST_TIMEOUT,min:1e3,max:12e4,step:1e3,onChange:a=>{const c=parseInt(a.target.value,10);isNaN(c)||h("REQUEST_TIMEOUT",c)}}),e.jsx(F,{text:n("settings.general.requestTimeout.unit.tooltip","Action timeout is measured in milliseconds."),children:e.jsx("span",{className:t.unit,children:n("settings.general.requestTimeout.unit","ms")})}),d==="REQUEST_TIMEOUT"&&e.jsx("span",{className:t.savedIndicator,children:n("settings.general.applied","Applied")})]})]})]}):e.jsx("div",{className:t.loading,children:n("settings.unavailable")})]})}function ue({enabled:o,saving:s,onChange:n}){const{t:d}=P(),{search:p}=k(),h=l.useRef(null),a=l.useRef(null),c=l.useId(),[g,r]=l.useState(!1),[y,x]=l.useState("idle"),b=l.useMemo(()=>new URLSearchParams(p).get("section")==="luau-validation",[p]),N=s||g;l.useEffect(()=>{var u,f,v;b&&((f=(u=h.current)==null?void 0:u.scrollIntoView)==null||f.call(u,{block:"start",behavior:"smooth"}),(v=h.current)==null||v.focus())},[b]),l.useEffect(()=>()=>{a.current&&clearTimeout(a.current)},[]);const S=l.useCallback(async u=>{r(!0),x("idle"),a.current&&(clearTimeout(a.current),a.current=null);try{await n(u),x("applied"),a.current=setTimeout(()=>{x("idle"),a.current=null},2e3)}catch{x("failed")}finally{r(!1)}},[n]);return e.jsxs("div",{id:"controls-luau-validation",ref:h,tabIndex:-1,className:`${t.card} ${t.validationCard}`,"data-testid":"luau-syntax-validation-card",children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsxs("div",{className:t.cardHeaderTitleGroup,children:[e.jsx("span",{children:d("controls.luauValidation.title","Luau Syntax Validation")}),e.jsx(Q,{topicId:"luauValidation",variant:"field",tooltip:d("controls.luauValidation.helpButton","How does it work?"),triggerClassName:`${t.cardHelpButton} ${t.touchTarget44}`})]}),e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:d("settings.general.liveApply","Live Apply")})]}),e.jsxs("div",{className:t.validationSettingRow,children:[e.jsxs("div",{className:t.validationSettingCopy,children:[e.jsx("span",{id:c,className:t.validationSettingLabel,children:d("controls.luauValidation.settingLabel","Check automatically after Script edits")}),e.jsx("span",{className:t.validationSettingStatus,children:o?d("controls.luauValidation.state.on","Current: On"):d("controls.luauValidation.state.off","Current: Off")})]}),e.jsxs("div",{className:t.validationPolicyControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${y==="failed"?t.savedIndicatorFailed:""} ${!N&&y==="idle"?t.savedIndicatorHidden:""}`,"data-testid":"luau-validation-save-feedback","aria-live":"polite",children:N?d("controls.luauValidation.saving","Saving…"):y==="applied"?d("controls.luauValidation.applied","Applied"):y==="failed"?d("controls.luauValidation.failed","Failed to apply"):null}),e.jsxs("label",{className:`${t.toggleSwitch} ${t.validationToggleTarget}`,"data-testid":"luau-validation-toggle",children:[e.jsx("input",{type:"checkbox",role:"switch",className:t.toggleInput,checked:o,disabled:N,"aria-labelledby":c,onChange:u=>{S(u.target.checked)}}),e.jsx("span",{className:t.toggleTrack,"aria-hidden":"true",children:e.jsx("span",{className:t.toggleThumb})})]})]})]})]})}function ve(){const{t:o}=P(),{search:s}=k(),{settings:n,updateHotSetting:d,saving:p,loading:h}=ae();return l.useMemo(()=>new URLSearchParams(s).get("section"),[s])==="license"?e.jsx(ne,{to:"/settings?section=license",replace:!0}):h?e.jsx("div",{className:t.page,children:e.jsx("div",{className:t.loading,children:o("common.loading")})}):e.jsxs("div",{className:t.page,children:[e.jsx(oe,{title:o("page.controls.title","Controls"),description:o("page.controls.description","Manage project root, Studio routing, and MCP live settings."),helpTopicId:"controls"}),e.jsx(le,{}),e.jsx(re,{}),e.jsx(ue,{enabled:(n==null?void 0:n.hot.SCRIPT_WRITE_VALIDATION_ENABLED)??!1,saving:p,onChange:c=>d("SCRIPT_WRITE_VALIDATION_ENABLED",c)}),e.jsx(de,{settings:n,updateHotSetting:d})]})}export{ve as Component};
|
|
1
|
+
import{u as P,j as e,d as q,i as z,c as k,r as l,v as K,w as Z,x as J,b as U,s as ee,y as te,h as D,N as ne}from"./index-DchewB5y.js";import{D as Q,P as oe}from"./PageHeader-CYbeZdtL.js";import{I as T}from"./InfoLabel-BGeOUBIl.js";import{s as j}from"./ConfirmModal.module-DJksQHBd.js";import{T as F}from"./TooltipText-sb-BSgUg.js";import{s as t,u as ae}from"./useSettings-D5XHMODc.js";import{C as B}from"./check-EdHXSSef.js";import{C as _}from"./copy-CePVq0VI.js";function H(o,s){return e.jsxs("div",{className:j.pathBlock,children:[e.jsx("span",{className:j.pathLabel,children:o}),e.jsx("code",{className:j.pathCode,children:s})]})}function ie(o){const n=/^[A-Z]:\\/i.test(o)||o.includes("\\")?"\\":"/";return`${o.replace(/[\\/]+$/,"")}${n}weppy-project-sync`}function se({open:o,step:s,selectedProjectRoot:n,studioConnected:d,loading:p=!1,errorMessage:h=null,onClose:a,onPick:c,onApply:g}){const{t:r}=P();if(!o)return null;const y=n?ie(n):"";return e.jsx("div",{className:j.backdrop,onClick:p?void 0:a,role:"presentation",children:e.jsxs("div",{className:j.modal,onClick:x=>x.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"project-root-change-modal-title",children:[e.jsx("h2",{id:"project-root-change-modal-title",className:j.title,children:s==="initial"?r("header.projectRootModal.initial.title","Change project root"):r("header.projectRootModal.confirm.title","Confirm new project root")}),e.jsx("p",{className:j.message,children:s==="initial"?d?r("header.projectRootModal.initial.body.connected","MCP will switch to the new project root and resync current Studio contents into the new target."):r("header.projectRootModal.initial.body.disconnected","MCP will switch to the new project root and use the new folder as the next sync target."):r("header.projectRootModal.confirm.body","Review the selected project folder before applying.")}),e.jsxs("div",{className:j.bodyGrid,children:[s==="initial"?e.jsxs(e.Fragment,{children:[H(r("header.projectRootModal.initial.nextSyncRoot","New sync target after selection"),r("header.projectRootModal.initial.nextSyncRoot.placeholder","<selected project folder>/weppy-project-sync")),e.jsxs("ul",{className:j.warningList,children:[d?e.jsxs(e.Fragment,{children:[e.jsx("li",{children:r("header.projectRootModal.initial.warningStop","Current sync stops immediately.")}),e.jsx("li",{children:r("header.projectRootModal.initial.warningFreshSync","The current Studio contents will be used to build a fresh full sync in the new target.")})]}):e.jsx("li",{children:r("header.projectRootModal.initial.warningDeferredSync","If Studio is not connected, full resync starts the next time the plugin connects.")}),e.jsx("li",{children:r("header.projectRootModal.initial.warningNoMove","Old sync folders are not moved automatically.")})]})]}):e.jsxs(e.Fragment,{children:[H(r("header.projectRootModal.confirm.projectRoot","Selected project folder"),n??""),H(r("header.projectRootModal.confirm.syncRoot","New sync target"),y),e.jsx("p",{className:j.message,children:r("header.projectRootModal.confirm.warningNoMove","Existing sync folders are not moved automatically.")})]}),h?e.jsx("p",{className:`${j.message} ${j.errorMessage}`,children:h}):null]}),e.jsxs("div",{className:j.actions,children:[e.jsx("button",{className:j.cancelButton,onClick:a,disabled:p,children:r("header.projectRootModal.cancel","Cancel")}),s==="initial"?e.jsx("button",{className:j.confirmButton,onClick:c,disabled:p,children:p?"...":r("header.projectRootModal.pick","Choose folder")}):e.jsx("button",{className:j.confirmButton,onClick:g,disabled:p||!n,children:p?"...":r("header.projectRootModal.apply","Apply change")})]})]})})}function W(o,s){if(o&&typeof o=="object"&&"message"in o&&typeof o.message=="string"){const n=o.message.trim();if(n.length>0)return n}return s}function le(){const{level:o,status:s}=q(),{t:n}=P(),{show:d}=z(),{search:p}=k(),h=l.useRef(null),[a,c]=l.useState(null),[g,r]=l.useState(!1),[y,x]=l.useState(null),[b,N]=l.useState(null),[S,u]=l.useState(!1),[f,v]=l.useState(!1),[L,C]=l.useState(null),M=l.useMemo(()=>new URLSearchParams(p).get("section")==="project-root",[p]),w=l.useCallback(async()=>{if(o==="disconnected"){c(null),r(!1);return}r(!1);try{const m=await K();c(m)}catch{c(null),r(!0)}},[o]);l.useEffect(()=>{w()},[w,s==null?void 0:s.connectedClients,s==null?void 0:s.sessionId]),l.useEffect(()=>{var m,E,V;M&&((E=(m=h.current)==null?void 0:m.scrollIntoView)==null||E.call(m,{block:"start",behavior:"smooth"}),(V=h.current)==null||V.focus())},[M]);const R=(m=!1)=>{!m&&(S||f)||(x(null),N(null),C(null))},i=()=>{o==="disconnected"||!a||(C(null),N(null),x("initial"))},I=async()=>{u(!0),C(null);try{const m=await J();if(m.cancelled||!m.projectRoot){R(!0);return}N(m.projectRoot),x("confirm")}catch(m){C(W(m,n("header.projectRootModal.error","Failed to change project root")))}finally{u(!1)}},A=async()=>{if(b){v(!0),C(null);try{const m=await Z(b);c(m),r(!1),R(!0)}catch(m){const E=W(m,n("header.projectRootModal.error","Failed to change project root"));C(E),d(E,"error")}finally{v(!1)}}},$=g?n("controls.projectRoot.unavailable","Project root unavailable"):n("common.loading","Loading..."),X=o==="disconnected"||!a;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{id:"controls-project-root",ref:h,tabIndex:-1,className:t.card,children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsx(T,{label:n("controls.projectRoot.title","Project Root"),tooltip:n("controls.projectRoot.title.tooltip","Authoritative project root and sync target used by MCP.")}),e.jsx(F,{text:n("controls.projectRoot.live.tooltip","Changing this updates MCP runtime state immediately after confirmation."),children:e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:n("settings.general.liveApply","Live Apply")})})]}),e.jsxs("dl",{className:t.controlGrid,children:[e.jsx("dt",{children:n("controls.projectRoot.projectRoot","Project Root")}),e.jsx("dd",{children:(a==null?void 0:a.projectRoot)??$}),e.jsx("dt",{children:n("controls.projectRoot.syncRoot","Sync Root")}),e.jsx("dd",{children:(a==null?void 0:a.projectSyncRoot)??$})]}),e.jsx("p",{className:t.controlHint,children:n("controls.projectRoot.hint","Use this only when MCP should write sync data under a different project folder. Existing sync folders are not moved automatically.")}),e.jsx("button",{type:"button",className:t.actionBtn,disabled:X,onClick:i,children:n("header.changeProjectRoot","Change Project Root")})]}),e.jsx(se,{open:y!==null,step:y??"initial",selectedProjectRoot:b,studioConnected:o==="studioConnected",loading:S||f,errorMessage:L,onClose:R,onPick:I,onApply:A})]})}function ce(o){if(!o)return null;const s=o.placeName?o.placeId!==void 0?`${o.placeName} · ${o.placeId}`:o.placeName:o.placeId!==void 0?String(o.placeId):null;return s?`${o.targetAlias} · ${s}`:o.targetAlias}function G(o,s){const n=Math.max(0,Math.floor((Date.now()-o)/1e3));return n<60?`${n}${s("connection.time.secondsAgo","s ago")}`:n<3600?`${Math.floor(n/60)}${s("connection.time.minutesAgo","m ago")}`:`${Math.floor(n/3600)}${s("connection.time.hoursAgo","h ago")}`}function re(){const{status:o,level:s}=q(),{t:n}=P(),{show:d}=z(),{search:p}=k(),h=l.useRef(null),a=l.useRef(null),[c,g]=l.useState(null),[r,y]=l.useState(null),[x,b]=l.useState("idle"),N=l.useMemo(()=>new URLSearchParams(p).get("section")==="studio-routing",[p]),S=l.useCallback(async()=>{if(s==="disconnected"){g(null);return}try{const i=await U.get("/api/dashboard/studio-routing");g(i)}catch{g(null)}},[s]);l.useEffect(()=>{S()},[S,o==null?void 0:o.connectedClients,o==null?void 0:o.sessionId]),l.useEffect(()=>{var i,I,A;N&&((I=(i=h.current)==null?void 0:i.scrollIntoView)==null||I.call(i,{block:"start",behavior:"smooth"}),(A=h.current)==null||A.focus())},[N]),l.useEffect(()=>()=>{a.current&&clearTimeout(a.current)},[]);const u=(c==null?void 0:c.studioRoutingMode)??(o==null?void 0:o.studioRoutingMode)??"recentPriority",f=(c==null?void 0:c.pinnedTargetClientId)??(o==null?void 0:o.pinnedTargetClientId)??null,v=ee((c==null?void 0:c.targets)??(o==null?void 0:o.pluginClients)??[],u,f),L=(c==null?void 0:c.priorityTarget)??te(v,u,f),C=ce(L),M=new Set(v.filter(i=>i.placeId!==void 0).map(i=>i.placeId).filter((i,I,A)=>A.filter($=>$===i).length>1)),w=async i=>{y(i.studioRoutingMode==="pinned"?i.pinnedTargetClientId??"pinned":"recentPriority"),b("idle"),a.current&&(clearTimeout(a.current),a.current=null);try{const I=await U.patch("/api/dashboard/studio-routing",i);g(I),b("applied"),a.current=setTimeout(()=>{b("idle"),a.current=null},2e3)}catch{b("failed"),d(n("connection.routing.updateFailed","Failed to update routing target"),"error")}finally{y(null)}},R=async i=>{try{await navigator.clipboard.writeText(i),d(n("connection.targets.copied","Copied value"),"success")}catch{d(n("connection.targets.copyFailed","Failed to copy value"),"error")}};return e.jsxs("div",{id:"controls-studio-routing",ref:h,tabIndex:-1,className:t.card,children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsxs("div",{className:t.cardHeaderTitleGroup,children:[e.jsx("span",{children:n("controls.studioRouting.title","Studio Routing")}),e.jsx(Q,{topicId:"studioRouting",variant:"field",tooltip:n("controls.studioRouting.helpButton","How does it work?"),triggerClassName:`${t.cardHelpButton} ${t.touchTarget44}`})]}),e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:n("settings.general.liveApply","Live Apply")})]}),e.jsxs("div",{className:t.routingOverview,children:[e.jsxs("div",{className:t.routingOverviewCopy,children:[e.jsx("span",{className:t.routingEyebrow,children:n("controls.studioRouting.priorityTitle","Priority for requests without a named Studio target")}),e.jsx("strong",{children:u==="pinned"?n("connection.routing.pinned","Manual: Pinned Studio"):n("connection.routing.recentPriority","Automatic: Recent priority")}),e.jsx("p",{children:n("controls.studioRouting.priorityDescription","Explicit Studio ID, Connection ID, or Place ID requests bypass this priority setting and route to the named Studio.")})]}),e.jsxs("div",{className:t.priorityTargetSummary,children:[e.jsx("span",{children:n("controls.studioRouting.state.currentTarget","Current priority target")}),e.jsx("strong",{children:C??n("controls.studioRouting.noPriorityTarget","No connected Studio target")}),e.jsx("span",{className:`${t.savedIndicator} ${t.routingFeedback} ${x==="failed"?t.savedIndicatorFailed:""} ${r===null&&x==="idle"?t.savedIndicatorHidden:""}`,"aria-live":"polite","data-testid":"studio-routing-save-feedback",children:r!==null?n("controls.studioRouting.saving","Applying…"):x==="applied"?n("controls.studioRouting.applied","Applied"):x==="failed"?n("controls.studioRouting.failed","Failed to apply"):null})]})]}),e.jsxs("div",{className:t.studioRoutingChoiceControl,role:"group","aria-label":n("connection.routing.priorityControl","Priority mode for requests without a named Studio target"),children:[e.jsxs("button",{type:"button",className:u==="recentPriority"?t.segmentActive:t.segment,disabled:r!==null,"aria-pressed":u==="recentPriority","aria-label":n("controls.studioRouting.mode.auto","Automatic"),onClick:()=>w({studioRoutingMode:"recentPriority"}),children:[e.jsx("span",{className:t.segmentIndicator,"aria-hidden":"true",children:u==="recentPriority"?e.jsx(B,{size:16}):null}),e.jsxs("span",{className:t.segmentCopy,children:[e.jsx("span",{className:t.segmentLabel,children:n("connection.routing.recentPriority","Automatic: Recent priority")}),e.jsx("small",{className:t.segmentDescription,children:n("controls.studioRouting.help.auto","Automatic uses the highest-priority active Studio, based on recent routed commands and connection order.")})]})]}),e.jsxs("button",{type:"button",className:u==="pinned"?t.segmentActive:t.segment,disabled:!v.length||r!==null,"aria-pressed":u==="pinned","aria-label":n("controls.studioRouting.mode.pinned","Studio fixed"),onClick:()=>w({studioRoutingMode:"pinned"}),children:[e.jsx("span",{className:t.segmentIndicator,"aria-hidden":"true",children:u==="pinned"?e.jsx(B,{size:16}):null}),e.jsxs("span",{className:t.segmentCopy,children:[e.jsx("span",{className:t.segmentLabel,children:n("connection.routing.pinned","Manual: Pinned Studio")}),e.jsx("small",{className:t.segmentDescription,children:n("controls.studioRouting.help.pinned","Studio fixed uses the selected Studio unless the request names a Studio ID, Connection ID, or Place ID.")})]})]})]}),v.length?null:e.jsx("p",{className:t.routingDisabledReason,children:n("controls.studioRouting.pinnedUnavailable","Connect a Studio target to use Studio fixed mode.")}),M.size>0?e.jsx("p",{className:t.routingWarning,children:n("controls.studioRouting.duplicatePlaceWarning","More than one connected Studio window has the same Place ID. Ask the AI agent to use Studio ID for that place.")}):null,e.jsx("div",{className:t.tableWrap,role:u==="pinned"?"radiogroup":void 0,"aria-label":u==="pinned"?n("controls.studioRouting.targetGroupLabel","Studio fixed target"):void 0,children:e.jsxs("table",{className:`${t.table} ${t.routingTargetsTable}`,children:[e.jsxs("colgroup",{children:[e.jsx("col",{className:t.routingActionColumn}),e.jsx("col",{span:6})]}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:n("connection.targets.routing","Routing")}),e.jsx("th",{children:n("connection.targets.target","Studio ID")}),e.jsx("th",{children:n("connection.targets.place","Place")}),e.jsx("th",{children:n("connection.targets.placeId","Place ID")}),e.jsx("th",{children:n("connection.targets.lastUsed","Last Used")}),e.jsx("th",{children:n("connection.targets.lastSeen","Last Seen")}),e.jsx("th",{children:n("connection.targets.clientId","Connection ID")})]})}),e.jsx("tbody",{children:v.length>0?v.map(i=>e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx("div",{className:t.routingActionSlot,children:u==="pinned"?e.jsxs("button",{type:"button",role:"radio","aria-checked":f===i.clientId,"aria-label":`${n("controls.studioRouting.selectTarget","Select fixed Studio")}: ${i.targetAlias}`,className:`${t.routingTargetRadio} ${f===i.clientId?t.routingTargetRadioActive:""}`,disabled:r!==null,onClick:()=>{f!==i.clientId&&w({studioRoutingMode:"pinned",pinnedTargetClientId:i.clientId})},children:[e.jsx("span",{className:t.routingRadioIndicator,"aria-hidden":"true",children:f===i.clientId?e.jsx(B,{size:12}):null}),e.jsx("span",{children:f===i.clientId?n("connection.routing.pinnedBadge","Pinned"):n("controls.studioRouting.select","Select")})]}):(L==null?void 0:L.clientId)===i.clientId?e.jsx("span",{className:t.routingBadge,children:n("connection.routing.priorityBadge","Priority")}):null})}),e.jsxs("td",{children:[e.jsx("span",{className:t.monoMuted,title:i.clientId,children:i.targetAlias}),e.jsx(D,{text:n("connection.targets.copyTargetAlias","Copy Studio ID"),children:e.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":n("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>R(i.targetAlias),children:e.jsx(_,{size:13,"aria-hidden":"true"})})})]}),e.jsx("td",{children:i.placeName??"-"}),e.jsxs("td",{children:[i.placeId??"-",i.placeId!==void 0?e.jsx(D,{text:n("connection.targets.copyPlaceId","Copy Place ID"),children:e.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":n("connection.targets.copyPlaceId","Copy Place ID"),onClick:()=>R(String(i.placeId)),children:e.jsx(_,{size:13,"aria-hidden":"true"})})}):null]}),e.jsx("td",{children:i.lastRoutedAt?G(i.lastRoutedAt,n):"-"}),e.jsx("td",{children:G(i.lastSeen,n)}),e.jsxs("td",{children:[e.jsx("span",{className:t.monoMuted,title:i.clientId,children:i.clientId.slice(0,10)}),e.jsx(D,{text:n("connection.targets.copyClientId","Copy Connection ID"),children:e.jsx("button",{type:"button",className:t.copyIconButton,"aria-label":n("connection.targets.copyClientId","Copy Connection ID"),onClick:()=>R(i.clientId),children:e.jsx(_,{size:13,"aria-hidden":"true"})})})]})]},i.clientId)):e.jsx("tr",{children:e.jsx("td",{colSpan:7,className:t.emptyRow,children:n("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")})})})]})})]})}const Y=["debug","info","warn","error"];function O({checked:o,onChange:s,testId:n,ariaLabel:d}){return e.jsxs("label",{className:t.toggleSwitch,"data-testid":n,children:[e.jsx("input",{type:"checkbox",className:t.toggleInput,checked:o,"aria-label":d,onChange:p=>s(p.target.checked)}),e.jsx("span",{className:t.toggleTrack,"aria-hidden":"true",children:e.jsx("span",{className:t.toggleThumb})})]})}function de({settings:o,updateHotSetting:s}){const{t:n}=P(),[d,p]=l.useState(null),h=l.useCallback(async(a,c)=>{try{await s(a,c),p(a),setTimeout(()=>p(g=>g===a?null:g),2e3)}catch{p(g=>g===a?null:g)}},[s]);return e.jsxs("div",{className:t.card,children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsx(T,{label:n("settings.general.title","General Settings"),tooltip:n("settings.general.title.tooltip","Hot settings that apply immediately when changed.")}),e.jsx(F,{text:n("settings.general.liveApply.tooltip","Changes in this section are applied immediately without a separate save button."),children:e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:n("settings.general.liveApply","Live Apply")})})]}),o?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.logLevel","Log Level"),tooltip:n("settings.general.logLevel.tooltip","Sets how much detail WEPPY Dashboard writes to its logs.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("select",{className:t.select,value:o.hot.LOG_LEVEL,onChange:a=>{const c=Y.find(g=>g===a.target.value);c&&h("LOG_LEVEL",c)},children:Y.map(a=>e.jsx("option",{value:a,children:a},a))}),d==="LOG_LEVEL"&&e.jsx("span",{className:t.savedIndicator,children:n("settings.general.applied")})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.localHistory","Tool History Recording"),tooltip:n("settings.general.localHistory.tooltip","Stores local tool execution history for the WEPPY Dashboard history views.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${d==="ENABLE_LOCAL_HISTORY"?"":t.savedIndicatorHidden}`,children:n("settings.general.applied","Applied")}),e.jsx(O,{checked:o.hot.ENABLE_LOCAL_HISTORY,ariaLabel:n("settings.general.localHistory","Tool History Recording"),testId:"settings-toggle-enable-local-history",onChange:a=>h("ENABLE_LOCAL_HISTORY",a)})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.localStatistics","Tool Statistics Collection"),tooltip:n("settings.general.localStatistics.tooltip","Aggregates local usage statistics for WEPPY Dashboard reporting.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${d==="ENABLE_LOCAL_STATISTICS"?"":t.savedIndicatorHidden}`,children:n("settings.general.applied","Applied")}),e.jsx(O,{checked:o.hot.ENABLE_LOCAL_STATISTICS,ariaLabel:n("settings.general.localStatistics","Tool Statistics Collection"),testId:"settings-toggle-enable-local-statistics",onChange:a=>h("ENABLE_LOCAL_STATISTICS",a)})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.contextCapture","Context Capture"),tooltip:n("settings.general.contextCapture.tooltip","When enabled, WEPPY Dashboard records structured execution context for changelog and playtest views.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${d==="ENABLE_CONTEXT_CAPTURE"?"":t.savedIndicatorHidden}`,children:n("settings.general.applied","Applied")}),e.jsx(O,{checked:o.hot.ENABLE_CONTEXT_CAPTURE,ariaLabel:n("settings.general.contextCapture","Context Capture"),testId:"settings-toggle-enable-context-capture",onChange:a=>h("ENABLE_CONTEXT_CAPTURE",a)})]})]}),e.jsxs("div",{className:t.settingRow,children:[e.jsx("span",{className:t.settingLabel,children:e.jsx(T,{label:n("settings.general.requestTimeout","Action Timeout"),tooltip:n("settings.general.requestTimeout.tooltip","Maximum time WEPPY Dashboard waits for an action before it fails.")})}),e.jsxs("div",{className:t.settingControl,children:[e.jsx("input",{type:"number",className:t.numberInput,value:o.hot.REQUEST_TIMEOUT,min:1e3,max:12e4,step:1e3,onChange:a=>{const c=parseInt(a.target.value,10);isNaN(c)||h("REQUEST_TIMEOUT",c)}}),e.jsx(F,{text:n("settings.general.requestTimeout.unit.tooltip","Action timeout is measured in milliseconds."),children:e.jsx("span",{className:t.unit,children:n("settings.general.requestTimeout.unit","ms")})}),d==="REQUEST_TIMEOUT"&&e.jsx("span",{className:t.savedIndicator,children:n("settings.general.applied","Applied")})]})]})]}):e.jsx("div",{className:t.loading,children:n("settings.unavailable")})]})}function ue({enabled:o,saving:s,onChange:n}){const{t:d}=P(),{search:p}=k(),h=l.useRef(null),a=l.useRef(null),c=l.useId(),[g,r]=l.useState(!1),[y,x]=l.useState("idle"),b=l.useMemo(()=>new URLSearchParams(p).get("section")==="luau-validation",[p]),N=s||g;l.useEffect(()=>{var u,f,v;b&&((f=(u=h.current)==null?void 0:u.scrollIntoView)==null||f.call(u,{block:"start",behavior:"smooth"}),(v=h.current)==null||v.focus())},[b]),l.useEffect(()=>()=>{a.current&&clearTimeout(a.current)},[]);const S=l.useCallback(async u=>{r(!0),x("idle"),a.current&&(clearTimeout(a.current),a.current=null);try{await n(u),x("applied"),a.current=setTimeout(()=>{x("idle"),a.current=null},2e3)}catch{x("failed")}finally{r(!1)}},[n]);return e.jsxs("div",{id:"controls-luau-validation",ref:h,tabIndex:-1,className:`${t.card} ${t.validationCard}`,"data-testid":"luau-syntax-validation-card",children:[e.jsxs("div",{className:t.cardHeader,children:[e.jsxs("div",{className:t.cardHeaderTitleGroup,children:[e.jsx("span",{children:d("controls.luauValidation.title","Luau Syntax Validation")}),e.jsx(Q,{topicId:"luauValidation",variant:"field",tooltip:d("controls.luauValidation.helpButton","How does it work?"),triggerClassName:`${t.cardHelpButton} ${t.touchTarget44}`})]}),e.jsx("span",{className:`${t.headerBadge} ${t.headerBadgeLive}`,children:d("settings.general.liveApply","Live Apply")})]}),e.jsxs("div",{className:t.validationSettingRow,children:[e.jsxs("div",{className:t.validationSettingCopy,children:[e.jsx("span",{id:c,className:t.validationSettingLabel,children:d("controls.luauValidation.settingLabel","Check automatically after Script edits")}),e.jsx("span",{className:t.validationSettingStatus,children:o?d("controls.luauValidation.state.on","Current: On"):d("controls.luauValidation.state.off","Current: Off")})]}),e.jsxs("div",{className:t.validationPolicyControl,children:[e.jsx("span",{className:`${t.savedIndicator} ${y==="failed"?t.savedIndicatorFailed:""} ${!N&&y==="idle"?t.savedIndicatorHidden:""}`,"data-testid":"luau-validation-save-feedback","aria-live":"polite",children:N?d("controls.luauValidation.saving","Saving…"):y==="applied"?d("controls.luauValidation.applied","Applied"):y==="failed"?d("controls.luauValidation.failed","Failed to apply"):null}),e.jsxs("label",{className:`${t.toggleSwitch} ${t.validationToggleTarget}`,"data-testid":"luau-validation-toggle",children:[e.jsx("input",{type:"checkbox",role:"switch",className:t.toggleInput,checked:o,disabled:N,"aria-labelledby":c,onChange:u=>{S(u.target.checked)}}),e.jsx("span",{className:t.toggleTrack,"aria-hidden":"true",children:e.jsx("span",{className:t.toggleThumb})})]})]})]})]})}function ve(){const{t:o}=P(),{search:s}=k(),{settings:n,updateHotSetting:d,saving:p,loading:h}=ae();return l.useMemo(()=>new URLSearchParams(s).get("section"),[s])==="license"?e.jsx(ne,{to:"/settings?section=license",replace:!0}):h?e.jsx("div",{className:t.page,children:e.jsx("div",{className:t.loading,children:o("common.loading")})}):e.jsxs("div",{className:t.page,children:[e.jsx(oe,{title:o("page.controls.title","Controls"),description:o("page.controls.description","Manage project root, Studio routing, and MCP live settings."),helpTopicId:"controls"}),e.jsx(le,{}),e.jsx(re,{}),e.jsx(ue,{enabled:(n==null?void 0:n.hot.SCRIPT_WRITE_VALIDATION_ENABLED)??!1,saving:p,onChange:c=>d("SCRIPT_WRITE_VALIDATION_ENABLED",c)}),e.jsx(de,{settings:n,updateHotSetting:d})]})}export{ve as Component};
|
package/dashboard/dist/assets/{CurrentPlaceScope-B60o8hpn.js → CurrentPlaceScope-DhPCqaMU.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as m,r as f,j as c,g as _}from"./index-
|
|
1
|
+
import{u as m,r as f,j as c,g as _}from"./index-DchewB5y.js";import{B as x}from"./PageHeader-CYbeZdtL.js";const j="_scope_to3mp_1",I="_main_to3mp_13",w="_label_to3mp_20",A="_selectorLabel_to3mp_28",L="_placeSelect_to3mp_35",k="_name_to3mp_48",y="_id_to3mp_59",E="_scopeBadge_to3mp_66",B="_copy_to3mp_70",U="_note_to3mp_82",n={scope:j,main:I,label:w,selectorLabel:A,placeSelect:L,name:k,id:y,scopeBadge:E,copy:B,note:U};function d(e,l){return l===null?null:e.places.find(a=>a.placeId===l)??null}function S(e){var l;return e.lastActivePlaceId!==null?e.lastActivePlaceId:((l=e.places[0])==null?void 0:l.placeId)??null}function N(e){return e.pluginConnected&&e.activePlaceId!==null?e.activePlaceId:S(e)}function q(e,l){if(e.pluginConnected&&e.activePlaceId!==null){const t=d(e,e.activePlaceId);return{label:l("placeScope.current.label","Current Place"),placeId:e.activePlaceId,placeName:e.activePlaceName??(t==null?void 0:t.placeName)??l("placeScope.unknownPlace","Unknown place"),badge:l("placeScope.live","Live"),live:!0,note:null}}const a=S(e),s=d(e,a);if(a!==null){const t=a===e.lastActivePlaceId?e.lastActivePlaceName:null;return{label:l("placeScope.lastActive.label","Last Active Place"),placeId:a,placeName:t??(s==null?void 0:s.placeName)??l("placeScope.unknownPlace","Unknown place"),badge:l("placeScope.pluginRequired","Plugin required"),live:!1,note:l("placeScope.pluginRequired.note","Connect WEPPY Plugin to confirm the live active place.")}}return{label:l("placeScope.noPlace.label","Place scope"),placeId:null,placeName:l("placeScope.noPlace.value","No place data available yet"),badge:l("placeScope.noPlace.badge","No place"),live:!1,note:l("placeScope.noPlace.note","Connect WEPPY Plugin and sync a place to create place-scoped data.")}}function F(e,l,a){const s=typeof l=="number"?d(e,l):null,t=N(e),o=(s==null?void 0:s.placeId)??t,r=d(e,o);if(o===null)return{label:a("placeScope.noPlace.label","Place scope"),placeId:null,placeName:a("placeScope.noPlace.value","No place data available yet"),badge:a("placeScope.noPlace.badge","No place"),live:!1,note:a("placeScope.noPlace.note","Connect WEPPY Plugin and sync a place to create place-scoped data.")};const u=e.pluginConnected&&e.activePlaceId===o,b=o===e.lastActivePlaceId?e.lastActivePlaceName:null;return{label:u?a("placeScope.current.label","Current Place"):a("placeScope.selected.label","Selected Place"),placeId:o,placeName:(r==null?void 0:r.placeName)??b??a("placeScope.unknownPlace","Unknown place"),badge:u?a("placeScope.live","Live"):a("placeScope.stored","Stored"),live:u,note:u?null:a("placeScope.selected.note","Showing stored data only. Studio routing is unchanged.")}}function R(e,l){switch(e){case"sync":return l("placeScope.surface.sync","Sync status and logs use this place.");case"changelog":return l("placeScope.surface.changelog","Changelog sessions use this place.");case"playtest":return l("placeScope.surface.playtest","Playtest reports use this place.");case"uiStudio":return l("placeScope.surface.uiStudio","UI captures and change history use this place.");case"tools":return l("placeScope.surface.tools","Tool history and statistics use this place.")}}function Y({surface:e,selectable:l=!1,selectedPlaceId:a=null,onSelectedPlaceIdChange:s}){const{t}=m(),[o,r]=f.useState(null),[u,b]=f.useState(!0);if(f.useEffect(()=>{let p=!1;async function v(){try{const h=await _();p||r(h)}catch{p||r(null)}finally{p||b(!1)}}return v(),()=>{p=!0}},[]),f.useEffect(()=>{if(!l||!o)return;const p=N(o);(typeof a!="number"||!d(o,a))&&a!==p&&(s==null||s(p))},[s,l,a,o]),u)return c.jsx("div",{className:n.scope,"aria-live":"polite",children:c.jsx("span",{className:n.label,children:t("placeScope.loading","Loading place scope...")})});if(!o)return c.jsx("div",{className:n.scope,"aria-live":"polite",children:c.jsx("span",{className:n.label,children:t("placeScope.unavailable","Place scope unavailable")})});const i=l?F(o,a,t):q(o,t),P=typeof i.placeId=="number"?String(i.placeId):"",g=l&&o.places.length>0;return c.jsxs("div",{className:n.scope,"aria-live":"polite",children:[c.jsxs("div",{className:n.main,children:[g?c.jsxs(c.Fragment,{children:[c.jsxs("label",{className:n.selectorLabel,children:[c.jsx("span",{className:n.label,children:t("placeScope.selector.label","Place data")}),c.jsx("select",{className:n.placeSelect,value:P,onChange:p=>{const v=Number.parseInt(p.currentTarget.value,10);s==null||s(Number.isInteger(v)?v:null)},children:o.places.map(p=>c.jsxs("option",{value:p.placeId,children:[p.placeName," (",p.placeId,")"]},p.placeId))})]}),c.jsx("span",{className:n.label,children:i.label}),c.jsx("span",{className:n.name,children:i.placeName})]}):c.jsxs(c.Fragment,{children:[c.jsx("span",{className:n.label,children:i.label}),c.jsx("span",{className:n.name,children:i.placeName})]}),i.placeId!==null?c.jsx("span",{className:n.id,children:i.placeId}):null,c.jsx(x,{variant:i.live?"success":"warning",shape:"pill",className:n.scopeBadge,children:i.badge})]}),c.jsxs("div",{className:n.copy,children:[c.jsx("span",{children:R(e,t)}),i.note?c.jsx("span",{className:n.note,children:i.note}):null]})]})}export{Y as C};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{u as _,r as x,j as e}from"./index-
|
|
1
|
+
import{u as _,r as x,j as e}from"./index-DchewB5y.js";const N="_container_uv8oc_2",j="_header_uv8oc_10",v="_modeBtn_uv8oc_18",g="_modeBtnActive_uv8oc_33",w="_unifiedView_uv8oc_40",L="_diffLine_uv8oc_46",b="_lineNum_uv8oc_55",C="_lineContent_uv8oc_64",S="_lineAdded_uv8oc_68",V="_lineRemoved_uv8oc_73",B="_lineContext_uv8oc_78",$="_sideBySide_uv8oc_83",A="_sidePane_uv8oc_90",P="_sideLabel_uv8oc_100",R="_sideContent_uv8oc_112",D="_empty_uv8oc_117",s={container:N,header:j,modeBtn:v,modeBtnActive:g,unifiedView:w,diffLine:L,lineNum:b,lineContent:C,lineAdded:S,lineRemoved:V,lineContext:B,sideBySide:$,sidePane:A,sideLabel:P,sideContent:R,empty:D};function k(n,i){const l=n.split(`
|
|
2
2
|
`),d=i.split(`
|
|
3
3
|
`),a=[],f=Math.max(l.length,d.length);let t=0,r=0;for(;(t<l.length||r<d.length)&&(t<l.length&&r<d.length?l[t]===d[r]?(a.push({type:"context",content:l[t],lineNum:r+1}),t++,r++):(a.push({type:"removed",content:l[t],lineNum:t+1}),t++,t<l.length&&l[t]===d[r]?(a.push({type:"added",content:d[r],lineNum:r+1}),r++):r<d.length&&(a.push({type:"added",content:d[r],lineNum:r+1}),r++)):t<l.length?(a.push({type:"removed",content:l[t],lineNum:t+1}),t++):r<d.length&&(a.push({type:"added",content:d[r],lineNum:r+1}),r++),!(a.length>f*3)););return a}function O({before:n,after:i}){const{t:l}=_(),[d,a]=x.useState("unified"),f=typeof n=="string"?n:n!=null?JSON.stringify(n,null,2):"",t=typeof i=="string"?i:i!=null?JSON.stringify(i,null,2):"",r=x.useMemo(()=>k(f,t),[f,t]);if(!f&&!t)return e.jsx("div",{className:s.container,children:e.jsx("div",{className:s.empty,children:l("changelog.diff.empty","No diff available")})});if(!f&&t){const c=t.split(`
|
|
4
4
|
`);return e.jsx("div",{className:s.container,children:e.jsx("div",{className:s.unifiedView,children:c.map((u,m)=>e.jsxs("div",{className:`${s.diffLine} ${s.lineAdded}`,children:[e.jsx("span",{className:s.lineNum,children:m+1}),e.jsxs("span",{className:s.lineContent,children:["+ ",u]})]},m))})})}return e.jsxs("div",{className:s.container,children:[e.jsxs("div",{className:s.header,children:[e.jsx("button",{className:`${s.modeBtn} ${d==="unified"?s.modeBtnActive:""}`,onClick:()=>a("unified"),children:l("changelog.diff.unified","Unified")}),e.jsx("button",{className:`${s.modeBtn} ${d==="side-by-side"?s.modeBtnActive:""}`,onClick:()=>a("side-by-side"),children:l("changelog.diff.sideBySide","Side by Side")})]}),d==="unified"?e.jsx("div",{className:s.unifiedView,children:r.map((c,u)=>e.jsxs("div",{className:`${s.diffLine} ${c.type==="added"?s.lineAdded:c.type==="removed"?s.lineRemoved:s.lineContext}`,children:[e.jsx("span",{className:s.lineNum,children:c.lineNum??""}),e.jsxs("span",{className:s.lineContent,children:[c.type==="added"?"+ ":c.type==="removed"?"- ":" ",c.content]})]},u))}):e.jsxs("div",{className:s.sideBySide,children:[e.jsxs("div",{className:s.sidePane,children:[e.jsx("div",{className:s.sideLabel,children:l("changelog.diff.before","Before")}),e.jsx("div",{className:s.sideContent,children:f.split(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as r,h as e}from"./index-
|
|
1
|
+
import{j as r,h as e}from"./index-DchewB5y.js";function s({label:t,tooltip:o}){return r.jsx(e,{text:o,children:t})}export{s as I};
|