@weppy/roblox-mcp 2.7.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +14 -17
  3. package/install.sh +3 -4
  4. package/package.json +1 -1
  5. package/plugins/weppy-roblox-mcp/.claude-plugin/plugin.json +1 -1
  6. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{ChangelogDetailPage-CIarzJIx.js → ChangelogDetailPage-DxktONbL.js} +1 -1
  7. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{ChangelogPage-C1uCKyqh.js → ChangelogPage-DOY-SmWM.js} +1 -1
  8. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{ConfirmModal-BDWSInRi.js → ConfirmModal-CmJCz5rg.js} +1 -1
  9. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{ConnectionPage-CWDwVCKg.js → ConnectionPage-BiiIQs7f.js} +1 -1
  10. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{GameChangeDetail-Bk8YUy4G.js → GameChangeDetail-D1kE2L_v.js} +1 -1
  11. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{InfoLabel-BJIFNYA5.js → InfoLabel-B9KT3kfU.js} +1 -1
  12. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{OverviewPage-Di0p7YY2.js → OverviewPage-T2WCTHpo.js} +1 -1
  13. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{PlaytestPage-Dxgz0SKW.js → PlaytestPage-CW8Xfp6b.js} +1 -1
  14. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{SettingsPage-DVgxRsfC.js → SettingsPage-DcUt5qjG.js} +1 -1
  15. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{StatusBadge-ilvVufN2.js → StatusBadge-Bxe88ki2.js} +1 -1
  16. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{SyncPage-IICMnq8v.js → SyncPage-C09YF6D5.js} +1 -1
  17. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{Tabs-pDS5zzr9.js → Tabs-BNtOqYlc.js} +1 -1
  18. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/TierComparison-Dyf-knpe.js +1 -0
  19. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{ToolsPage-DEhsoa36.js → ToolsPage-HKbmsKMQ.js} +1 -1
  20. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{TooltipText-bSKcc3-P.js → TooltipText-Baw38jOU.js} +1 -1
  21. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{UiStudioPage-BHhd3zUv.js → UiStudioPage-Cbgl7xIC.js} +1 -1
  22. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{WhatsNewPage-ErpENbsZ.js → WhatsNewPage-BlOSWgSn.js} +1 -1
  23. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{index-BPAvjNNu.js → index-FfT2oWAB.js} +28 -28
  24. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{sample-requests-DDQ3XchF.js → sample-requests-X_hsWdLX.js} +1 -1
  25. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{useLiveUptime-HYmdQdHf.js → useLiveUptime-DhJz484L.js} +1 -1
  26. package/plugins/weppy-roblox-mcp/dashboard/dist/index.html +1 -1
  27. package/plugins/weppy-roblox-mcp/dist/index.js +4 -4
  28. package/plugins/weppy-roblox-mcp/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
  29. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/TierComparison-BXMCd1IB.js +0 -2
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Weppy Roblox MCP — MCP server that lets AI coding agents control a live Roblox Studio session with 21 tools, 140+ actions, bidirectional sync, automated playtest, and multi-place support",
9
- "version": "2.7.0"
9
+ "version": "2.7.1"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "weppy-roblox-mcp",
14
14
  "source": "./plugins/weppy-roblox-mcp",
15
15
  "description": "Weppy Roblox MCP — MCP server that lets AI coding agents control a live Roblox Studio session with 21 tools, 140+ actions, bidirectional sync, automated playtest, and multi-place support",
16
- "version": "2.7.0",
16
+ "version": "2.7.1",
17
17
  "author": {
18
18
  "name": "hope1026"
19
19
  },
package/CHANGELOG.md CHANGED
@@ -3,33 +3,30 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
5
 
6
- ## [2.7.0] - 2026-05-05
7
-
8
- ### Features
6
+ ## [2.7.1] - 2026-05-05
9
7
 
10
- - **UI Studio (Pro) — major upgrade** — `manage_ui` now supports a full design loop: open the dashboard's UI Studio page to see a per-request **History tab** (with before/after snapshots and design suggestions side-by-side), an **Analysis tab** with comparison modal, and a **Design Check** action that replaces the old `lint` action and reports issues against the quality bar. AI agents can also fetch a **partial design brief** scoped to the part of the tree they're editing, get **asset recommendations** (icons, ornaments, imagery) wired into the brief, and generate previews that respect a new isolated `UIVisibilityScope` so agent-driven UI work doesn't leak into your Studio session. Note: the old `manage_ui` action `lint` has been renamed to `design_check` — update any explicit calls. Stored UI Studio history from previous versions remains readable.
11
-
12
- - **UI Studio retention & storage controls** — A new **Storage** card on the dashboard lets you set a retention policy (max age + max size) for UI Studio request history. The retention runner cleans old runs in the background and supports dry-run preview before deletion. History entries can also be batch-selected and deleted from the Analysis tab.
13
-
14
- - **UI Studio dashboard redesign** — The UI Studio page is now split into **History** and **Analysis** tabs with a redesigned snapshot drawer (persistent toolbar, focus trap, drawer/dialog comparison view), tooltip help across UI Studio + Settings, a new connection guide for first-time users, and localized analysis detail strings. Thumbnails now use `object-fit: contain` so layouts aren't cropped.
8
+ ### Improvements
15
9
 
16
- - **Reverse sync infers correct property types** — When you edit synced files locally and push them back to Studio, the server now resolves property types via class-aware metadata instead of guessing from value shape. This fixes cases where edits to enum, color, or vector properties on specific instance classes would silently land as the wrong type.
10
+ - **Stability hardening** — Internal reliability improvements across the MCP server and Roblox Studio plugin. No behavior changes for existing workflows.
17
11
 
18
- - **GA4 telemetry: per-user attribution + better error diagnostics** — Telemetry events now include a stable `user_id` so the dashboard funnels reflect real users (with a documented DebugView verification path), and command failures emit structured error classification so you can tell config issues from runtime crashes from network failures at a glance. Telemetry is opt-in and unchanged for users who haven't enabled it.
12
+ ## [2.7.0] - 2026-05-05
19
13
 
20
- ### Bug Fixes
14
+ ### Features
21
15
 
22
- - **Installer: legacy `@weppy/roblox-mcp` entries auto-upgrade to `@latest`** If you previously installed the MCP via an older one-liner that pinned a bare package name, the installer now rewrites that entry to `@latest` instead of leaving it on a stale version. Combined with `npx --ignore-existing` the next launch picks up the new release without manual config edits.
16
+ - **UI Studio launch**A new workflow for iterating on Roblox Studio UI design together with an AI agent. From the UI Studio page in the dashboard, you can now use:
17
+ - **History tab** — Compare before/after snapshots and design suggestions for each request, side by side.
18
+ - **Analysis tab** — Snapshot comparison modal with batch selection and deletion.
19
+ - **Design Check** — Reviews your UI against design quality criteria and surfaces concrete improvements.
23
20
 
24
- - **Installer: Claude Code detection on Windows** — The installer mis-detected Claude Code on Windows and could fail with a confusing "already exists" error even on first install. Detection is now correct and an existing valid registration is treated as success.
21
+ ### Improvements
25
22
 
26
- - **Dashboard tooltips no longer clipped** — Tooltips inside scrollable cards (Settings, UI Studio history) were clipped by `overflow:hidden` ancestors. They now render via a portal and display fully regardless of container.
23
+ - **More accurate property types when syncing local edits back to Studio** — When you edit synced files locally and push the changes back to Studio, the server now resolves property types via class-aware metadata instead of guessing from value shape. Edits to enum, color, or vector properties on specific instances are no longer silently saved as the wrong type.
27
24
 
28
- ### Documentation
25
+ ### Bug Fixes
29
26
 
30
- - **UI Studio guide rewritten as a 3-layer English resource** — The design-system guide now reads top-down (intent families tokens), expands the palette/imagery/ornamentation/composition family menus, documents the quality-bar gate and slab-look anti-pattern, and clarifies multiline text encoding and transparent root defaults. Available via the `weppy://ui-studio/guide` MCP resource.
27
+ - **Claude Code detection on Windows** — On Windows, Claude Code could be mis-detected and even a fresh install would fail with a confusing "already exists" error. Detection is now correct, and an existing valid registration is treated as success.
31
28
 
32
- - **Public docs: UI Studio added to README and llms files** — `deploy/publish/hope1026-roblox-mcp/README.md` and the `llms.txt` / `llms-full.txt` files now describe UI Studio capabilities so AI agents and human readers see it as a first-class feature.
29
+ - **Dashboard tooltips no longer clipped** — Tooltips inside scrollable areas (Settings, UI Studio history) were being cut off. They now display in full regardless of the surrounding container.
33
30
 
34
31
 
35
32
 
package/install.sh CHANGED
@@ -120,8 +120,7 @@ try {
120
120
  ' >/dev/null 2>&1
121
121
  }
122
122
 
