@chrrxs/robloxstudio-mcp 3.0.3 → 3.0.4

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.
@@ -880,12 +880,12 @@ local routeMap = {
880
880
  ["/api/get-memory-breakdown"] = MemoryHandlers.getMemoryBreakdown,
881
881
  ["/api/get-scene-analysis"] = SceneAnalysisHandlers.getSceneAnalysis,
882
882
  }
883
- local function processRequest(request)
883
+ local function processRequest(request, context)
884
884
  local endpoint = request.endpoint
885
885
  local data = request.data or {}
886
886
  local handler = routeMap[endpoint]
887
887
  if handler then
888
- return handler(data)
888
+ return handler(data, context)
889
889
  else
890
890
  return {
891
891
  error = `Unknown endpoint: {endpoint}`,
@@ -905,7 +905,7 @@ local function getConnectionStatus()
905
905
  end
906
906
  return "connecting"
907
907
  end
908
- local function dispatchStreamRequest(request)
908
+ local function dispatchStreamRequest(request, context)
909
909
  if request.logicalSessionId ~= PluginSession.id then
910
910
  return ClientBroker.dispatchClientRequest(request.logicalSessionId, request.target, request.endpoint, request.data)
911
911
  end
@@ -922,7 +922,7 @@ local function dispatchStreamRequest(request)
922
922
  return processRequest({
923
923
  endpoint = request.endpoint,
924
924
  data = request.data,
925
- })
925
+ }, context)
926
926
  end
927
927
  local function handleReady(response)
928
928
  local conn = State.getActiveConnection()
@@ -1154,6 +1154,81 @@ return {
1154
1154
  </Properties>
1155
1155
  </Item>
1156
1156
  <Item class="ModuleScript" referent="5">
1157
+ <Properties>
1158
+ <string name="Name">CooperativeJobRunner</string>
1159
+ <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
1160
+ local DEADLINE_EXCEEDED = "__RSMCP_COOPERATIVE_JOB_DEADLINE_EXCEEDED__"
1161
+ local CANCELLED = "__RSMCP_COOPERATIVE_JOB_CANCELLED__"
1162
+ local MAX_SLICE_SECONDS = 0.008
1163
+ local CLOCK_CHECK_INTERVAL = 64
1164
+ local activeJobs = {}
1165
+ local function runExclusive(key, execution, work)
1166
+ local _key = key
1167
+ local activeRequestId = activeJobs[_key]
1168
+ if activeRequestId ~= nil then
1169
+ return {
1170
+ error = "plugin_busy",
1171
+ activeRequestId = activeRequestId,
1172
+ }
1173
+ end
1174
+ local _key_1 = key
1175
+ local _requestId = execution.requestId
1176
+ activeJobs[_key_1] = _requestId
1177
+ local sliceStartedAt = os.clock()
1178
+ local operationsUntilClockCheck = 0
1179
+ local control = {
1180
+ checkpoint = function(self)
1181
+ local _result = execution.isCancelled
1182
+ if _result ~= nil then
1183
+ _result = _result()
1184
+ end
1185
+ if _result then
1186
+ error(CANCELLED, 0)
1187
+ end
1188
+ if operationsUntilClockCheck > 0 then
1189
+ operationsUntilClockCheck -= 1
1190
+ return nil
1191
+ end
1192
+ operationsUntilClockCheck = CLOCK_CHECK_INTERVAL - 1
1193
+ local now = os.clock()
1194
+ if execution.deadlineAt ~= nil and now >= execution.deadlineAt then
1195
+ error(DEADLINE_EXCEEDED, 0)
1196
+ end
1197
+ if now - sliceStartedAt >= MAX_SLICE_SECONDS then
1198
+ task.wait()
1199
+ sliceStartedAt = os.clock()
1200
+ end
1201
+ end,
1202
+ }
1203
+ local ok, result = pcall(function()
1204
+ return work(control)
1205
+ end)
1206
+ local _key_2 = key
1207
+ activeJobs[_key_2] = nil
1208
+ if not ok then
1209
+ if result == DEADLINE_EXCEEDED then
1210
+ return {
1211
+ error = "deadline_exceeded",
1212
+ requestId = execution.requestId,
1213
+ }
1214
+ end
1215
+ if result == CANCELLED then
1216
+ return {
1217
+ error = "cancelled",
1218
+ requestId = execution.requestId,
1219
+ }
1220
+ end
1221
+ error(result, 0)
1222
+ end
1223
+ return result
1224
+ end
1225
+ return {
1226
+ runExclusive = runExclusive,
1227
+ }
1228
+ ]]></string>
1229
+ </Properties>
1230
+ </Item>
1231
+ <Item class="ModuleScript" referent="6">
1157
1232
  <Properties>
1158
1233
  <string name="Name">EvalBridges</string>
1159
1234
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -1273,9 +1348,9 @@ local function computeBridgeStamp()
1273
1348
  for i = 1, #combined do
1274
1349
  h = (h * 33 + (string.byte(combined, i))) % 2147483647
1275
1350
  end
1276
- -- "3.0.3" is replaced with the package version at package time
1351
+ -- "3.0.4" is replaced with the package version at package time
1277
1352
  -- (scripts/build-plugin.mjs injectVersion), so a release bump also restamps.
1278
- return `{tostring(h)}-3.0.3`
1353
+ return `{tostring(h)}-3.0.4`
1279
1354
  end
1280
1355
  local BRIDGE_STAMP = computeBridgeStamp()
1281
1356
  local function setSource(scriptInst, source)
@@ -1428,11 +1503,11 @@ return {
1428
1503
  ]]></string>
1429
1504
  </Properties>
1430
1505
  </Item>
1431
- <Item class="Folder" referent="6">
1506
+ <Item class="Folder" referent="7">
1432
1507
  <Properties>
1433
1508
  <string name="Name">handlers</string>
1434
1509
  </Properties>
1435
- <Item class="ModuleScript" referent="7">
1510
+ <Item class="ModuleScript" referent="8">
1436
1511
  <Properties>
1437
1512
  <string name="Name">AssetHandlers</string>
1438
1513
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -1873,7 +1948,7 @@ return {
1873
1948
  ]]></string>
1874
1949
  </Properties>
1875
1950
  </Item>
1876
- <Item class="ModuleScript" referent="8">
1951
+ <Item class="ModuleScript" referent="9">
1877
1952
  <Properties>
1878
1953
  <string name="Name">BreakpointHandlers</string>
1879
1954
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -2391,7 +2466,7 @@ return {
2391
2466
  ]]></string>
2392
2467
  </Properties>
2393
2468
  </Item>
2394
- <Item class="ModuleScript" referent="9">
2469
+ <Item class="ModuleScript" referent="10">
2395
2470
  <Properties>
2396
2471
  <string name="Name">CaptureHandlers</string>
