@weppy/roblox-mcp 2.14.6 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dashboard/dist/assets/{AssetsPage-DfB3E1vb.js → AssetsPage-D3-InAlf.js} +1 -1
  3. package/dashboard/dist/assets/{ChangelogDetailPage-C-VVfjbe.js → ChangelogDetailPage-fmLGEZVO.js} +1 -1
  4. package/dashboard/dist/assets/{ChangelogPage-CkSIdLom.js → ChangelogPage-6KtWInS5.js} +1 -1
  5. package/dashboard/dist/assets/{ConfirmModal-BXbkJq3w.js → ConfirmModal-DJp4ax33.js} +1 -1
  6. package/dashboard/dist/assets/ConnectionPage-D375gmxK.js +11 -0
  7. package/dashboard/dist/assets/{ControlsPage-CBnZkDGD.js → ControlsPage-C7zSLjWc.js} +1 -1
  8. package/dashboard/dist/assets/{CurrentPlaceScope-DJheb09C.js → CurrentPlaceScope-DrtUw6py.js} +1 -1
  9. package/dashboard/dist/assets/{GameChangeDetail-3hQlAqDP.js → GameChangeDetail-Bd5Hg2ZD.js} +1 -1
  10. package/dashboard/dist/assets/{InfoLabel-Cc4MKAYc.js → InfoLabel-HLPMIIL4.js} +1 -1
  11. package/dashboard/dist/assets/{OverviewPage-lps48EeB.js → OverviewPage-Bmem2hyc.js} +1 -1
  12. package/dashboard/dist/assets/{PageHeader-DezmLDg1.js → PageHeader-Cvi0LO4r.js} +1 -1
  13. package/dashboard/dist/assets/{PlaytestPage-N2blmofL.js → PlaytestPage-ChFkixWj.js} +1 -1
  14. package/dashboard/dist/assets/{SettingsPage-D1Et0FOx.js → SettingsPage-v3EWZSAn.js} +1 -1
  15. package/dashboard/dist/assets/{StatusBadge-C3ARQLqC.js → StatusBadge-Cf1Ncow3.js} +1 -1
  16. package/dashboard/dist/assets/{SyncPage-DXgj8uBq.js → SyncPage-BG7u00IT.js} +1 -1
  17. package/dashboard/dist/assets/{Tabs-iku37C2G.js → Tabs-2QEkInbt.js} +1 -1
  18. package/dashboard/dist/assets/{ToolsPage-Cpz4X8R_.js → ToolsPage-DbtQxCAM.js} +1 -1
  19. package/dashboard/dist/assets/{TooltipText-CMx5IM6p.js → TooltipText-1fJvqtMt.js} +1 -1
  20. package/dashboard/dist/assets/{UiPrimitive-ojecpNs1.js → UiPrimitive-CsV5QE01.js} +1 -1
  21. package/dashboard/dist/assets/{UiStudioPage-htI6Z7xJ.js → UiStudioPage-ZLA3xIIN.js} +1 -1
  22. package/dashboard/dist/assets/{WhatsNewPage-DAQ11-Xx.js → WhatsNewPage-S4qEx4iN.js} +1 -1
  23. package/dashboard/dist/assets/{copy-BCrOOq8E.js → copy-d0x3Roiq.js} +1 -1
  24. package/dashboard/dist/assets/{index-B1MZBjK4.js → index-C_exRd2o.js} +67 -35
  25. package/dashboard/dist/assets/{sample-requests-DXD3uKZy.js → sample-requests-BRAniRWZ.js} +1 -1
  26. package/dashboard/dist/assets/{useLiveUptime-fm3oNIW5.js → useLiveUptime-D0TQTjV7.js} +1 -1
  27. package/dashboard/dist/assets/{useSettings-BGSD8gFB.js → useSettings-DlZqZGnP.js} +1 -1
  28. package/dashboard/dist/index.html +1 -1
  29. package/dist/index.js +248 -243
  30. package/package.json +1 -1
  31. package/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
  32. package/dashboard/dist/assets/ConnectionPage-ECCqDYiG.js +0 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weppy/roblox-mcp",
3
- "version": "2.14.6",
3
+ "version": "2.15.0",
4
4
  "description": "MCP (Model Context Protocol) server for Roblox Studio integration - enables AI coding agents to interact with Roblox Studio in real-time",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
