@chrrxs/robloxstudio-mcp-inspector 2.8.1 → 2.9.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.
@@ -770,11 +770,239 @@ return {
770
770
  ]]></string>
771
771
  </Properties>
772
772
  </Item>
773
- <Item class="Folder" referent="4">
773
+ <Item class="ModuleScript" referent="4">
774
+ <Properties>
775
+ <string name="Name">EvalBridges</string>
776
+ <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
777
+ local TS = require(script.Parent.Parent.include.RuntimeLib)
778
+ -- Game-VM eval bridges, ported from chrrxs/roblox-mcp-primitives.
779
+ --
780
+ -- Our standard `execute_luau target=server/client-N` runs in the plugin VM
781
+ -- with a fresh ModuleScript per call. That gives a clean sandbox but means
782
+ -- `require(SomeModule)` returns a fresh copy, not the one the running game
783
+ -- scripts hold. So runtime-mutated module state is invisible to probes.
784
+ --
785
+ -- These bridges fix that by living inside the user's game scripts:
786
+ -- - Server: a Script in ServerScriptService that creates a BindableFunction
787
+ -- (for our server-peer plugin to invoke directly) plus a RemoteFunction
788
+ -- (kept for parity with the upstream primitive's client-callable shape).
789
+ -- - Client: a LocalScript in StarterPlayer.StarterPlayerScripts that
790
+ -- creates a BindableFunction. Plugin invokes it with a fresh ModuleScript
791
+ -- payload; require() runs inside the LocalScript VM so it shares the
792
+ -- game's require cache.
793
+ --
794
+ -- Lifecycle: TestHandlers.startPlaytest inserts both scripts into the EDIT
795
+ -- DM right before ExecutePlayModeAsync. ExecutePlayModeAsync clones the
796
+ -- DataModel into the play DMs, so the scripts come along and run there.
797
+ -- TestHandlers cleans them up from the edit DM when ExecutePlayModeAsync
798
+ -- returns (test ended for any reason: stop_playtest, manual close, EndTest).
799
+ --
800
+ -- Archivable handling: ExecutePlayModeAsync's deep-clone SKIPS instances
801
+ -- with Archivable=false (verified empirically in v2.9.0 testing - bridges
802
+ -- never reached the play DMs because we'd set them to false). We now keep
803
+ -- Archivable=true so the clone works, and rely on cleanupBridges() to
804
+ -- remove the scripts from the edit DM when the test ends. The only failure
805
+ -- mode is the user saving DURING an active playtest, which would persist
806
+ -- the bridges to the .rbxl - that's a no-op next session because
807
+ -- installBridges() always calls cleanupBridges() first to clear stale
808
+ -- instances. The RemoteFunction/BindableFunction that the bridge scripts
809
+ -- CREATE at runtime stay Archivable=false (they're runtime-only and should
810
+ -- never appear in a save).
811
+ local _services = TS.import(script, script.Parent.Parent, "node_modules", "@rbxts", "services")
812
+ local ServerScriptService = _services.ServerScriptService
813
+ local StarterPlayer = _services.StarterPlayer
814
+ local ScriptEditorService = game:GetService("ScriptEditorService")
815
+ local function getStarterPlayerScripts()
816
+ return StarterPlayer:FindFirstChild("StarterPlayerScripts")
817
+ end
818
+ local SERVER_SCRIPT_NAME = "__MCP_ServerEvalBridge"
819
+ local CLIENT_SCRIPT_NAME = "__MCP_ClientEvalBridge"
820
+ -- Public so the eval_*_runtime tool wrappers can reference the same names.
821
+ local BRIDGE_NAMES = {
822
+ serverScript = SERVER_SCRIPT_NAME,
823
+ clientScript = CLIENT_SCRIPT_NAME,
824
+ serverRemote = "__MCP_ServerEvalRemote",
825
+ serverLocal = "__MCP_ServerEvalLocal",
826
+ clientLocal = "__MCP_ClientEvalBridge",
827
+ }
828
+ -- Embedded Luau. The double `${...}` references our exported names so a
829
+ -- rename here propagates to both the script source and the tool wrappers.
830
+ local SERVER_BRIDGE_SOURCE = `\
831
+ -- Auto-installed by @chrrxs/robloxstudio-mcp at start_playtest, removed at\
832
+ -- stop_playtest. Provides shared-require-cache eval on the server peer for\
833
+ -- the eval_server_runtime MCP tool.\
834
+ \
835
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")\
836
+ local ServerScriptService = game:GetService("ServerScriptService")\
837
+ local RunService = game:GetService("RunService")\
838
+ \
839
+ if not RunService:IsStudio() then\
840
+ return\
841
+ end\
842
+ \
843
+ local function evalCode(source)\
844
+ if type(source) ~= "string" then\
845
+ return false, "source must be a string"\
846
+ end\
847
+ local fn, compileErr = loadstring(source, "MCPServerEval")\
848
+ if not fn then\
849
+ local errStr = tostring(compileErr or "loadstring returned nil")\
850
+ -- Roblox returns nil from loadstring when LoadStringEnabled=false.\
851
+ -- Surface a clear, actionable error.\
852
+ if string.find(errStr, "not enabled", 1, true)\
853
+ or string.find(errStr, "disabled", 1, true)\
854
+ or errStr == "loadstring returned nil"\
855
+ then\
856
+ return false,\
857
+ "ServerScriptService.LoadStringEnabled is false. eval_server_runtime requires it. "\
858
+ .. "Enable it in Studio (ServerScriptService > Properties > LoadStringEnabled = true) "\
859
+ .. "and restart the playtest."\
860
+ end\
861
+ return false, errStr\
862
+ end\
863
+ return pcall(fn)\
864
+ end\
865
+ \
866
+ -- Defensive cleanup of stale instances from a prior session.\
867
+ local prevRf = ReplicatedStorage:FindFirstChild("{BRIDGE_NAMES.serverRemote}")\
868
+ if prevRf then prevRf:Destroy() end\
869
+ local prevBf = ServerScriptService:FindFirstChild("{BRIDGE_NAMES.serverLocal}")\
870
+ if prevBf then prevBf:Destroy() end\
871
+ \
872
+ local rf = Instance.new("RemoteFunction")\
873
+ rf.Name = "{BRIDGE_NAMES.serverRemote}"\
874
+ rf.Archivable = false\
875
+ rf.Parent = ReplicatedStorage\
876
+ rf.OnServerInvoke = function(_player, source)\
877
+ return evalCode(source)\
878
+ end\
879
+ \
880
+ local bf = Instance.new("BindableFunction")\
881
+ bf.Name = "{BRIDGE_NAMES.serverLocal}"\
882
+ bf.Archivable = false\
883
+ bf.Parent = ServerScriptService\
884
+ bf.OnInvoke = function(source)\
885
+ return evalCode(source)\
886
+ end\
887
+ `
888
+ local CLIENT_BRIDGE_SOURCE = `\
889
+ -- Auto-installed by @chrrxs/robloxstudio-mcp at start_playtest, removed at\
890
+ -- stop_playtest. Provides shared-require-cache eval on the client peer for\
891
+ -- the eval_client_runtime MCP tool.\
892
+ \
893
+ local ReplicatedStorage = game:GetService("ReplicatedStorage")\
894
+ local RunService = game:GetService("RunService")\
895
+ \
896
+ if not RunService:IsStudio() then\
897
+ return\
898
+ end\
899
+ \
900
+ local prevBf = ReplicatedStorage:FindFirstChild("{BRIDGE_NAMES.clientLocal}")\
901
+ if prevBf then prevBf:Destroy() end\
902
+ \
903
+ local bf = Instance.new("BindableFunction")\
904
+ bf.Name = "{BRIDGE_NAMES.clientLocal}"\
905
+ bf.Archivable = false\
906
+ bf.Parent = ReplicatedStorage\
907
+ bf.OnInvoke = function(payload)\
908
+ if typeof(payload) ~= "Instance" or not payload:IsA("ModuleScript") then\
909
+ return false, "payload must be a ModuleScript instance"\
910
+ end\
911
+ return pcall(require, payload)\
912
+ end\
913
+ `
914
+ local function setSource(scriptInst, source)
915
+ -- ScriptEditorService is the cleaner API and integrates with Studio's
916
+ -- edit history; fall back to direct Source mutation (allowed in plugin
917
+ -- context with PluginSecurity) if the edit service rejects the call.
918
+ local seOk = pcall(function()
919
+ ScriptEditorService:UpdateSourceAsync(scriptInst, function()
920
+ return source
921
+ end)
922
+ end)
923
+ if not seOk then
924
+ scriptInst.Source = source
925
+ end
926
+ end
927
+ local function findBridges()
928
+ local sps = getStarterPlayerScripts()
929
+ return {
930
+ server = ServerScriptService:FindFirstChild(SERVER_SCRIPT_NAME),
931
+ client = if sps then sps:FindFirstChild(CLIENT_SCRIPT_NAME) else nil,
932
+ }
933
+ end
934
+ local function cleanupBridges()
935
+ local _binding = findBridges()
936
+ local server = _binding.server
937
+ local client = _binding.client
938
+ if server then
939
+ pcall(function()
940
+ return server:Destroy()
941
+ end)
942
+ end
943
+ if client then
944
+ pcall(function()
945
+ return client:Destroy()
946
+ end)
947
+ end
948
+ end
949
+ local function installBridges()
950
+ -- Defensive: clear any stale bridges from a prior unclean exit before
951
+ -- inserting fresh. The injected script also self-cleans its
952
+ -- ReplicatedStorage/ServerScriptService children at startup, but the
953
+ -- containing Script/LocalScript objects themselves we must clear here.
954
+ cleanupBridges()
955
+ local ok, err = pcall(function()
956
+ local serverScript = Instance.new("Script")
957
+ serverScript.Name = SERVER_SCRIPT_NAME
958
+ -- Archivable=true so ExecutePlayModeAsync's deep-clone includes the
959
+ -- script. cleanupBridges() removes it from the edit DM when the
960
+ -- playtest ends.
961
+ setSource(serverScript, SERVER_BRIDGE_SOURCE)
962
+ serverScript.Parent = ServerScriptService
963
+ local sps = getStarterPlayerScripts()
964
+ if not sps then
965
+ error("StarterPlayer.StarterPlayerScripts not found - cannot install client eval bridge")
966
+ end
967
+ local clientScript = Instance.new("LocalScript")
968
+ clientScript.Name = CLIENT_SCRIPT_NAME
969
+ setSource(clientScript, CLIENT_BRIDGE_SOURCE)
970
+ clientScript.Parent = sps
971
+ end)
972
+ if not ok then
973
+ return {
974
+ installed = false,
975
+ error = tostring(err),
976
+ }
977
+ end
978
+ return {
979
+ installed = true,
980
+ }
981
+ end
982
+ -- Heuristic check so start_playtest can surface a warning when
983
+ -- LoadStringEnabled is false (eval_server_runtime won't work in that mode).
984
+ -- We can't import the runtime LoadStringEnabled value cleanly without
985
+ -- pulling in the type — read defensively.
986
+ local function loadStringEnabled()
987
+ local ok, value = pcall(function()
988
+ return ServerScriptService.LoadStringEnabled
989
+ end)
990
+ return ok and value == true
991
+ end
992
+ return {
993
+ cleanupBridges = cleanupBridges,
994
+ installBridges = installBridges,
995
+ loadStringEnabled = loadStringEnabled,
996
+ BRIDGE_NAMES = BRIDGE_NAMES,
997
+ }
998
+ ]]></string>
999
+ </Properties>
1000
+ </Item>
1001
+ <Item class="Folder" referent="5">
774
1002
  <Properties>
775
1003
  <string name="Name">handlers</string>
776
1004
  </Properties>
777
- <Item class="ModuleScript" referent="5">
1005
+ <Item class="ModuleScript" referent="6">
778
1006
  <Properties>
779
1007
  <string name="Name">AssetHandlers</string>
780
1008
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -1060,7 +1288,7 @@ return {
1060
1288
  ]]></string>