2397
2472
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -2635,7 +2710,7 @@ return {
2635
2710
  ]]></string>
2636
2711
  </Properties>
2637
2712
  </Item>
2638
- <Item class="ModuleScript" referent="10">
2713
+ <Item class="ModuleScript" referent="11">
2639
2714
  <Properties>
2640
2715
  <string name="Name">EvalRuntimeHandlers</string>
2641
2716
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -2789,7 +2864,7 @@ return {
2789
2864
  ]]></string>
2790
2865
  </Properties>
2791
2866
  </Item>
2792
- <Item class="ModuleScript" referent="11">
2867
+ <Item class="ModuleScript" referent="12">
2793
2868
  <Properties>
2794
2869
  <string name="Name">GenerateModelHandlers</string>
2795
2870
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -2994,7 +3069,7 @@ return {
2994
3069
  ]]></string>
2995
3070
  </Properties>
2996
3071
  </Item>
2997
- <Item class="ModuleScript" referent="12">
3072
+ <Item class="ModuleScript" referent="13">
2998
3073
  <Properties>
2999
3074
  <string name="Name">InputHandlers</string>
3000
3075
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -3194,7 +3269,7 @@ return {
3194
3269
  ]]></string>
3195
3270
  </Properties>
3196
3271
  </Item>
3197
- <Item class="ModuleScript" referent="13">
3272
+ <Item class="ModuleScript" referent="14">
3198
3273
  <Properties>
3199
3274
  <string name="Name">LogHandlers</string>
3200
3275
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -3220,7 +3295,7 @@ return {
3220
3295
  ]]></string>
3221
3296
  </Properties>
3222
3297
  </Item>
3223
- <Item class="ModuleScript" referent="14">
3298
+ <Item class="ModuleScript" referent="15">
3224
3299
  <Properties>
3225
3300
  <string name="Name">MemoryHandlers</string>
3226
3301
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -3288,7 +3363,7 @@ return {
3288
3363
  ]]></string>
3289
3364
  </Properties>
3290
3365
  </Item>
3291
- <Item class="ModuleScript" referent="15">
3366
+ <Item class="ModuleScript" referent="16">
3292
3367
  <Properties>
3293
3368
  <string name="Name">MetadataHandlers</string>
3294
3369
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -3619,7 +3694,7 @@ return {
3619
3694
  ]]></string>
3620
3695
  </Properties>
3621
3696
  </Item>
3622
- <Item class="ModuleScript" referent="16">
3697
+ <Item class="ModuleScript" referent="17">
3623
3698
  <Properties>
3624
3699
  <string name="Name">MicroProfilerHandlers</string>
3625
3700
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -5372,7 +5447,7 @@ return {
5372
5447
  ]]></string>
5373
5448
  </Properties>
5374
5449
  </Item>
5375
- <Item class="ModuleScript" referent="17">
5450
+ <Item class="ModuleScript" referent="18">
5376
5451
  <Properties>
5377
5452
  <string name="Name">PropertyHandlers</string>
5378
5453
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -5457,12 +5532,14 @@ return {
5457
5532
  ]]></string>
5458
5533
  </Properties>
5459
5534
  </Item>
5460
- <Item class="ModuleScript" referent="18">
5535
+ <Item class="ModuleScript" referent="19">
5461
5536
  <Properties>
5462
5537
  <string name="Name">QueryHandlers</string>
5463
5538
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
5464
5539
  local TS = require(script.Parent.Parent.Parent.include.RuntimeLib)
5465
5540
  local Utils = TS.import(script, script.Parent.Parent, "Utils")
5541
+ local CooperativeJobRunner = TS.import(script, script.Parent.Parent, "CooperativeJobRunner")
5542
+ local ScriptSearch = TS.import(script, script.Parent.Parent, "ScriptSearch")
5466
5543
  local _binding = Utils
5467
5544
  local getInstancePath = _binding.getInstancePath
5468
5545
  local getInstanceByPath = _binding.getInstanceByPath
@@ -6055,265 +6132,46 @@ local function getProjectStructure(requestData)
6055
6132
  result.timestamp = tick()
6056
6133
  return result
6057
6134
  end