Binary file
@@ -1,11 +0,0 @@
1
- import{i as tt,u as et,r as d,j as t,f as nt,a as U,D as st,L as it,M as ct,k as W,e as at,l as lt,s as rt}from"./index-B1MZBjK4.js";import{I as p}from"./InfoLabel-Cc4MKAYc.js";import{P as dt}from"./PageHeader-DezmLDg1.js";import{S as ot}from"./StatusBadge-C3ARQLqC.js";import{T as X}from"./TooltipText-CMx5IM6p.js";import{C as J}from"./ConfirmModal-BXbkJq3w.js";import{u as gt,f as ut}from"./useLiveUptime-fm3oNIW5.js";import{C as K}from"./copy-BCrOOq8E.js";import"./UiPrimitive-ojecpNs1.js";import"./ConfirmModal.module-DJksQHBd.js";/**
2
- * @license lucide-react v1.8.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const pt=[["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"}]],ht=tt("bot",pt);/**
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 yt=[["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"}]],mt=tt("server",yt),xt="_container_1h084_2",_t="_entry_1h084_14",St="_timestamp_1h084_21",jt="_message_1h084_27",vt="_warn_1h084_34",kt="_error_1h084_39",ft="_empty_1h084_44",F={container:xt,entry:_t,timestamp:St,message:jt,warn:vt,error:kt,empty:ft};function Ct(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 bt({entries:e}){const{t:s}=et(),n=d.useRef(null);return d.useEffect(()=>{const i=n.current;i&&(i.scrollTop=i.scrollHeight)},[e.length]),t.jsx("div",{ref:n,className:F.container,children:e.length===0?t.jsx("div",{className:F.empty,children:s("connection.log.empty","No events yet")}):e.map((i,r)=>t.jsxs("div",{className:`${F.entry} ${i.type?F[i.type]:""}`,children:[t.jsx("span",{className:F.timestamp,children:Ct(i.timestamp)}),t.jsx("span",{className:F.message,children:i.message})]},r))})}const Q=50;function wt(){const e=new Date;return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function Nt(){const{level:e,status:s,error:n}=nt(),[i,r]=d.useState(null),[y,g]=d.useState(null),[c,N]=d.useState([]),C=d.useRef(null),A=d.useCallback((u,j)=>{N(w=>{const S=[...w,{timestamp:wt(),message:u,type:j}];return S.length>Q?S.slice(-Q):S})},[]),m=d.useCallback(async()=>{try{const u=await U.get("/connection-info");r(u)}catch{r(null)}},[]),M=d.useCallback(async()=>{try{const u=await U.get("/api/dashboard/studio-routing");g(u)}catch{g(null)}},[]),I=d.useCallback(async u=>{const j=await U.patch("/api/dashboard/studio-routing",u);return g(j),await m(),j},[m]),$=d.useCallback(async()=>{try{const u=await U.get("/api/dashboard/connection-log");N(u.entries??[])}catch{N([])}},[]),H=d.useCallback(async()=>{await U.post("/api/dashboard/connection-log/clear"),N([])},[]),b=d.useCallback(async u=>{await U.post("/api/dashboard/kill-agent",{instanceId:u}),await m()},[m]);return d.useEffect(()=>{e!=="disconnected"&&s?(m(),M()):g(null),$()},[e,s,m,$,M]),d.useEffect(()=>{const u=new st;C.current=u,u.connect();const j=u.on("connection",S=>{const h=S;h.status!=="updated"&&h.clientId&&A(`Plugin ${h.status} — ${h.clientId}`,h.status==="disconnected"?"warn":"info"),m(),M()}),w=u.on("mcp_status",S=>{const h=S,z=h.status==="registered"?"registered":"unregistered";A(`MCP ${z} — ${h.aiClientName}`,h.status==="registered"?"info":"warn"),m(),M()});return()=>{j(),w(),u.disconnect(),C.current=null}},[A,m,M]),{status:s,connectionInfo:i,studioRouting:y,connectionLog:c,level:e,error:n,clearConnectionLog:H,killAgent:b,updateStudioRouting:I}}const It="_page_14kg9_2",Lt="_card_14kg9_11",At="_topologyCard_14kg9_19",Mt="_topologyDisconnected_14kg9_26",Pt="_topologyHeader_14kg9_30",Bt="_topologyIntro_14kg9_38",$t="_topologyNetwork_14kg9_45",Et="_topologyLinks_14kg9_49",Tt="_topologyLink_14kg9_49",Ht="_topologyLink_agent_14kg9_66",Dt="_topologyLink_studio_14kg9_70",Ot="_topologyGrid_14kg9_74",Ut="_topologyColumn_14kg9_83",Ft="_topologyColumnHeader_14kg9_90",zt="_topologyColumnHeaderSpacer_14kg9_101",Gt="_topologyCount_14kg9_105",Wt="_topologyList_14kg9_120",qt="_topologyListCentered_14kg9_128",Vt="_topologyNode_14kg9_132",Kt="_topologyNodeTitle_14kg9_140",Yt="_topologyNodeMeta_14kg9_156",Rt="_topologyNodeSubtle_14kg9_157",Xt="_topologyState_14kg9_170",Jt="_topologyEmpty_14kg9_183",Qt="_topologyOverflow_14kg9_198",Zt="_topologyOverflowButton_14kg9_213",te="_topologyServerColumn_14kg9_236",ee="_topologyServer_14kg9_236",oe="_topologyServerIcon_14kg9_254",ne="_topologyServerBody_14kg9_267",se="_topologyServerTitle_14kg9_276",ie="_topologyServerMeta_14kg9_283",ce="_routingSummaryCompact_14kg9_290",ae="_disabled_14kg9_298",le="_cardHeader_14kg9_304",re="_cardHint_14kg9_317",de="_clearButton_14kg9_324",ge="_serverGrid_14kg9_348",ue="_statusRow_14kg9_366",pe="_metaItem_14kg9_373",he="_table_14kg9_380",ye="_tableWrap_14kg9_400",me="_routingSummary_14kg9_290",xe="_manageLink_14kg9_416",_e="_segment_14kg9_442",Se="_segmentActive_14kg9_443",je="_targetPrimary_14kg9_477",ve="_monoMuted_14kg9_481",ke="_copyIconButton_14kg9_485",fe="_routingBadge_14kg9_510",Ce="_studioStateBadge_14kg9_524",be="_studioState_running_14kg9_539",we="_studioState_paused_14kg9_545",Ne="_studioState_edit_14kg9_551",Ie="_studioState_unknown_14kg9_557",Le="_toggleBtn_14kg9_564",Ae="_disconnected_14kg9_579",Me="_disconnectedActions_14kg9_596",Pe="_btn_14kg9_603",Be="_activity_active_14kg9_621",$e="_activity_stale_14kg9_622",Ee="_activity_unknown_14kg9_623",Te="_killBtn_14kg9_647",He="_emptyRow_14kg9_671",o={page:It,card:Lt,topologyCard:At,topologyDisconnected:Mt,topologyHeader:Pt,topologyIntro:Bt,topologyNetwork:$t,topologyLinks:Et,topologyLink:Tt,topologyLink_agent:Ht,topologyLink_studio:Dt,topologyGrid:Ot,topologyColumn:Ut,topologyColumnHeader:Ft,topologyColumnHeaderSpacer:zt,topologyCount:Gt,topologyList:Wt,topologyListCentered:qt,topologyNode:Vt,topologyNodeTitle:Kt,topologyNodeMeta:Yt,topologyNodeSubtle:Rt,topologyState:Xt,topologyEmpty:Jt,topologyOverflow:Qt,topologyOverflowButton:Zt,topologyServerColumn:te,topologyServer:ee,topologyServerIcon:oe,topologyServerBody:ne,topologyServerTitle:se,topologyServerMeta:ie,routingSummaryCompact:ce,disabled:ae,cardHeader:le,cardHint:re,clearButton:de,serverGrid:ge,statusRow:ue,metaItem:pe,table:he,tableWrap:ye,routingSummary:me,manageLink:xe,segment:_e,segmentActive:Se,targetPrimary:je,monoMuted:ve,copyIconButton:ke,routingBadge:fe,studioStateBadge:Ce,studioState_running:be,studioState_paused:we,studioState_edit:Ne,studioState_unknown:Ie,toggleBtn:Le,disconnected:Ae,disconnectedActions:Me,btn:Pe,activity_active:Be,activity_stale:$e,activity_unknown:Ee,killBtn:Te,emptyRow:He},V=5;function De(e){return e?Date.now()-e<3e4?"active":"stale":"unknown"}function Oe(e,s){return e==="active"?s("connection.topology.active","Active"):e==="stale"?s("connection.topology.stale","Stale"):s("connection.topology.unknown","Unknown")}function Ue(e){return e.length>10?e.slice(0,10):e}function Z(e,s){return e.replace("{count}",String(s))}function Fe(e,s,n){const i=e.studioState??"unknown",r={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"),g=e.studioStateUpdatedAt?n(e.studioStateUpdatedAt):s("connection.targets.studioState.updatedUnknown","not reported");return{state:i,label:r[i],tooltip:`${y} · ${g}`}}function ze(e,s){return e.length!==s.length?!1:e.every((n,i)=>{const r=s[i];return r!==void 0&&n.id===r.id&&n.side===r.side&&Math.abs(n.x1-r.x1)<.5&&Math.abs(n.y1-r.y1)<.5&&Math.abs(n.x2-r.x2)<.5&&Math.abs(n.y2-r.y2)<.5})}function f(e,s,n){return{x:s-e.left,y:n-e.top}}function Ge(e,s,n,i){if(s.right<=n.left){const g=f(i,s.right,s.top+s.height/2),c=f(i,n.left,n.top+n.height/2);return{id:e,side:"agent",x1:g.x,y1:g.y,x2:c.x,y2:c.y}}if(s.bottom<=n.top){const g=f(i,s.left+s.width/2,s.bottom),c=f(i,n.left+n.width/2,n.top);return{id:e,side:"agent",x1:g.x,y1:g.y,x2:c.x,y2:c.y}}const r=f(i,s.left+s.width/2,s.top),y=f(i,n.left+n.width/2,n.bottom);return{id:e,side:"agent",x1:r.x,y1:r.y,x2:y.x,y2:y.y}}function We(e,s,n,i){if(n.right<=s.left){const g=f(i,s.left,s.top+s.height/2),c=f(i,n.right,n.top+n.height/2);return{id:e,side:"studio",x1:g.x,y1:g.y,x2:c.x,y2:c.y}}if(n.bottom<=s.top){const g=f(i,s.left+s.width/2,s.top),c=f(i,n.left+n.width/2,n.bottom);return{id:e,side:"studio",x1:g.x,y1:g.y,x2:c.x,y2:c.y}}const r=f(i,s.left+s.width/2,s.bottom),y=f(i,n.left+n.width/2,n.top);return{id:e,side:"studio",x1:r.x,y1:r.y,x2:y.x,y2:y.y}}function qe({agents:e,isDisconnected:s,pinnedTargetClientId:n,priorityTarget:i,status:r,studioRoutingMode:y,studioTargets:g,t:c,timeAgo:N,onCopySelector:C,onManageRouting:A}){const[m,M]=d.useState(!1),[I,$]=d.useState(!1),[H,b]=d.useState([]),u=d.useRef(null),j=d.useRef(null),w=d.useRef(new Map),S=d.useRef(new Map),h=y==="pinned"?c("connection.routing.pinned","Manual: Pinned Studio"):c("connection.routing.recentPriority","Automatic: Recent priority"),z=s?"offline":"online",k=d.useMemo(()=>m?e:e.slice(0,V),[e,m]),D=Math.max(0,e.length-k.length),v=d.useMemo(()=>I?g:g.slice(0,V),[g,I]),E=Math.max(0,g.length-v.length),Y=[o.topologyList,k.length<=1?o.topologyListCentered:""].filter(Boolean).join(" "),R=[o.topologyList,v.length<=1?o.topologyListCentered:""].filter(Boolean).join(" "),O=d.useCallback(a=>x=>{if(x){w.current.set(a,x);return}w.current.delete(a)},[]),l=d.useCallback(a=>x=>{if(x){S.current.set(a,x);return}S.current.delete(a)},[]),L=d.useCallback(()=>{const a=u.current,x=j.current;if(!a||!x){b([]);return}const _=a.getBoundingClientRect(),P=x.getBoundingClientRect(),q=[];k.forEach(B=>{const G=w.current.get(B.instanceId);G&&q.push(Ge(`agent-${B.instanceId}`,G.getBoundingClientRect(),P,_))}),v.forEach(B=>{const G=S.current.get(B.clientId);G&&q.push(We(`studio-${B.clientId}`,G.getBoundingClientRect(),P,_))}),b(B=>ze(B,q)?B:q)},[k,v]);return d.useLayoutEffect(()=>{L();const a=[u.current,j.current,...k.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,k,v]),t.jsxs("section",{className:`${o.topologyCard} ${s?o.topologyDisconnected:""}`,"aria-label":c("connection.topology.ariaLabel","Connection topology"),children:[t.jsxs("div",{className:o.topologyHeader,children:[t.jsxs("div",{children:[t.jsx("div",{className:o.cardHeader,children:c("connection.topology.title","Connection topology")}),t.jsx("p",{className:o.topologyIntro,children:c("connection.topology.description","AI agents and Roblox Studio windows connect through one WEPPY MCP Server.")})]}),t.jsx(it,{to:"/controls?section=studio-routing",className:o.manageLink,onClick:A,children:c("connection.routing.manage","Manage routing")})]}),t.jsxs("div",{className:o.topologyNetwork,ref:u,children:[t.jsx("svg",{"aria-hidden":"true",className:o.topologyLinks,"data-testid":"topology-connection-lines",focusable:"false",children:H.map(a=>t.jsx("line",{className:`${o.topologyLink} ${o[`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))}),t.jsxs("div",{className:o.topologyGrid,children:[t.jsxs("div",{className:o.topologyColumn,children:[t.jsxs("div",{className:o.topologyColumnHeader,children:[t.jsx(ht,{size:15,"aria-hidden":"true"}),t.jsx("span",{children:c("connection.agents.title","AI Agents")}),t.jsx("span",{className:o.topologyCount,children:e.length})]}),t.jsxs("div",{className:Y,children:[e.length>0?k.map(a=>{const x=De(a.lastSeen),_=a.aiClientName??Ue(a.instanceId),P=a.lastSeen??a.lastCommandAt??a.connectedAt;return t.jsxs("div",{className:o.topologyNode,ref:O(a.instanceId),children:[t.jsxs("div",{className:o.topologyNodeTitle,children:[t.jsx("span",{className:o[`activity_${x}`]}),t.jsx("strong",{children:_}),t.jsx("span",{className:o.topologyState,children:Oe(x,c)})]}),t.jsx("div",{className:o.topologyNodeMeta,children:P?`${c("connection.topology.lastActivity","Last activity")} ${N(P)}`:c("connection.topology.noActivity","No recent activity")})]},a.instanceId)}):t.jsx("div",{className:o.topologyEmpty,children:c("connection.agents.none","No agents connected")}),e.length>V?t.jsxs("div",{className:o.topologyOverflow,children:[D>0?t.jsx("span",{children:Z(c("connection.topology.moreAgents","+{count} more agents"),D)}):t.jsx("span",{children:c("connection.topology.allAgentsVisible","All agents visible")}),t.jsx("button",{type:"button",className:o.topologyOverflowButton,"aria-label":m?c("connection.topology.showLessAgents","Show less AI agents"):c("connection.topology.showAllAgents","Show all AI agents"),onClick:()=>M(a=>!a),children:m?c("connection.topology.showLess","Show less"):c("connection.topology.showAll","Show all")})]}):null]})]}),t.jsxs("div",{className:o.topologyServerColumn,children:[t.jsx("div",{className:o.topologyColumnHeaderSpacer,"aria-hidden":"true"}),t.jsxs("div",{className:`${o.topologyNode} ${o.topologyServer}`,ref:j,children:[t.jsx("div",{className:o.topologyServerIcon,children:t.jsx(mt,{size:18,"aria-hidden":"true"})}),t.jsxs("div",{className:o.topologyServerBody,children:[t.jsx("div",{className:o.topologyServerTitle,children:c("connection.topology.serverTitle","MCP Server")}),t.jsx(ot,{status:z}),t.jsxs("div",{className:o.topologyServerMeta,children:[r!=null&&r.version?`v${r.version}`:c("connection.topology.versionUnknown","Version unknown"),r!=null&&r.sessionId?` · ${c("connection.server.session","Session")} ${r.sessionId.slice(0,8)}`:""]}),t.jsx("div",{className:o.routingSummaryCompact,children:t.jsx("span",{className:o.routingBadge,children:h})})]})]})]}),t.jsxs("div",{className:o.topologyColumn,children:[t.jsxs("div",{className:o.topologyColumnHeader,children:[t.jsx(ct,{size:15,"aria-hidden":"true"}),t.jsx("span",{children:c("connection.targets.title","Studio Targets")}),t.jsx("span",{className:o.topologyCount,children:g.length})]}),t.jsxs("div",{className:R,children:[g.length>0?v.map(a=>{const x=y==="pinned"&&n===a.clientId,_=y==="recentPriority"&&(i==null?void 0:i.clientId)===a.clientId,P=Fe(a,c,N);return t.jsxs("div",{className:o.topologyNode,ref:l(a.clientId),children:[t.jsxs("div",{className:o.topologyNodeTitle,children:[t.jsx("span",{className:o.targetPrimary,children:a.targetAlias}),t.jsx(W,{text:c("connection.targets.copyTargetAlias","Copy Studio ID"),children:t.jsx("button",{type:"button",className:o.copyIconButton,"aria-label":c("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>C(a.targetAlias,"target_alias"),children:t.jsx(K,{size:13,"aria-hidden":"true"})})}),x?t.jsx("span",{className:o.routingBadge,children:c("connection.routing.pinnedBadge","Pinned")}):_?t.jsx("span",{className:o.routingBadge,children:c("connection.routing.priorityBadge","Priority")}):null,t.jsx(W,{text:P.tooltip,children:t.jsx("span",{className:`${o.studioStateBadge} ${o[`studioState_${P.state}`]}`,children:P.label})})]}),t.jsxs("div",{className:o.topologyNodeMeta,children:[t.jsx("span",{children:a.placeName??c("connection.topology.placeUnknown","Place unknown")}),a.placeId!==void 0?` · ${a.placeId}`:""]}),t.jsxs("div",{className:o.topologyNodeSubtle,children:[a.connectionState," · ",c("connection.targets.lastSeen","Last Seen")," ",N(a.lastSeen)]})]},a.clientId)}):t.jsx("div",{className:o.topologyEmpty,children:c("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")}),g.length>V?t.jsxs("div",{className:o.topologyOverflow,children:[E>0?t.jsx("span",{children:Z(c("connection.topology.moreStudios","+{count} more studios"),E)}):t.jsx("span",{children:c("connection.topology.allStudiosVisible","All studios visible")}),t.jsx("button",{type:"button",className:o.topologyOverflowButton,"aria-label":I?c("connection.topology.showLessStudios","Show less Studio targets"):c("connection.topology.showAllStudios","Show all Studio targets"),onClick:()=>$(a=>!a),children:I?c("connection.topology.showLess","Show less"):c("connection.topology.showAll","Show all")})]}):null]})]})]})]})]})}function T(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 Ve(e){return e?Date.now()-e<3e4?"active":"stale":"unknown"}function Ke(e,s){const n=e.studioState??"unknown",i={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")},r=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?T(e.studioStateUpdatedAt,s):s("connection.targets.studioState.updatedUnknown","not reported"),g=e.playtestMode&&e.playtestMode!=="unknown"?` · ${e.playtestMode}`:"";return{state:n,label:`${i[n]}${g}`,tooltip:`${r} · ${y}`}}function so(){const{t:e}=et(),{trackEvent:s}=at(),{status:n,connectionInfo:i,studioRouting:r,connectionLog:y,level:g,clearConnectionLog:c,killAgent:N}=Nt(),{show:C}=lt(),[A,m]=d.useState(!0),[M,I]=d.useState(!1),[$,H]=d.useState(!1),[b,u]=d.useState(null),[j,w]=d.useState(!1),S=gt(n==null?void 0:n.uptime),h=g==="disconnected",z=h?"offline":"online",k=(r==null?void 0:r.studioRoutingMode)??(n==null?void 0:n.studioRoutingMode)??"recentPriority",D=(r==null?void 0:r.pinnedTargetClientId)??(n==null?void 0:n.pinnedTargetClientId)??null,v=rt((r==null?void 0:r.targets)??(n==null?void 0:n.pluginClients)??[],k,D),E=(r==null?void 0:r.priorityTarget)??v[0],Y=async()=>{if(b){w(!0);try{await N(b.instanceId),C(e("connection.agents.killed","Agent killed"),"success"),u(null)}catch{C(e("connection.agents.killFailed","Failed to kill agent"),"error")}finally{w(!1)}}},R=async()=>{H(!0);try{await c(),C(e("toast.clearSuccess","Cleared successfully"),"success"),I(!1)}catch{C(e("toast.clearFailed","Failed to clear data"),"error")}finally{H(!1)}},O=async(l,L)=>{try{await navigator.clipboard.writeText(l),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 t.jsxs("div",{className:o.page,children:[t.jsx(dt,{title:e("page.connection.title","Connection"),description:e("page.connection.description","Inspect MCP server, AI agent, Studio plugin, and connection log status."),helpTopicId:"connection",helpState:{connectionLevel:g}}),t.jsx(qe,{agents:(i==null?void 0:i.mcpInstances)??[],isDisconnected:h,pinnedTargetClientId:D,priorityTarget:E,status:n??null,studioRoutingMode:k,studioTargets:v,t:e,timeAgo:l=>T(l,e),onCopySelector:O,onManageRouting:()=>s("dashboard_click_event",{click_target:"connection_manage_routing",page:"connection"})}),t.jsxs("div",{className:o.card,children:[t.jsx("div",{className:o.cardHeader,children:e("connection.server.title","Server Status")}),h?t.jsxs("div",{className:o.disconnected,children:[t.jsx("h3",{children:e("level.l0.title")}),t.jsx("p",{children:e("level.l0.message")}),t.jsx("p",{children:e("common.reconnecting")}),t.jsxs("div",{className:o.disconnectedActions,children:[t.jsx("button",{className:o.btn,onClick:()=>window.location.reload(),children:e("connection.reconnect","Reconnect")}),t.jsx("button",{className:o.btn,onClick:()=>{window.location.hash="#/settings"},children:e("connection.checkSettings","Check Settings")})]})]}):t.jsxs(t.Fragment,{children:[t.jsx("div",{className:o.statusRow,children:t.jsx(ot,{status:z})}),t.jsxs("dl",{className:o.serverGrid,children:[(n==null?void 0:n.version)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:t.jsx(p,{label:e("connection.server.version","Version"),tooltip:e("connection.server.version.tooltip","Installed MCP server version")})}),t.jsx("dd",{children:t.jsx(X,{text:e("connection.server.version.tooltip","Installed MCP server version"),children:`v${n.version}`})})]}),(n==null?void 0:n.pid)!=null&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:t.jsx(p,{label:e("connection.server.pid","PID"),tooltip:e("connection.server.pid.tooltip","Operating system process identifier")})}),t.jsx("dd",{children:n.pid})]}),(n==null?void 0:n.uptime)!=null&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:t.jsx(p,{label:e("connection.server.uptime","Uptime"),tooltip:e("connection.server.uptime.tooltip","Time elapsed since the MCP server started")})}),t.jsx("dd",{children:ut(S??n.uptime)})]}),(n==null?void 0:n.sessionId)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:t.jsx(p,{label:e("connection.server.session","Session"),tooltip:e("connection.server.session.tooltip","Current MCP session identifier")})}),t.jsx("dd",{children:n.sessionId.slice(0,8)})]}),(i==null?void 0:i.serverExecutable)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:t.jsx(p,{label:e("connection.server.exec","Exec"),tooltip:e("connection.server.exec.tooltip","Executable path used to launch the MCP server")})}),t.jsx("dd",{children:i.serverExecutable})]})]})]})]}),t.jsxs("div",{className:`${o.card} ${h?o.disabled:""}`,children:[t.jsxs("div",{className:o.cardHeader,children:[t.jsxs("span",{children:[e("connection.agents.title","AI Agents")," ","(",(i==null?void 0:i.mcpInstanceCount)??0,")"]}),t.jsx("button",{className:o.toggleBtn,onClick:()=>m(l=>!l),"aria-label":A?e("common.collapse","Collapse"):e("common.expand","Expand"),children:A?"▾":"▸"})]}),A&&t.jsxs("table",{className:o.table,children:[t.jsx("thead",{children:t.jsxs("tr",{children:[t.jsx("th",{children:e("connection.agents.name","Agent")}),t.jsx("th",{children:t.jsx(p,{label:e("connection.server.pid","PID"),tooltip:e("connection.server.pid.tooltip","Operating system process identifier")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.agents.projectRoot","Project Root"),tooltip:e("connection.agents.projectRoot.tooltip","Authoritative project root for sync ownership")})}),t.jsx("th",{children:e("connection.agents.connected","Connected")}),t.jsx("th",{children:t.jsx(p,{label:e("connection.agents.lastSeen","Last Seen"),tooltip:e("connection.agents.lastSeen.tooltip","Most recent heartbeat or activity from this agent")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.agents.lastCommand","Last Command"),tooltip:e("connection.agents.lastCommand.tooltip","Most recent tool call executed by this agent")})}),t.jsx("th",{})]})}),t.jsx("tbody",{children:i!=null&&i.mcpInstances&&i.mcpInstances.length>0?i.mcpInstances.map(l=>t.jsxs("tr",{children:[t.jsxs("td",{children:[t.jsx("span",{className:o[`activity_${Ve(l.lastSeen)}`]}),l.aiClientName??e("connection.agents.unknown","Unknown")]}),t.jsx("td",{children:l.pid}),t.jsx("td",{children:l.projectRoot??l.cwd??e("connection.agents.projectRoot.unresolved","Unresolved")}),t.jsx("td",{children:T(l.connectedAt,e)}),t.jsx("td",{children:l.lastSeen?T(l.lastSeen,e):"-"}),t.jsx("td",{children:l.lastCommandAt?T(l.lastCommandAt,e):"-"}),t.jsx("td",{children:!l.isServer&&t.jsx("button",{className:o.killBtn,onClick:()=>{s("dashboard_click_event",{click_target:"connection_kill_agent",page:"connection"}),u({instanceId:l.instanceId,name:l.aiClientName??l.instanceId.slice(0,8)})},children:e("connection.agents.kill","Kill")})})]},l.instanceId)):t.jsx("tr",{children:t.jsx("td",{colSpan:7,className:o.emptyRow,children:e("connection.agents.none","No agents connected")})})})]})]}),t.jsxs("div",{className:`${o.card} ${h?o.disabled:""}`,children:[t.jsxs("div",{className:o.cardHeader,children:[e("connection.targets.title","Studio Targets")," ","(",v.length,")"]}),t.jsx("p",{className:o.cardHint,children:e("connection.targets.help","When multiple Studio windows are connected, tell the agent to use Studio ID studio-1 to choose one.")}),t.jsx("div",{className:o.tableWrap,children:t.jsxs("table",{className:o.table,children:[t.jsx("thead",{children:t.jsxs("tr",{children:[t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.target","Studio ID"),tooltip:e("connection.targets.target.tooltip","Short name for this Roblox Studio window")})}),t.jsx("th",{children:e("connection.targets.place","Place")}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.placeId","Place ID"),tooltip:e("connection.targets.placeId.tooltip","Roblox Place ID for this Studio window")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.clientId","Connection ID"),tooltip:e("connection.targets.clientId.tooltip","Full connection ID for diagnostics. Usually use Studio ID instead.")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.studioState","Studio State"),tooltip:e("connection.targets.studioState.tooltip","Current edit/play runtime state reported by this Studio window")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.session","Session"),tooltip:e("connection.targets.session.tooltip","Command channel state for this Studio target")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.lastUsed","Last Used"),tooltip:e("connection.targets.lastUsed.tooltip","Most recent plugin-route request routed to this Studio target")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.lastSeen","Last Seen"),tooltip:e("connection.targets.lastSeen.tooltip","Most recent heartbeat received from this Studio target")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.version","Version"),tooltip:e("connection.targets.version.tooltip","Installed plugin version reported by Studio")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.routing","Routing"),tooltip:e("connection.targets.routing.tooltip","Routing priority for requests without a named Studio target")})}),t.jsx("th",{children:t.jsx(p,{label:e("connection.targets.inFlight","In Flight"),tooltip:e("connection.targets.inFlight.tooltip","Active command request currently routed to this Studio target")})})]})}),t.jsx("tbody",{children:v.length>0?v.map(l=>{const L=l.clientId.slice(0,10),a=Ke(l,e);return t.jsxs("tr",{children:[t.jsxs("td",{children:[t.jsx("span",{className:o.monoMuted,title:l.clientId,children:l.targetAlias}),t.jsx(W,{text:e("connection.targets.copyTargetAlias","Copy Studio ID"),children:t.jsx("button",{type:"button",className:o.copyIconButton,"aria-label":e("connection.targets.copyTargetAlias","Copy Studio ID"),onClick:()=>O(l.targetAlias,"target_alias"),children:t.jsx(K,{size:13,"aria-hidden":"true"})})})]}),t.jsx("td",{children:t.jsx("span",{className:o.targetPrimary,children:l.placeName??"-"})}),t.jsxs("td",{children:[l.placeId??"-",l.placeId!==void 0?t.jsx(W,{text:e("connection.targets.copyPlaceId","Copy Place ID"),children:t.jsx("button",{type:"button",className:o.copyIconButton,"aria-label":e("connection.targets.copyPlaceId","Copy Place ID"),onClick:()=>O(String(l.placeId),"place_id"),children:t.jsx(K,{size:13,"aria-hidden":"true"})})}):null]}),t.jsxs("td",{children:[t.jsx("span",{className:o.monoMuted,title:l.clientId,children:L}),t.jsx(W,{text:e("connection.targets.copyClientId","Copy Connection ID"),children:t.jsx("button",{type:"button",className:o.copyIconButton,"aria-label":e("connection.targets.copyClientId","Copy Connection ID"),onClick:()=>O(l.clientId,"client_id"),children:t.jsx(K,{size:13,"aria-hidden":"true"})})})]}),t.jsx("td",{children:t.jsx(X,{text:a.tooltip,children:t.jsx("span",{className:`${o.studioStateBadge} ${o[`studioState_${a.state}`]}`,children:a.label})})}),t.jsx("td",{children:l.connectionState}),t.jsx("td",{children:l.lastRoutedAt?T(l.lastRoutedAt,e):"-"}),t.jsx("td",{children:T(l.lastSeen,e)}),t.jsx("td",{children:l.pluginVersion??"-"}),t.jsx("td",{children:k==="pinned"&&D===l.clientId?t.jsx("span",{className:o.routingBadge,children:e("connection.routing.pinnedBadge","Pinned")}):k==="recentPriority"&&(E==null?void 0:E.clientId)===l.clientId?t.jsx("span",{className:o.routingBadge,children:e("connection.routing.priorityBadge","Priority")}):t.jsx("span",{className:o.monoMuted,children:"-"})}),t.jsx("td",{children:l.inFlightRequestId?l.inFlightRequestId.slice(0,8):"-"})]},l.clientId)}):t.jsx("tr",{children:t.jsx("td",{colSpan:11,className:o.emptyRow,children:e("connection.targets.none","No Studio targets connected. Open Roblox Studio and connect WEPPY Plugin.")})})})]})})]}),t.jsxs("div",{className:`${o.card} ${h?o.disabled:""}`,children:[t.jsxs("div",{className:o.cardHeader,children:[t.jsx("span",{children:e("connection.log.title","Connection Log")}),t.jsx("button",{className:o.clearButton,onClick:()=>{s("dashboard_click_event",{click_target:"connection_clear_log",page:"connection"}),I(!0)},children:e("common.clear","Clear")})]}),t.jsx(bt,{entries:y})]}),t.jsx(J,{open:M,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:$,onCancel:()=>!$&&I(!1),onConfirm:R}),t.jsx(J,{open:!!b,title:e("connection.agents.kill.title","Kill agent?"),message:`"${b==null?void 0:b.name}" 프로세스를 강제 종료합니다. 해당 에이전트의 진행 중인 작업이 중단됩니다.`,cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("connection.agents.kill","Kill"),loading:j,onCancel:()=>!j&&u(null),onConfirm:Y})]})}export{so as Component};