1061
1289
  </Properties>
1062
1290
  </Item>
1063
- <Item class="ModuleScript" referent="6">
1291
+ <Item class="ModuleScript" referent="7">
1064
1292
  <Properties>
1065
1293
  <string name="Name">BuildHandlers</string>
1066
1294
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -1625,7 +1853,7 @@ return {
1625
1853
  ]]></string>
1626
1854
  </Properties>
1627
1855
  </Item>
1628
- <Item class="ModuleScript" referent="7">
1856
+ <Item class="ModuleScript" referent="8">
1629
1857
  <Properties>
1630
1858
  <string name="Name">CaptureHandlers</string>
1631
1859
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -1791,7 +2019,7 @@ return {
1791
2019
  ]]></string>
1792
2020
  </Properties>
1793
2021
  </Item>
1794
- <Item class="ModuleScript" referent="8">
2022
+ <Item class="ModuleScript" referent="9">
1795
2023
  <Properties>
1796
2024
  <string name="Name">InputHandlers</string>
1797
2025
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -1945,7 +2173,7 @@ return {
1945
2173
  ]]></string>
1946
2174
  </Properties>
1947
2175
  </Item>
1948
- <Item class="ModuleScript" referent="9">
2176
+ <Item class="ModuleScript" referent="10">
1949
2177
  <Properties>