6058
- -- Split a Lua pattern on TOP-LEVEL "|" into alternatives. Lua patterns have no
6059
- -- alternation operator, so "foo|bar" would otherwise be matched as the literal
6060
- -- text "foo|bar" and silently never hit. "%|" stays a literal pipe, and "%bxy"
6061
- -- keeps both balanced-match delimiter characters.
6062
- local function splitLuaAlternation(pattern)
6063
- local parts = {}
6064
- local current = ""
6065
- local i = 1
6066
- local n = #pattern
6067
- local inCharClass = false
6068
- while i <= n do
6069
- local c = string.sub(pattern, i, i)
6070
- if c == "%" then
6071
- if string.sub(pattern, i + 1, i + 1) == "b" then
6072
- current ..= string.sub(pattern, i, math.min(i + 3, n))
6073
- i += 4
6074
- continue
6075
- end
6076
- -- Preserve an escape pair (e.g. %|, %., %d) intact.
6077
- current ..= string.sub(pattern, i, i + 1)
6078
- i += 2
6079
- elseif c == "[" then
6080
- inCharClass = true
6081
- current ..= c
6082
- i += 1
6083
- elseif c == "]" then
6084
- inCharClass = false
6085
- current ..= c
6086
- i += 1
6087
- elseif c == "|" and not inCharClass then
6088
- local _current = current
6089
- table.insert(parts, _current)
6090
- current = ""
6091
- i += 1
6092
- else
6093
- current ..= c
6094
- i += 1
6095
- end
6096
- end
6097
- local _current = current
6098
- table.insert(parts, _current)
6099
- return parts
6100
- end
6101
- -- Return the earliest match across alternatives (mirrors regex alternation).
6102
- local function findFirstPattern(line, alternatives)
6103
- local bestStart
6104
- local bestEnd
6105
- for _, alt in alternatives do
6106
- if alt == "" then
6107
- continue
6108
- end
6109
- local s, e = string.find(line, alt)
6110
- if s ~= nil and (bestStart == nil or s < bestStart) then
6111
- bestStart = s
6112
- bestEnd = e
6135
+ local scriptSearch = ScriptSearch.createScriptSearch({
6136
+ resolveRoot = function(self, path)
6137
+ return getInstanceByPath(path)
6138
+ end,
6139
+ getChildren = function(self, instance)
6140
+ return instance:GetChildren()
6141
+ end,
6142
+ readScript = function(self, instance, classFilter)
6143
+ if not instance:IsA("LuaSourceContainer") or (classFilter ~= nil and instance.ClassName ~= classFilter) then
6144
+ return nil
6113
6145
  end
6114
- end
6115
- return { bestStart, bestEnd }
6116
- end
6117
- local function grepScripts(requestData)
6118
- local pattern = requestData.pattern
6119
- if not (pattern ~= "" and pattern) then
6120
- return {
6121
- error = "pattern is required",
6122
- }
6123
- end
6124
- local _condition = (requestData.usePattern)
6125
- if _condition == nil then
6126
- _condition = false
6127
- end
6128
- local usePattern = _condition
6129
- if usePattern and requestData.caseSensitive == false then
6130
- return {
6131
- error = "Case-insensitive Lua pattern search is not supported. Omit caseSensitive or pass caseSensitive: true with usePattern: true, or use literal search.",
6146
+ local snapshot = {
6147
+ instancePath = getInstancePath(instance),
6148
+ name = instance.Name,
6149
+ className = instance.ClassName,
6150
+ source = readScriptSource(instance),
6132
6151
  }
6133
- end
6134
- local _result
6135
- if usePattern then
6136
- _result = true
6137
- else
6138
- local _condition_1 = (requestData.caseSensitive)
6139
- if _condition_1 == nil then
6140
- _condition_1 = false
6152
+ if instance:IsA("BaseScript") then
6153
+ snapshot.enabled = instance.Enabled
6141
6154
  end
6142
- _result = _condition_1
6143
- end
6144
- local caseSensitive = _result
6145
- local _condition_1 = (requestData.contextLines)
6146
- if _condition_1 == nil then
6147
- _condition_1 = 0
6148
- end
6149
- local contextLines = _condition_1
6150
- local _condition_2 = (requestData.maxResults)
6151
- if _condition_2 == nil then
6152
- _condition_2 = 100
6153
- end
6154
- local maxResults = _condition_2
6155
- local _condition_3 = (requestData.maxResultsPerScript)
6156
- if _condition_3 == nil then
6157
- _condition_3 = 0
6158
- end
6159
- local maxResultsPerScript = _condition_3
6160
- local _condition_4 = (requestData.filesOnly)
6161
- if _condition_4 == nil then
6162
- _condition_4 = false
6163
- end
6164
- local filesOnly = _condition_4
6165
- local _condition_5 = (requestData.path)
6166
- if _condition_5 == nil then
6167
- _condition_5 = ""
6168
- end
6169
- local searchPath = _condition_5
6170
- local classFilter = requestData.classFilter
6171
- local startInstance = if searchPath ~= "" then getInstanceByPath(searchPath) else game
6172
- if not startInstance then
6173
- return {
6174
- error = `Path not found: {searchPath}`,
6175
- }
6155
+ return snapshot
6156
+ end,
6157
+ })
6158
+ local function grepScripts(requestData, execution)
6159
+ local result = CooperativeJobRunner.runExclusive("script-source-search", execution, function(control)
6160
+ return scriptSearch.search(requestData, control)
6161
+ end)
6162
+ if result.error == "plugin_busy" then
6163
+ local _object = table.clone(result)
6164
+ setmetatable(_object, nil)
6165
+ _object.message = "Another grep_scripts request is already running in this Studio DataModel. Retry after it completes."
6166
+ return _object
6176
6167
  end
6177
- -- Prepare pattern for matching
6178
- local searchPattern = if caseSensitive then pattern else string.lower(pattern)
6179
- -- Pre-split top-level "|" alternation once (pattern mode only).
6180
- local patternAlternatives = if usePattern then splitLuaAlternation(searchPattern) else nil
6181
- local results = {}
6182
- local totalMatches = 0
6183
- local scriptsSearched = 0
6184
- local hitLimit = false
6185
- local function searchInstance(instance)
6186
- if hitLimit then
6187
- return nil
6188
- end
6189
- if instance:IsA("LuaSourceContainer") then
6190
- -- Apply class filter
6191
- if classFilter ~= "" and classFilter then
6192
- local _exp = string.lower(instance.ClassName)
6193
- local _arg0 = string.lower(classFilter)
6194
- local _value = (string.find(_exp, _arg0))
6195
- if not (_value ~= 0 and _value == _value and _value) then
6196
- return nil
6197
- end
6198
- end
6199
- scriptsSearched += 1
6200
- local source = readScriptSource(instance)
6201
- local lines = Utils.splitLines(source)
6202
- local scriptMatches = {}
6203
- local scriptMatchCount = 0
6204
- for i = 0, #lines - 1 do
6205
- if hitLimit then
6206
- break
6207
- end
6208
- if maxResultsPerScript > 0 and scriptMatchCount >= maxResultsPerScript then
6209
- break
6210
- end
6211
- local line = lines[i + 1]
6212
- local searchLine = if caseSensitive then line else string.lower(line)
6213
- local matchStart
6214
- local matchEnd
6215
- if usePattern then
6216
- local _binding_1 = findFirstPattern(searchLine, patternAlternatives)
6217
- matchStart = _binding_1[1]
6218
- matchEnd = _binding_1[2]
6219
- else
6220
- matchStart, matchEnd = string.find(searchLine, searchPattern, 1, true)
6221
- end
6222
- if matchStart ~= nil then
6223
- scriptMatchCount += 1
6224
- totalMatches += 1
6225
- if totalMatches > maxResults then
6226
- hitLimit = true
6227
- break
6228
- end
6229
- if not filesOnly then
6230
- -- Gather context lines
6231
- local before = {}
6232
- local after = {}
6233
- if contextLines > 0 then
6234
- local beforeStart = math.max(0, i - contextLines)
6235
- do
6236
- local j = beforeStart
6237
- local _shouldIncrement = false
6238
- while true do
6239
- if _shouldIncrement then
6240
- j += 1
6241
- else
6242
- _shouldIncrement = true
6243
- end
6244
- if not (j < i) then
6245
- break
6246
- end
6247
- local _arg0 = lines[j + 1]
6248
- table.insert(before, _arg0)
6249
- end
6250
- end
6251
- local afterEnd = math.min(#lines - 1, i + contextLines)
6252
- do
6253
- local j = i + 1
6254
- local _shouldIncrement = false
6255
- while true do
6256
- if _shouldIncrement then
6257
- j += 1
6258
- else
6259
- _shouldIncrement = true
6260
- end
6261
- if not (j <= afterEnd) then
6262
- break
6263
- end
6264
- local _arg0 = lines[j + 1]
6265
- table.insert(after, _arg0)
6266
- end
6267
- end
6268
- end
6269
- local _arg0 = {
6270
- line = i + 1,
6271
- column = matchStart,
6272
- text = line,
6273
- before = before,
6274
- after = after,
6275
- }
6276
- table.insert(scriptMatches, _arg0)
6277
- end
6278
- end
6279
- end
6280
- if scriptMatchCount > 0 then
6281
- local scriptResult = {
6282
- instancePath = getInstancePath(instance),
6283
- name = instance.Name,
6284
- className = instance.ClassName,
6285
- matches = scriptMatches,
6286
- }
6287
- if instance:IsA("BaseScript") then
6288
- scriptResult.enabled = instance.Enabled
6289
- end
6290
- table.insert(results, scriptResult)
6291
- end
6292
- end
6293
- for _, child in instance:GetChildren() do
6294
- if hitLimit then
6295
- return nil
6296
- end
6297
- searchInstance(child)
6298
- end
6168
+ if result.error == "deadline_exceeded" then
6169
+ local _object = table.clone(result)
6170
+ setmetatable(_object, nil)
6171
+ _object.message = "grep_scripts exceeded its bridge deadline before the scan completed."
6172
+ return _object
6299
6173
  end
6300
- searchInstance(startInstance)
6301
- return {
6302
- results = results,
6303
- pattern = pattern,
6304
- totalMatches = if hitLimit then `>{maxResults}` else totalMatches,
6305
- scriptsSearched = scriptsSearched,
6306
- scriptsMatched = #results,
6307
- truncated = hitLimit,
6308
- options = {
6309
- caseSensitive = caseSensitive,
6310
- contextLines = contextLines,
6311
- usePattern = usePattern,
6312
- filesOnly = filesOnly,
6313
- maxResults = maxResults,
6314
- maxResultsPerScript = maxResultsPerScript,
6315
- },
6316
- }
6174
+ return result
6317
6175
  end
6318
6176
  return {
6319
6177
  getFileTree = getFileTree,
@@ -6329,7 +6187,7 @@ return {
6329
6187
  ]]></string>
6330
6188
  </Properties>
6331
6189
  </Item>
6332
- <Item class="ModuleScript" referent="19">
6190
+ <Item class="ModuleScript" referent="20">
6333
6191
  <Properties>
6334
6192
  <string name="Name">SceneAnalysisHandlers</string>
6335
6193
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -6578,7 +6436,7 @@ return {
6578
6436
  ]]></string>
6579
6437
  </Properties>
6580
6438
  </Item>
6581
- <Item class="ModuleScript" referent="20">
6439
+ <Item class="ModuleScript" referent="21">
6582
6440
  <Properties>
6583
6441
  <string name="Name">ScriptHandlers</string>
6584
6442
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -7250,7 +7108,7 @@ return {
7250
7108
  ]]></string>
