@chrrxs/robloxstudio-mcp-inspector 2.14.0 → 2.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +232 -21
- package/package.json +2 -2
- package/studio-plugin/INSTALLATION.md +13 -3
- package/studio-plugin/MCPInspectorPlugin.rbxmx +336 -34
- package/studio-plugin/MCPPlugin.rbxmx +336 -34
- package/studio-plugin/src/modules/ClientBroker.ts +12 -2
- package/studio-plugin/src/modules/Communication.ts +22 -5
- package/studio-plugin/src/modules/State.ts +2 -0
- package/studio-plugin/src/modules/UI.ts +20 -0
- package/studio-plugin/src/modules/handlers/SceneAnalysisHandlers.ts +216 -0
- package/studio-plugin/src/types/index.d.ts +6 -0
|
@@ -102,9 +102,11 @@ local RunService = _services.RunService
|
|
|
102
102
|
local ServerStorage = _services.ServerStorage
|
|
103
103
|
local RuntimeLogBuffer = TS.import(script, script.Parent, "RuntimeLogBuffer")
|
|
104
104
|
local MemoryHandlers = TS.import(script, script.Parent, "handlers", "MemoryHandlers")
|
|
105
|
+
local SceneAnalysisHandlers = TS.import(script, script.Parent, "handlers", "SceneAnalysisHandlers")
|
|
105
106
|
local CaptureHandlers = TS.import(script, script.Parent, "handlers", "CaptureHandlers")
|
|
106
107
|
local InputHandlers = TS.import(script, script.Parent, "handlers", "InputHandlers")
|
|
107
108
|
local LuauExec = TS.import(script, script.Parent, "LuauExec")
|
|
109
|
+
local State = TS.import(script, script.Parent, "State")
|
|
108
110
|
local StudioTestService = game:GetService("StudioTestService")
|
|
109
111
|
-- Mirror of Communication.computeInstanceId() — duplicated here because the
|
|
110
112
|
-- client broker runs in the play-server DM where it can't easily import from
|
|
@@ -167,6 +169,7 @@ local CLIENT_BROKER_ALLOWED_ENDPOINTS = {
|
|
|
167
169
|
["/api/execute-luau"] = true,
|
|
168
170
|
["/api/get-runtime-logs"] = true,
|
|
169
171
|
["/api/get-memory-breakdown"] = true,
|
|
172
|
+
["/api/get-scene-analysis"] = true,
|
|
170
173
|
["/api/multiplayer-test-state"] = true,
|
|
171
174
|
["/api/multiplayer-test-leave-client"] = true,
|
|
172
175
|
["/api/capture-begin"] = true,
|
|
@@ -199,6 +202,8 @@ local function reRegisterProxy(proxyId, role)
|
|
|
199
202
|
placeName = resolvePlaceName(),
|
|
200
203
|
dataModelName = game.Name,
|
|
201
204
|
isRunning = RunService:IsRunning(),
|
|
205
|
+
pluginVersion = State.CURRENT_VERSION,
|
|
206
|
+
pluginVariant = State.PLUGIN_VARIANT,
|
|
202
207
|
})
|
|
203
208
|
end)
|
|
204
209
|
end
|
|
@@ -324,7 +329,7 @@ end
|
|
|
324
329
|
local function setupClientBroker()
|
|
325
330
|
local rf = ReplicatedStorage:WaitForChild(BROKER_NAME, 10)
|
|
326
331
|
if not rf or not rf:IsA("RemoteFunction") then
|
|
327
|
-
warn(`[
|
|
332
|
+
warn(`[robloxstudio-mcp] client: {BROKER_NAME} not found`)
|
|
328
333
|
return nil
|
|
329
334
|
end
|
|
330
335
|
rf.OnClientInvoke = function(payload)
|
|
@@ -340,6 +345,9 @@ local function setupClientBroker()
|
|
|
340
345
|
if payload and payload.endpoint == "/api/get-memory-breakdown" then
|
|
341
346
|
return MemoryHandlers.getMemoryBreakdown(payload.data or {})
|
|
342
347
|
end
|
|
348
|
+
if payload and payload.endpoint == "/api/get-scene-analysis" then
|
|
349
|
+
return SceneAnalysisHandlers.getSceneAnalysis(payload.data or {})
|
|
350
|
+
end
|
|
343
351
|
if payload and payload.endpoint == "/api/multiplayer-test-state" then
|
|
344
352
|
return handleMultiplayerTestState()
|
|
345
353
|
end
|
|
@@ -451,9 +459,11 @@ local function registerProxy(player, rf)
|
|
|
451
459
|
placeName = resolvePlaceName(),
|
|
452
460
|
dataModelName = game.Name,
|
|
453
461
|
isRunning = RunService:IsRunning(),
|
|
462
|
+
pluginVersion = State.CURRENT_VERSION,
|
|
463
|
+
pluginVariant = State.PLUGIN_VARIANT,
|
|
454
464
|
})
|
|
455
465
|
if not ok or not res or not res.Success then
|
|
456
|
-
warn(`[
|
|
466
|
+
warn(`[robloxstudio-mcp] proxy register failed for {player.Name}`)
|
|
457
467
|
return nil
|
|
458
468
|
end
|
|
459
469
|
local body = HttpService:JSONDecode(res.Body)
|
|
@@ -551,6 +561,7 @@ local InputHandlers = TS.import(script, script.Parent, "handlers", "InputHandler
|
|
|
551
561
|
local LogHandlers = TS.import(script, script.Parent, "handlers", "LogHandlers")
|
|
552
562
|
local SerializationHandlers = TS.import(script, script.Parent, "handlers", "SerializationHandlers")
|
|
553
563
|
local MemoryHandlers = TS.import(script, script.Parent, "handlers", "MemoryHandlers")
|
|
564
|
+
local SceneAnalysisHandlers = TS.import(script, script.Parent, "handlers", "SceneAnalysisHandlers")
|
|
554
565
|
-- Per-plugin-load random GUID. Used as the /poll URL param so the server
|
|
555
566
|
-- can tell our polls apart from any other plugin's polls. Not user-facing —
|
|
556
567
|
-- MCP tools and the LLM operate on instanceId (the place identifier).
|
|
@@ -578,6 +589,8 @@ end
|
|
|
578
589
|
local instanceId = computeInstanceId()
|
|
579
590
|
local assignedRole
|
|
580
591
|
local duplicateInstanceRole = false
|
|
592
|
+
local hasVersionMismatch = false
|
|
593
|
+
local lastVersionMismatchWarningKey
|
|
581
594
|
-- Cache the published place name from MarketplaceService:GetProductInfo so
|
|
582
595
|
-- /ready can carry a friendly identifier (e.g. "Natural Disasters") distinct
|
|
583
596
|
-- from game.Name (the DataModel name, often "Place1" in edit). We only fetch
|
|
@@ -683,6 +696,7 @@ local routeMap = {
|
|
|
683
696
|
["/api/export-rbxm"] = SerializationHandlers.exportRbxm,
|
|
684
697
|
["/api/import-rbxm"] = SerializationHandlers.importRbxm,
|
|
685
698
|
["/api/get-memory-breakdown"] = MemoryHandlers.getMemoryBreakdown,
|
|
699
|
+
["/api/get-scene-analysis"] = SceneAnalysisHandlers.getSceneAnalysis,
|
|
686
700
|
}
|
|
687
701
|
local function processRequest(request)
|
|
688
702
|
local endpoint = request.endpoint
|
|
@@ -776,6 +790,8 @@ function sendReady(conn)
|
|
|
776
790
|
placeName = resolvePlaceName(),
|
|
777
791
|
dataModelName = game.Name,
|
|
778
792
|
isRunning = RunService:IsRunning(),
|
|
793
|
+
pluginVersion = State.CURRENT_VERSION,
|
|
794
|
+
pluginVariant = State.PLUGIN_VARIANT,
|
|
779
795
|
pluginReady = true,
|
|
780
796
|
timestamp = tick(),
|
|
781
797
|
}),
|
|
@@ -841,6 +857,23 @@ local function pollForRequests(connIndex)
|
|
|
841
857
|
local mcpConnected = data.mcpConnected == true
|
|
842
858
|
conn.lastHttpOk = true
|
|
843
859
|
conn.lastMcpOk = mcpConnected
|
|
860
|
+
local _condition = data.serverVersion
|
|
861
|
+
if _condition == nil then
|
|
862
|
+
_condition = "unknown"
|
|
863
|
+
end
|
|
864
|
+
local serverVersion = _condition
|
|
865
|
+
if data.versionMismatch == true then
|
|
866
|
+
hasVersionMismatch = true
|
|
867
|
+
local warningKey = `{State.CURRENT_VERSION}:{serverVersion}`
|
|
868
|
+
if lastVersionMismatchWarningKey ~= warningKey then
|
|
869
|
+
lastVersionMismatchWarningKey = warningKey
|
|
870
|
+
warn(`[MCPPlugin] Version mismatch: Studio plugin v{State.CURRENT_VERSION} / MCP v{serverVersion}. Run npx -y @chrrxs/robloxstudio-mcp@latest --auto-install-plugin and restart Studio.`)
|
|
871
|
+
end
|
|
872
|
+
UI.showBanner("version-mismatch", `Plugin v{State.CURRENT_VERSION} / MCP v{serverVersion} mismatch`)
|
|
873
|
+
elseif hasVersionMismatch then
|
|
874
|
+
hasVersionMismatch = false
|
|
875
|
+
UI.hideBanner("version-mismatch")
|
|
876
|
+
end
|
|
844
877
|
-- Server tells us when its in-memory instances map doesn't have us
|
|
845
878
|
-- (e.g. after an MCP process restart). Re-issue /ready immediately so
|
|
846
879
|
-- target=server/client-N start routing again. The throttle inside
|
|
@@ -853,12 +886,12 @@ local function pollForRequests(connIndex)
|
|
|
853
886
|
local el = ui
|
|
854
887
|
el.step1Dot.BackgroundColor3 = Color3.fromRGB(34, 197, 94)
|
|
855
888
|
el.step1Label.Text = "HTTP server (OK)"
|
|
856
|
-
local
|
|
857
|
-
if
|
|
889
|
+
local _condition_1 = mcpConnected
|
|
890
|
+
if _condition_1 then
|
|
858
891
|
local _value = (string.find(el.statusLabel.Text, "Connected"))
|
|
859
|
-
|
|
892
|
+
_condition_1 = not (_value ~= 0 and _value == _value and _value)
|
|
860
893
|
end
|
|
861
|
-
if
|
|
894
|
+
if _condition_1 then
|
|
862
895
|
el.statusLabel.Text = "Connected"
|
|
863
896
|
el.statusLabel.TextColor3 = Color3.fromRGB(34, 197, 94)
|
|
864
897
|
el.statusIndicator.BackgroundColor3 = Color3.fromRGB(34, 197, 94)
|
|
@@ -889,11 +922,11 @@ local function pollForRequests(connIndex)
|
|
|
889
922
|
conn.mcpWaitStartTime = tick()
|
|
890
923
|
end
|
|
891
924
|
local _exp = tick()
|
|
892
|
-
local
|
|
893
|
-
if
|
|
894
|
-
|
|
925
|
+
local _condition_2 = conn.mcpWaitStartTime
|
|
926
|
+
if _condition_2 == nil then
|
|
927
|
+
_condition_2 = tick()
|
|
895
928
|
end
|
|
896
|
-
local elapsed = _exp -
|
|
929
|
+
local elapsed = _exp - _condition_2
|
|
897
930
|
el.troubleshootLabel.Visible = elapsed > 8
|
|
898
931
|
UI.startPulseAnimation()
|
|
899
932
|
end
|
|
@@ -1102,11 +1135,9 @@ local function checkForUpdates()
|
|
|
1102
1135
|
if _condition ~= "" and _condition then
|
|
1103
1136
|
local latestVersion = data.version
|
|
1104
1137
|
if Utils.compareVersions(State.CURRENT_VERSION, latestVersion) < 0 then
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
ui.contentFrame.Position = UDim2.new(0, 8, 0, 92)
|
|
1109
|
-
ui.contentFrame.Size = UDim2.new(1, -16, 1, -100)
|
|
1138
|
+
if not hasVersionMismatch then
|
|
1139
|
+
UI.showBanner("update", `v{latestVersion} available - github.com/chrrxs/robloxstudio-mcp`)
|
|
1140
|
+
end
|
|
1110
1141
|
end
|
|
1111
1142
|
end
|
|
1112
1143
|
end
|
|
@@ -1256,9 +1287,9 @@ local function computeBridgeStamp()
|
|
|
1256
1287
|
for i = 1, #combined do
|
|
1257
1288
|
h = (h * 33 + (string.byte(combined, i))) % 2147483647
|
|
1258
1289
|
end
|
|
1259
|
-
-- "2.
|
|
1290
|
+
-- "2.15.1" is replaced with the package version at package time
|
|
1260
1291
|
-- (scripts/build-plugin.mjs injectVersion), so a release bump also restamps.
|
|
1261
|
-
return `{tostring(h)}-2.
|
|
1292
|
+
return `{tostring(h)}-2.15.1`
|
|
1262
1293
|
end
|
|
1263
1294
|
local BRIDGE_STAMP = computeBridgeStamp()
|
|
1264
1295
|
local function setSource(scriptInst, source)
|
|
@@ -5070,6 +5101,255 @@ return {
|
|
|
5070
5101
|
</Properties>
|
|
5071
5102
|
</Item>
|
|
5072
5103
|
<Item class="ModuleScript" referent="16">
|
|
5104
|
+
<Properties>
|
|
5105
|
+
<string name="Name">SceneAnalysisHandlers</string>
|
|
5106
|
+
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
5107
|
+
local MODE_CONFIGS = {
|
|
5108
|
+
instance_composition = {
|
|
5109
|
+
method = "GetInstanceCompositionAsync",
|
|
5110
|
+
query = function(service)
|
|
5111
|
+
return service:GetInstanceCompositionAsync()
|
|
5112
|
+
end,
|
|
5113
|
+
},
|
|
5114
|
+
script_memory = {
|
|
5115
|
+
method = "GetScriptMemoryAsync",
|
|
5116
|
+
query = function(service)
|
|
5117
|
+
return service:GetScriptMemoryAsync()
|
|
5118
|
+
end,
|
|
5119
|
+
},
|
|
5120
|
+
unparented_instances = {
|
|
5121
|
+
method = "GetUnparentedInstancesAsync",
|
|
5122
|
+
query = function(service)
|
|
5123
|
+
return service:GetUnparentedInstancesAsync()
|
|
5124
|
+
end,
|
|
5125
|
+
},
|
|
5126
|
+
triangle_composition = {
|
|
5127
|
+
method = "GetTriangleCompositionAsync",
|
|
5128
|
+
query = function(service)
|
|
5129
|
+
return service:GetTriangleCompositionAsync()
|
|
5130
|
+
end,
|
|
5131
|
+
sortByTriangles = true,
|
|
5132
|
+
},
|
|
5133
|
+
animation_memory = {
|
|
5134
|
+
method = "GetAnimationMemoryAsync",
|
|
5135
|
+
query = function(service)
|
|
5136
|
+
return service:GetAnimationMemoryAsync()
|
|
5137
|
+
end,
|
|
5138
|
+
},
|
|
5139
|
+
audio_memory = {
|
|
5140
|
+
method = "GetAudioMemoryAsync",
|
|
5141
|
+
query = function(service)
|
|
5142
|
+
return service:GetAudioMemoryAsync()
|
|
5143
|
+
end,
|
|
5144
|
+
},
|
|
5145
|
+
}
|
|
5146
|
+
local ALL_MODES = { "instance_composition", "script_memory", "unparented_instances", "triangle_composition", "animation_memory", "audio_memory" }
|
|
5147
|
+
local function betaDisabledError()
|
|
5148
|
+
return {
|
|
5149
|
+
error = "scene_analysis_not_enabled",
|
|
5150
|
+
message = "SceneAnalysisService is not enabled. Enable Scene Analysis in Studio Beta Features and restart Studio.",
|
|
5151
|
+
betaFeatureRequired = true,
|
|
5152
|
+
}
|
|
5153
|
+
end
|
|
5154
|
+
local function isBetaDisabledError(value)
|
|
5155
|
+
local _value = value
|
|
5156
|
+
local _condition = type(_value) == "string"
|
|
5157
|
+
if _condition then
|
|
5158
|
+
_condition = (string.find(value, "SceneAnalysisService is not enabled", 1, true)) ~= nil
|
|
5159
|
+
end
|
|
5160
|
+
return _condition
|
|
5161
|
+
end
|
|
5162
|
+
local function getSceneAnalysisService()
|
|
5163
|
+
local provider = game
|
|
5164
|
+
local ok, service = pcall(function()
|
|
5165
|
+
return provider:GetService("SceneAnalysisService")
|
|
5166
|
+
end)
|
|
5167
|
+
if not ok or not service then
|
|
5168
|
+
return {
|
|
5169
|
+
error = "scene_analysis_unavailable",
|
|
5170
|
+
message = `SceneAnalysisService is unavailable: {tostring(service)}`,
|
|
5171
|
+
}
|
|
5172
|
+
end
|
|
5173
|
+
return service
|
|
5174
|
+
end
|
|
5175
|
+
local function normalizeMode(mode)
|
|
5176
|
+
if mode == nil or mode == "all" then
|
|
5177
|
+
return "all"
|
|
5178
|
+
end
|
|
5179
|
+
local _mode = mode
|
|
5180
|
+
local _condition = not (type(_mode) == "string")
|
|
5181
|
+
if not _condition then
|
|
5182
|
+
_condition = MODE_CONFIGS[mode] == nil
|
|
5183
|
+
end
|
|
5184
|
+
if _condition then
|
|
5185
|
+
return {
|
|
5186
|
+
error = "invalid_mode",
|
|
5187
|
+
message = `mode must be one of: all, {table.concat(ALL_MODES, ", ")}`,
|
|
5188
|
+
}
|
|
5189
|
+
end
|
|
5190
|
+
return mode
|
|
5191
|
+
end
|
|
5192
|
+
local function normalizeTopN(topN)
|
|
5193
|
+
local _topN = topN
|
|
5194
|
+
if not (type(_topN) == "number") then
|
|
5195
|
+
return 10
|
|
5196
|
+
end
|
|
5197
|
+
return math.clamp(math.floor(topN), 1, 100)
|
|
5198
|
+
end
|
|
5199
|
+
local function countLeaves(node)
|
|
5200
|
+
local children = node.Children
|
|
5201
|
+
if children and #children > 0 then
|
|
5202
|
+
local total = 0
|
|
5203
|
+
for _, child in children do
|
|
5204
|
+
total += countLeaves(child)
|
|
5205
|
+
end
|
|
5206
|
+
return total
|
|
5207
|
+
end
|
|
5208
|
+
return 1
|
|
5209
|
+
end
|
|
5210
|
+
local function flattenLeaves(node, out)
|
|
5211
|
+
local children = node.Children
|
|
5212
|
+
if children and #children > 0 then
|
|
5213
|
+
for _, child in children do
|
|
5214
|
+
flattenLeaves(child, out)
|
|
5215
|
+
end
|
|
5216
|
+
return nil
|
|
5217
|
+
end
|
|
5218
|
+
local _out = out
|
|
5219
|
+
local _node = node
|
|
5220
|
+
table.insert(_out, _node)
|
|
5221
|
+
end
|
|
5222
|
+
local function compactEntry(node)
|
|
5223
|
+
local entry = {
|
|
5224
|
+
name = node.Name,
|
|
5225
|
+
}
|
|
5226
|
+
if node.Size ~= nil then
|
|
5227
|
+
entry.size = node.Size
|
|
5228
|
+
end
|
|
5229
|
+
if node.Sizes ~= nil then
|
|
5230
|
+
entry.sizes = node.Sizes
|
|
5231
|
+
end
|
|
5232
|
+
if node.AssetId ~= nil then
|
|
5233
|
+
entry.asset_id = node.AssetId
|
|
5234
|
+
end
|
|
5235
|
+
return entry
|
|
5236
|
+
end
|
|
5237
|
+
local function compactRoot(node, leafCount)
|
|
5238
|
+
local children = node.Children
|
|
5239
|
+
local root = {
|
|
5240
|
+
name = node.Name,
|
|
5241
|
+
child_count = if children then #children else 0,
|
|
5242
|
+
leaf_count = leafCount,
|
|
5243
|
+
}
|
|
5244
|
+
if node.Size ~= nil then
|
|
5245
|
+
root.size = node.Size
|
|
5246
|
+
end
|
|
5247
|
+
if node.Sizes ~= nil then
|
|
5248
|
+
root.sizes = node.Sizes
|
|
5249
|
+
end
|
|
5250
|
+
return root
|
|
5251
|
+
end
|
|
5252
|
+
local function metric(node, sortByTriangles)
|
|
5253
|
+
if sortByTriangles then
|
|
5254
|
+
local sizes = node.Sizes
|
|
5255
|
+
local triangles = if sizes then sizes.Triangles else nil
|
|
5256
|
+
local _condition = triangles
|
|
5257
|
+
if _condition == nil then
|
|
5258
|
+
_condition = 0
|
|
5259
|
+
end
|
|
5260
|
+
return _condition
|
|
5261
|
+
end
|
|
5262
|
+
local _condition = node.Size
|
|
5263
|
+
if _condition == nil then
|
|
5264
|
+
_condition = 0
|
|
5265
|
+
end
|
|
5266
|
+
return _condition
|
|
5267
|
+
end
|
|
5268
|
+
local function summarizeMode(mode, config, service, topN, raw)
|
|
5269
|
+
local started = os.clock()
|
|
5270
|
+
local ok, result = pcall(function()
|
|
5271
|
+
return config.query(service)
|
|
5272
|
+
end)
|
|
5273
|
+
local elapsedMs = math.floor((os.clock() - started) * 1000)
|
|
5274
|
+
if not ok then
|
|
5275
|
+
if isBetaDisabledError(result) then
|
|
5276
|
+
return betaDisabledError()
|
|
5277
|
+
end
|
|
5278
|
+
return {
|
|
5279
|
+
error = "scene_analysis_query_failed",
|
|
5280
|
+
mode = mode,
|
|
5281
|
+
method = config.method,
|
|
5282
|
+
message = tostring(result),
|
|
5283
|
+
}
|
|
5284
|
+
end
|
|
5285
|
+
local tree = result
|
|
5286
|
+
local leaves = {}
|
|
5287
|
+
flattenLeaves(tree, leaves)
|
|
5288
|
+
table.sort(leaves, function(a, b)
|
|
5289
|
+
return metric(a, config.sortByTriangles == true) > metric(b, config.sortByTriangles == true)
|
|
5290
|
+
end)
|
|
5291
|
+
local top = {}
|
|
5292
|
+
do
|
|
5293
|
+
local i = 0
|
|
5294
|
+
local _shouldIncrement = false
|
|
5295
|
+
while true do
|
|
5296
|
+
if _shouldIncrement then
|
|
5297
|
+
i += 1
|
|
5298
|
+
else
|
|
5299
|
+
_shouldIncrement = true
|
|
5300
|
+
end
|
|
5301
|
+
if not (i < math.min(topN, #leaves)) then
|
|
5302
|
+
break
|
|
5303
|
+
end
|
|
5304
|
+
local _arg0 = compactEntry(leaves[i + 1])
|
|
5305
|
+
table.insert(top, _arg0)
|
|
5306
|
+
end
|
|
5307
|
+
end
|
|
5308
|
+
local body = {
|
|
5309
|
+
mode = mode,
|
|
5310
|
+
method = config.method,
|
|
5311
|
+
elapsed_ms = elapsedMs,
|
|
5312
|
+
root = compactRoot(tree, #leaves),
|
|
5313
|
+
top = top,
|
|
5314
|
+
}
|
|
5315
|
+
if raw then
|
|
5316
|
+
body.tree = tree
|
|
5317
|
+
end
|
|
5318
|
+
return body
|
|
5319
|
+
end
|
|
5320
|
+
local function getSceneAnalysis(requestData)
|
|
5321
|
+
local mode = normalizeMode(requestData.mode)
|
|
5322
|
+
if not (type(mode) == "string") then
|
|
5323
|
+
return mode
|
|
5324
|
+
end
|
|
5325
|
+
local serviceOrError = getSceneAnalysisService()
|
|
5326
|
+
local _value = serviceOrError.IsA
|
|
5327
|
+
if not (_value ~= 0 and _value == _value and _value ~= "" and _value) then
|
|
5328
|
+
return serviceOrError
|
|
5329
|
+
end
|
|
5330
|
+
local service = serviceOrError
|
|
5331
|
+
local topN = normalizeTopN(requestData.topN)
|
|
5332
|
+
local raw = requestData.raw == true
|
|
5333
|
+
if mode ~= "all" then
|
|
5334
|
+
return summarizeMode(mode, MODE_CONFIGS[mode], service, topN, raw)
|
|
5335
|
+
end
|
|
5336
|
+
local body = {}
|
|
5337
|
+
for _, m in ALL_MODES do
|
|
5338
|
+
local result = summarizeMode(m, MODE_CONFIGS[m], service, topN, raw)
|
|
5339
|
+
if result.error == "scene_analysis_not_enabled" then
|
|
5340
|
+
return result
|
|
5341
|
+
end
|
|
5342
|
+
body[m] = result
|
|
5343
|
+
end
|
|
5344
|
+
return body
|
|
5345
|
+
end
|
|
5346
|
+
return {
|
|
5347
|
+
getSceneAnalysis = getSceneAnalysis,
|
|
5348
|
+
}
|
|
5349
|
+
]]></string>
|
|
5350
|
+
</Properties>
|
|
5351
|
+
</Item>
|
|
5352
|
+
<Item class="ModuleScript" referent="17">
|
|
5073
5353
|
<Properties>
|
|
5074
5354
|
<string name="Name">ScriptHandlers</string>
|
|
5075
5355
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -5765,7 +6045,7 @@ return {
|
|
|
5765
6045
|
]]></string>
|
|
5766
6046
|
</Properties>
|
|
5767
6047
|
</Item>
|
|
5768
|
-
<Item class="ModuleScript" referent="
|
|
6048
|
+
<Item class="ModuleScript" referent="18">
|
|
5769
6049
|
<Properties>
|
|
5770
6050
|
<string name="Name">SerializationHandlers</string>
|
|
5771
6051
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -5951,7 +6231,7 @@ return {
|
|
|
5951
6231
|
]]></string>
|
|
5952
6232
|
</Properties>
|
|
5953
6233
|
</Item>
|
|
5954
|
-
<Item class="ModuleScript" referent="
|
|
6234
|
+
<Item class="ModuleScript" referent="19">
|
|
5955
6235
|
<Properties>
|
|
5956
6236
|
<string name="Name">TestHandlers</string>
|
|
5957
6237
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -6584,7 +6864,7 @@ return {
|
|
|
6584
6864
|
</Properties>
|
|
6585
6865
|
</Item>
|
|
6586
6866
|
</Item>
|
|
6587
|
-
<Item class="ModuleScript" referent="
|
|
6867
|
+
<Item class="ModuleScript" referent="20">
|
|
6588
6868
|
<Properties>
|
|
6589
6869
|
<string name="Name">LuauExec</string>
|
|
6590
6870
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -6902,7 +7182,7 @@ return {
|
|
|
6902
7182
|
]]></string>
|
|
6903
7183
|
</Properties>
|
|
6904
7184
|
</Item>
|
|
6905
|
-
<Item class="ModuleScript" referent="
|
|
7185
|
+
<Item class="ModuleScript" referent="21">
|
|
6906
7186
|
<Properties>
|
|
6907
7187
|
<string name="Name">Recording</string>
|
|
6908
7188
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -6932,7 +7212,7 @@ return {
|
|
|
6932
7212
|
]]></string>
|
|
6933
7213
|
</Properties>
|
|
6934
7214
|
</Item>
|
|
6935
|
-
<Item class="ModuleScript" referent="
|
|
7215
|
+
<Item class="ModuleScript" referent="22">
|
|
6936
7216
|
<Properties>
|
|
6937
7217
|
<string name="Name">RenderMonitor</string>
|
|
6938
7218
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -7000,7 +7280,7 @@ return {
|
|
|
7000
7280
|
]]></string>
|
|
7001
7281
|
</Properties>
|
|
7002
7282
|
</Item>
|
|
7003
|
-
<Item class="ModuleScript" referent="
|
|
7283
|
+
<Item class="ModuleScript" referent="23">
|
|
7004
7284
|
<Properties>
|
|
7005
7285
|
<string name="Name">RuntimeLogBuffer</string>
|
|
7006
7286
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -7181,11 +7461,12 @@ return {
|
|
|
7181
7461
|
]]></string>
|
|
7182
7462
|
</Properties>
|
|
7183
7463
|
</Item>
|
|
7184
|
-
<Item class="ModuleScript" referent="
|
|
7464
|
+
<Item class="ModuleScript" referent="24">
|
|
7185
7465
|
<Properties>
|
|
7186
7466
|
<string name="Name">State</string>
|
|
7187
7467
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
7188
|
-
local CURRENT_VERSION = "2.
|
|
7468
|
+
local CURRENT_VERSION = "2.15.1"
|
|
7469
|
+
local PLUGIN_VARIANT = "inspector"
|
|
7189
7470
|
local MAX_CONNECTIONS = 5
|
|
7190
7471
|
local BASE_PORT = 58741
|
|
7191
7472
|
local activeTabIndex = 0
|
|
@@ -7263,6 +7544,7 @@ local function getConnections()
|
|
|
7263
7544
|
end
|
|
7264
7545
|
return {
|
|
7265
7546
|
CURRENT_VERSION = CURRENT_VERSION,
|
|
7547
|
+
PLUGIN_VARIANT = PLUGIN_VARIANT,
|
|
7266
7548
|
MAX_CONNECTIONS = MAX_CONNECTIONS,
|
|
7267
7549
|
BASE_PORT = BASE_PORT,
|
|
7268
7550
|
connections = connections,
|
|
@@ -7277,7 +7559,7 @@ return {
|
|
|
7277
7559
|
]]></string>
|
|
7278
7560
|
</Properties>
|
|
7279
7561
|
</Item>
|
|
7280
|
-
<Item class="ModuleScript" referent="
|
|
7562
|
+
<Item class="ModuleScript" referent="25">
|
|
7281
7563
|
<Properties>
|
|
7282
7564
|
<string name="Name">StopPlayMonitor</string>
|
|
7283
7565
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -7422,7 +7704,7 @@ return {
|
|
|
7422
7704
|
]]></string>
|
|
7423
7705
|
</Properties>
|
|
7424
7706
|
</Item>
|
|
7425
|
-
<Item class="ModuleScript" referent="
|
|
7707
|
+
<Item class="ModuleScript" referent="26">
|
|
7426
7708
|
<Properties>
|
|
7427
7709
|
<string name="Name">UI</string>
|
|
7428
7710
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -7435,6 +7717,7 @@ local buttonHover = false
|
|
|
7435
7717
|
local toolbarButton
|
|
7436
7718
|
local toolbarIcons
|
|
7437
7719
|
local lastToolbarIcon
|
|
7720
|
+
local activeBannerKind
|
|
7438
7721
|
local updateToolbarIcon
|
|
7439
7722
|
local function setToolbarButton(btn, icons)
|
|
7440
7723
|
toolbarButton = btn
|
|
@@ -7465,6 +7748,23 @@ local TWEEN_QUICK = TweenInfo.new(0.15, Enum.EasingStyle.Quad, Enum.EasingDirect
|
|
|
7465
7748
|
local function tweenProp(instance, props)
|
|
7466
7749
|
TweenService:Create(instance, TWEEN_QUICK, props):Play()
|
|
7467
7750
|
end
|
|
7751
|
+
local function showBanner(kind, text)
|
|
7752
|
+
activeBannerKind = kind
|
|
7753
|
+
elements.updateBannerText.Text = text
|
|
7754
|
+
elements.updateBanner.Visible = true
|
|
7755
|
+
elements.contentFrame.Position = UDim2.new(0, 8, 0, 92)
|
|
7756
|
+
elements.contentFrame.Size = UDim2.new(1, -16, 1, -100)
|
|
7757
|
+
end
|
|
7758
|
+
local function hideBanner(kind)
|
|
7759
|
+
if kind ~= nil and activeBannerKind ~= kind then
|
|
7760
|
+
return nil
|
|
7761
|
+
end
|
|
7762
|
+
activeBannerKind = nil
|
|
7763
|
+
elements.updateBanner.Visible = false
|
|
7764
|
+
elements.updateBannerText.Text = ""
|
|
7765
|
+
elements.contentFrame.Position = UDim2.new(0, 8, 0, 66)
|
|
7766
|
+
elements.contentFrame.Size = UDim2.new(1, -16, 1, -74)
|
|
7767
|
+
end
|
|
7468
7768
|
local C = {
|
|
7469
7769
|
bg = Color3.fromRGB(14, 14, 14),
|
|
7470
7770
|
card = Color3.fromRGB(22, 22, 22),
|
|
@@ -8166,6 +8466,8 @@ return {
|
|
|
8166
8466
|
startPulseAnimation = startPulseAnimation,
|
|
8167
8467
|
setToolbarButton = setToolbarButton,
|
|
8168
8468
|
updateToolbarIcon = updateToolbarIcon,
|
|
8469
|
+
showBanner = showBanner,
|
|
8470
|
+
hideBanner = hideBanner,
|
|
8169
8471
|
getElements = function()
|
|
8170
8472
|
return elements
|
|
8171
8473
|
end,
|
|
@@ -8173,7 +8475,7 @@ return {
|
|
|
8173
8475
|
]]></string>
|
|
8174
8476
|
</Properties>
|
|
8175
8477
|
</Item>
|
|
8176
|
-
<Item class="ModuleScript" referent="
|
|
8478
|
+
<Item class="ModuleScript" referent="27">
|
|
8177
8479
|
<Properties>
|
|
8178
8480
|
<string name="Name">Utils</string>
|
|
8179
8481
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -8703,11 +9005,11 @@ return {
|
|
|
8703
9005
|
</Properties>
|
|
8704
9006
|
</Item>
|
|
8705
9007
|
</Item>
|
|
8706
|
-
<Item class="Folder" referent="
|
|
9008
|
+
<Item class="Folder" referent="31">
|
|
8707
9009
|
<Properties>
|
|
8708
9010
|
<string name="Name">include</string>
|
|
8709
9011
|
</Properties>
|
|
8710
|
-
<Item class="ModuleScript" referent="
|
|
9012
|
+
<Item class="ModuleScript" referent="28">
|
|
8711
9013
|
<Properties>
|
|
8712
9014
|
<string name="Name">Promise</string>
|
|
8713
9015
|
<string name="Source"><![CDATA[--[[
|
|
@@ -10781,7 +11083,7 @@ return Promise
|
|
|
10781
11083
|
]]></string>
|
|
10782
11084
|
</Properties>
|
|
10783
11085
|
</Item>
|
|
10784
|
-
<Item class="ModuleScript" referent="
|
|
11086
|
+
<Item class="ModuleScript" referent="29">
|
|
10785
11087
|
<Properties>
|
|
10786
11088
|
<string name="Name">RuntimeLib</string>
|
|
10787
11089
|
<string name="Source"><![CDATA[local Promise = require(script.Parent.Promise)
|
|
@@ -11048,15 +11350,15 @@ return TS
|
|
|
11048
11350
|
</Properties>
|
|
11049
11351
|
</Item>
|
|
11050
11352
|
</Item>
|
|
11051
|
-
<Item class="Folder" referent="
|
|
11353
|
+
<Item class="Folder" referent="32">
|
|
11052
11354
|
<Properties>
|
|
11053
11355
|
<string name="Name">node_modules</string>
|
|
11054
11356
|
</Properties>
|
|
11055
|
-
<Item class="Folder" referent="
|
|
11357
|
+
<Item class="Folder" referent="33">
|
|
11056
11358
|
<Properties>
|
|
11057
11359
|
<string name="Name">@rbxts</string>
|
|
11058
11360
|
</Properties>
|
|
11059
|
-
<Item class="ModuleScript" referent="
|
|
11361
|
+
<Item class="ModuleScript" referent="30">
|
|
11060
11362
|
<Properties>
|
|
11061
11363
|
<string name="Name">services</string>
|
|
11062
11364
|
<string name="Source"><![CDATA[return setmetatable({}, {
|