1950
2178
  <string name="Name">InstanceHandlers</string>
1951
2179
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -2452,7 +2680,7 @@ return {
2452
2680
  ]]></string>
2453
2681
  </Properties>
2454
2682
  </Item>
2455
- <Item class="ModuleScript" referent="10">
2683
+ <Item class="ModuleScript" referent="11">
2456
2684
  <Properties>
2457
2685
  <string name="Name">MetadataHandlers</string>
2458
2686
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -2911,13 +3139,56 @@ local function executeLuau(requestData)
2911
3139
  table.insert(output, _arg0)
2912
3140
  oldWarn(unpack(args))
2913
3141
  end
3142
+ -- Try loadstring first (preserves print/warn interception). When
3143
+ -- ServerScriptService.LoadStringEnabled=false AND the plugin runs in a
3144
+ -- peer where the engine respects that gate (notably the play-server DM
3145
+ -- in some Studio configurations), loadstring either returns nil with a
3146
+ -- "loadstring() is not available" message OR throws that same message
3147
+ -- directly. Both paths must trigger the ModuleScript + require
3148
+ -- fallback. The fallback can't intercept print/warn since the
3149
+ -- ModuleScript runs in its own environment, so the output array stays
3150
+ -- empty in that branch - the playtest log buffer already captures
3151
+ -- prints separately via LogService.MessageOut.
3152
+ local runViaModuleScript = function()
3153
+ local m = Instance.new("ModuleScript")
3154
+ m.Name = "__MCPExecLuauPayload"
3155
+ local okSet, setErr = pcall(function()
3156
+ m.Source = code
3157
+ end)
3158
+ if not okSet then
3159
+ m:Destroy()
3160
+ error(`ModuleScript Source set failed: {tostring(setErr)}`)
3161
+ end
3162
+ m.Parent = game:GetService("Workspace")
3163
+ local okReq, reqResult = pcall(function()
3164
+ return require(m)
3165
+ end)
3166
+ m:Destroy()
3167
+ if not okReq then
3168
+ error(tostring(reqResult))
3169
+ end
3170
+ return reqResult
3171
+ end
3172
+ local isLoadstringUnavailable = function(err)
3173
+ local errStr = tostring(err)
3174
+ local matchStart = string.find(errStr, "not available", 1, true)
3175
+ return matchStart ~= nil
3176
+ end
2914
3177
  local success, result = pcall(function()
2915
3178
  local fn, compileError = loadstring(code)
2916
3179
  if not fn then
3180
+ if isLoadstringUnavailable(compileError) then
3181
+ return runViaModuleScript()
3182
+ end
2917
3183
  error(`Compile error: {compileError}`)
2918
3184
  end
2919
3185
  return fn()
2920
3186
  end)