7251
7109
  </Properties>
7252
7110
  </Item>
7253
- <Item class="ModuleScript" referent="21">
7111
+ <Item class="ModuleScript" referent="22">
7254
7112
  <Properties>
7255
7113
  <string name="Name">ScriptProfilerHandlers</string>
7256
7114
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -7713,7 +7571,7 @@ return {
7713
7571
  ]]></string>
7714
7572
  </Properties>
7715
7573
  </Item>
7716
- <Item class="ModuleScript" referent="22">
7574
+ <Item class="ModuleScript" referent="23">
7717
7575
  <Properties>
7718
7576
  <string name="Name">SerializationHandlers</string>
7719
7577
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -7899,7 +7757,7 @@ return {
7899
7757
  ]]></string>
7900
7758
  </Properties>
7901
7759
  </Item>
7902
- <Item class="ModuleScript" referent="23">
7760
+ <Item class="ModuleScript" referent="24">
7903
7761
  <Properties>
7904
7762
  <string name="Name">TestHandlers</string>
7905
7763
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -8278,7 +8136,7 @@ return {
8278
8136
  </Properties>
8279
8137
  </Item>
8280
8138
  </Item>
8281
- <Item class="ModuleScript" referent="24">
8139
+ <Item class="ModuleScript" referent="25">
8282
8140
  <Properties>
8283
8141
  <string name="Name">HttpDiagnostics</string>
8284
8142
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -8359,7 +8217,7 @@ return {
8359
8217
  ]]></string>
8360
8218
  </Properties>
8361
8219
  </Item>
8362
- <Item class="ModuleScript" referent="25">
8220
+ <Item class="ModuleScript" referent="26">
8363
8221
  <Properties>
8364
8222
  <string name="Name">LuauExec</string>
8365
8223
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -8793,7 +8651,7 @@ return {
8793
8651
  ]]></string>
8794
8652
  </Properties>
8795
8653
  </Item>
8796
- <Item class="ModuleScript" referent="26">
8654
+ <Item class="ModuleScript" referent="27">
8797
8655
  <Properties>
8798
8656
  <string name="Name">PluginSession</string>
8799
8657
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -8885,7 +8743,7 @@ return {
8885
8743
  ]]></string>
8886
8744
  </Properties>
8887
8745
  </Item>
8888
- <Item class="ModuleScript" referent="27">
8746
+ <Item class="ModuleScript" referent="28">
8889
8747
  <Properties>
8890
8748
  <string name="Name">Recording</string>
8891
8749
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -8915,7 +8773,7 @@ return {
8915
8773
  ]]></string>
8916
8774
  </Properties>
8917
8775
  </Item>
8918
- <Item class="ModuleScript" referent="28">
8776
+ <Item class="ModuleScript" referent="29">
8919
8777
  <Properties>
8920
8778
  <string name="Name">RenderMonitor</string>
8921
8779
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -8983,7 +8841,7 @@ return {
8983
8841
  ]]></string>
8984
8842
  </Properties>
8985
8843
  </Item>
8986
- <Item class="ModuleScript" referent="29">
8844
+ <Item class="ModuleScript" referent="30">
8987
8845
  <Properties>
8988
8846
  <string name="Name">RuntimeLogBuffer</string>
8989
8847
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -9238,7 +9096,334 @@ return {
9238
9096
  ]]></string>
9239
9097
  </Properties>
9240
9098
  </Item>
