@el4cteo/rbx-studio-mcp 0.6.1 → 0.6.7
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/README.md +28 -2
- package/dist/bridge/console.js +182 -0
- package/dist/bridge/console.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/cloudassets.js +233 -0
- package/dist/lib/cloudassets.js.map +1 -0
- package/dist/lib/credentials.js +180 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/livedata.js +325 -0
- package/dist/lib/livedata.js.map +1 -0
- package/dist/lib/liveluau.js +83 -0
- package/dist/lib/liveluau.js.map +1 -0
- package/dist/lib/liveops.js +358 -0
- package/dist/lib/liveops.js.map +1 -0
- package/dist/lib/opencloud.js +235 -0
- package/dist/lib/opencloud.js.map +1 -0
- package/dist/tools/anim.js +159 -0
- package/dist/tools/anim.js.map +1 -0
- package/dist/tools/audio.js +96 -0
- package/dist/tools/audio.js.map +1 -0
- package/dist/tools/character.js +95 -5
- package/dist/tools/character.js.map +1 -1
- package/dist/tools/data.js +292 -0
- package/dist/tools/data.js.map +1 -0
- package/dist/tools/device.js +77 -7
- package/dist/tools/device.js.map +1 -1
- package/dist/tools/discover.js +80 -4
- package/dist/tools/discover.js.map +1 -1
- package/dist/tools/exec.js +96 -2
- package/dist/tools/exec.js.map +1 -1
- package/dist/tools/input.js +35 -9
- package/dist/tools/input.js.map +1 -1
- package/dist/tools/perf.js +74 -7
- package/dist/tools/perf.js.map +1 -1
- package/dist/tools/scripts.js +162 -6
- package/dist/tools/scripts.js.map +1 -1
- package/dist/tools/spatial.js +135 -0
- package/dist/tools/spatial.js.map +1 -0
- package/dist/tools/universe.js +177 -0
- package/dist/tools/universe.js.map +1 -0
- package/dist/tools/upload.js +294 -0
- package/dist/tools/upload.js.map +1 -0
- package/dist/tools/world.js +675 -51
- package/dist/tools/world.js.map +1 -1
- package/package.json +2 -2
- package/plugin/src/Commands.luau +31 -7
- package/plugin/src/Config.luau +65 -65
- package/plugin/src/Console.luau +1909 -1843
- package/plugin/src/Emulation.luau +172 -0
- package/plugin/src/Phrase.luau +816 -618
- package/plugin/src/Png.luau +8 -4
- package/plugin/src/Prompt.luau +965 -961
- package/plugin/src/Secret.luau +86 -0
- package/plugin/src/Serialize.luau +440 -8
- package/plugin/src/Undo.luau +94 -6
- package/plugin/src/handlers/Anim.luau +897 -0
- package/plugin/src/handlers/Assets.luau +286 -2
- package/plugin/src/handlers/Audio.luau +411 -0
- package/plugin/src/handlers/Capture.luau +155 -20
- package/plugin/src/handlers/Character.luau +823 -361
- package/plugin/src/handlers/Data.luau +539 -0
- package/plugin/src/handlers/Device.luau +394 -139
- package/plugin/src/handlers/Discover.luau +685 -363
- package/plugin/src/handlers/Geometry.luau +722 -450
- package/plugin/src/handlers/Instances.luau +84 -4
- package/plugin/src/handlers/Perf.luau +227 -0
- package/plugin/src/handlers/Scripts.luau +673 -539
- package/plugin/src/handlers/Session.luau +3 -0
- package/plugin/src/handlers/Spatial.luau +334 -0
- package/plugin/src/handlers/Viewport.luau +268 -0
- package/plugin/src/handlers/World.luau +89 -15
- package/plugin/src/init.server.luau +9 -1
- package/scripts/build-plugin.mjs +20 -0
- package/scripts/check-plugin.mjs +171 -124
package/plugin/src/Undo.luau
CHANGED
|
@@ -20,6 +20,75 @@ local ChangeHistoryService = game:GetService("ChangeHistoryService")
|
|
|
20
20
|
|
|
21
21
|
local Undo = {}
|
|
22
22
|
|
|
23
|
+
--[[
|
|
24
|
+
One recording at a time, per session.
|
|
25
|
+
|
|
26
|
+
`onCommand` runs every command on its own task so a slow handler cannot
|
|
27
|
+
stall the stream, which is right -- and it means two agents pointed at the
|
|
28
|
+
same edit session have their batches in flight at once. Nothing below this
|
|
29
|
+
line is safe under that. `TryBeginRecording` returns nil while another
|
|
30
|
+
recording is open, so the second batch would run with no recording of its
|
|
31
|
+
own: its changes land inside the FIRST batch's undo step, one Ctrl+Z reverts
|
|
32
|
+
both, and if the first batch fails its `Cancel` reverts the second agent's
|
|
33
|
+
work as well -- work that was already reported as done.
|
|
34
|
+
|
|
35
|
+
Today's handlers do not yield inside a recording, so Luau's cooperative
|
|
36
|
+
scheduling hides all of that. That is an accident of how they happen to be
|
|
37
|
+
written, not a property of the design: the first `*Async` call added inside
|
|
38
|
+
a `record` body would open the window silently, and the symptom would be a
|
|
39
|
+
rolled-back edit in someone else's session. So the guarantee is made
|
|
40
|
+
structural here instead of being left to every handler to preserve.
|
|
41
|
+
|
|
42
|
+
Mutations queue; reads never come through this file at all, so they stay
|
|
43
|
+
parallel. Uncontended -- the normal case, one agent -- this costs one
|
|
44
|
+
boolean test.
|
|
45
|
+
]]
|
|
46
|
+
local held = false
|
|
47
|
+
local owner: thread? = nil
|
|
48
|
+
local waiting: { thread } = {}
|
|
49
|
+
|
|
50
|
+
local function acquire()
|
|
51
|
+
--[[
|
|
52
|
+
A recording opened inside another recording is the same thread, and
|
|
53
|
+
waiting for a lock it already holds would hang the session outright.
|
|
54
|
+
Nesting is not used today; this makes adding it a coarser undo step
|
|
55
|
+
rather than a deadlock.
|
|
56
|
+
]]
|
|
57
|
+
if held and owner == coroutine.running() then
|
|
58
|
+
return false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if held then
|
|
62
|
+
table.insert(waiting, coroutine.running())
|
|
63
|
+
-- Resumed by `release`, which hands the lock over rather than dropping
|
|
64
|
+
-- it, so there is nothing to re-check on the way out.
|
|
65
|
+
coroutine.yield()
|
|
66
|
+
return true
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
held = true
|
|
70
|
+
owner = coroutine.running()
|
|
71
|
+
return true
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
local function release(acquired: boolean)
|
|
75
|
+
if not acquired then
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
local nextThread = table.remove(waiting, 1)
|
|
80
|
+
if nextThread == nil then
|
|
81
|
+
held = false
|
|
82
|
+
owner = nil
|
|
83
|
+
return
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
-- `held` deliberately stays true: the lock passes straight to the waiter,
|
|
87
|
+
-- so a command arriving in between cannot jump the queue.
|
|
88
|
+
owner = nextThread
|
|
89
|
+
task.spawn(nextThread)
|
|
90
|
+
end
|
|
91
|
+
|
|
23
92
|
--[[
|
|
24
93
|
Drops the redo entry a cancelled recording leaves behind.
|
|
25
94
|
|
|
@@ -52,10 +121,12 @@ end
|
|
|
52
121
|
Runs `body` inside a named recording. Returns its result, and whether a
|
|
53
122
|
recording was actually opened.
|
|
54
123
|
|
|
55
|
-
`TryBeginRecording` returns nil when
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
124
|
+
`TryBeginRecording` returns nil when a recording is already open or when
|
|
125
|
+
history is unavailable. Since the lock above, that can no longer be another
|
|
126
|
+
MCP batch: it is Studio's own, the user mid-drag in the viewport. The work
|
|
127
|
+
still runs in that case -- refusing to act would be worse than a slightly
|
|
128
|
+
coarser undo stack -- it simply joins the surrounding recording, and the lock
|
|
129
|
+
is still held throughout so the batch stays whole.
|
|
59
130
|
|
|
60
131
|
That second return value is not decoration. Whether an operation is undoable
|
|
61
132
|
is something tools tell the agent, and therefore the user, so it has to be
|
|
@@ -63,19 +134,28 @@ end
|
|
|
63
134
|
to no undo entry at all is worse than no claim.
|
|
64
135
|
]]
|
|
65
136
|
function Undo.record<T>(name: string, displayName: string, body: () -> T): (T, boolean)
|
|
137
|
+
local acquired = acquire()
|
|
138
|
+
|
|
66
139
|
local identifier = ChangeHistoryService:TryBeginRecording(name, displayName)
|
|
67
140
|
if not identifier then
|
|
68
|
-
|
|
141
|
+
local ok, result = pcall(body)
|
|
142
|
+
release(acquired)
|
|
143
|
+
if not ok then
|
|
144
|
+
error(result, 0)
|
|
145
|
+
end
|
|
146
|
+
return result, false
|
|
69
147
|
end
|
|
70
148
|
|
|
71
149
|
local ok, result = pcall(body)
|
|
72
150
|
if ok then
|
|
73
151
|
ChangeHistoryService:FinishRecording(identifier, Enum.FinishRecordingOperation.Commit)
|
|
152
|
+
release(acquired)
|
|
74
153
|
return result, true
|
|
75
154
|
end
|
|
76
155
|
|
|
77
156
|
ChangeHistoryService:FinishRecording(identifier, Enum.FinishRecordingOperation.Cancel)
|
|
78
157
|
dropRedo()
|
|
158
|
+
release(acquired)
|
|
79
159
|
error(result, 0)
|
|
80
160
|
end
|
|
81
161
|
|
|
@@ -85,13 +165,21 @@ end
|
|
|
85
165
|
and therefore tell the agent exactly what did and did not apply.
|
|
86
166
|
]]
|
|
87
167
|
function Undo.recordPartial<T>(name: string, displayName: string, body: () -> T): (T, boolean)
|
|
168
|
+
local acquired = acquire()
|
|
169
|
+
|
|
88
170
|
local identifier = ChangeHistoryService:TryBeginRecording(name, displayName)
|
|
89
171
|
if not identifier then
|
|
90
|
-
|
|
172
|
+
local ok, result = pcall(body)
|
|
173
|
+
release(acquired)
|
|
174
|
+
if not ok then
|
|
175
|
+
error(result, 0)
|
|
176
|
+
end
|
|
177
|
+
return result, false
|
|
91
178
|
end
|
|
92
179
|
|
|
93
180
|
local ok, result = pcall(body)
|
|
94
181
|
ChangeHistoryService:FinishRecording(identifier, Enum.FinishRecordingOperation.Commit)
|
|
182
|
+
release(acquired)
|
|
95
183
|
if not ok then
|
|
96
184
|
error(result, 0)
|
|
97
185
|
end
|