3187
+ -- loadstring throws (not returns nil) in some plugin contexts when
3188
+ -- LoadStringEnabled=false. Catch that here as a second-chance fallback.
3189
+ if not success and isLoadstringUnavailable(result) then
3190
+ success, result = pcall(runViaModuleScript)
3191
+ end
2921
3192
  env.print = oldPrint
2922
3193
  env.warn = oldWarn
2923
3194
  if success then
@@ -3035,7 +3306,7 @@ return {
3035
3306
  ]]></string>
3036
3307
  </Properties>
3037
3308
  </Item>
3038
- <Item class="ModuleScript" referent="11">
3309
+ <Item class="ModuleScript" referent="12">
3039
3310
  <Properties>
3040
3311
  <string name="Name">PropertyHandlers</string>
3041
3312
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -3287,7 +3558,7 @@ return {
3287
3558
  ]]></string>
3288
3559
  </Properties>
3289
3560
  </Item>
3290
- <Item class="ModuleScript" referent="12">
3561
+ <Item class="ModuleScript" referent="13">
3291
3562
  <Properties>
3292
3563
  <string name="Name">QueryHandlers</string>
3293
3564
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -4314,7 +4585,7 @@ return {
4314
4585
  ]]></string>
4315
4586
  </Properties>
4316
4587
  </Item>