9241
- <Item class="ModuleScript" referent="30">
9099
+ <Item class="ModuleScript" referent="31">
9100
+ <Properties>
9101
+ <string name="Name">ScriptSearch</string>
9102
+ <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
9103
+ local function splitLuaAlternation(pattern)
9104
+ local parts = {}
9105
+ local current = ""
9106
+ local index = 1
9107
+ local inCharacterClass = false
9108
+ while index <= #pattern do
9109
+ local character = string.sub(pattern, index, index)
9110
+ if character == "%" then
9111
+ if string.sub(pattern, index + 1, index + 1) == "b" then
9112
+ current ..= string.sub(pattern, index, math.min(index + 3, #pattern))
9113
+ index += 4
9114
+ else
9115
+ current ..= string.sub(pattern, index, index + 1)
9116
+ index += 2
9117
+ end
9118
+ elseif character == "[" then
9119
+ inCharacterClass = true
9120
+ current ..= character
9121
+ index += 1
9122
+ elseif character == "]" then
9123
+ inCharacterClass = false
9124
+ current ..= character
9125
+ index += 1
9126
+ elseif character == "|" and not inCharacterClass then
9127
+ local _current = current
9128
+ table.insert(parts, _current)
9129
+ current = ""
9130
+ index += 1
9131
+ else
9132
+ current ..= character
9133
+ index += 1
9134
+ end
9135
+ end
9136
+ local _current = current
9137
+ table.insert(parts, _current)
9138
+ return parts
9139
+ end
9140
+ local function findFirstPattern(line, alternatives, control)
9141
+ local earliest
9142
+ for _, alternative in alternatives do
9143
+ control:checkpoint()
9144
+ if alternative == "" then
9145
+ continue
9146
+ end
9147
+ local start = string.find(line, alternative)
9148
+ if start ~= nil and (earliest == nil or start < earliest) then
9149
+ earliest = start
9150
+ end
9151
+ end
9152
+ return earliest
9153
+ end
9154
+ local function readLine(source, start)
9155
+ local boundary = string.find(source, "[\r\n]", start)
9156
+ if boundary == nil then
9157
+ return { string.sub(source, start), nil }
9158
+ end
9159
+ local nextStart = boundary + 1
9160
+ if string.sub(source, boundary, boundary) == "\r" and string.sub(source, nextStart, nextStart) == "\n" then
9161
+ nextStart += 1
9162
+ end
9163
+ return { string.sub(source, start, boundary - 1), if nextStart <= #source then nextStart else nil }
9164
+ end
9165
+ local MAX_RESULTS = 10_000
9166
+ local LITERAL_CHUNK_BYTES = 64 * 1024
9167
+ local MAX_PATTERN_BYTES = 4096
9168
+ local MAX_CONTEXT_LINES = 100
9169
+ local function sourceCanMatchLiteral(source, pattern, caseSensitive, control)
9170
+ if #source == 0 then
9171
+ return false
9172
+ end
9173
+ local overlapBytes = math.max(#pattern - 1, 0)
9174
+ local chunkStart = 1
9175
+ while chunkStart <= #source do
9176
+ control:checkpoint()
9177
+ local chunkEnd = math.min(#source, chunkStart + LITERAL_CHUNK_BYTES + overlapBytes - 1)
9178
+ local chunk = string.sub(source, chunkStart, chunkEnd)
9179
+ local candidate = if caseSensitive then chunk else string.lower(chunk)
9180
+ if (string.find(candidate, pattern, 1, true)) ~= nil then
9181
+ return true
9182
+ end
9183
+ if chunkEnd >= #source then
9184
+ return false
9185
+ end
9186
+ chunkStart += LITERAL_CHUNK_BYTES
9187
+ end
9188
+ return false
9189
+ end
9190
+ local function createScriptSearch(corpus)
9191
+ local function search(requestData, control)
9192
+ local requestedPattern = requestData.pattern
9193
+ if not (type(requestedPattern) == "string") or requestedPattern == "" then
9194
+ return {
9195
+ error = "pattern is required",
9196
+ }
9197
+ end
9198
+ if #requestedPattern > MAX_PATTERN_BYTES then
9199
+ return {
9200
+ error = "invalid_request",
9201
+ message = `pattern must contain between 1 and {MAX_PATTERN_BYTES} bytes`,
9202
+ }
9203
+ end
9204
+ local pattern = requestedPattern
9205
+ for _, optionName in { "usePattern", "caseSensitive", "filesOnly" } do
9206
+ local option = requestData[optionName]
9207
+ if option ~= nil and not (type(option) == "boolean") then
9208
+ return {
9209
+ error = "invalid_request",
9210
+ message = `{optionName} must be a boolean`,
9211
+ }
9212
+ end
9213
+ end
9214
+ local _condition = (requestData.usePattern)
9215
+ if _condition == nil then
9216
+ _condition = false
9217
+ end
9218
+ local usePattern = _condition
9219
+ if usePattern and requestData.caseSensitive == false then
9220
+ return {
9221
+ error = "Case-insensitive Lua pattern search is not supported.",
9222
+ }
9223
+ end
9224
+ local _result
9225
+ if usePattern then
9226
+ _result = true
9227
+ else
9228
+ local _condition_1 = (requestData.caseSensitive)
9229
+ if _condition_1 == nil then
9230
+ _condition_1 = false
9231
+ end
9232
+ _result = _condition_1
9233
+ end
9234
+ local caseSensitive = _result
9235
+ local _condition_1 = (requestData.filesOnly)
9236
+ if _condition_1 == nil then
9237
+ _condition_1 = false
9238
+ end
9239
+ local filesOnly = _condition_1
9240
+ local requestedContextLines = requestData.contextLines
9241
+ if requestedContextLines ~= nil and (not (type(requestedContextLines) == "number") or math.floor(requestedContextLines) ~= requestedContextLines or requestedContextLines < 0 or requestedContextLines > MAX_CONTEXT_LINES) then
9242
+ return {
9243
+ error = "invalid_request",
9244
+ message = `contextLines must be an integer between 0 and {MAX_CONTEXT_LINES}`,
9245
+ }
9246
+ end
9247
+ local _condition_2 = requestedContextLines
9248
+ if _condition_2 == nil then
9249
+ _condition_2 = 0
9250
+ end
9251
+ local contextLines = _condition_2
9252
+ local requestedMaxResults = requestData.maxResults
9253
+ if requestedMaxResults ~= nil and (not (type(requestedMaxResults) == "number") or math.floor(requestedMaxResults) ~= requestedMaxResults or requestedMaxResults < 1 or requestedMaxResults > MAX_RESULTS) then
9254
+ return {
9255
+ error = "invalid_request",
9256
+ message = `maxResults must be an integer between 1 and {MAX_RESULTS}`,
9257
+ }
9258
+ end
9259
+ local _condition_3 = requestedMaxResults
9260
+ if _condition_3 == nil then
9261
+ _condition_3 = 100
9262
+ end
9263
+ local maxResults = _condition_3
9264
+ local requestedMaxResultsPerScript = requestData.maxResultsPerScript
9265
+ if requestedMaxResultsPerScript ~= nil and (not (type(requestedMaxResultsPerScript) == "number") or math.floor(requestedMaxResultsPerScript) ~= requestedMaxResultsPerScript or requestedMaxResultsPerScript < 0 or requestedMaxResultsPerScript > MAX_RESULTS) then
9266
+ return {
9267
+ error = "invalid_request",
9268
+ message = `maxResultsPerScript must be an integer between 0 and {MAX_RESULTS}`,
9269
+ }
9270
+ end
9271
+ local _condition_4 = requestedMaxResultsPerScript
9272
+ if _condition_4 == nil then
9273
+ _condition_4 = 0
9274
+ end
9275
+ local maxResultsPerScript = _condition_4
9276
+ local classFilter = requestData.classFilter
9277
+ local _condition_5 = (requestData.path)
9278
+ if _condition_5 == nil then
9279
+ _condition_5 = ""
9280
+ end
9281
+ local searchPath = _condition_5
9282
+ local root = corpus:resolveRoot(searchPath)
9283
+ if root == nil then
9284
+ return {
9285
+ error = `Path not found: {searchPath}`,
9286
+ }
9287
+ end
9288
+ local searchPattern = if caseSensitive then pattern else string.lower(pattern)
9289
+ local patternAlternatives = if usePattern then splitLuaAlternation(searchPattern) else nil
9290
+ local results = {}
9291
+ local stack = { root }
9292
+ local totalMatches = 0
9293
+ local scriptsSearched = 0
9294
+ local hitLimit = false
9295
+ while #stack > 0 and not hitLimit do
9296
+ control:checkpoint()
9297
+ -- ▼ Array.pop ▼
9298
+ local _length = #stack
9299
+ local _result_1 = stack[_length]
9300
+ stack[_length] = nil
9301
+ -- ▲ Array.pop ▲
9302
+ local instance = _result_1
9303
+ local snapshot = corpus:readScript(instance, classFilter)
9304
+ if snapshot ~= nil and (classFilter == nil or snapshot.className == classFilter) then
9305
+ scriptsSearched += 1
9306
+ local scriptMatches = {}
9307
+ local before = {}
9308
+ local pendingAfter = {}
9309
+ local scriptMatchCount = 0
9310
+ local lineNumber = 1
9311
+ local lineStart = 1
9312
+ local canMatch = usePattern or sourceCanMatchLiteral(snapshot.source, searchPattern, caseSensitive, control)
9313
+ if canMatch then
9314
+ while lineStart ~= nil and not hitLimit do
9315
+ control:checkpoint()
9316
+ local _binding = readLine(snapshot.source, lineStart)
9317
+ local line = _binding[1]
9318
+ local nextLineStart = _binding[2]
9319
+ for _, pending in pendingAfter do
9320
+ if pending.remaining > 0 then
9321
+ local _exp = pending.match.after
9322
+ table.insert(_exp, line)
9323
+ pending.remaining -= 1
9324
+ end
9325
+ end
9326
+ while #pendingAfter > 0 and pendingAfter[1].remaining == 0 do
9327
+ table.remove(pendingAfter, 1)
9328
+ end
9329
+ local candidate = if caseSensitive then line else string.lower(line)
9330
+ local matchStart = if usePattern then findFirstPattern(candidate, patternAlternatives, control) else (string.find(candidate, searchPattern, 1, true))
9331
+ if matchStart ~= nil and (maxResultsPerScript == 0 or scriptMatchCount < maxResultsPerScript) then
9332
+ scriptMatchCount += 1
9333
+ totalMatches += 1
9334
+ if totalMatches > maxResults then
9335
+ hitLimit = true
9336
+ break
9337
+ end
9338
+ if not filesOnly then
9339
+ local _object = {
9340
+ line = lineNumber,
9341
+ column = matchStart,
9342
+ text = line,
9343
+ }
9344
+ local _left = "before"
9345
+ local _array = {}
9346
+ local _length_1 = #_array
9347
+ table.move(before, 1, #before, _length_1 + 1, _array)
9348
+ _object[_left] = _array
9349
+ _object.after = {}
9350
+ local lineMatch = _object
9351
+ table.insert(scriptMatches, lineMatch)
9352
+ if contextLines > 0 then
9353
+ local _arg0 = {
9354
+ match = lineMatch,
9355
+ remaining = contextLines,
9356
+ }
9357
+ table.insert(pendingAfter, _arg0)
9358
+ end
9359
+ end
9360
+ end
9361
+ if maxResultsPerScript > 0 and scriptMatchCount >= maxResultsPerScript and #pendingAfter == 0 then
9362
+ break
9363
+ end
9364
+ if contextLines > 0 then
9365
+ table.insert(before, line)
9366
+ while #before > contextLines do
9367
+ table.remove(before, 1)
9368
+ end
9369
+ end
9370
+ lineStart = nextLineStart
9371
+ if nextLineStart == nil then
9372
+ break
9373
+ end
9374
+ lineNumber += 1
9375
+ end
9376
+ end
9377
+ if scriptMatchCount > 0 then
9378
+ local scriptResult = {
9379
+ instancePath = snapshot.instancePath,
9380
+ name = snapshot.name,
9381
+ className = snapshot.className,
9382
+ matches = scriptMatches,
9383
+ }
9384
+ if snapshot.enabled ~= nil then
9385
+ scriptResult.enabled = snapshot.enabled
9386
+ end
9387
+ table.insert(results, scriptResult)
9388
+ end
9389
+ end
9390
+ local children = {}
9391
+ for _, child in corpus:getChildren(instance) do
9392
+ table.insert(children, child)
9393
+ end
9394
+ for index = #children - 1, 0, -1 do
9395
+ local _arg0 = children[index + 1]
9396
+ table.insert(stack, _arg0)
9397
+ end
9398
+ end
9399
+ return {
9400
+ results = results,
9401
+ pattern = pattern,
9402
+ totalMatches = if hitLimit then `>{maxResults}` else totalMatches,
9403
+ scriptsSearched = scriptsSearched,
9404
+ scriptsMatched = #results,
9405
+ truncated = hitLimit,
9406
+ options = {
9407
+ caseSensitive = caseSensitive,
9408
+ contextLines = contextLines,
9409
+ usePattern = usePattern,
9410
+ filesOnly = filesOnly,
9411
+ maxResults = maxResults,
9412
+ maxResultsPerScript = maxResultsPerScript,
9413
+ },
9414
+ }
9415
+ end
9416
+ return {
9417
+ search = search,
9418
+ }
9419
+ end
9420
+ return {
9421
+ createScriptSearch = createScriptSearch,
9422
+ }
9423
+ ]]></string>
9424
+ </Properties>
9425
+ </Item>
9426
+ <Item class="ModuleScript" referent="32">
9242
9427
  <Properties>
9243
9428
  <string name="Name">ServerUrlSettings</string>
9244
9429
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -9377,11 +9562,11 @@ return {
9377
9562
  ]]></string>
9378
9563
  </Properties>
9379
9564
  </Item>
9380
- <Item class="ModuleScript" referent="31">
9565
+ <Item class="ModuleScript" referent="33">
9381
9566
  <Properties>
9382
9567
  <string name="Name">State</string>
9383
9568
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
9384
- local CURRENT_VERSION = "3.0.3"
9569
+ local CURRENT_VERSION = "3.0.4"
9385
9570
  local PLUGIN_VARIANT = "main"
9386
9571
  local BASE_PORT = 58741
9387
9572
  local function createConnection(port)
@@ -9411,7 +9596,7 @@ return {
9411
9596
  ]]></string>
9412
9597
  </Properties>
9413
9598
  </Item>
9414
- <Item class="ModuleScript" referent="32">
9599
+ <Item class="ModuleScript" referent="34">
9415
9600
  <Properties>
9416
9601
  <string name="Name">StopPlayMonitor</string>
9417
9602
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -9702,7 +9887,7 @@ return {
9702
9887
  ]]></string>
9703
9888
  </Properties>
9704
9889
  </Item>
9705
- <Item class="ModuleScript" referent="33">
9890
+ <Item class="ModuleScript" referent="35">
9706
9891
  <Properties>
9707
9892
  <string name="Name">StudioEventStream</string>
9708
9893
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -9723,7 +9908,7 @@ local reconnectAttempt = 0
9723
9908
  local streamClient
9724
9909
  local streamConnections = {}
9725
9910
  local lastValidEventAt = 0
9726
- local inFlightRequestIds = {}
9911
+ local inFlightRequests = {}
9727
9912
  local pendingResponses = {}
9728
9913
  local terminalResponseIds = {}
9729
9914
  local terminalResponseOrder = {}
@@ -9780,6 +9965,21 @@ local function decodeMessage(message)
9780
9965
  _object[_left_2] = if type(_pluginVariant) == "string" then envelope.pluginVariant else nil
9781
9966
  return _object
9782
9967
  end
9968
+ if envelope.kind == "cancel" then
9969
+ local _requestId = envelope.requestId
9970
+ local _condition = not (type(_requestId) == "string")
9971
+ if not _condition then
9972
+ _condition = (envelope.reason ~= "timeout" and envelope.reason ~= "aborted" and envelope.reason ~= "connection_closed")
9973
+ end
9974
+ if _condition then
9975
+ return nil
9976
+ end
9977
+ return {
9978
+ kind = "cancel",
9979
+ requestId = envelope.requestId,
9980
+ reason = envelope.reason,
9981
+ }
9982
+ end
9783
9983
  if envelope.kind == "request" then
9784
9984
  local _requestId = envelope.requestId
9785
9985
  local _condition = not (type(_requestId) == "string")
@@ -9792,6 +9992,13 @@ local function decodeMessage(message)
9792
9992
  if not _condition then
9793
9993
  local _endpoint = envelope.endpoint
9794
9994
  _condition = not (type(_endpoint) == "string")
9995
+ if not _condition then
9996
+ local _remainingMs = envelope.remainingMs
9997
+ _condition = not (type(_remainingMs) == "number")
9998
+ if not _condition then
9999
+ _condition = envelope.remainingMs < 0
10000
+ end
10001
+ end
9795
10002
  end
9796
10003
  end
9797
10004
  end
@@ -9810,6 +10017,7 @@ local function decodeMessage(message)
9810
10017
  target = envelope.target,
9811
10018
  endpoint = envelope.endpoint,
9812
10019
  data = data,
10020
+ remainingMs = envelope.remainingMs,
9813
10021
  }