123
- # Add the MCP server under the canonical `mcpServers` wrapper in the Antigravity
124
- # config and strip any legacy flat key left over from earlier versions.
123
+ # Antigravity 설정에 canonical mcpServers 래퍼로 MCP 서버를 추가하고 legacy flat key를 정리
125
124
  add_antigravity_mcp_config() {
126
125
  local config_path="$1"
127
126
  local parent_dir
@@ -657,8 +656,8 @@ if confirm " Run npx -y @weppy/roblox-mcp@latest --setup?"; then
657
656
  fi
658
657
 
659
658
  if [ -n "${setup_tmp_dir:-}" ] && [ -d "$setup_tmp_dir" ]; then
660
- # Isolate stdin with /dev/null so the stdio MCP server does not swallow the
661
- # remaining bytes of this script when installed via `curl | bash`.
659
+ # stdin /dev/null 격리: curl|bash 파이프 모드에서 stdio MCP 서버가
660
+ # bash의 남은 스크립트 바이트를 소비해버리는 문제를 방지한다
662
661
  # The @latest tag forces npx to resolve from the registry instead of
663
662
  # reusing an older version pinned in the npm cache.
664
663
  if (cd "$setup_tmp_dir" && npx -y "@weppy/roblox-mcp@latest" --setup </dev/null); then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weppy/roblox-mcp",
3
- "version": "2.7.0",
3
+ "version": "2.7.1",
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": "plugins/weppy-roblox-mcp/dist/index.js",
6
6
  "type": "module",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "weppy-roblox-mcp",
3
3
  "description": "MCP server for Roblox Studio integration - AI-powered game development with specialized agents and skills",
4
- "version": "2.7.0",
4
+ "version": "2.7.1",
5
5
  "author": {
6
6
  "name": "hope1026"
7
7
  },
@@ -1 +1 @@
1
- import{r,a as R,u as M,b as B,c as V,j as e}from"./index-BPAvjNNu.js";import{I as G}from"./InfoLabel-BJIFNYA5.js";import{G as D}from"./GameChangeDetail-Bk8YUy4G.js";import{T as m}from"./TooltipText-bSKcc3-P.js";function F(n){const s={scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0};for(const l of n)switch(l.category){case"script":l.changeType==="create"?s.scriptsCreated++:s.scriptsModified++;break;case"instance":l.changeType==="create"?s.instancesCreated++:l.changeType==="delete"?s.instancesDeleted++:l.changeType==="move"&&s.instancesMoved++;break;case"property":s.propertiesChanged++;break;case"lighting":s.lightingChanged=!0;break;case"terrain":s.terrainChanged=!0;break;case"asset":s.assetsInserted++;break}return s}function P(n){const[s,l]=r.useState(""),[a,d]=r.useState(""),[u,q]=r.useState(),[w,y]=r.useState("completed"),[I,E]=r.useState([]),[L,O]=r.useState([]),[x,f]=r.useState([]),[p,_]=r.useState(),[j,b]=r.useState(),[v,S]=r.useState(),[C,N]=r.useState({scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0}),[T,g]=r.useState(!0),[k,h]=r.useState(null),i=r.useCallback(async()=>{if(n){g(!0),h(null);try{const[c,o]=await Promise.all([R.get(`/api/dashboard/changelog/${n}`),R.get(`/api/dashboard/changelog/${n}/changes`)]);l(c.entryId),d(c.startTime),q(c.endTime),y(c.status),E(c.entries),O(c.failures),_(c.contextSummary),b(c.replayMetadata),S(c.verificationSummary),f(o.changes),N(F(o.changes))}catch(c){h(c instanceof Error?c.message:"Failed to load changelog detail")}finally{g(!1)}}},[n]);return r.useEffect(()=>{i()},[i]),{entryId:s,startTime:a,endTime:u,status:w,entries:I,failures:L,changes:x,changeSummary:C,contextSummary:p,replayMetadata:j,verificationSummary:v,loading:T,error:k,refresh:i}}const U={script:"📝",instance:"🧱",property:"🎨",lighting:"🌅",terrain:"⛰️",asset:"📦"};function H(n){return U[n]??"❓"}const W="_page_q2jbi_2",Y="_header_q2jbi_10",z="_backLink_q2jbi_16",J="_headerTitle_q2jbi_29",Q="_headerTime_q2jbi_37",X="_statusActive_q2jbi_44",Z="_statusCompleted_q2jbi_49",ee="_section_q2jbi_54",te="_sectionTitle_q2jbi_61",ne="_summaryGrid_q2jbi_74",ae="_summaryCard_q2jbi_80",ie="_summaryCardActive_q2jbi_94",se="_summaryIcon_q2jbi_99",ce="_summaryCount_q2jbi_105",re="_summaryLabel_q2jbi_112",oe="_contextGrid_q2jbi_121",le="_contextRow_q2jbi_127",de="_contextKey_q2jbi_133",me="_contextValue_q2jbi_141",ge="_timelineFilter_q2jbi_149",he="_filterLabel_q2jbi_156",ue="_filterSelect_q2jbi_162",ye="_timeline_q2jbi_149",xe="_timelineEntry_q2jbi_182",fe="_timelineTime_q2jbi_199",pe="_timelineIcon_q2jbi_207",_e="_timelineBody_q2jbi_212",je="_timelineSummary_q2jbi_217",be="_timelineTarget_q2jbi_224",ve="_timelineConfidence_q2jbi_231",Se="_confidenceExact_q2jbi_240",Ce="_confidencePartial_q2jbi_245",Ne="_confidenceAfterOnly_q2jbi_250",Te="_confidenceIntentOnly_q2jbi_255",ke="_confidenceUnknown_q2jbi_260",qe="_timelineExpanded_q2jbi_266",we="_empty_q2jbi_338",Ie="_loading_q2jbi_347",Ee="_error_q2jbi_356",t={page:W,header:Y,backLink:z,headerTitle:J,headerTime:Q,statusActive:X,statusCompleted:Z,section:ee,sectionTitle:te,summaryGrid:ne,summaryCard:ae,summaryCardActive:ie,summaryIcon:se,summaryCount:ce,summaryLabel:re,contextGrid:oe,contextRow:le,contextKey:de,contextValue:me,timelineFilter:ge,filterLabel:he,filterSelect:ue,timeline:ye,timelineEntry:xe,timelineTime:fe,timelineIcon:pe,timelineBody:_e,timelineSummary:je,timelineTarget:be,timelineConfidence:ve,confidenceExact:Se,confidencePartial:Ce,confidenceAfterOnly:Ne,confidenceIntentOnly:Te,confidenceUnknown:ke,timelineExpanded:qe,empty:we,loading:Ie,error:Ee},$=[{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 A(n){if(!n)return"--:--";const s=new Date(n);return`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}`}function Le(n){if(!n)return"--:--:--";const s=new Date(n);return`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}:${String(s.getSeconds()).padStart(2,"0")}`}function Oe(n,s){if(!n||!s)return"";const l=new Date(s).getTime()-new Date(n).getTime();return l<0?"":`${Math.round(l/6e4)}min`}function Ae(n){switch(n){case"exact":return t.confidenceExact;case"partial":return t.confidencePartial;case"after-only":return t.confidenceAfterOnly;case"intent-only":return t.confidenceIntentOnly;default:return t.confidenceUnknown}}function Ke(n,s){switch(s){case"exact":return n("changelog.detail.confidence.exact","Exact");case"partial":return n("changelog.detail.confidence.partial","Partial");case"after-only":return n("changelog.detail.confidence.afterOnly","After only");case"intent-only":return n("changelog.detail.confidence.intentOnly","Intent only");default:return n("changelog.detail.confidence.unknown","Unknown")}}function Re(n,s){switch(s){case"exact":return n("changelog.detail.confidence.exact.tooltip","Both the before and after state were confirmed for this change.");case"partial":return n("changelog.detail.confidence.partial.tooltip","Only part of the before and after state could be confirmed for this change.");case"after-only":return n("changelog.detail.confidence.afterOnly.tooltip","Only the resulting state after the change could be confirmed.");case"intent-only":return n("changelog.detail.confidence.intentOnly.tooltip","Only the requested action was recorded, not the resulting state.");default:return n("changelog.detail.confidence.unknown.tooltip","This change could not be confidently classified from the available data.")}}function Ge(){var x,f,p,_,j,b,v,S,C,N,T,g,k,h;const{t:n}=M(),{id:s}=B(),l=V(),a=P(s),[d,u]=r.useState("all"),[q,w]=r.useState(null),y=r.useMemo(()=>[...d==="all"?a.changes:a.changes.filter(c=>c.category===d)].reverse(),[a.changes,d]);if(a.loading)return e.jsx("div",{className:t.loading,children:n("common.loading","Loading...")});if(a.error)return e.jsxs("div",{className:t.error,children:[a.error,e.jsx("br",{}),e.jsxs("span",{className:t.backLink,onClick:()=>l("/changelog"),children:["←"," ",n("changelog.detail.backToList","Back to list")]})]});const I=Oe(a.startTime,a.endTime),E=a.endTime?`${A(a.startTime)} → ${A(a.endTime)} (${I})`:`${A(a.startTime)} → ${n("changelog.card.inProgress","in progress")}`,L=!!((x=a.contextSummary)!=null&&x.intent||(f=a.contextSummary)!=null&&f.testScenario||(p=a.contextSummary)!=null&&p.expectedBehavior||(_=a.contextSummary)!=null&&_.observedBehavior),O=!!((j=a.verificationSummary)!=null&&j.label||(b=a.verificationSummary)!=null&&b.status||(v=a.verificationSummary)!=null&&v.testTimestamp);return e.jsxs("div",{className:t.page,children:[e.jsxs("div",{className:t.header,children:[e.jsxs("span",{className:t.backLink,onClick:()=>l("/changelog"),children:["←"," ",n("sidebar.changelog","Changelog")]}),e.jsx("span",{className:t.headerTitle,children:"|"}),e.jsx("span",{className:t.headerTime,children:E}),e.jsx(m,{text:a.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:a.status==="active"?t.statusActive:t.statusCompleted,children:a.status==="active"?n("changelog.card.active","Active"):n("changelog.card.completed","Completed")})})]}),e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.summaryGrid,children:$.map(i=>{const c=a.changeSummary;let o;switch(i.key){case"script":o=c.scriptsModified+c.scriptsCreated;break;case"instance":o=c.instancesCreated+c.instancesDeleted+c.instancesMoved;break;case"property":o=c.propertiesChanged;break;case"lighting":o=c.lightingChanged?1:0;break;case"terrain":o=c.terrainChanged?1:0;break;case"asset":o=c.assetsInserted;break;default:o=0}const K=d===i.key;return e.jsxs("div",{className:`${t.summaryCard} ${K?t.summaryCardActive:""}`,onClick:()=>u(K?"all":i.key),children:[e.jsx("span",{className:t.summaryIcon,children:i.icon}),e.jsx("div",{className:t.summaryCount,children:o}),e.jsx("div",{className:t.summaryLabel,children:n(i.labelKey,i.key)})]},i.key)})})]}),L&&e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.contextGrid,children:[((S=a.contextSummary)==null?void 0:S.intent)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.intent})]}),((C=a.contextSummary)==null?void 0:C.testScenario)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("playtest.context.why","Why this test ran")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.testScenario})]}),((N=a.contextSummary)==null?void 0:N.expectedBehavior)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("playtest.context.expected","Expected")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.expectedBehavior})]}),((T=a.contextSummary)==null?void 0:T.observedBehavior)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("playtest.context.observed","Observed")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.observedBehavior})]})]})]}),O&&e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.contextGrid,children:[((g=a.verificationSummary)==null?void 0:g.label)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.detail.verification.label","Result")}),e.jsx("span",{className:t.contextValue,children:a.verificationSummary.label})]}),((k=a.verificationSummary)==null?void 0:k.status)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.detail.verification.status","Status")}),e.jsx("span",{className:t.contextValue,children:a.verificationSummary.status})]}),((h=a.verificationSummary)==null?void 0:h.testTimestamp)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.detail.verification.timestamp","Recorded at")}),e.jsx("span",{className:t.contextValue,children:a.verificationSummary.testTimestamp})]})]})]}),e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.timelineFilter,children:[e.jsx("span",{className:t.filterLabel,children:e.jsx(G,{label:`${n("changelog.detail.filterCategory","Category")}:`,tooltip:n("changelog.detail.filterCategory.tooltip","Filter the timeline to a single change category.")})}),e.jsxs("select",{className:t.filterSelect,value:d,onChange:i=>u(i.target.value),children:[e.jsx("option",{value:"all",children:n("tools.filter.all","All")}),$.map(i=>e.jsxs("option",{value:i.key,children:[i.icon," ",n(i.labelKey,i.key)]},i.key))]})]}),y.length===0?e.jsx("div",{className:t.empty,children:n("changelog.detail.noChanges","No changes in this category")}):e.jsx("div",{className:t.timeline,children:y.map((i,c)=>{const o=q===c;return e.jsxs("div",{children:[e.jsxs("div",{className:t.timelineEntry,onClick:()=>w(o?null:c),children:[e.jsx("span",{className:t.timelineTime,children:Le(i.timestamp)}),e.jsx("span",{className:t.timelineIcon,children:H(i.category)}),e.jsxs("div",{className:t.timelineBody,children:[e.jsxs("div",{className:t.timelineSummary,children:[i.summary,e.jsx(m,{text:Re(n,i.confidence),children:e.jsx("span",{className:`${t.timelineConfidence} ${Ae(i.confidence)}`,children:Ke(n,i.confidence)})})]}),e.jsx("div",{className:t.timelineTarget,children:i.target})]})]}),o&&e.jsx("div",{className:t.timelineExpanded,children:e.jsx(D,{change:i})})]},c)})})]})]})}export{Ge as Component};
1
+ import{r,a as R,u as M,b as B,c as V,j as e}from"./index-FfT2oWAB.js";import{I as G}from"./InfoLabel-B9KT3kfU.js";import{G as D}from"./GameChangeDetail-D1kE2L_v.js";import{T as m}from"./TooltipText-Baw38jOU.js";function F(n){const s={scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0};for(const l of n)switch(l.category){case"script":l.changeType==="create"?s.scriptsCreated++:s.scriptsModified++;break;case"instance":l.changeType==="create"?s.instancesCreated++:l.changeType==="delete"?s.instancesDeleted++:l.changeType==="move"&&s.instancesMoved++;break;case"property":s.propertiesChanged++;break;case"lighting":s.lightingChanged=!0;break;case"terrain":s.terrainChanged=!0;break;case"asset":s.assetsInserted++;break}return s}function P(n){const[s,l]=r.useState(""),[a,d]=r.useState(""),[u,q]=r.useState(),[w,y]=r.useState("completed"),[I,E]=r.useState([]),[L,O]=r.useState([]),[x,f]=r.useState([]),[p,_]=r.useState(),[j,b]=r.useState(),[v,S]=r.useState(),[C,N]=r.useState({scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0}),[T,g]=r.useState(!0),[k,h]=r.useState(null),i=r.useCallback(async()=>{if(n){g(!0),h(null);try{const[c,o]=await Promise.all([R.get(`/api/dashboard/changelog/${n}`),R.get(`/api/dashboard/changelog/${n}/changes`)]);l(c.entryId),d(c.startTime),q(c.endTime),y(c.status),E(c.entries),O(c.failures),_(c.contextSummary),b(c.replayMetadata),S(c.verificationSummary),f(o.changes),N(F(o.changes))}catch(c){h(c instanceof Error?c.message:"Failed to load changelog detail")}finally{g(!1)}}},[n]);return r.useEffect(()=>{i()},[i]),{entryId:s,startTime:a,endTime:u,status:w,entries:I,failures:L,changes:x,changeSummary:C,contextSummary:p,replayMetadata:j,verificationSummary:v,loading:T,error:k,refresh:i}}const U={script:"📝",instance:"🧱",property:"🎨",lighting:"🌅",terrain:"⛰️",asset:"📦"};function H(n){return U[n]??"❓"}const W="_page_q2jbi_2",Y="_header_q2jbi_10",z="_backLink_q2jbi_16",J="_headerTitle_q2jbi_29",Q="_headerTime_q2jbi_37",X="_statusActive_q2jbi_44",Z="_statusCompleted_q2jbi_49",ee="_section_q2jbi_54",te="_sectionTitle_q2jbi_61",ne="_summaryGrid_q2jbi_74",ae="_summaryCard_q2jbi_80",ie="_summaryCardActive_q2jbi_94",se="_summaryIcon_q2jbi_99",ce="_summaryCount_q2jbi_105",re="_summaryLabel_q2jbi_112",oe="_contextGrid_q2jbi_121",le="_contextRow_q2jbi_127",de="_contextKey_q2jbi_133",me="_contextValue_q2jbi_141",ge="_timelineFilter_q2jbi_149",he="_filterLabel_q2jbi_156",ue="_filterSelect_q2jbi_162",ye="_timeline_q2jbi_149",xe="_timelineEntry_q2jbi_182",fe="_timelineTime_q2jbi_199",pe="_timelineIcon_q2jbi_207",_e="_timelineBody_q2jbi_212",je="_timelineSummary_q2jbi_217",be="_timelineTarget_q2jbi_224",ve="_timelineConfidence_q2jbi_231",Se="_confidenceExact_q2jbi_240",Ce="_confidencePartial_q2jbi_245",Ne="_confidenceAfterOnly_q2jbi_250",Te="_confidenceIntentOnly_q2jbi_255",ke="_confidenceUnknown_q2jbi_260",qe="_timelineExpanded_q2jbi_266",we="_empty_q2jbi_338",Ie="_loading_q2jbi_347",Ee="_error_q2jbi_356",t={page:W,header:Y,backLink:z,headerTitle:J,headerTime:Q,statusActive:X,statusCompleted:Z,section:ee,sectionTitle:te,summaryGrid:ne,summaryCard:ae,summaryCardActive:ie,summaryIcon:se,summaryCount:ce,summaryLabel:re,contextGrid:oe,contextRow:le,contextKey:de,contextValue:me,timelineFilter:ge,filterLabel:he,filterSelect:ue,timeline:ye,timelineEntry:xe,timelineTime:fe,timelineIcon:pe,timelineBody:_e,timelineSummary:je,timelineTarget:be,timelineConfidence:ve,confidenceExact:Se,confidencePartial:Ce,confidenceAfterOnly:Ne,confidenceIntentOnly:Te,confidenceUnknown:ke,timelineExpanded:qe,empty:we,loading:Ie,error:Ee},$=[{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 A(n){if(!n)return"--:--";const s=new Date(n);return`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}`}function Le(n){if(!n)return"--:--:--";const s=new Date(n);return`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}:${String(s.getSeconds()).padStart(2,"0")}`}function Oe(n,s){if(!n||!s)return"";const l=new Date(s).getTime()-new Date(n).getTime();return l<0?"":`${Math.round(l/6e4)}min`}function Ae(n){switch(n){case"exact":return t.confidenceExact;case"partial":return t.confidencePartial;case"after-only":return t.confidenceAfterOnly;case"intent-only":return t.confidenceIntentOnly;default:return t.confidenceUnknown}}function Ke(n,s){switch(s){case"exact":return n("changelog.detail.confidence.exact","Exact");case"partial":return n("changelog.detail.confidence.partial","Partial");case"after-only":return n("changelog.detail.confidence.afterOnly","After only");case"intent-only":return n("changelog.detail.confidence.intentOnly","Intent only");default:return n("changelog.detail.confidence.unknown","Unknown")}}function Re(n,s){switch(s){case"exact":return n("changelog.detail.confidence.exact.tooltip","Both the before and after state were confirmed for this change.");case"partial":return n("changelog.detail.confidence.partial.tooltip","Only part of the before and after state could be confirmed for this change.");case"after-only":return n("changelog.detail.confidence.afterOnly.tooltip","Only the resulting state after the change could be confirmed.");case"intent-only":return n("changelog.detail.confidence.intentOnly.tooltip","Only the requested action was recorded, not the resulting state.");default:return n("changelog.detail.confidence.unknown.tooltip","This change could not be confidently classified from the available data.")}}function Ge(){var x,f,p,_,j,b,v,S,C,N,T,g,k,h;const{t:n}=M(),{id:s}=B(),l=V(),a=P(s),[d,u]=r.useState("all"),[q,w]=r.useState(null),y=r.useMemo(()=>[...d==="all"?a.changes:a.changes.filter(c=>c.category===d)].reverse(),[a.changes,d]);if(a.loading)return e.jsx("div",{className:t.loading,children:n("common.loading","Loading...")});if(a.error)return e.jsxs("div",{className:t.error,children:[a.error,e.jsx("br",{}),e.jsxs("span",{className:t.backLink,onClick:()=>l("/changelog"),children:["←"," ",n("changelog.detail.backToList","Back to list")]})]});const I=Oe(a.startTime,a.endTime),E=a.endTime?`${A(a.startTime)} → ${A(a.endTime)} (${I})`:`${A(a.startTime)} → ${n("changelog.card.inProgress","in progress")}`,L=!!((x=a.contextSummary)!=null&&x.intent||(f=a.contextSummary)!=null&&f.testScenario||(p=a.contextSummary)!=null&&p.expectedBehavior||(_=a.contextSummary)!=null&&_.observedBehavior),O=!!((j=a.verificationSummary)!=null&&j.label||(b=a.verificationSummary)!=null&&b.status||(v=a.verificationSummary)!=null&&v.testTimestamp);return e.jsxs("div",{className:t.page,children:[e.jsxs("div",{className:t.header,children:[e.jsxs("span",{className:t.backLink,onClick:()=>l("/changelog"),children:["←"," ",n("sidebar.changelog","Changelog")]}),e.jsx("span",{className:t.headerTitle,children:"|"}),e.jsx("span",{className:t.headerTime,children:E}),e.jsx(m,{text:a.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:a.status==="active"?t.statusActive:t.statusCompleted,children:a.status==="active"?n("changelog.card.active","Active"):n("changelog.card.completed","Completed")})})]}),e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.summaryGrid,children:$.map(i=>{const c=a.changeSummary;let o;switch(i.key){case"script":o=c.scriptsModified+c.scriptsCreated;break;case"instance":o=c.instancesCreated+c.instancesDeleted+c.instancesMoved;break;case"property":o=c.propertiesChanged;break;case"lighting":o=c.lightingChanged?1:0;break;case"terrain":o=c.terrainChanged?1:0;break;case"asset":o=c.assetsInserted;break;default:o=0}const K=d===i.key;return e.jsxs("div",{className:`${t.summaryCard} ${K?t.summaryCardActive:""}`,onClick:()=>u(K?"all":i.key),children:[e.jsx("span",{className:t.summaryIcon,children:i.icon}),e.jsx("div",{className:t.summaryCount,children:o}),e.jsx("div",{className:t.summaryLabel,children:n(i.labelKey,i.key)})]},i.key)})})]}),L&&e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.contextGrid,children:[((S=a.contextSummary)==null?void 0:S.intent)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.intent})]}),((C=a.contextSummary)==null?void 0:C.testScenario)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("playtest.context.why","Why this test ran")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.testScenario})]}),((N=a.contextSummary)==null?void 0:N.expectedBehavior)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("playtest.context.expected","Expected")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.expectedBehavior})]}),((T=a.contextSummary)==null?void 0:T.observedBehavior)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("playtest.context.observed","Observed")}),e.jsx("span",{className:t.contextValue,children:a.contextSummary.observedBehavior})]})]})]}),O&&e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.contextGrid,children:[((g=a.verificationSummary)==null?void 0:g.label)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.detail.verification.label","Result")}),e.jsx("span",{className:t.contextValue,children:a.verificationSummary.label})]}),((k=a.verificationSummary)==null?void 0:k.status)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.detail.verification.status","Status")}),e.jsx("span",{className:t.contextValue,children:a.verificationSummary.status})]}),((h=a.verificationSummary)==null?void 0:h.testTimestamp)&&e.jsxs("div",{className:t.contextRow,children:[e.jsx("span",{className:t.contextKey,children:n("changelog.detail.verification.timestamp","Recorded at")}),e.jsx("span",{className:t.contextValue,children:a.verificationSummary.testTimestamp})]})]})]}),e.jsxs("div",{className:t.section,children:[e.jsx("div",{className:t.sectionTitle,children:e.jsx(m,{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:t.timelineFilter,children:[e.jsx("span",{className:t.filterLabel,children:e.jsx(G,{label:`${n("changelog.detail.filterCategory","Category")}:`,tooltip:n("changelog.detail.filterCategory.tooltip","Filter the timeline to a single change category.")})}),e.jsxs("select",{className:t.filterSelect,value:d,onChange:i=>u(i.target.value),children:[e.jsx("option",{value:"all",children:n("tools.filter.all","All")}),$.map(i=>e.jsxs("option",{value:i.key,children:[i.icon," ",n(i.labelKey,i.key)]},i.key))]})]}),y.length===0?e.jsx("div",{className:t.empty,children:n("changelog.detail.noChanges","No changes in this category")}):e.jsx("div",{className:t.timeline,children:y.map((i,c)=>{const o=q===c;return e.jsxs("div",{children:[e.jsxs("div",{className:t.timelineEntry,onClick:()=>w(o?null:c),children:[e.jsx("span",{className:t.timelineTime,children:Le(i.timestamp)}),e.jsx("span",{className:t.timelineIcon,children:H(i.category)}),e.jsxs("div",{className:t.timelineBody,children:[e.jsxs("div",{className:t.timelineSummary,children:[i.summary,e.jsx(m,{text:Re(n,i.confidence),children:e.jsx("span",{className:`${t.timelineConfidence} ${Ae(i.confidence)}`,children:Ke(n,i.confidence)})})]}),e.jsx("div",{className:t.timelineTarget,children:i.target})]})]}),o&&e.jsx("div",{className:t.timelineExpanded,children:e.jsx(D,{change:i})})]},c)})})]})]})}export{Ge as Component};
@@ -1 +1 @@
1
- import{r as i,a as A,D as O,u as R,j as t,c as P,l as V,m as K}from"./index-BPAvjNNu.js";import{C as G}from"./ConfirmModal-BDWSInRi.js";import{T as I}from"./TooltipText-bSKcc3-P.js";import{T as H}from"./Tabs-pDS5zzr9.js";const U=10;function Z(){const[s,m]=i.useState([]),[e,a]=i.useState(0),[h,p]=i.useState(!1),[c,f]=i.useState(!0),[l,x]=i.useState(0),[g,v]=i.useState("all"),y=i.useRef(null),o=i.useCallback(async(u,_)=>{f(!0);try{const C={limit:String(U),offset:String(u)};_!=="all"&&(C.status=_);const b=await A.get("/api/dashboard/changelog",C);m(b.entries),a(b.total),p(b.hasMore)}catch{m([]),a(0),p(!1)}finally{f(!1)}},[]),T=i.useCallback(()=>{o(l,g)},[o,l,g]),N=i.useCallback(async()=>{await A.post("/api/dashboard/changelog/clear"),m([]),a(0),p(!1)},[]);return i.useEffect(()=>{o(l,g)},[o,l,g]),i.useEffect(()=>{const u=new O;y.current=u,u.connect();const _=u.on("command",()=>{o(l,g)});return()=>{_(),u.disconnect(),y.current=null}},[o,l,g]),{entries:s,total:e,hasMore:h,loading:c,offset:l,statusFilter:g,setOffset:x,setStatusFilter:v,refresh:T,clear:N}}const q="_card_1n89u_2",z="_header_1n89u_17",J="_statusBadge_1n89u_24",Q="_statusDot_1n89u_35",W="_active_1n89u_41",X="_completed_1n89u_50",Y="_timeRange_1n89u_58",ee="_summaryList_1n89u_65",te="_summaryItem_1n89u_71",se="_summaryIcon_1n89u_80",ae="_summaryText_1n89u_86",ne="_progressBar_1n89u_91",oe="_progressFill_1n89u_99",ce="_emptySummary_1n89u_112",ie="_contextBlock_1n89u_120",le="_contextLabel_1n89u_129",re="_contextValue_1n89u_137",n={card:q,header:z,statusBadge:J,statusDot:Q,active:W,completed:X,timeRange:Y,summaryList:ee,summaryItem:te,summaryIcon:se,summaryText:ae,progressBar:ne,progressFill:oe,emptySummary:ce,contextBlock:ie,contextLabel:le,contextValue:re};function D(s){if(!s)return"--:--";const m=new Date(s);return`${String(m.getHours()).padStart(2,"0")}:${String(m.getMinutes()).padStart(2,"0")}`}function de({entry:s,onClick:m}){var C,b,$,w,B,k,L,M,E,F;const{t:e}=R(),a=s.changeSummary,h=s.status==="active",p=s.isBootstrapOnly===!0,c=[],f=a.scriptsModified+a.scriptsCreated;if(f>0){const r=[];a.scriptsModified>0&&r.push(`${a.scriptsModified} ${e("changelog.card.modified","modified")}`),a.scriptsCreated>0&&r.push(`${a.scriptsCreated} ${e("changelog.card.created","created")}`);const j=`${f} ${e("changelog.card.scripts","scripts")} ${r.join(", ")}`;c.push({icon:"📝",text:j,tooltip:e("changelog.card.scripts.tooltip","Script changes made in this session.")})}const l=a.instancesCreated+a.instancesDeleted+a.instancesMoved;if(l>0){const r=[];a.instancesCreated>0&&r.push(`${a.instancesCreated} ${e("changelog.card.created","created")}`),a.instancesDeleted>0&&r.push(`${a.instancesDeleted} ${e("changelog.card.deleted","deleted")}`),a.instancesMoved>0&&r.push(`${a.instancesMoved} ${e("changelog.card.moved","moved")}`);const j=`${l} ${e("changelog.card.instances","instances")} ${r.join(", ")}`;c.push({icon:"🧱",text:j,tooltip:e("changelog.card.instances.tooltip","Instance create, delete, move, or clone changes in this session.")})}a.propertiesChanged>0&&c.push({icon:"🎨",text:`${a.propertiesChanged} ${e("changelog.card.propertiesChanged","properties changed")}`,tooltip:e("changelog.card.propertiesChanged.tooltip","Property value changes recorded for this session.")}),a.lightingChanged&&c.push({icon:"🌅",text:e("changelog.card.lightingConfigured","Lighting configured"),tooltip:e("changelog.card.lightingConfigured.tooltip","Lighting or atmosphere settings changed in this session.")}),a.terrainChanged&&c.push({icon:"⛰️",text:e("changelog.card.terrainConfigured","Terrain configured"),tooltip:e("changelog.card.terrainConfigured.tooltip","Terrain data or terrain settings changed in this session.")}),a.assetsInserted>0&&c.push({icon:"📦",text:`${a.assetsInserted} ${e("changelog.card.assetsInserted","assets inserted")}`,tooltip:e("changelog.card.assetsInserted.tooltip","Assets inserted into the place during this session.")});const x=D(s.startTime),g=h?e("changelog.card.inProgress","in progress"):s.endTime?D(s.endTime):"--:--",v=p?e("changelog.card.bootstrapStatus","Bootstrap"):h?e("changelog.card.active","Active"):e("changelog.card.completed","Completed"),y=p?e("changelog.card.bootstrapStatus.tooltip","This session only contains the initial sync bootstrap snapshot."):h?e("changelog.card.active.tooltip","This session is still receiving new game changes."):e("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),o=p?e("changelog.card.bootstrapSummary","Initial sync snapshot"):e("changelog.card.noChanges","No changes yet"),T=p?e("changelog.card.bootstrapSummary.tooltip","Initial file sync writes are collapsed into a single bootstrap snapshot row."):e("changelog.card.noChanges.tooltip","No game changes have been extracted for this session yet."),N=(b=(C=s.contextSummary)==null?void 0:C.intent)==null?void 0:b.trim(),u=((k=(B=(w=($=s.contextSummary)==null?void 0:$.affectedAreas)==null?void 0:w[0])==null?void 0:B.label)==null?void 0:k.trim())||((M=(L=s.contextSummary)==null?void 0:L.testScenario)==null?void 0:M.trim()),_=(F=(E=s.verificationSummary)==null?void 0:E.label)==null?void 0:F.trim();return t.jsxs("div",{className:n.card,onClick:m,children:[t.jsxs("div",{className:n.header,children:[t.jsx(I,{text:y,children:t.jsxs("span",{className:`${n.statusBadge} ${h?n.active:n.completed}`,children:[t.jsx("span",{className:n.statusDot}),v]})}),t.jsxs("span",{className:n.timeRange,children:[x,"~",g]})]}),t.jsx("div",{className:n.summaryList,children:c.length>0?c.map((r,j)=>t.jsxs("div",{className:n.summaryItem,children:[t.jsx("span",{className:n.summaryIcon,children:r.icon}),t.jsx(I,{text:r.tooltip,children:t.jsx("span",{className:n.summaryText,children:r.text})})]},j)):t.jsx(I,{text:T,children:t.jsx("span",{className:n.emptySummary,style:{display:"block"},children:o})})}),N&&t.jsxs("div",{className:n.contextBlock,children:[t.jsx("span",{className:n.contextLabel,children:e("changelog.card.sessionIntent","Session intent")}),t.jsx("span",{className:n.contextValue,children:N})]}),!N&&u&&t.jsxs("div",{className:n.contextBlock,children:[t.jsx("span",{className:n.contextLabel,children:e("changelog.card.representativeArea","Representative area")}),t.jsx("span",{className:n.contextValue,children:u})]}),_&&t.jsxs("div",{className:n.contextBlock,children:[t.jsx("span",{className:n.contextLabel,children:e("changelog.card.verification","Verification")}),t.jsx("span",{className:n.contextValue,children:_})]}),h&&t.jsx("div",{className:n.progressBar,children:t.jsx("div",{className:n.progressFill})})]})}const ge="_page_1ynbw_2",me="_limitNotice_1ynbw_9",he="_limitNoticeTitle_1ynbw_18",pe="_limitNoticeText_1ynbw_25",ue="_clearButton_1ynbw_33",fe="_list_1ynbw_54",xe="_empty_1ynbw_61",_e="_loading_1ynbw_70",ye="_pagination_1ynbw_79",be="_pageInfo_1ynbw_87",ve="_btn_1ynbw_93",d={page:ge,limitNotice:me,limitNoticeTitle:he,limitNoticeText:pe,clearButton:ue,list:fe,empty:xe,loading:_e,pagination:ye,pageInfo:be,btn:ve},S=10,Ne=[{key:"all",labelKey:"changelog.filter.all"},{key:"active",labelKey:"changelog.filter.active"},{key:"completed",labelKey:"changelog.filter.completed"}];function Ie(){const{t:s}=R(),m=P(),e=Z(),a=V(),{show:h}=K(),[p,c]=i.useState(!1),[f,l]=i.useState(!1),x=!a.loading&&a.tier==="basic",g=x?e.entries.slice(0,3):e.entries,v=!x&&e.total>S,y=async()=>{l(!0);try{await e.clear(),h(s("toast.clearSuccess","Cleared successfully"),"success"),c(!1)}catch{h(s("toast.clearFailed","Failed to clear data"),"error")}finally{l(!1)}};return t.jsxs("div",{className:d.page,children:[t.jsx(H,{items:Ne.map(o=>({key:o.key,label:s(o.labelKey,o.key.charAt(0).toUpperCase()+o.key.slice(1))})),value:e.statusFilter,onChange:o=>{e.setStatusFilter(o),e.setOffset(0)},rightActions:t.jsx("button",{className:d.clearButton,onClick:()=>c(!0),children:s("common.clear","Clear")})}),e.loading&&e.entries.length===0&&t.jsx("div",{className:d.loading,children:s("common.loading","Loading...")}),!e.loading&&e.entries.length===0?t.jsx("div",{className:d.empty,children:s("changelog.empty","No changelog entries yet")}):t.jsx("div",{className:d.list,children:g.map(o=>t.jsx(de,{entry:o,onClick:()=>m(`/changelog/${o.entryId}`)},o.entryId))}),v&&t.jsxs("div",{className:d.pagination,children:[t.jsx("button",{className:d.btn,disabled:e.offset===0,onClick:()=>e.setOffset(Math.max(0,e.offset-S)),children:s("tools.page.prev","Prev")}),t.jsxs("span",{className:d.pageInfo,children:[e.offset+1,"–",Math.min(e.offset+S,e.total)," / ",e.total]}),t.jsx("button",{className:d.btn,disabled:!e.hasMore,onClick:()=>e.setOffset(e.offset+S),children:s("tools.page.next","Next")})]}),x&&t.jsx(t.Fragment,{children:t.jsxs("div",{className:d.limitNotice,children:[t.jsx("div",{className:d.limitNoticeTitle,children:s("changelog.basic.limit.title","Basic preview shows the latest 3 sessions")}),t.jsx("div",{className:d.limitNoticeText,children:s("changelog.basic.limit.body","Upgrade to Pro to browse the full changelog timeline for this place.")})]})}),t.jsx(G,{open:p,title:s("changelog.clear.title","Clear changelog?"),message:s("changelog.clear.message","This permanently removes the stored changelog for the current place."),cancelLabel:s("common.cancel","Cancel"),confirmLabel:s("common.clear","Clear"),loading:f,onCancel:()=>!f&&c(!1),onConfirm:y})]})}export{Ie as Component};
1
+ import{r as i,a as A,D as O,u as R,j as t,c as P,l as V,m as K}from"./index-FfT2oWAB.js";import{C as G}from"./ConfirmModal-CmJCz5rg.js";import{T as I}from"./TooltipText-Baw38jOU.js";import{T as H}from"./Tabs-BNtOqYlc.js";const U=10;function Z(){const[s,m]=i.useState([]),[e,a]=i.useState(0),[h,p]=i.useState(!1),[c,f]=i.useState(!0),[l,x]=i.useState(0),[g,v]=i.useState("all"),y=i.useRef(null),o=i.useCallback(async(u,_)=>{f(!0);try{const C={limit:String(U),offset:String(u)};_!=="all"&&(C.status=_);const b=await A.get("/api/dashboard/changelog",C);m(b.entries),a(b.total),p(b.hasMore)}catch{m([]),a(0),p(!1)}finally{f(!1)}},[]),T=i.useCallback(()=>{o(l,g)},[o,l,g]),N=i.useCallback(async()=>{await A.post("/api/dashboard/changelog/clear"),m([]),a(0),p(!1)},[]);return i.useEffect(()=>{o(l,g)},[o,l,g]),i.useEffect(()=>{const u=new O;y.current=u,u.connect();const _=u.on("command",()=>{o(l,g)});return()=>{_(),u.disconnect(),y.current=null}},[o,l,g]),{entries:s,total:e,hasMore:h,loading:c,offset:l,statusFilter:g,setOffset:x,setStatusFilter:v,refresh:T,clear:N}}const q="_card_1n89u_2",z="_header_1n89u_17",J="_statusBadge_1n89u_24",Q="_statusDot_1n89u_35",W="_active_1n89u_41",X="_completed_1n89u_50",Y="_timeRange_1n89u_58",ee="_summaryList_1n89u_65",te="_summaryItem_1n89u_71",se="_summaryIcon_1n89u_80",ae="_summaryText_1n89u_86",ne="_progressBar_1n89u_91",oe="_progressFill_1n89u_99",ce="_emptySummary_1n89u_112",ie="_contextBlock_1n89u_120",le="_contextLabel_1n89u_129",re="_contextValue_1n89u_137",n={card:q,header:z,statusBadge:J,statusDot:Q,active:W,completed:X,timeRange:Y,summaryList:ee,summaryItem:te,summaryIcon:se,summaryText:ae,progressBar:ne,progressFill:oe,emptySummary:ce,contextBlock:ie,contextLabel:le,contextValue:re};function D(s){if(!s)return"--:--";const m=new Date(s);return`${String(m.getHours()).padStart(2,"0")}:${String(m.getMinutes()).padStart(2,"0")}`}function de({entry:s,onClick:m}){var C,b,$,w,B,k,L,M,E,F;const{t:e}=R(),a=s.changeSummary,h=s.status==="active",p=s.isBootstrapOnly===!0,c=[],f=a.scriptsModified+a.scriptsCreated;if(f>0){const r=[];a.scriptsModified>0&&r.push(`${a.scriptsModified} ${e("changelog.card.modified","modified")}`),a.scriptsCreated>0&&r.push(`${a.scriptsCreated} ${e("changelog.card.created","created")}`);const j=`${f} ${e("changelog.card.scripts","scripts")} ${r.join(", ")}`;c.push({icon:"📝",text:j,tooltip:e("changelog.card.scripts.tooltip","Script changes made in this session.")})}const l=a.instancesCreated+a.instancesDeleted+a.instancesMoved;if(l>0){const r=[];a.instancesCreated>0&&r.push(`${a.instancesCreated} ${e("changelog.card.created","created")}`),a.instancesDeleted>0&&r.push(`${a.instancesDeleted} ${e("changelog.card.deleted","deleted")}`),a.instancesMoved>0&&r.push(`${a.instancesMoved} ${e("changelog.card.moved","moved")}`);const j=`${l} ${e("changelog.card.instances","instances")} ${r.join(", ")}`;c.push({icon:"🧱",text:j,tooltip:e("changelog.card.instances.tooltip","Instance create, delete, move, or clone changes in this session.")})}a.propertiesChanged>0&&c.push({icon:"🎨",text:`${a.propertiesChanged} ${e("changelog.card.propertiesChanged","properties changed")}`,tooltip:e("changelog.card.propertiesChanged.tooltip","Property value changes recorded for this session.")}),a.lightingChanged&&c.push({icon:"🌅",text:e("changelog.card.lightingConfigured","Lighting configured"),tooltip:e("changelog.card.lightingConfigured.tooltip","Lighting or atmosphere settings changed in this session.")}),a.terrainChanged&&c.push({icon:"⛰️",text:e("changelog.card.terrainConfigured","Terrain configured"),tooltip:e("changelog.card.terrainConfigured.tooltip","Terrain data or terrain settings changed in this session.")}),a.assetsInserted>0&&c.push({icon:"📦",text:`${a.assetsInserted} ${e("changelog.card.assetsInserted","assets inserted")}`,tooltip:e("changelog.card.assetsInserted.tooltip","Assets inserted into the place during this session.")});const x=D(s.startTime),g=h?e("changelog.card.inProgress","in progress"):s.endTime?D(s.endTime):"--:--",v=p?e("changelog.card.bootstrapStatus","Bootstrap"):h?e("changelog.card.active","Active"):e("changelog.card.completed","Completed"),y=p?e("changelog.card.bootstrapStatus.tooltip","This session only contains the initial sync bootstrap snapshot."):h?e("changelog.card.active.tooltip","This session is still receiving new game changes."):e("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),o=p?e("changelog.card.bootstrapSummary","Initial sync snapshot"):e("changelog.card.noChanges","No changes yet"),T=p?e("changelog.card.bootstrapSummary.tooltip","Initial file sync writes are collapsed into a single bootstrap snapshot row."):e("changelog.card.noChanges.tooltip","No game changes have been extracted for this session yet."),N=(b=(C=s.contextSummary)==null?void 0:C.intent)==null?void 0:b.trim(),u=((k=(B=(w=($=s.contextSummary)==null?void 0:$.affectedAreas)==null?void 0:w[0])==null?void 0:B.label)==null?void 0:k.trim())||((M=(L=s.contextSummary)==null?void 0:L.testScenario)==null?void 0:M.trim()),_=(F=(E=s.verificationSummary)==null?void 0:E.label)==null?void 0:F.trim();return t.jsxs("div",{className:n.card,onClick:m,children:[t.jsxs("div",{className:n.header,children:[t.jsx(I,{text:y,children:t.jsxs("span",{className:`${n.statusBadge} ${h?n.active:n.completed}`,children:[t.jsx("span",{className:n.statusDot}),v]})}),t.jsxs("span",{className:n.timeRange,children:[x,"~",g]})]}),t.jsx("div",{className:n.summaryList,children:c.length>0?c.map((r,j)=>t.jsxs("div",{className:n.summaryItem,children:[t.jsx("span",{className:n.summaryIcon,children:r.icon}),t.jsx(I,{text:r.tooltip,children:t.jsx("span",{className:n.summaryText,children:r.text})})]},j)):t.jsx(I,{text:T,children:t.jsx("span",{className:n.emptySummary,style:{display:"block"},children:o})})}),N&&t.jsxs("div",{className:n.contextBlock,children:[t.jsx("span",{className:n.contextLabel,children:e("changelog.card.sessionIntent","Session intent")}),t.jsx("span",{className:n.contextValue,children:N})]}),!N&&u&&t.jsxs("div",{className:n.contextBlock,children:[t.jsx("span",{className:n.contextLabel,children:e("changelog.card.representativeArea","Representative area")}),t.jsx("span",{className:n.contextValue,children:u})]}),_&&t.jsxs("div",{className:n.contextBlock,children:[t.jsx("span",{className:n.contextLabel,children:e("changelog.card.verification","Verification")}),t.jsx("span",{className:n.contextValue,children:_})]}),h&&t.jsx("div",{className:n.progressBar,children:t.jsx("div",{className:n.progressFill})})]})}const ge="_page_1ynbw_2",me="_limitNotice_1ynbw_9",he="_limitNoticeTitle_1ynbw_18",pe="_limitNoticeText_1ynbw_25",ue="_clearButton_1ynbw_33",fe="_list_1ynbw_54",xe="_empty_1ynbw_61",_e="_loading_1ynbw_70",ye="_pagination_1ynbw_79",be="_pageInfo_1ynbw_87",ve="_btn_1ynbw_93",d={page:ge,limitNotice:me,limitNoticeTitle:he,limitNoticeText:pe,clearButton:ue,list:fe,empty:xe,loading:_e,pagination:ye,pageInfo:be,btn:ve},S=10,Ne=[{key:"all",labelKey:"changelog.filter.all"},{key:"active",labelKey:"changelog.filter.active"},{key:"completed",labelKey:"changelog.filter.completed"}];function Ie(){const{t:s}=R(),m=P(),e=Z(),a=V(),{show:h}=K(),[p,c]=i.useState(!1),[f,l]=i.useState(!1),x=!a.loading&&a.tier==="basic",g=x?e.entries.slice(0,3):e.entries,v=!x&&e.total>S,y=async()=>{l(!0);try{await e.clear(),h(s("toast.clearSuccess","Cleared successfully"),"success"),c(!1)}catch{h(s("toast.clearFailed","Failed to clear data"),"error")}finally{l(!1)}};return t.jsxs("div",{className:d.page,children:[t.jsx(H,{items:Ne.map(o=>({key:o.key,label:s(o.labelKey,o.key.charAt(0).toUpperCase()+o.key.slice(1))})),value:e.statusFilter,onChange:o=>{e.setStatusFilter(o),e.setOffset(0)},rightActions:t.jsx("button",{className:d.clearButton,onClick:()=>c(!0),children:s("common.clear","Clear")})}),e.loading&&e.entries.length===0&&t.jsx("div",{className:d.loading,children:s("common.loading","Loading...")}),!e.loading&&e.entries.length===0?t.jsx("div",{className:d.empty,children:s("changelog.empty","No changelog entries yet")}):t.jsx("div",{className:d.list,children:g.map(o=>t.jsx(de,{entry:o,onClick:()=>m(`/changelog/${o.entryId}`)},o.entryId))}),v&&t.jsxs("div",{className:d.pagination,children:[t.jsx("button",{className:d.btn,disabled:e.offset===0,onClick:()=>e.setOffset(Math.max(0,e.offset-S)),children:s("tools.page.prev","Prev")}),t.jsxs("span",{className:d.pageInfo,children:[e.offset+1,"–",Math.min(e.offset+S,e.total)," / ",e.total]}),t.jsx("button",{className:d.btn,disabled:!e.hasMore,onClick:()=>e.setOffset(e.offset+S),children:s("tools.page.next","Next")})]}),x&&t.jsx(t.Fragment,{children:t.jsxs("div",{className:d.limitNotice,children:[t.jsx("div",{className:d.limitNoticeTitle,children:s("changelog.basic.limit.title","Basic preview shows the latest 3 sessions")}),t.jsx("div",{className:d.limitNoticeText,children:s("changelog.basic.limit.body","Upgrade to Pro to browse the full changelog timeline for this place.")})]})}),t.jsx(G,{open:p,title:s("changelog.clear.title","Clear changelog?"),message:s("changelog.clear.message","This permanently removes the stored changelog for the current place."),cancelLabel:s("common.cancel","Cancel"),confirmLabel:s("common.clear","Clear"),loading:f,onCancel:()=>!f&&c(!1),onConfirm:y})]})}export{Ie as Component};
@@ -1 +1 @@
1
- import{j as s,w as e}from"./index-BPAvjNNu.js";function x({open:c,title:i,message:n,cancelLabel:t,confirmLabel:o,loading:a=!1,onCancel:l,onConfirm:r}){return c?s.jsx("div",{className:e.backdrop,onClick:a?void 0:l,children:s.jsxs("div",{className:e.modal,onClick:d=>d.stopPropagation(),children:[s.jsx("h2",{className:e.title,children:i}),s.jsx("p",{className:e.message,children:n}),s.jsxs("div",{className:e.actions,children:[s.jsx("button",{className:e.cancelButton,onClick:l,disabled:a,children:t}),s.jsx("button",{className:e.confirmButton,onClick:r,disabled:a,children:a?"...":o})]})]})}):null}export{x as C};
1
+ import{j as s,w as e}from"./index-FfT2oWAB.js";function x({open:c,title:i,message:n,cancelLabel:t,confirmLabel:o,loading:a=!1,onCancel:l,onConfirm:r}){return c?s.jsx("div",{className:e.backdrop,onClick:a?void 0:l,children:s.jsxs("div",{className:e.modal,onClick:d=>d.stopPropagation(),children:[s.jsx("h2",{className:e.title,children:i}),s.jsx("p",{className:e.message,children:n}),s.jsxs("div",{className:e.actions,children:[s.jsx("button",{className:e.cancelButton,onClick:l,disabled:a,children:t}),s.jsx("button",{className:e.confirmButton,onClick:r,disabled:a,children:a?"...":o})]})]})}):null}export{x as C};
@@ -1 +1 @@
1
- import{u as R,r as i,j as e,d as E,a as w,D as B,m as P}from"./index-BPAvjNNu.js";import{I as r}from"./InfoLabel-BJIFNYA5.js";import{S as T}from"./StatusBadge-ilvVufN2.js";import{T as D}from"./TooltipText-bSKcc3-P.js";import{C as $}from"./ConfirmModal-BDWSInRi.js";import{u as F,f as H}from"./useLiveUptime-HYmdQdHf.js";const U="_container_1h084_2",K="_entry_1h084_14",G="_timestamp_1h084_21",O="_message_1h084_27",V="_warn_1h084_34",X="_error_1h084_39",z="_empty_1h084_44",_={container:U,entry:K,timestamp:G,message:O,warn:V,error:X,empty:z};function J(n){const t=new Date(n);return Number.isNaN(t.getTime())?n:`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}function Q({entries:n}){const{t}=R(),o=i.useRef(null);return i.useEffect(()=>{const l=o.current;l&&(l.scrollTop=l.scrollHeight)},[n.length]),e.jsx("div",{ref:o,className:_.container,children:n.length===0?e.jsx("div",{className:_.empty,children:t("connection.log.empty","No events yet")}):n.map((l,j)=>e.jsxs("div",{className:`${_.entry} ${l.type?_[l.type]:""}`,children:[e.jsx("span",{className:_.timestamp,children:J(l.timestamp)}),e.jsx("span",{className:_.message,children:l.message})]},j))})}const A=50;function W(){const n=new Date;return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function Y(){const{level:n,status:t,error:o}=E(),[l,j]=i.useState(null),[k,f]=i.useState([]),g=i.useRef(null),u=i.useCallback((a,d)=>{f(x=>{const m=[...x,{timestamp:W(),message:a,type:d}];return m.length>A?m.slice(-A):m})},[]),h=i.useCallback(async()=>{try{const a=await w.get("/connection-info");j(a)}catch{j(null)}},[]),y=i.useCallback(async()=>{try{const a=await w.get("/api/dashboard/connection-log");f(a.entries??[])}catch{f([])}},[]),v=i.useCallback(async()=>{await w.post("/api/dashboard/connection-log/clear"),f([])},[]),S=i.useCallback(async a=>{await w.post("/api/dashboard/kill-agent",{instanceId:a}),await h()},[h]);return i.useEffect(()=>{n!=="disconnected"&&t&&h(),y()},[n,t,h,y]),i.useEffect(()=>{const a=new B;g.current=a,a.connect();const d=a.on("connection",m=>{const p=m,b=p.status==="connected"?"connected":"disconnected";u(`Plugin ${b} — ${p.clientId}`,p.status==="connected"?"info":"warn")}),x=a.on("mcp_status",m=>{const p=m,b=p.status==="registered"?"registered":"unregistered";u(`MCP ${b} — ${p.aiClientName}`,p.status==="registered"?"info":"warn"),h()});return()=>{d(),x(),a.disconnect(),g.current=null}},[u,h]),{status:t,connectionInfo:l,connectionLog:k,level:n,error:o,clearConnectionLog:v,killAgent:S}}const Z="_page_sf4qa_2",ee="_card_sf4qa_10",ne="_disabled_sf4qa_18",te="_cardHeader_sf4qa_24",se="_clearButton_sf4qa_37",ce="_serverGrid_sf4qa_47",oe="_statusRow_sf4qa_65",ie="_metaItem_sf4qa_72",ae="_table_sf4qa_79",le="_toggleBtn_sf4qa_104",re="_disconnected_sf4qa_119",de="_disconnectedActions_sf4qa_136",me="_btn_sf4qa_143",pe="_activity_active_sf4qa_161",he="_activity_stale_sf4qa_162",ge="_activity_unknown_sf4qa_163",ue="_killBtn_sf4qa_187",xe="_emptyRow_sf4qa_207",s={page:Z,card:ee,disabled:ne,cardHeader:te,clearButton:se,serverGrid:ce,statusRow:oe,metaItem:ie,table:ae,toggleBtn:le,disconnected:re,disconnectedActions:de,btn:me,activity_active:pe,activity_stale:he,activity_unknown:ge,killBtn:ue,emptyRow:xe};function N(n,t){const o=Math.max(0,Math.floor((Date.now()-n)/1e3));return o<60?`${o}${t("connection.time.secondsAgo","s ago")}`:o<3600?`${Math.floor(o/60)}${t("connection.time.minutesAgo","m ago")}`:`${Math.floor(o/3600)}${t("connection.time.hoursAgo","h ago")}`}function je(n){return n?Date.now()-n<3e4?"active":"stale":"unknown"}function Se(){var I;const{t:n}=R(),{status:t,connectionInfo:o,connectionLog:l,level:j,clearConnectionLog:k,killAgent:f}=Y(),{show:g}=P(),[u,h]=i.useState(!0),[y,v]=i.useState(!1),[S,a]=i.useState(!1),[d,x]=i.useState(null),[m,p]=i.useState(!1),b=F(t==null?void 0:t.uptime),C=j==="disconnected",L=C?"offline":"online",q=async()=>{if(d){p(!0);try{await f(d.instanceId),g(n("connection.agents.killed","Agent killed"),"success"),x(null)}catch{g(n("connection.agents.killFailed","Failed to kill agent"),"error")}finally{p(!1)}}},M=async()=>{a(!0);try{await k(),g(n("toast.clearSuccess","Cleared successfully"),"success"),v(!1)}catch{g(n("toast.clearFailed","Failed to clear data"),"error")}finally{a(!1)}};return e.jsxs("div",{className:s.page,children:[e.jsxs("div",{className:s.card,children:[e.jsx("div",{className:s.cardHeader,children:n("connection.server.title","Server Status")}),C?e.jsxs("div",{className:s.disconnected,children:[e.jsx("h3",{children:n("level.l0.title")}),e.jsx("p",{children:n("level.l0.message")}),e.jsx("p",{children:n("common.reconnecting")}),e.jsxs("div",{className:s.disconnectedActions,children:[e.jsx("button",{className:s.btn,onClick:()=>window.location.reload(),children:n("connection.reconnect","Reconnect")}),e.jsx("button",{className:s.btn,onClick:()=>{window.location.hash="#/settings"},children:n("connection.checkSettings","Check Settings")})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:s.statusRow,children:e.jsx(T,{status:L})}),e.jsxs("dl",{className:s.serverGrid,children:[(t==null?void 0:t.version)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.version","Version"),tooltip:n("connection.server.version.tooltip","Installed MCP server version")})}),e.jsx("dd",{children:e.jsx(D,{text:n("connection.server.version.tooltip","Installed MCP server version"),children:`v${t.version}`})})]}),(t==null?void 0:t.pid)!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.pid","PID"),tooltip:n("connection.server.pid.tooltip","Operating system process identifier")})}),e.jsx("dd",{children:t.pid})]}),(t==null?void 0:t.uptime)!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.uptime","Uptime"),tooltip:n("connection.server.uptime.tooltip","Time elapsed since the MCP server started")})}),e.jsx("dd",{children:H(b??t.uptime)})]}),(t==null?void 0:t.sessionId)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.session","Session"),tooltip:n("connection.server.session.tooltip","Current MCP session identifier")})}),e.jsx("dd",{children:t.sessionId.slice(0,8)})]}),(o==null?void 0:o.serverExecutable)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.exec","Exec"),tooltip:n("connection.server.exec.tooltip","Executable path used to launch the MCP server")})}),e.jsx("dd",{children:o.serverExecutable})]})]})]})]}),e.jsxs("div",{className:`${s.card} ${C?s.disabled:""}`,children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsxs("span",{children:[n("connection.agents.title","AI Agents")," ","(",(o==null?void 0:o.mcpInstanceCount)??0,")"]}),e.jsx("button",{className:s.toggleBtn,onClick:()=>h(c=>!c),"aria-label":u?n("common.collapse","Collapse"):n("common.expand","Expand"),children:u?"▾":"▸"})]}),u&&e.jsxs("table",{className:s.table,children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:n("connection.agents.name","Agent")}),e.jsx("th",{children:e.jsx(r,{label:n("connection.server.pid","PID"),tooltip:n("connection.server.pid.tooltip","Operating system process identifier")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.agents.projectRoot","Project Root"),tooltip:n("connection.agents.projectRoot.tooltip","Authoritative project root for sync ownership")})}),e.jsx("th",{children:n("connection.agents.connected","Connected")}),e.jsx("th",{children:e.jsx(r,{label:n("connection.agents.lastSeen","Last Seen"),tooltip:n("connection.agents.lastSeen.tooltip","Most recent heartbeat or activity from this agent")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.agents.lastCommand","Last Command"),tooltip:n("connection.agents.lastCommand.tooltip","Most recent tool call executed by this agent")})}),e.jsx("th",{})]})}),e.jsx("tbody",{children:o!=null&&o.mcpInstances&&o.mcpInstances.length>0?o.mcpInstances.map(c=>e.jsxs("tr",{children:[e.jsxs("td",{children:[e.jsx("span",{className:s[`activity_${je(c.lastSeen)}`]}),c.aiClientName??n("connection.agents.unknown","Unknown")]}),e.jsx("td",{children:c.pid}),e.jsx("td",{children:c.projectRoot??c.cwd??n("connection.agents.projectRoot.unresolved","Unresolved")}),e.jsx("td",{children:N(c.connectedAt,n)}),e.jsx("td",{children:c.lastSeen?N(c.lastSeen,n):"-"}),e.jsx("td",{children:c.lastCommandAt?N(c.lastCommandAt,n):"-"}),e.jsx("td",{children:!c.isServer&&e.jsx("button",{className:s.killBtn,onClick:()=>x({instanceId:c.instanceId,name:c.aiClientName??c.instanceId.slice(0,8)}),children:n("connection.agents.kill","Kill")})})]},c.instanceId)):e.jsx("tr",{children:e.jsx("td",{colSpan:7,className:s.emptyRow,children:n("connection.agents.none","No agents connected")})})})]})]}),e.jsxs("div",{className:`${s.card} ${C?s.disabled:""}`,children:[e.jsxs("div",{className:s.cardHeader,children:[n("connection.plugins.title","Plugins")," ","(",((I=t==null?void 0:t.pluginClients)==null?void 0:I.length)??0,")"]}),e.jsxs("table",{className:s.table,children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:n("connection.plugins.place","Place")}),e.jsx("th",{children:e.jsx(r,{label:n("connection.plugins.clientId","Client ID"),tooltip:n("connection.plugins.clientId.tooltip","Unique plugin client identifier for this Studio connection")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.plugins.lastSeen","Last Seen"),tooltip:n("connection.plugins.lastSeen.tooltip","Most recent heartbeat received from the plugin")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.plugins.version","Ver"),tooltip:n("connection.plugins.version.tooltip","Installed plugin version reported by Studio")})})]})}),e.jsx("tbody",{children:t!=null&&t.pluginClients&&t.pluginClients.length>0?t.pluginClients.map(c=>e.jsxs("tr",{children:[e.jsx("td",{children:c.placeName??c.projectName??"-"}),e.jsx("td",{children:c.clientId.slice(0,10)}),e.jsx("td",{children:N(c.lastSeen,n)}),e.jsx("td",{children:c.pluginVersion??"-"})]},c.clientId)):e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:s.emptyRow,children:n("connection.plugins.none","No plugins connected")})})})]})]}),e.jsxs("div",{className:`${s.card} ${C?s.disabled:""}`,children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsx("span",{children:n("connection.log.title","Connection Log")}),e.jsx("button",{className:s.clearButton,onClick:()=>v(!0),children:n("common.clear","Clear")})]}),e.jsx(Q,{entries:l})]}),e.jsx($,{open:y,title:n("connection.clear.title","Clear connection log?"),message:n("connection.clear.message","This permanently removes the stored connection log for the current project."),cancelLabel:n("common.cancel","Cancel"),confirmLabel:n("common.clear","Clear"),loading:S,onCancel:()=>!S&&v(!1),onConfirm:M}),e.jsx($,{open:!!d,title:n("connection.agents.kill.title","Kill agent?"),message:`"${d==null?void 0:d.name}" 프로세스를 강제 종료합니다. 해당 에이전트의 진행 중인 작업이 중단됩니다.`,cancelLabel:n("common.cancel","Cancel"),confirmLabel:n("connection.agents.kill","Kill"),loading:m,onCancel:()=>!m&&x(null),onConfirm:q})]})}export{Se as Component};
1
+ import{u as R,r as i,j as e,d as E,a as w,D as B,m as P}from"./index-FfT2oWAB.js";import{I as r}from"./InfoLabel-B9KT3kfU.js";import{S as T}from"./StatusBadge-Bxe88ki2.js";import{T as D}from"./TooltipText-Baw38jOU.js";import{C as $}from"./ConfirmModal-CmJCz5rg.js";import{u as F,f as H}from"./useLiveUptime-DhJz484L.js";const U="_container_1h084_2",K="_entry_1h084_14",G="_timestamp_1h084_21",O="_message_1h084_27",V="_warn_1h084_34",X="_error_1h084_39",z="_empty_1h084_44",_={container:U,entry:K,timestamp:G,message:O,warn:V,error:X,empty:z};function J(n){const t=new Date(n);return Number.isNaN(t.getTime())?n:`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}function Q({entries:n}){const{t}=R(),o=i.useRef(null);return i.useEffect(()=>{const l=o.current;l&&(l.scrollTop=l.scrollHeight)},[n.length]),e.jsx("div",{ref:o,className:_.container,children:n.length===0?e.jsx("div",{className:_.empty,children:t("connection.log.empty","No events yet")}):n.map((l,j)=>e.jsxs("div",{className:`${_.entry} ${l.type?_[l.type]:""}`,children:[e.jsx("span",{className:_.timestamp,children:J(l.timestamp)}),e.jsx("span",{className:_.message,children:l.message})]},j))})}const A=50;function W(){const n=new Date;return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function Y(){const{level:n,status:t,error:o}=E(),[l,j]=i.useState(null),[k,f]=i.useState([]),g=i.useRef(null),u=i.useCallback((a,d)=>{f(x=>{const m=[...x,{timestamp:W(),message:a,type:d}];return m.length>A?m.slice(-A):m})},[]),h=i.useCallback(async()=>{try{const a=await w.get("/connection-info");j(a)}catch{j(null)}},[]),y=i.useCallback(async()=>{try{const a=await w.get("/api/dashboard/connection-log");f(a.entries??[])}catch{f([])}},[]),v=i.useCallback(async()=>{await w.post("/api/dashboard/connection-log/clear"),f([])},[]),S=i.useCallback(async a=>{await w.post("/api/dashboard/kill-agent",{instanceId:a}),await h()},[h]);return i.useEffect(()=>{n!=="disconnected"&&t&&h(),y()},[n,t,h,y]),i.useEffect(()=>{const a=new B;g.current=a,a.connect();const d=a.on("connection",m=>{const p=m,b=p.status==="connected"?"connected":"disconnected";u(`Plugin ${b} — ${p.clientId}`,p.status==="connected"?"info":"warn")}),x=a.on("mcp_status",m=>{const p=m,b=p.status==="registered"?"registered":"unregistered";u(`MCP ${b} — ${p.aiClientName}`,p.status==="registered"?"info":"warn"),h()});return()=>{d(),x(),a.disconnect(),g.current=null}},[u,h]),{status:t,connectionInfo:l,connectionLog:k,level:n,error:o,clearConnectionLog:v,killAgent:S}}const Z="_page_sf4qa_2",ee="_card_sf4qa_10",ne="_disabled_sf4qa_18",te="_cardHeader_sf4qa_24",se="_clearButton_sf4qa_37",ce="_serverGrid_sf4qa_47",oe="_statusRow_sf4qa_65",ie="_metaItem_sf4qa_72",ae="_table_sf4qa_79",le="_toggleBtn_sf4qa_104",re="_disconnected_sf4qa_119",de="_disconnectedActions_sf4qa_136",me="_btn_sf4qa_143",pe="_activity_active_sf4qa_161",he="_activity_stale_sf4qa_162",ge="_activity_unknown_sf4qa_163",ue="_killBtn_sf4qa_187",xe="_emptyRow_sf4qa_207",s={page:Z,card:ee,disabled:ne,cardHeader:te,clearButton:se,serverGrid:ce,statusRow:oe,metaItem:ie,table:ae,toggleBtn:le,disconnected:re,disconnectedActions:de,btn:me,activity_active:pe,activity_stale:he,activity_unknown:ge,killBtn:ue,emptyRow:xe};function N(n,t){const o=Math.max(0,Math.floor((Date.now()-n)/1e3));return o<60?`${o}${t("connection.time.secondsAgo","s ago")}`:o<3600?`${Math.floor(o/60)}${t("connection.time.minutesAgo","m ago")}`:`${Math.floor(o/3600)}${t("connection.time.hoursAgo","h ago")}`}function je(n){return n?Date.now()-n<3e4?"active":"stale":"unknown"}function Se(){var I;const{t:n}=R(),{status:t,connectionInfo:o,connectionLog:l,level:j,clearConnectionLog:k,killAgent:f}=Y(),{show:g}=P(),[u,h]=i.useState(!0),[y,v]=i.useState(!1),[S,a]=i.useState(!1),[d,x]=i.useState(null),[m,p]=i.useState(!1),b=F(t==null?void 0:t.uptime),C=j==="disconnected",L=C?"offline":"online",q=async()=>{if(d){p(!0);try{await f(d.instanceId),g(n("connection.agents.killed","Agent killed"),"success"),x(null)}catch{g(n("connection.agents.killFailed","Failed to kill agent"),"error")}finally{p(!1)}}},M=async()=>{a(!0);try{await k(),g(n("toast.clearSuccess","Cleared successfully"),"success"),v(!1)}catch{g(n("toast.clearFailed","Failed to clear data"),"error")}finally{a(!1)}};return e.jsxs("div",{className:s.page,children:[e.jsxs("div",{className:s.card,children:[e.jsx("div",{className:s.cardHeader,children:n("connection.server.title","Server Status")}),C?e.jsxs("div",{className:s.disconnected,children:[e.jsx("h3",{children:n("level.l0.title")}),e.jsx("p",{children:n("level.l0.message")}),e.jsx("p",{children:n("common.reconnecting")}),e.jsxs("div",{className:s.disconnectedActions,children:[e.jsx("button",{className:s.btn,onClick:()=>window.location.reload(),children:n("connection.reconnect","Reconnect")}),e.jsx("button",{className:s.btn,onClick:()=>{window.location.hash="#/settings"},children:n("connection.checkSettings","Check Settings")})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:s.statusRow,children:e.jsx(T,{status:L})}),e.jsxs("dl",{className:s.serverGrid,children:[(t==null?void 0:t.version)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.version","Version"),tooltip:n("connection.server.version.tooltip","Installed MCP server version")})}),e.jsx("dd",{children:e.jsx(D,{text:n("connection.server.version.tooltip","Installed MCP server version"),children:`v${t.version}`})})]}),(t==null?void 0:t.pid)!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.pid","PID"),tooltip:n("connection.server.pid.tooltip","Operating system process identifier")})}),e.jsx("dd",{children:t.pid})]}),(t==null?void 0:t.uptime)!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.uptime","Uptime"),tooltip:n("connection.server.uptime.tooltip","Time elapsed since the MCP server started")})}),e.jsx("dd",{children:H(b??t.uptime)})]}),(t==null?void 0:t.sessionId)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.session","Session"),tooltip:n("connection.server.session.tooltip","Current MCP session identifier")})}),e.jsx("dd",{children:t.sessionId.slice(0,8)})]}),(o==null?void 0:o.serverExecutable)&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{children:e.jsx(r,{label:n("connection.server.exec","Exec"),tooltip:n("connection.server.exec.tooltip","Executable path used to launch the MCP server")})}),e.jsx("dd",{children:o.serverExecutable})]})]})]})]}),e.jsxs("div",{className:`${s.card} ${C?s.disabled:""}`,children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsxs("span",{children:[n("connection.agents.title","AI Agents")," ","(",(o==null?void 0:o.mcpInstanceCount)??0,")"]}),e.jsx("button",{className:s.toggleBtn,onClick:()=>h(c=>!c),"aria-label":u?n("common.collapse","Collapse"):n("common.expand","Expand"),children:u?"▾":"▸"})]}),u&&e.jsxs("table",{className:s.table,children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:n("connection.agents.name","Agent")}),e.jsx("th",{children:e.jsx(r,{label:n("connection.server.pid","PID"),tooltip:n("connection.server.pid.tooltip","Operating system process identifier")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.agents.projectRoot","Project Root"),tooltip:n("connection.agents.projectRoot.tooltip","Authoritative project root for sync ownership")})}),e.jsx("th",{children:n("connection.agents.connected","Connected")}),e.jsx("th",{children:e.jsx(r,{label:n("connection.agents.lastSeen","Last Seen"),tooltip:n("connection.agents.lastSeen.tooltip","Most recent heartbeat or activity from this agent")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.agents.lastCommand","Last Command"),tooltip:n("connection.agents.lastCommand.tooltip","Most recent tool call executed by this agent")})}),e.jsx("th",{})]})}),e.jsx("tbody",{children:o!=null&&o.mcpInstances&&o.mcpInstances.length>0?o.mcpInstances.map(c=>e.jsxs("tr",{children:[e.jsxs("td",{children:[e.jsx("span",{className:s[`activity_${je(c.lastSeen)}`]}),c.aiClientName??n("connection.agents.unknown","Unknown")]}),e.jsx("td",{children:c.pid}),e.jsx("td",{children:c.projectRoot??c.cwd??n("connection.agents.projectRoot.unresolved","Unresolved")}),e.jsx("td",{children:N(c.connectedAt,n)}),e.jsx("td",{children:c.lastSeen?N(c.lastSeen,n):"-"}),e.jsx("td",{children:c.lastCommandAt?N(c.lastCommandAt,n):"-"}),e.jsx("td",{children:!c.isServer&&e.jsx("button",{className:s.killBtn,onClick:()=>x({instanceId:c.instanceId,name:c.aiClientName??c.instanceId.slice(0,8)}),children:n("connection.agents.kill","Kill")})})]},c.instanceId)):e.jsx("tr",{children:e.jsx("td",{colSpan:7,className:s.emptyRow,children:n("connection.agents.none","No agents connected")})})})]})]}),e.jsxs("div",{className:`${s.card} ${C?s.disabled:""}`,children:[e.jsxs("div",{className:s.cardHeader,children:[n("connection.plugins.title","Plugins")," ","(",((I=t==null?void 0:t.pluginClients)==null?void 0:I.length)??0,")"]}),e.jsxs("table",{className:s.table,children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:n("connection.plugins.place","Place")}),e.jsx("th",{children:e.jsx(r,{label:n("connection.plugins.clientId","Client ID"),tooltip:n("connection.plugins.clientId.tooltip","Unique plugin client identifier for this Studio connection")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.plugins.lastSeen","Last Seen"),tooltip:n("connection.plugins.lastSeen.tooltip","Most recent heartbeat received from the plugin")})}),e.jsx("th",{children:e.jsx(r,{label:n("connection.plugins.version","Ver"),tooltip:n("connection.plugins.version.tooltip","Installed plugin version reported by Studio")})})]})}),e.jsx("tbody",{children:t!=null&&t.pluginClients&&t.pluginClients.length>0?t.pluginClients.map(c=>e.jsxs("tr",{children:[e.jsx("td",{children:c.placeName??c.projectName??"-"}),e.jsx("td",{children:c.clientId.slice(0,10)}),e.jsx("td",{children:N(c.lastSeen,n)}),e.jsx("td",{children:c.pluginVersion??"-"})]},c.clientId)):e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:s.emptyRow,children:n("connection.plugins.none","No plugins connected")})})})]})]}),e.jsxs("div",{className:`${s.card} ${C?s.disabled:""}`,children:[e.jsxs("div",{className:s.cardHeader,children:[e.jsx("span",{children:n("connection.log.title","Connection Log")}),e.jsx("button",{className:s.clearButton,onClick:()=>v(!0),children:n("common.clear","Clear")})]}),e.jsx(Q,{entries:l})]}),e.jsx($,{open:y,title:n("connection.clear.title","Clear connection log?"),message:n("connection.clear.message","This permanently removes the stored connection log for the current project."),cancelLabel:n("common.cancel","Cancel"),confirmLabel:n("common.clear","Clear"),loading:S,onCancel:()=>!S&&v(!1),onConfirm:M}),e.jsx($,{open:!!d,title:n("connection.agents.kill.title","Kill agent?"),message:`"${d==null?void 0:d.name}" 프로세스를 강제 종료합니다. 해당 에이전트의 진행 중인 작업이 중단됩니다.`,cancelLabel:n("common.cancel","Cancel"),confirmLabel:n("connection.agents.kill","Kill"),loading:m,onCancel:()=>!m&&x(null),onConfirm:q})]})}export{Se as Component};
@@ -1,4 +1,4 @@
1
- import{u as _,r as x,j as e}from"./index-BPAvjNNu.js";const N="_container_uv8oc_2",j="_header_uv8oc_10",v="_modeBtn_uv8oc_18",g="_modeBtnActive_uv8oc_33",b="_unifiedView_uv8oc_40",w="_diffLine_uv8oc_46",L="_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:b,diffLine:w,lineNum:L,lineContent:C,lineAdded:S,lineRemoved:V,lineContext:B,sideBySide:$,sidePane:A,sideLabel:P,sideContent:R,empty:D};function k(n,i){const o=n.split(`
1
+ import{u as _,r as x,j as e}from"./index-FfT2oWAB.js";const N="_container_uv8oc_2",j="_header_uv8oc_10",v="_modeBtn_uv8oc_18",g="_modeBtnActive_uv8oc_33",b="_unifiedView_uv8oc_40",w="_diffLine_uv8oc_46",L="_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:b,diffLine:w,lineNum:L,lineContent:C,lineAdded:S,lineRemoved:V,lineContext:B,sideBySide:$,sidePane:A,sideLabel:P,sideContent:R,empty:D};function k(n,i){const o=n.split(`
2
2
  `),d=i.split(`
3
3
  `),a=[],f=Math.max(o.length,d.length);let t=0,l=0;for(;(t<o.length||l<d.length)&&(t<o.length&&l<d.length?o[t]===d[l]?(a.push({type:"context",content:o[t],lineNum:l+1}),t++,l++):(a.push({type:"removed",content:o[t],lineNum:t+1}),t++,t<o.length&&o[t]===d[l]?(a.push({type:"added",content:d[l],lineNum:l+1}),l++):l<d.length&&(a.push({type:"added",content:d[l],lineNum:l+1}),l++)):t<o.length?(a.push({type:"removed",content:o[t],lineNum:t+1}),t++):l<d.length&&(a.push({type:"added",content:d[l],lineNum:l+1}),l++),!(a.length>f*3)););return a}function O({before:n,after:i}){const{t:o}=_(),[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):"",l=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:o("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:o("changelog.diff.unified","Unified")}),e.jsx("button",{className:`${s.modeBtn} ${d==="side-by-side"?s.modeBtnActive:""}`,onClick:()=>a("side-by-side"),children:o("changelog.diff.sideBySide","Side by Side")})]}),d==="unified"?e.jsx("div",{className:s.unifiedView,children:l.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:o("changelog.diff.before","Before")}),e.jsx("div",{className:s.sideContent,children:f.split(`
@@ -1 +1 @@
1
- import{j as r,T as e}from"./index-BPAvjNNu.js";function s({label:t,tooltip:o}){return r.jsx(e,{text:o,children:t})}export{s as I};
1
+ import{j as r,T as e}from"./index-FfT2oWAB.js";function s({label:t,tooltip:o}){return r.jsx(e,{text:o,children:t})}export{s as I};
@@ -1 +1 @@
1
- import{j as t,u as P,r as v,d as G,l as L,a as M,D as F}from"./index-BPAvjNNu.js";import{I as V}from"./InfoLabel-BJIFNYA5.js";import{S as A}from"./StatusBadge-ilvVufN2.js";import{T as U}from"./TooltipText-bSKcc3-P.js";import{G as z}from"./GameChangeDetail-Bk8YUy4G.js";import{u as O,f as X}from"./useLiveUptime-HYmdQdHf.js";const q="_page_1xgxh_2",J="_card_1xgxh_10",K="_cardHeader_1xgxh_17",Q="_disconnectCard_1xgxh_28",W="_disconnectIcon_1xgxh_36",Y="_disconnectTitle_1xgxh_41",Z="_disconnectMessage_1xgxh_48",ee="_reconnectGuide_1xgxh_55",te="_guideStep_1xgxh_64",se="_stepNumber_1xgxh_72",ne="_reconnectIndicator_1xgxh_88",ie="_reconnectDot_1xgxh_98",ce="_pulse_1xgxh_1",re="_disconnectActions_1xgxh_112",ae="_btn_1xgxh_118",oe="_btnSecondary_1xgxh_134",le="_metricRow_1xgxh_152",de="_metricGrid_1xgxh_158",me="_metricCard_1xgxh_164",ge="_metric_ok_1xgxh_174",he="_metric_warn_1xgxh_179",xe="_metric_error_1xgxh_184",ue="_metricHeader_1xgxh_189",ve="_metricIcon_1xgxh_200",_e="_metricTitle_1xgxh_204",pe="_metricValue_1xgxh_208",fe="_metricSubtitle_1xgxh_215",Ce="_guideCard_1xgxh_225",je="_guideTitle_1xgxh_232",we="_checklist_1xgxh_239",Ne="_feedEmpty_1xgxh_263",ye="_feedList_1xgxh_270",Te="_feedItem_1xgxh_278",Se="_feedTime_1xgxh_291",Ie="_feedIcon_1xgxh_298",be="_feedSummary_1xgxh_304",ke="_feedText_1xgxh_313",Me="_feedContext_1xgxh_321",De="_feedItemClickable_1xgxh_330",Be="_feedChevron_1xgxh_338",Ee="_feedDetail_1xgxh_347",He="_feedDetailPre_1xgxh_356",$e="_feedDetailText_1xgxh_365",Pe="_changelogSummary_1xgxh_372",Re="_changeTag_1xgxh_381",Ge="_tierBar_1xgxh_393",Le="_tierBarTrack_1xgxh_399",Fe="_tierBarFillBasic_1xgxh_407",Ve="_tierBarFillPro_1xgxh_412",Ae="_tierLabels_1xgxh_417",s={page:q,card:J,cardHeader:K,disconnectCard:Q,disconnectIcon:W,disconnectTitle:Y,disconnectMessage:Z,reconnectGuide:ee,guideStep:te,stepNumber:se,reconnectIndicator:ne,reconnectDot:ie,pulse:ce,disconnectActions:re,btn:ae,btnSecondary:oe,metricRow:le,metricGrid:de,metricCard:me,metric_ok:ge,metric_warn:he,metric_error:xe,metricHeader:ue,metricIcon:ve,metricTitle:_e,metricValue:pe,metricSubtitle:fe,guideCard:Ce,guideTitle:je,checklist:we,feedEmpty:Ne,feedList:ye,feedItem:Te,feedTime:Se,feedIcon:Ie,feedSummary:be,feedText:ke,feedContext:Me,feedItemClickable:De,feedChevron:Be,feedDetail:Ee,feedDetailPre:He,feedDetailText:$e,changelogSummary:Pe,changeTag:Re,tierBar:Ge,tierBarTrack:Le,tierBarFillBasic:Fe,tierBarFillPro:Ve,tierLabels:Ae};function j({title:e,value:i,icon:c,subtitle:r,status:o,children:n}){const l=o?s[`metric_${o}`]:"";return t.jsxs("div",{className:`${s.metricCard} ${l}`,children:[t.jsxs("div",{className:s.metricHeader,children:[c&&t.jsx("span",{className:s.metricIcon,children:c}),t.jsx("span",{className:s.metricTitle,children:e})]}),t.jsx("div",{className:s.metricValue,children:i}),r&&t.jsx("div",{className:s.metricSubtitle,children:r}),n]})}function Ue(e){var c,r;const i=e==null?void 0:e.contextSummary;return(i==null?void 0:i.intent)??((r=(c=i==null?void 0:i.affectedAreas)==null?void 0:c[0])==null?void 0:r.label)??(i==null?void 0:i.testScenario)??null}function B({changes:e}){const{t:i}=P(),[c,r]=v.useState(null);return e.length===0?t.jsx("div",{className:s.feedEmpty,children:i("overview.feed.empty")}):t.jsx("div",{className:s.feedList,children:e.map((o,n)=>{const l=c===n,h=o.raw,m=h&&(h.before!=null||h.after!=null||h.details!=null),d=Ue(h);return t.jsxs("div",{children:[t.jsxs("div",{className:`${s.feedItem} ${m?s.feedItemClickable:""}`,onClick:()=>m&&r(l?null:n),children:[t.jsx("span",{className:s.feedTime,children:o.timestamp}),t.jsx("span",{className:s.feedIcon,children:o.icon}),t.jsxs("span",{className:s.feedText,children:[t.jsx("span",{className:s.feedSummary,children:o.summary}),d&&t.jsx("span",{className:s.feedContext,children:d})]}),m&&t.jsx("span",{className:s.feedChevron,children:l?"▴":"▾"})]}),l&&h&&t.jsx("div",{className:s.feedDetail,children:t.jsx(z,{change:h})})]},n)})})}const E=20;function R(e){return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function H(){return R(new Date)}function $(e){switch(e){case"script":return"📝";case"instance":return"🧱";case"property":return"🎨";case"lighting":return"💡";case"terrain":return"⛰️";case"asset":return"📦";default:return"🔧"}}function ze(){const{level:e,status:i}=G(),c=L(),[r,o]=v.useState(null),[n,l]=v.useState(null),[h,m]=v.useState(null),[d,w]=v.useState([]),N=v.useRef(null),S=v.useCallback(async()=>{try{const a=await M.get("/connection-info");o(a)}catch{o(null)}},[]),_=v.useCallback(async()=>{try{const a=await M.get("/api/dashboard/changelog/active");if(m(a),a.recentChanges&&a.recentChanges.length>0){const f=a.recentChanges.map(x=>({timestamp:x.timestamp?R(new Date(x.timestamp)):H(),icon:$(x.category),summary:x.summary,category:x.category,raw:x}));w(f)}}catch{m(null)}},[]),y=v.useCallback(async()=>{try{const a=await M.get("/sync/status");l(a)}catch{l(null)}},[]);return v.useEffect(()=>{e!=="disconnected"?(S(),_(),y()):(o(null),l(null),m(null));const a=new F;N.current=a,a.connect();const f=a.on("game_change",p=>{const u=p,T={timestamp:H(),icon:$(u.category),summary:u.summary,category:u.category};w(I=>{const C=[T,...I];return C.length>E?C.slice(0,E):C}),_()}),x=a.on("sync",p=>{const u=p;l(T=>({...T,state:u.status,...u.placeId?{placeId:u.placeId}:{}}))});return()=>{f(),x(),a.disconnect(),N.current=null}},[e,S,_,y]),{level:e,status:i,connectionInfo:r,syncStatus:n,changeSummary:h,recentChanges:d,tier:c}}function D(e){return e.scriptsModified+e.scriptsCreated+e.instancesCreated+e.instancesDeleted+e.instancesMoved+e.propertiesChanged+e.assetsInserted+(e.lightingChanged?1:0)+(e.terrainChanged?1:0)}function Oe(e,i){switch(e){case"syncing":return i("status.syncing","Syncing");case"initializing":return i("status.initializing","Initializing");case"error":return i("status.error","Error");default:return i("status.idle","Idle")}}function Xe(e){switch(e){case"syncing":return"ok";case"initializing":return"warn";case"error":return"error";default:return"ok"}}function k(e,i,c,r){return t.jsxs("div",{className:e.metricSubtitle,children:[t.jsx(V,{label:i,tooltip:c}),": ",r]},i)}function g(e,i){return t.jsx(U,{text:i,children:e})}function Ze(){var I,C;const{t:e}=P(),{level:i,status:c,connectionInfo:r,syncStatus:o,changeSummary:n,recentChanges:l}=ze(),h=O(c==null?void 0:c.uptime);if(i==="disconnected")return t.jsx("div",{className:s.page,children:t.jsxs("div",{className:s.disconnectCard,children:[t.jsx("div",{className:s.disconnectIcon,children:"⚠️"}),t.jsx("h2",{className:s.disconnectTitle,children:e("overview.l0.title")}),t.jsx("p",{className:s.disconnectMessage,children:e("overview.l0.message")}),t.jsxs("div",{className:s.reconnectGuide,children:[t.jsxs("div",{className:s.guideStep,children:[t.jsx("span",{className:s.stepNumber,children:"1"}),t.jsx("span",{children:e("overview.l0.step1")})]}),t.jsxs("div",{className:s.guideStep,children:[t.jsx("span",{className:s.stepNumber,children:"2"}),t.jsx("span",{children:e("overview.l0.step2")})]})]}),t.jsxs("div",{className:s.reconnectIndicator,children:[t.jsx("span",{className:s.reconnectDot}),e("overview.l0.reconnecting")]}),t.jsxs("div",{className:s.disconnectActions,children:[t.jsx("button",{className:s.btn,onClick:()=>window.location.reload(),children:e("overview.l0.reconnectBtn")}),t.jsx("button",{className:s.btnSecondary,onClick:()=>{window.location.hash="#/settings"},children:e("overview.l0.settingsBtn")})]})]})});const m=(r==null?void 0:r.mcpInstanceCount)??0,d=((I=r==null?void 0:r.mcpInstances)==null?void 0:I.find(b=>!b.isServer&&b.aiClientName))??((C=r==null?void 0:r.mcpInstances)==null?void 0:C.find(b=>!!b.aiClientName))??null,w=(c==null?void 0:c.pluginClients)??[],N=w.length>0,S=(c==null?void 0:c.sessionId)??(r==null?void 0:r.sessionId)??"-",_=e("overview.metric.server.tooltip","MCP server runtime and process status"),y=e("overview.metric.plugin.tooltip","Roblox Studio plugin connection and version status"),a=e("overview.metric.agent.tooltip","Connected AI coding agents and their runtime state"),f=e("overview.metric.sync.tooltip","Current Studio to local sync activity"),x=c?[k(s,e("overview.meta.version","Version"),e("overview.meta.version.tooltip","Installed MCP server version"),`v${c.version}`),k(s,e("overview.meta.session","Session"),e("overview.meta.session.tooltip","Current MCP session identifier"),S),k(s,e("overview.meta.pid","PID"),e("overview.meta.pid.tooltip","Operating system process identifier"),String(c.pid??"-")),k(s,e("overview.meta.uptime","Uptime"),e("overview.meta.uptime.tooltip","Time elapsed since the MCP server started"),X(h??c.uptime))]:[];if(i==="serverOnly")return t.jsxs("div",{className:s.page,children:[t.jsxs("div",{className:s.metricRow,children:[t.jsx(j,{title:g(e("overview.metric.server"),_),value:g(e("status.online"),_),icon:"🖥️",status:"ok",children:t.jsxs(t.Fragment,{children:[x,t.jsx(A,{status:"online"})]})}),t.jsx(j,{title:g(e("overview.metric.agent"),a),value:g((d==null?void 0:d.aiClientName)??e("overview.metric.noAgent"),a),icon:"🤖",subtitle:m>1?`${m} ${e("overview.metric.agent.instancesUnit","instances")}`:void 0,status:d?"ok":"warn"})]}),t.jsxs("div",{className:s.guideCard,children:[t.jsx("h3",{className:s.guideTitle,children:e("overview.l1.pluginGuide")}),t.jsxs("ul",{className:s.checklist,children:[t.jsx("li",{children:e("overview.l1.check1")}),t.jsx("li",{children:e("overview.l1.check2")})]})]}),t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.feed.title")}),l.length>0?t.jsx(B,{changes:l}):t.jsx("div",{className:s.feedEmpty,children:e("overview.l1.feedHint")})]}),n&&D(n)>0&&t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.changelog.title")}),t.jsxs("div",{className:s.changelogSummary,children:[t.jsxs("span",{children:[e("overview.changelog.entries","Entries"),": ",D(n)]}),n.scriptsModified>0&&t.jsxs("span",{className:s.changeTag,children:["📝"," ",n.scriptsModified," ",e("overview.changelog.scripts")]}),n.instancesCreated>0&&t.jsxs("span",{className:s.changeTag,children:["🧱"," ",n.instancesCreated," ",e("overview.changelog.instances")]}),n.propertiesChanged>0&&t.jsxs("span",{className:s.changeTag,children:["🎨"," ",n.propertiesChanged," ",e("overview.changelog.properties")]}),n.assetsInserted>0&&t.jsxs("span",{className:s.changeTag,children:["📦"," ",n.assetsInserted," ",e("overview.changelog.assets")]})]})]})]});const p=w[0],u=n?D(n):0,T=!!n&&u>0;return t.jsxs("div",{className:s.page,children:[t.jsxs("div",{className:s.metricGrid,children:[t.jsx(j,{title:g(e("overview.metric.server"),_),value:g(e("status.online"),_),icon:"🖥️",status:"ok",children:t.jsx(t.Fragment,{children:x})}),t.jsx(j,{title:g(e("overview.metric.plugin"),y),value:g(e(N?"status.online":"status.offline"),y),icon:"🔌",subtitle:p?`${p.placeName??p.projectName??"-"} / v${p.pluginVersion??"-"}`:void 0,status:N?"ok":"error"}),t.jsx(j,{title:g(e("overview.metric.agent"),a),value:g((d==null?void 0:d.aiClientName)??e("overview.metric.noAgent"),a),icon:"🤖",subtitle:m>1?`${m} ${e("overview.metric.agent.instancesUnit","instances")}`:void 0,status:d?"ok":"warn"}),t.jsx(j,{title:g(e("overview.metric.sync"),f),value:g(Oe(o==null?void 0:o.state,e),f),icon:"🔄",status:Xe(o==null?void 0:o.state)})]}),t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.feed.title")}),t.jsx(B,{changes:l})]}),T&&t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.changelog.title")}),t.jsxs("div",{className:s.changelogSummary,children:[t.jsxs("span",{children:[e("overview.changelog.entries","Entries"),": ",u]}),n.scriptsModified>0&&t.jsxs("span",{className:s.changeTag,children:["📝"," ",n.scriptsModified," ",e("overview.changelog.scripts")]}),n.instancesCreated>0&&t.jsxs("span",{className:s.changeTag,children:["🧱"," ",n.instancesCreated," ",e("overview.changelog.instances")]}),n.propertiesChanged>0&&t.jsxs("span",{className:s.changeTag,children:["🎨"," ",n.propertiesChanged," ",e("overview.changelog.properties")]}),n.assetsInserted>0&&t.jsxs("span",{className:s.changeTag,children:["📦"," ",n.assetsInserted," ",e("overview.changelog.assets")]})]})]})]})}export{Ze as Component};
1
+ import{j as t,u as P,r as v,d as G,l as L,a as M,D as F}from"./index-FfT2oWAB.js";import{I as V}from"./InfoLabel-B9KT3kfU.js";import{S as A}from"./StatusBadge-Bxe88ki2.js";import{T as U}from"./TooltipText-Baw38jOU.js";import{G as z}from"./GameChangeDetail-D1kE2L_v.js";import{u as O,f as X}from"./useLiveUptime-DhJz484L.js";const q="_page_1xgxh_2",J="_card_1xgxh_10",K="_cardHeader_1xgxh_17",Q="_disconnectCard_1xgxh_28",W="_disconnectIcon_1xgxh_36",Y="_disconnectTitle_1xgxh_41",Z="_disconnectMessage_1xgxh_48",ee="_reconnectGuide_1xgxh_55",te="_guideStep_1xgxh_64",se="_stepNumber_1xgxh_72",ne="_reconnectIndicator_1xgxh_88",ie="_reconnectDot_1xgxh_98",ce="_pulse_1xgxh_1",re="_disconnectActions_1xgxh_112",ae="_btn_1xgxh_118",oe="_btnSecondary_1xgxh_134",le="_metricRow_1xgxh_152",de="_metricGrid_1xgxh_158",me="_metricCard_1xgxh_164",ge="_metric_ok_1xgxh_174",he="_metric_warn_1xgxh_179",xe="_metric_error_1xgxh_184",ue="_metricHeader_1xgxh_189",ve="_metricIcon_1xgxh_200",_e="_metricTitle_1xgxh_204",pe="_metricValue_1xgxh_208",fe="_metricSubtitle_1xgxh_215",Ce="_guideCard_1xgxh_225",je="_guideTitle_1xgxh_232",we="_checklist_1xgxh_239",Ne="_feedEmpty_1xgxh_263",ye="_feedList_1xgxh_270",Te="_feedItem_1xgxh_278",Se="_feedTime_1xgxh_291",Ie="_feedIcon_1xgxh_298",be="_feedSummary_1xgxh_304",ke="_feedText_1xgxh_313",Me="_feedContext_1xgxh_321",De="_feedItemClickable_1xgxh_330",Be="_feedChevron_1xgxh_338",Ee="_feedDetail_1xgxh_347",He="_feedDetailPre_1xgxh_356",$e="_feedDetailText_1xgxh_365",Pe="_changelogSummary_1xgxh_372",Re="_changeTag_1xgxh_381",Ge="_tierBar_1xgxh_393",Le="_tierBarTrack_1xgxh_399",Fe="_tierBarFillBasic_1xgxh_407",Ve="_tierBarFillPro_1xgxh_412",Ae="_tierLabels_1xgxh_417",s={page:q,card:J,cardHeader:K,disconnectCard:Q,disconnectIcon:W,disconnectTitle:Y,disconnectMessage:Z,reconnectGuide:ee,guideStep:te,stepNumber:se,reconnectIndicator:ne,reconnectDot:ie,pulse:ce,disconnectActions:re,btn:ae,btnSecondary:oe,metricRow:le,metricGrid:de,metricCard:me,metric_ok:ge,metric_warn:he,metric_error:xe,metricHeader:ue,metricIcon:ve,metricTitle:_e,metricValue:pe,metricSubtitle:fe,guideCard:Ce,guideTitle:je,checklist:we,feedEmpty:Ne,feedList:ye,feedItem:Te,feedTime:Se,feedIcon:Ie,feedSummary:be,feedText:ke,feedContext:Me,feedItemClickable:De,feedChevron:Be,feedDetail:Ee,feedDetailPre:He,feedDetailText:$e,changelogSummary:Pe,changeTag:Re,tierBar:Ge,tierBarTrack:Le,tierBarFillBasic:Fe,tierBarFillPro:Ve,tierLabels:Ae};function j({title:e,value:i,icon:c,subtitle:r,status:o,children:n}){const l=o?s[`metric_${o}`]:"";return t.jsxs("div",{className:`${s.metricCard} ${l}`,children:[t.jsxs("div",{className:s.metricHeader,children:[c&&t.jsx("span",{className:s.metricIcon,children:c}),t.jsx("span",{className:s.metricTitle,children:e})]}),t.jsx("div",{className:s.metricValue,children:i}),r&&t.jsx("div",{className:s.metricSubtitle,children:r}),n]})}function Ue(e){var c,r;const i=e==null?void 0:e.contextSummary;return(i==null?void 0:i.intent)??((r=(c=i==null?void 0:i.affectedAreas)==null?void 0:c[0])==null?void 0:r.label)??(i==null?void 0:i.testScenario)??null}function B({changes:e}){const{t:i}=P(),[c,r]=v.useState(null);return e.length===0?t.jsx("div",{className:s.feedEmpty,children:i("overview.feed.empty")}):t.jsx("div",{className:s.feedList,children:e.map((o,n)=>{const l=c===n,h=o.raw,m=h&&(h.before!=null||h.after!=null||h.details!=null),d=Ue(h);return t.jsxs("div",{children:[t.jsxs("div",{className:`${s.feedItem} ${m?s.feedItemClickable:""}`,onClick:()=>m&&r(l?null:n),children:[t.jsx("span",{className:s.feedTime,children:o.timestamp}),t.jsx("span",{className:s.feedIcon,children:o.icon}),t.jsxs("span",{className:s.feedText,children:[t.jsx("span",{className:s.feedSummary,children:o.summary}),d&&t.jsx("span",{className:s.feedContext,children:d})]}),m&&t.jsx("span",{className:s.feedChevron,children:l?"▴":"▾"})]}),l&&h&&t.jsx("div",{className:s.feedDetail,children:t.jsx(z,{change:h})})]},n)})})}const E=20;function R(e){return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function H(){return R(new Date)}function $(e){switch(e){case"script":return"📝";case"instance":return"🧱";case"property":return"🎨";case"lighting":return"💡";case"terrain":return"⛰️";case"asset":return"📦";default:return"🔧"}}function ze(){const{level:e,status:i}=G(),c=L(),[r,o]=v.useState(null),[n,l]=v.useState(null),[h,m]=v.useState(null),[d,w]=v.useState([]),N=v.useRef(null),S=v.useCallback(async()=>{try{const a=await M.get("/connection-info");o(a)}catch{o(null)}},[]),_=v.useCallback(async()=>{try{const a=await M.get("/api/dashboard/changelog/active");if(m(a),a.recentChanges&&a.recentChanges.length>0){const f=a.recentChanges.map(x=>({timestamp:x.timestamp?R(new Date(x.timestamp)):H(),icon:$(x.category),summary:x.summary,category:x.category,raw:x}));w(f)}}catch{m(null)}},[]),y=v.useCallback(async()=>{try{const a=await M.get("/sync/status");l(a)}catch{l(null)}},[]);return v.useEffect(()=>{e!=="disconnected"?(S(),_(),y()):(o(null),l(null),m(null));const a=new F;N.current=a,a.connect();const f=a.on("game_change",p=>{const u=p,T={timestamp:H(),icon:$(u.category),summary:u.summary,category:u.category};w(I=>{const C=[T,...I];return C.length>E?C.slice(0,E):C}),_()}),x=a.on("sync",p=>{const u=p;l(T=>({...T,state:u.status,...u.placeId?{placeId:u.placeId}:{}}))});return()=>{f(),x(),a.disconnect(),N.current=null}},[e,S,_,y]),{level:e,status:i,connectionInfo:r,syncStatus:n,changeSummary:h,recentChanges:d,tier:c}}function D(e){return e.scriptsModified+e.scriptsCreated+e.instancesCreated+e.instancesDeleted+e.instancesMoved+e.propertiesChanged+e.assetsInserted+(e.lightingChanged?1:0)+(e.terrainChanged?1:0)}function Oe(e,i){switch(e){case"syncing":return i("status.syncing","Syncing");case"initializing":return i("status.initializing","Initializing");case"error":return i("status.error","Error");default:return i("status.idle","Idle")}}function Xe(e){switch(e){case"syncing":return"ok";case"initializing":return"warn";case"error":return"error";default:return"ok"}}function k(e,i,c,r){return t.jsxs("div",{className:e.metricSubtitle,children:[t.jsx(V,{label:i,tooltip:c}),": ",r]},i)}function g(e,i){return t.jsx(U,{text:i,children:e})}function Ze(){var I,C;const{t:e}=P(),{level:i,status:c,connectionInfo:r,syncStatus:o,changeSummary:n,recentChanges:l}=ze(),h=O(c==null?void 0:c.uptime);if(i==="disconnected")return t.jsx("div",{className:s.page,children:t.jsxs("div",{className:s.disconnectCard,children:[t.jsx("div",{className:s.disconnectIcon,children:"⚠️"}),t.jsx("h2",{className:s.disconnectTitle,children:e("overview.l0.title")}),t.jsx("p",{className:s.disconnectMessage,children:e("overview.l0.message")}),t.jsxs("div",{className:s.reconnectGuide,children:[t.jsxs("div",{className:s.guideStep,children:[t.jsx("span",{className:s.stepNumber,children:"1"}),t.jsx("span",{children:e("overview.l0.step1")})]}),t.jsxs("div",{className:s.guideStep,children:[t.jsx("span",{className:s.stepNumber,children:"2"}),t.jsx("span",{children:e("overview.l0.step2")})]})]}),t.jsxs("div",{className:s.reconnectIndicator,children:[t.jsx("span",{className:s.reconnectDot}),e("overview.l0.reconnecting")]}),t.jsxs("div",{className:s.disconnectActions,children:[t.jsx("button",{className:s.btn,onClick:()=>window.location.reload(),children:e("overview.l0.reconnectBtn")}),t.jsx("button",{className:s.btnSecondary,onClick:()=>{window.location.hash="#/settings"},children:e("overview.l0.settingsBtn")})]})]})});const m=(r==null?void 0:r.mcpInstanceCount)??0,d=((I=r==null?void 0:r.mcpInstances)==null?void 0:I.find(b=>!b.isServer&&b.aiClientName))??((C=r==null?void 0:r.mcpInstances)==null?void 0:C.find(b=>!!b.aiClientName))??null,w=(c==null?void 0:c.pluginClients)??[],N=w.length>0,S=(c==null?void 0:c.sessionId)??(r==null?void 0:r.sessionId)??"-",_=e("overview.metric.server.tooltip","MCP server runtime and process status"),y=e("overview.metric.plugin.tooltip","Roblox Studio plugin connection and version status"),a=e("overview.metric.agent.tooltip","Connected AI coding agents and their runtime state"),f=e("overview.metric.sync.tooltip","Current Studio to local sync activity"),x=c?[k(s,e("overview.meta.version","Version"),e("overview.meta.version.tooltip","Installed MCP server version"),`v${c.version}`),k(s,e("overview.meta.session","Session"),e("overview.meta.session.tooltip","Current MCP session identifier"),S),k(s,e("overview.meta.pid","PID"),e("overview.meta.pid.tooltip","Operating system process identifier"),String(c.pid??"-")),k(s,e("overview.meta.uptime","Uptime"),e("overview.meta.uptime.tooltip","Time elapsed since the MCP server started"),X(h??c.uptime))]:[];if(i==="serverOnly")return t.jsxs("div",{className:s.page,children:[t.jsxs("div",{className:s.metricRow,children:[t.jsx(j,{title:g(e("overview.metric.server"),_),value:g(e("status.online"),_),icon:"🖥️",status:"ok",children:t.jsxs(t.Fragment,{children:[x,t.jsx(A,{status:"online"})]})}),t.jsx(j,{title:g(e("overview.metric.agent"),a),value:g((d==null?void 0:d.aiClientName)??e("overview.metric.noAgent"),a),icon:"🤖",subtitle:m>1?`${m} ${e("overview.metric.agent.instancesUnit","instances")}`:void 0,status:d?"ok":"warn"})]}),t.jsxs("div",{className:s.guideCard,children:[t.jsx("h3",{className:s.guideTitle,children:e("overview.l1.pluginGuide")}),t.jsxs("ul",{className:s.checklist,children:[t.jsx("li",{children:e("overview.l1.check1")}),t.jsx("li",{children:e("overview.l1.check2")})]})]}),t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.feed.title")}),l.length>0?t.jsx(B,{changes:l}):t.jsx("div",{className:s.feedEmpty,children:e("overview.l1.feedHint")})]}),n&&D(n)>0&&t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.changelog.title")}),t.jsxs("div",{className:s.changelogSummary,children:[t.jsxs("span",{children:[e("overview.changelog.entries","Entries"),": ",D(n)]}),n.scriptsModified>0&&t.jsxs("span",{className:s.changeTag,children:["📝"," ",n.scriptsModified," ",e("overview.changelog.scripts")]}),n.instancesCreated>0&&t.jsxs("span",{className:s.changeTag,children:["🧱"," ",n.instancesCreated," ",e("overview.changelog.instances")]}),n.propertiesChanged>0&&t.jsxs("span",{className:s.changeTag,children:["🎨"," ",n.propertiesChanged," ",e("overview.changelog.properties")]}),n.assetsInserted>0&&t.jsxs("span",{className:s.changeTag,children:["📦"," ",n.assetsInserted," ",e("overview.changelog.assets")]})]})]})]});const p=w[0],u=n?D(n):0,T=!!n&&u>0;return t.jsxs("div",{className:s.page,children:[t.jsxs("div",{className:s.metricGrid,children:[t.jsx(j,{title:g(e("overview.metric.server"),_),value:g(e("status.online"),_),icon:"🖥️",status:"ok",children:t.jsx(t.Fragment,{children:x})}),t.jsx(j,{title:g(e("overview.metric.plugin"),y),value:g(e(N?"status.online":"status.offline"),y),icon:"🔌",subtitle:p?`${p.placeName??p.projectName??"-"} / v${p.pluginVersion??"-"}`:void 0,status:N?"ok":"error"}),t.jsx(j,{title:g(e("overview.metric.agent"),a),value:g((d==null?void 0:d.aiClientName)??e("overview.metric.noAgent"),a),icon:"🤖",subtitle:m>1?`${m} ${e("overview.metric.agent.instancesUnit","instances")}`:void 0,status:d?"ok":"warn"}),t.jsx(j,{title:g(e("overview.metric.sync"),f),value:g(Oe(o==null?void 0:o.state,e),f),icon:"🔄",status:Xe(o==null?void 0:o.state)})]}),t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.feed.title")}),t.jsx(B,{changes:l})]}),T&&t.jsxs("div",{className:s.card,children:[t.jsx("div",{className:s.cardHeader,children:e("overview.changelog.title")}),t.jsxs("div",{className:s.changelogSummary,children:[t.jsxs("span",{children:[e("overview.changelog.entries","Entries"),": ",u]}),n.scriptsModified>0&&t.jsxs("span",{className:s.changeTag,children:["📝"," ",n.scriptsModified," ",e("overview.changelog.scripts")]}),n.instancesCreated>0&&t.jsxs("span",{className:s.changeTag,children:["🧱"," ",n.instancesCreated," ",e("overview.changelog.instances")]}),n.propertiesChanged>0&&t.jsxs("span",{className:s.changeTag,children:["🎨"," ",n.propertiesChanged," ",e("overview.changelog.properties")]}),n.assetsInserted>0&&t.jsxs("span",{className:s.changeTag,children:["📦"," ",n.assetsInserted," ",e("overview.changelog.assets")]})]})]})]})}export{Ze as Component};
@@ -1,4 +1,4 @@
1
- import{r as n,a as v,u as S,j as e,k as H,l as D,m as E,o as U}from"./index-BPAvjNNu.js";import{D as $,T as O}from"./TierComparison-BXMCd1IB.js";import{I as P}from"./InfoLabel-BJIFNYA5.js";import{T as _}from"./TooltipText-bSKcc3-P.js";import{C as F}from"./ConfirmModal-BDWSInRi.js";const W=5e3;function V(t){const r=(t==null?void 0:t.enabled)??!0,[d,o]=n.useState([]),[a,l]=n.useState(null),[m,i]=n.useState(r),c=n.useRef(null),h=n.useCallback(async()=>{try{const x=await v.get("/api/dashboard/playtest/history");o(x.entries??[])}catch{}},[]),p=n.useCallback(async()=>{if(!r){i(!1);return}await h(),i(!1)},[r,h]),y=n.useCallback(async()=>{r&&(await v.post("/api/dashboard/playtest/history/clear"),o([]),l(null))},[r]),j=n.useCallback(async x=>{if(r)try{const w=await v.get(`/api/dashboard/playtest/report/${x}`);l(w)}catch{l(null)}},[r]);return n.useEffect(()=>{if(!r){i(!1);return}return p(),c.current=setInterval(p,W),()=>{c.current&&clearInterval(c.current)}},[r,p]),{history:d,selectedReport:a,loading:m,loadReport:j,clearHistory:y}}function Y(t){const r="2026-03-27T15:26:00.000Z",d={testScenario:t("playtest.sample.context.why","Spawn into the arena, survive the opener, and verify the HUD responds immediately."),expectedBehavior:t("playtest.sample.context.expected","The player spawns safely, the countdown UI appears within one second, and the first wave starts without errors."),observedBehavior:t("playtest.sample.context.observed","Spawn protection held, the HUD updated on time, and wave one completed with no gameplay regressions.")};return{history:[{timestamp:r,testName:t("playtest.sample.history.name","Sample Arena Smoke Test"),mode:"play",status:"passed",durationMs:4820,contextId:"sample_playtest_preview",contextSummary:d}],report:{markdown:t("playtest.sample.report.markdown",`# Sample Arena Smoke Test
1
+ import{r as n,a as v,u as S,j as e,k as H,l as D,m as E,o as U}from"./index-FfT2oWAB.js";import{D as $,T as O}from"./TierComparison-Dyf-knpe.js";import{I as P}from"./InfoLabel-B9KT3kfU.js";import{T as _}from"./TooltipText-Baw38jOU.js";import{C as F}from"./ConfirmModal-CmJCz5rg.js";const W=5e3;function V(t){const r=(t==null?void 0:t.enabled)??!0,[d,o]=n.useState([]),[a,l]=n.useState(null),[m,i]=n.useState(r),c=n.useRef(null),h=n.useCallback(async()=>{try{const x=await v.get("/api/dashboard/playtest/history");o(x.entries??[])}catch{}},[]),p=n.useCallback(async()=>{if(!r){i(!1);return}await h(),i(!1)},[r,h]),y=n.useCallback(async()=>{r&&(await v.post("/api/dashboard/playtest/history/clear"),o([]),l(null))},[r]),j=n.useCallback(async x=>{if(r)try{const w=await v.get(`/api/dashboard/playtest/report/${x}`);l(w)}catch{l(null)}},[r]);return n.useEffect(()=>{if(!r){i(!1);return}return p(),c.current=setInterval(p,W),()=>{c.current&&clearInterval(c.current)}},[r,p]),{history:d,selectedReport:a,loading:m,loadReport:j,clearHistory:y}}function Y(t){const r="2026-03-27T15:26:00.000Z",d={testScenario:t("playtest.sample.context.why","Spawn into the arena, survive the opener, and verify the HUD responds immediately."),expectedBehavior:t("playtest.sample.context.expected","The player spawns safely, the countdown UI appears within one second, and the first wave starts without errors."),observedBehavior:t("playtest.sample.context.observed","Spawn protection held, the HUD updated on time, and wave one completed with no gameplay regressions.")};return{history:[{timestamp:r,testName:t("playtest.sample.history.name","Sample Arena Smoke Test"),mode:"play",status:"passed",durationMs:4820,contextId:"sample_playtest_preview",contextSummary:d}],report:{markdown:t("playtest.sample.report.markdown",`# Sample Arena Smoke Test
2
2
 
3
3
  - Spawn flow: PASS
4
4
  - HUD countdown: PASS