4317
- <Item class="ModuleScript" referent="13">
4588
+ <Item class="ModuleScript" referent="14">
4318
4589
  <Properties>
4319
4590
  <string name="Name">ScriptHandlers</string>
4320
4591
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -5010,7 +5281,7 @@ return {
5010
5281
  ]]></string>
5011
5282
  </Properties>
5012
5283
  </Item>
5013
- <Item class="ModuleScript" referent="14">
5284
+ <Item class="ModuleScript" referent="15">
5014
5285
  <Properties>
5015
5286
  <string name="Name">TestHandlers</string>
5016
5287
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -5018,6 +5289,10 @@ local TS = require(script.Parent.Parent.Parent.include.RuntimeLib)
5018
5289
  local _services = TS.import(script, script.Parent.Parent.Parent, "node_modules", "@rbxts", "services")
5019
5290
  local HttpService = _services.HttpService
5020
5291
  local LogService = _services.LogService
5292
+ local _EvalBridges = TS.import(script, script.Parent.Parent, "EvalBridges")
5293
+ local installBridges = _EvalBridges.installBridges
5294
+ local cleanupBridges = _EvalBridges.cleanupBridges
5295
+ local loadStringEnabled = _EvalBridges.loadStringEnabled
5021
5296
  local StudioTestService = game:GetService("StudioTestService")
5022
5297
  local ServerScriptService = game:GetService("ServerScriptService")
5023
5298
  local ScriptEditorService = game:GetService("ScriptEditorService")
@@ -5174,6 +5449,14 @@ local function startPlaytest(requestData)
5174
5449
  if not injected then
5175
5450
  warn(`[MCP] Failed to inject stop listener: {injErr}`)
5176
5451
  end
5452
+ -- Auto-install the game-VM eval bridges (ServerEvalBridge + ClientEvalBridge)
5453
+ -- so eval_server_runtime / eval_client_runtime work without manual setup.
5454
+ -- Bridges are cleaned up from the edit DM after the play DMs tear down.
5455
+ local bridgeInstall = installBridges()
5456
+ local hasLoadString = loadStringEnabled()
5457
+ if not bridgeInstall.installed then
5458
+ warn(`[MCP] Eval bridge install failed: {bridgeInstall.error}`)
5459
+ end
5177
5460
  if numPlayers ~= nil and mode == "run" then
5178
5461
  local TestService = game:GetService("TestService")
5179
5462
  TestService.NumberOfPlayers = math.clamp(numPlayers, 1, 8)
@@ -5196,12 +5479,22 @@ local function startPlaytest(requestData)
5196
5479
  end
5197
5480
  testRunning = false
5198
5481
  cleanupStopListener()
5482
+ cleanupBridges()
5199
5483
  end)
5200
5484
  local msg = if numPlayers ~= nil then `Playtest started in {mode} mode with {numPlayers} player(s)` else `Playtest started in {mode} mode`