9814
10022
  end
9815
10023
  return nil
@@ -9977,6 +10185,21 @@ local function encodeResponse(requestId, response)
9977
10185
  error = `Plugin response serialization failed: {tostring(encoded)}`,
9978
10186
  })
9979
10187
  end
10188
+ local function cancelRequest(event)
10189
+ local _requestId = event.requestId
10190
+ local inFlight = inFlightRequests[_requestId]
10191
+ if inFlight ~= nil then
10192
+ inFlight.cancelled = true
10193
+ end
10194
+ local _requestId_1 = event.requestId
10195
+ local pending = pendingResponses[_requestId_1]
10196
+ if pending ~= nil then
10197
+ pending.retryToken += 1
10198
+ local _requestId_2 = event.requestId
10199
+ pendingResponses[_requestId_2] = nil
10200
+ end
10201
+ rememberTerminalResponse(event.requestId)
10202
+ end
9980
10203
  local function dispatchRequest(request)
9981
10204
  local _requestId = request.requestId
9982
10205
  local _condition = terminalResponseIds[_requestId] ~= nil
@@ -9985,7 +10208,7 @@ local function dispatchRequest(request)
9985
10208
  _condition = pendingResponses[_requestId_1] ~= nil
9986
10209
  if not _condition then
9987
10210
  local _requestId_2 = request.requestId
9988
- _condition = inFlightRequestIds[_requestId_2] ~= nil
10211
+ _condition = inFlightRequests[_requestId_2] ~= nil
9989
10212
  end
9990
10213
  end
9991
10214
  if _condition then
@@ -9995,12 +10218,48 @@ local function dispatchRequest(request)
9995
10218
  if not active or dispatchOptions == nil then
9996
10219
  return nil
9997
10220
  end
10221
+ local inFlight = {
10222
+ cancelled = false,
10223
+ }
10224
+ local context = {
10225
+ requestId = request.requestId,
10226
+ deadlineAt = os.clock() + request.remainingMs / 1000,
10227
+ isCancelled = function()
10228
+ return inFlight.cancelled
10229
+ end,
10230
+ }
9998
10231
  local _requestId_1 = request.requestId
9999
- inFlightRequestIds[_requestId_1] = true
10232
+ inFlightRequests[_requestId_1] = inFlight
10000
10233
  task.spawn(function()
10234
+ local _condition_1 = inFlight.cancelled
10235
+ if not _condition_1 then
10236
+ local _requestId_2 = request.requestId
10237
+ _condition_1 = terminalResponseIds[_requestId_2] ~= nil
10238
+ end
10239
+ if _condition_1 then
10240
+ local _requestId_2 = request.requestId
10241
+ if inFlightRequests[_requestId_2] == inFlight then
10242
+ local _requestId_3 = request.requestId
10243
+ inFlightRequests[_requestId_3] = nil
10244
+ end
10245
+ return nil
10246
+ end
10001
10247
  local dispatchOk, response = pcall(function()
10002
- return dispatchOptions.dispatchRequest(request)
10248
+ return dispatchOptions.dispatchRequest(request, context)
10003
10249
  end)
10250
+ local _condition_2 = inFlight.cancelled
10251
+ if not _condition_2 then
10252
+ local _requestId_2 = request.requestId
10253
+ _condition_2 = terminalResponseIds[_requestId_2] ~= nil
10254
+ end
10255
+ if _condition_2 then
10256
+ local _requestId_2 = request.requestId
10257
+ if inFlightRequests[_requestId_2] == inFlight then
10258
+ local _requestId_3 = request.requestId
10259
+ inFlightRequests[_requestId_3] = nil
10260
+ end
10261
+ return nil
10262
+ end
10004
10263
  local responseData = if dispatchOk then response else {
10005
10264
  error = tostring(response),
10006
10265
  }
@@ -10013,7 +10272,7 @@ local function dispatchRequest(request)
10013
10272
  local _requestId_2 = request.requestId
10014
10273
  pendingResponses[_requestId_2] = entry
10015
10274
  local _requestId_3 = request.requestId
10016
- inFlightRequestIds[_requestId_3] = nil
10275
+ inFlightRequests[_requestId_3] = nil
10017
10276
  postPendingResponse(request.requestId, entry)
10018
10277
  end)