5201
- return {
5485
+ local response = {
5202
5486
  success = true,
5203
5487
  message = msg,
5488
+ evalBridges = if bridgeInstall.installed then "installed" else `failed: {bridgeInstall.error}`,
5204
5489
  }
5490
+ -- Surface loadstring availability up-front so callers know whether
5491
+ -- eval_server_runtime will work before they try it. eval_client_runtime
5492
+ -- doesn't need loadstring (it uses ModuleScript+require), so this only
5493
+ -- affects the server bridge.
5494
+ if not hasLoadString then
5495
+ response.serverEvalNote = "ServerScriptService.LoadStringEnabled is false. eval_server_runtime will not work " .. "until you enable it (ServerScriptService > Properties > LoadStringEnabled = true) " .. "and restart the playtest. eval_client_runtime is unaffected."
5496
+ end
5497
+ return response
5205
5498
  end
5206
5499
  local function stopPlaytest(_requestData)
5207
5500
  -- Server-side routing (tools/index.ts:stopPlaytest) sends /api/stop-playtest
@@ -5307,7 +5600,7 @@ return {
5307
5600
  </Properties>
5308
5601
  </Item>
5309
5602
  </Item>
5310
- <Item class="ModuleScript" referent="15">
5603
+ <Item class="ModuleScript" referent="16">
5311
5604
  <Properties>
5312
5605
  <string name="Name">Recording</string>
5313
5606
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -5337,11 +5630,11 @@ return {
5337
5630
  ]]></string>
5338
5631
  </Properties>
5339
5632
  </Item>
5340
- <Item class="ModuleScript" referent="16">
5633
+ <Item class="ModuleScript" referent="17">
5341
5634
  <Properties>
5342
5635
  <string name="Name">State</string>
5343
5636
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
5344
- local CURRENT_VERSION = "2.8.1"
5637
+ local CURRENT_VERSION = "2.9.1"
5345
5638
  local MAX_CONNECTIONS = 5
5346
5639
  local BASE_PORT = 58741
5347
5640
  local activeTabIndex = 0
@@ -5433,7 +5726,7 @@ return {
5433
5726
  ]]></string>
5434
5727
  </Properties>
5435
5728
  </Item>
5436
- <Item class="ModuleScript" referent="17">
5729
+ <Item class="ModuleScript" referent="18">
5437
5730
  <Properties>
5438
5731
  <string name="Name">UI</string>
5439
5732
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -6153,7 +6446,7 @@ return {
6153
6446
  ]]></string>
6154
6447
  </Properties>
6155
6448
  </Item>
6156
- <Item class="ModuleScript" referent="18">
6449
+ <Item class="ModuleScript" referent="19">
6157
6450
  <Properties>
6158
6451
  <string name="Name">Utils</string>
6159
6452
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -6683,11 +6976,11 @@ return {
6683
6976
  </Properties>
6684
6977
  </Item>
6685
6978
  </Item>
6686
- <Item class="Folder" referent="22">
6979
+ <Item class="Folder" referent="23">
6687
6980
  <Properties>
6688
6981
  <string name="Name">include</string>
6689
6982
  </Properties>
6690
- <Item class="ModuleScript" referent="19">
6983
+ <Item class="ModuleScript" referent="20">
6691
6984
  <Properties>
6692
6985
  <string name="Name">Promise</string>
6693
6986
  <string name="Source"><![CDATA[--[[
@@ -8761,7 +9054,7 @@ return Promise
8761
9054
  ]]></string>
8762
9055
  </Properties>
8763
9056
  </Item>
8764
- <Item class="ModuleScript" referent="20">
9057
+ <Item class="ModuleScript" referent="21">
8765
9058
  <Properties>
8766
9059
  <string name="Name">RuntimeLib</string>
8767
9060
  <string name="Source"><![CDATA[local Promise = require(script.Parent.Promise)
@@ -9028,15 +9321,15 @@ return TS
9028
9321
  </Properties>
9029
9322
  </Item>
9030
9323
  </Item>
9031
- <Item class="Folder" referent="23">
9324
+ <Item class="Folder" referent="24">
9032
9325
  <Properties>
9033
9326
  <string name="Name">node_modules</string>
9034
9327
  </Properties>
9035
- <Item class="Folder" referent="24">
9328
+ <Item class="Folder" referent="25">
9036
9329
  <Properties>
9037
9330
  <string name="Name">@rbxts</string>
9038
9331
  </Properties>
9039
- <Item class="ModuleScript" referent="21">
9332
+ <Item class="ModuleScript" referent="22">
9040
9333
  <Properties>
9041
9334
  <string name="Name">services</string>
9042
9335
  <string name="Source"><![CDATA[return setmetatable({}, {