10019
10278
  end
@@ -10232,6 +10491,10 @@ function connect(expectedGeneration)
10232
10491
  end)
10233
10492
  return nil
10234
10493
  end
10494
+ if event.kind == "cancel" then
10495
+ cancelRequest(event)
10496
+ return nil
10497
+ end
10235
10498
  if event.kind == "request" then
10236
10499
  dispatchRequest(event)
10237
10500
  return nil
@@ -10285,6 +10548,11 @@ function stop()
10285
10548
  local currentOptions = options
10286
10549
  active = false
10287
10550
  generation += 1
10551
+ for _, inFlight in inFlightRequests do
10552
+ inFlight.cancelled = true
10553
+ end
10554
+ table.clear(inFlightRequests)
10555
+ table.clear(pendingResponses)
10288
10556
  closeCurrentStream()
10289
10557
  table.clear(readyFailureLogKeys)
10290
10558
  options = nil
@@ -10313,7 +10581,7 @@ return {
10313
10581
  ]]></string>
10314
10582
  </Properties>
10315
10583
  </Item>
10316
- <Item class="ModuleScript" referent="34">
10584
+ <Item class="ModuleScript" referent="36">
10317
10585
  <Properties>
10318
10586
  <string name="Name">UI</string>
10319
10587
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -10865,7 +11133,7 @@ return {
10865
11133
  ]]></string>
10866
11134
  </Properties>
10867
11135
  </Item>
10868
- <Item class="ModuleScript" referent="35">
11136
+ <Item class="ModuleScript" referent="37">
10869
11137
  <Properties>
10870
11138
  <string name="Name">Utils</string>
10871
11139
  <string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
@@ -11149,21 +11417,11 @@ local function splitLines(source)
11149
11417
  end
11150
11418
  local normalized = (string.gsub((string.gsub(_condition, "\r\n", "\n")), "\r", "\n"))
11151
11419
  local endsWithNewline = string.sub(normalized, -1) == "\n"
11152
- local lines = {}
11153
- local start = 1
11154
- while true do
11155
- local newlinePos = string.find(normalized, "\n", start, true)
11156
- if newlinePos ~= nil then
11157
- local _arg0 = string.sub(normalized, start, newlinePos - 1)
11158
- table.insert(lines, _arg0)
11159
- start = newlinePos + 1
11160
- else
11161
- local remainder = string.sub(normalized, start)
11162
- if remainder ~= "" or not endsWithNewline then
11163
- table.insert(lines, remainder)
11164
- end
11165
- break
11166
- end
11420
+ local lines = string.split(normalized, "\n")
11421
+ -- split() includes a final empty field for a trailing newline. Keep the
11422
+ -- existing splitLines contract, which tracks that newline separately.
11423
+ if endsWithNewline and lines[#lines] == "" then
11424
+ lines[#lines] = nil
11167
11425
  end
11168
11426
  if #lines == 0 then
11169
11427
  table.insert(lines, "")
@@ -11178,15 +11436,21 @@ local function joinLines(lines, hadTrailingNewline)
11178
11436
  return source
11179
11437
  end
11180
11438
  local function readScriptSource(instance)
11181
- local ok, result = pcall(function()
11439
+ local editorOk, editorSource = pcall(function()
11440
+ return ScriptEditorService:GetEditorSource(instance)
11441
+ end)
11442
+ if editorOk then
11443
+ return editorSource
11444
+ end
11445
+ local documentOk, documentSource = pcall(function()
11182
11446
  local doc = ScriptEditorService:FindScriptDocument(instance)
11183
11447
  if doc then
11184
11448
  return doc:GetText()
11185
11449
  end
11186
11450
  return nil
11187
11451
  end)
11188
- if ok and result ~= nil then
11189
- return result
11452
+ if documentOk and documentSource ~= nil then
11453
+ return documentSource
11190
11454
  end
11191
11455
  -- @rbxts/types does not expose PluginSecurity Source reads.
11192
11456
  local readableScript = instance
@@ -11710,11 +11974,11 @@ return {
11710
11974
  </Properties>
11711
11975
  </Item>
11712
11976
  </Item>
11713
- <Item class="Folder" referent="40">
11977
+ <Item class="Folder" referent="42">
11714
11978
  <Properties>
11715
11979
  <string name="Name">include</string>
11716
11980
  </Properties>
11717
- <Item class="ModuleScript" referent="36">
11981
+ <Item class="ModuleScript" referent="38">
11718
11982
  <Properties>
11719
11983
  <string name="Name">LibMP</string>
11720
11984
  <string name="Source"><![CDATA[-- =============================================================================
@@ -168098,7 +168362,7 @@ return LibMP
168098
168362
  ]]></string>
168099
168363
  </Properties>
168100
168364
  </Item>
168101
- <Item class="ModuleScript" referent="37">
168365
+ <Item class="ModuleScript" referent="39">
168102
168366
  <Properties>
168103
168367
  <string name="Name">Promise</string>
168104
168368
  <string name="Source"><![CDATA[--[[
@@ -170172,7 +170436,7 @@ return Promise
170172
170436
  ]]></string>
170173
170437
  </Properties>
170174
170438
  </Item>
170175
- <Item class="ModuleScript" referent="38">
170439
+ <Item class="ModuleScript" referent="40">
170176
170440
  <Properties>
170177
170441
  <string name="Name">RuntimeLib</string>
170178
170442
  <string name="Source"><![CDATA[local Promise = require(script.Parent.Promise)
@@ -170439,15 +170703,15 @@ return TS
170439
170703
  </Properties>
170440
170704
  </Item>
170441
170705
  </Item>
170442
- <Item class="Folder" referent="41">
170706
+ <Item class="Folder" referent="43">
170443
170707
  <Properties>
170444
170708
  <string name="Name">node_modules</string>
170445
170709
  </Properties>
170446
- <Item class="Folder" referent="42">
170710
+ <Item class="Folder" referent="44">
170447
170711
  <Properties>
170448
170712
  <string name="Name">@rbxts</string>
170449
170713
  </Properties>
170450
- <Item class="ModuleScript" referent="39">
170714
+ <Item class="ModuleScript" referent="41">
170451
170715
  <Properties>
170452
170716
  <string name="Name">services</string>
170453
170717
  <string name="Source"><![CDATA[return setmetatable({}, {