@el4cteo/rbx-studio-mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/bridge/rpc.js +243 -0
- package/dist/bridge/rpc.js.map +1 -0
- package/dist/bridge/server.js +281 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/apidump.js +269 -0
- package/dist/lib/apidump.js.map +1 -0
- package/dist/lib/errors.js +38 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/format.js +191 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/pluginbuild.js +83 -0
- package/dist/lib/pluginbuild.js.map +1 -0
- package/dist/lib/png.js +84 -0
- package/dist/lib/png.js.map +1 -0
- package/dist/lib/protocol.js +22 -0
- package/dist/lib/protocol.js.map +1 -0
- package/dist/lib/tool.js +27 -0
- package/dist/lib/tool.js.map +1 -0
- package/dist/resources.js +70 -0
- package/dist/resources.js.map +1 -0
- package/dist/tools/api.js +78 -0
- package/dist/tools/api.js.map +1 -0
- package/dist/tools/character.js +94 -0
- package/dist/tools/character.js.map +1 -0
- package/dist/tools/debug.js +211 -0
- package/dist/tools/debug.js.map +1 -0
- package/dist/tools/device.js +74 -0
- package/dist/tools/device.js.map +1 -0
- package/dist/tools/discover.js +217 -0
- package/dist/tools/discover.js.map +1 -0
- package/dist/tools/exec.js +191 -0
- package/dist/tools/exec.js.map +1 -0
- package/dist/tools/input.js +96 -0
- package/dist/tools/input.js.map +1 -0
- package/dist/tools/instances.js +261 -0
- package/dist/tools/instances.js.map +1 -0
- package/dist/tools/perf.js +367 -0
- package/dist/tools/perf.js.map +1 -0
- package/dist/tools/playtest.js +153 -0
- package/dist/tools/playtest.js.map +1 -0
- package/dist/tools/screenshot.js +75 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/scripts.js +316 -0
- package/dist/tools/scripts.js.map +1 -0
- package/dist/tools/session.js +152 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/world.js +281 -0
- package/dist/tools/world.js.map +1 -0
- package/package.json +62 -0
- package/plugin/default.project.json +6 -0
- package/plugin/src/Config.luau +59 -0
- package/plugin/src/Console.luau +657 -0
- package/plugin/src/Context.luau +35 -0
- package/plugin/src/Dispatch.luau +90 -0
- package/plugin/src/Editor.luau +142 -0
- package/plugin/src/Emulation.luau +151 -0
- package/plugin/src/LogBuffer.luau +277 -0
- package/plugin/src/Net.luau +102 -0
- package/plugin/src/Paths.luau +255 -0
- package/plugin/src/Phrase.luau +465 -0
- package/plugin/src/Png.luau +238 -0
- package/plugin/src/Scope.luau +78 -0
- package/plugin/src/ScriptEdit.luau +100 -0
- package/plugin/src/Serialize.luau +287 -0
- package/plugin/src/TextEdit.luau +296 -0
- package/plugin/src/Transport.luau +328 -0
- package/plugin/src/Undo.luau +72 -0
- package/plugin/src/Visuals.luau +710 -0
- package/plugin/src/handlers/Api.luau +242 -0
- package/plugin/src/handlers/Assets.luau +145 -0
- package/plugin/src/handlers/Capture.luau +187 -0
- package/plugin/src/handlers/Character.luau +361 -0
- package/plugin/src/handlers/Debug.luau +391 -0
- package/plugin/src/handlers/Device.luau +119 -0
- package/plugin/src/handlers/Discover.luau +289 -0
- package/plugin/src/handlers/Exec.luau +270 -0
- package/plugin/src/handlers/Geometry.luau +261 -0
- package/plugin/src/handlers/Input.luau +287 -0
- package/plugin/src/handlers/Instances.luau +389 -0
- package/plugin/src/handlers/Perf.luau +645 -0
- package/plugin/src/handlers/Playtest.luau +205 -0
- package/plugin/src/handlers/Scripts.luau +387 -0
- package/plugin/src/handlers/Session.luau +168 -0
- package/plugin/src/handlers/Viewport.luau +302 -0
- package/plugin/src/handlers/World.luau +176 -0
- package/plugin/src/init.server.luau +317 -0
- package/scripts/build-plugin.mjs +157 -0
- package/scripts/check-plugin.mjs +97 -0
- package/scripts/install-plugin.mjs +39 -0
- package/scripts/latency.mjs +201 -0
- package/scripts/locate-luau.mjs +51 -0
- package/scripts/sourcemap.mjs +58 -0
- package/scripts/test-plugin.mjs +82 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../../src/tools/perf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { json } from "../lib/format.js";
|
|
3
|
+
import { defineTool } from "../lib/tool.js";
|
|
4
|
+
/**
|
|
5
|
+
* The studioId of the running playtest's server session, or null.
|
|
6
|
+
*
|
|
7
|
+
* Prefers the cached context so the common case costs nothing, and asks the
|
|
8
|
+
* sessions directly when nothing is cached -- which is the situation right
|
|
9
|
+
* after this tool started a test, since the new session has never been queried
|
|
10
|
+
* and its context is exactly what the caller needs.
|
|
11
|
+
*/
|
|
12
|
+
async function findPlaytestSession(bridge) {
|
|
13
|
+
const sessions = bridge.list();
|
|
14
|
+
const cached = sessions.find((session) => session.context?.includes("playtest"));
|
|
15
|
+
if (cached)
|
|
16
|
+
return cached.studioId;
|
|
17
|
+
const unknown = sessions.filter((session) => session.context === undefined);
|
|
18
|
+
const probed = await Promise.all(unknown.map(async (session) => {
|
|
19
|
+
try {
|
|
20
|
+
const status = await bridge.call("studio.status", {}, { studioId: session.studioId, timeoutMs: 3_000 });
|
|
21
|
+
bridge.notePlaceName(session.studioId, status.placeName, status.context);
|
|
22
|
+
return status.context?.includes("playtest") ? session.studioId : null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
return probed.find((id) => id !== null) ?? null;
|
|
29
|
+
}
|
|
30
|
+
export function registerPlaytestTools(context) {
|
|
31
|
+
const { bridge } = context;
|
|
32
|
+
defineTool(context, {
|
|
33
|
+
name: "playtest",
|
|
34
|
+
title: "Run, pause and stop the simulation",
|
|
35
|
+
description: "Starts and stops playtests, so scripts can be made to run and then " +
|
|
36
|
+
"observed without asking the user to press anything.\n\n" +
|
|
37
|
+
"`play` is the Play button: a character spawns and `Players.PlayerAdded` " +
|
|
38
|
+
"fires. `run` is Run mode, which executes scripts with no player at all. " +
|
|
39
|
+
"`multiplayer` starts a test with several players for testing " +
|
|
40
|
+
"replication. `state` reports without changing anything.\n\n" +
|
|
41
|
+
"Pressing play adds a SECOND connected session for the playtest's server, " +
|
|
42
|
+
"and that is where the running game lives — `console`, `performance` and " +
|
|
43
|
+
"`execute_luau` must target its studioId, not the editor's. Call " +
|
|
44
|
+
"`list_studios` after starting and look for the entry whose context is a " +
|
|
45
|
+
"playtest.\n\n" +
|
|
46
|
+
"A test does not block this call: it starts and the reply reports the " +
|
|
47
|
+
"state reached. Studio only ends it when something inside calls " +
|
|
48
|
+
"`StudioTestService:EndTest(value)` or when `stop` is used here; whatever " +
|
|
49
|
+
"EndTest passed comes back as `lastResult` on a later `state`. That makes " +
|
|
50
|
+
"a scripted check possible end to end: `args` is readable inside the test " +
|
|
51
|
+
"via `StudioTestService:GetTestArgs()`, so a test can be told what to do " +
|
|
52
|
+
"and report back what happened.\n\n" +
|
|
53
|
+
"Stopping discards everything the playtest changed, exactly as pressing " +
|
|
54
|
+
"Stop does. Build in edit mode, then play — not the other way round.\n\n" +
|
|
55
|
+
"The reply says whether the mode actually moved, not merely that Studio " +
|
|
56
|
+
"accepted the request.",
|
|
57
|
+
inputSchema: {
|
|
58
|
+
op: z
|
|
59
|
+
.enum(["play", "run", "multiplayer", "stop", "state"])
|
|
60
|
+
.describe("'play' starts a playtest with a character, 'run' runs scripts with " +
|
|
61
|
+
"no player, 'multiplayer' starts a several-player test, 'stop' ends " +
|
|
62
|
+
"it and discards its changes, 'state' only reports."),
|
|
63
|
+
players: z
|
|
64
|
+
.number()
|
|
65
|
+
.int()
|
|
66
|
+
.min(1)
|
|
67
|
+
.max(8)
|
|
68
|
+
.default(2)
|
|
69
|
+
.describe("multiplayer only: how many players to start."),
|
|
70
|
+
args: z
|
|
71
|
+
.string()
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Value handed to the test, readable inside it with " +
|
|
74
|
+
"`StudioTestService:GetTestArgs()`. Use it to tell a test which " +
|
|
75
|
+
"case to exercise."),
|
|
76
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
77
|
+
},
|
|
78
|
+
readOnly: false,
|
|
79
|
+
destructive: true,
|
|
80
|
+
}, async (args) => {
|
|
81
|
+
//[[
|
|
82
|
+
// Stopping is routed rather than sent where it was asked.
|
|
83
|
+
//
|
|
84
|
+
// Starting a playtest creates a second session, which immediately makes
|
|
85
|
+
// every later call ambiguous -- including the stop for the test just
|
|
86
|
+
// started, so the tool could begin something it could not end. And the
|
|
87
|
+
// stop cannot be served by the editor session anyway: `LeaveTest` is
|
|
88
|
+
// client-DataModel only and a playtest client can never reach this
|
|
89
|
+
// bridge, so only `EndTest`, from the playtest's server session, ends a
|
|
90
|
+
// test. Both problems have the same answer: find that session.
|
|
91
|
+
//]]
|
|
92
|
+
if (args.op === "stop") {
|
|
93
|
+
const playtest = await findPlaytestSession(bridge);
|
|
94
|
+
if (playtest) {
|
|
95
|
+
//[[
|
|
96
|
+
// The stop is sent to the session it will destroy, so its reply is
|
|
97
|
+
// expected to go missing and a transport failure here says nothing
|
|
98
|
+
// about whether the test ended. The answer comes from the editor
|
|
99
|
+
// session, which survives — and which is also the only session that
|
|
100
|
+
// holds the value EndTest passed back.
|
|
101
|
+
//]]
|
|
102
|
+
await bridge
|
|
103
|
+
.call("playtest.control", { op: "endTest", value: args.args }, {
|
|
104
|
+
studioId: playtest,
|
|
105
|
+
timeoutMs: 10_000,
|
|
106
|
+
})
|
|
107
|
+
.catch(() => null);
|
|
108
|
+
const survivor = bridge.list().find((session) => session.studioId !== playtest);
|
|
109
|
+
if (survivor) {
|
|
110
|
+
//[[
|
|
111
|
+
// Waited for, not sampled. The teardown is deliberately deferred so
|
|
112
|
+
// the reply can leave first, and tearing a DataModel down is not
|
|
113
|
+
// instant either — so a single read taken straight afterwards
|
|
114
|
+
// reports a test still running that is already on its way out. That
|
|
115
|
+
// is the same false report as before, just pointing the other way.
|
|
116
|
+
//]]
|
|
117
|
+
const deadline = Date.now() + 10_000;
|
|
118
|
+
let after;
|
|
119
|
+
for (;;) {
|
|
120
|
+
after = await bridge.call("playtest.control", { op: "state" }, { studioId: survivor.studioId, timeoutMs: 10_000 });
|
|
121
|
+
const settled = after.state.editModeActive !== false && !after.state.testPending;
|
|
122
|
+
if (settled || Date.now() >= deadline)
|
|
123
|
+
break;
|
|
124
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
125
|
+
}
|
|
126
|
+
const stopped = after.state.editModeActive !== false && !after.state.testPending;
|
|
127
|
+
return json(after.state, stopped
|
|
128
|
+
? undefined
|
|
129
|
+
: "The stop was sent but Studio is still in a test. Check whether " +
|
|
130
|
+
"something inside it is holding the session open.");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const response = await bridge.call("playtest.control", { op: args.op, players: args.players, args: args.args }, { studioId: args.studioId, timeoutMs: 30_000 });
|
|
135
|
+
const notes = [];
|
|
136
|
+
if (args.op !== "state" && !response.changed) {
|
|
137
|
+
notes.push(response.reason ?? "Studio accepted the call but nothing changed.");
|
|
138
|
+
}
|
|
139
|
+
else if (response.reason) {
|
|
140
|
+
notes.push(response.reason);
|
|
141
|
+
}
|
|
142
|
+
// The running game is a different session from the one just asked to start
|
|
143
|
+
// it, and every subsequent read has to go to that one instead. Said here
|
|
144
|
+
// because the alternative is an agent reading the editor's empty log and
|
|
145
|
+
// concluding the playtest did nothing.
|
|
146
|
+
if ((args.op === "play" || args.op === "multiplayer") && response.state.testPending) {
|
|
147
|
+
notes.push("The playtest runs in its own session. Call list_studios and target the " +
|
|
148
|
+
"entry whose context is a playtest for console, performance and execute_luau.");
|
|
149
|
+
}
|
|
150
|
+
return json(response.state, notes.length > 0 ? notes.join("\n") : undefined);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=playtest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playtest.js","sourceRoot":"","sources":["../../src/tools/playtest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { zstdDecompressSync } from "node:zlib";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { image } from "../lib/format.js";
|
|
4
|
+
import { encodePng } from "../lib/png.js";
|
|
5
|
+
import { defineTool } from "../lib/tool.js";
|
|
6
|
+
/**
|
|
7
|
+
* Turns whatever the plugin sent into base64 PNG.
|
|
8
|
+
*
|
|
9
|
+
* Two shapes arrive because the plugin cannot always produce the good one.
|
|
10
|
+
* Where `EncodingService` exists it sends Zstd-compressed raw RGB, and the PNG
|
|
11
|
+
* is built here with real deflate. Where it does not, it falls back to the
|
|
12
|
+
* hand-written Luau encoder, whose output is a valid PNG carrying uncompressed
|
|
13
|
+
* stored blocks — larger, but a picture either way.
|
|
14
|
+
*/
|
|
15
|
+
function toPngBase64(response) {
|
|
16
|
+
if (response.encoding !== "zstd-rgb") {
|
|
17
|
+
return response.data;
|
|
18
|
+
}
|
|
19
|
+
const rgb = zstdDecompressSync(Buffer.from(response.data, "base64"));
|
|
20
|
+
return encodePng(rgb, response.width, response.height).toString("base64");
|
|
21
|
+
}
|
|
22
|
+
export function registerScreenshotTools(context) {
|
|
23
|
+
const { bridge } = context;
|
|
24
|
+
defineTool(context, {
|
|
25
|
+
name: "screenshot",
|
|
26
|
+
title: "See the Studio viewport",
|
|
27
|
+
description: "Takes a picture of the Studio viewport and returns it as an image you " +
|
|
28
|
+
"can actually look at.\n\n" +
|
|
29
|
+
"Every other tool here reads the data model — names, properties, " +
|
|
30
|
+
"numbers — which answers 'is it there' but never 'does it look right'. " +
|
|
31
|
+
"A part can be at the correct position, anchored, correctly sized, and " +
|
|
32
|
+
"still be buried inside a wall, facing backwards, or hidden behind a " +
|
|
33
|
+
"GUI. Take a screenshot after building something visual, and before " +
|
|
34
|
+
"reporting that it worked.\n\n" +
|
|
35
|
+
"It captures the viewport as the user currently sees it, so it shows " +
|
|
36
|
+
"their camera angle, not a framing of your choosing. Frame the subject " +
|
|
37
|
+
"with `viewport op=\"focus\"` first — that is what makes this tool " +
|
|
38
|
+
"worth calling.\n\n" +
|
|
39
|
+
"NOT AVAILABLE WHILE A PLAYTEST IS RUNNING. Studio only lets a client " +
|
|
40
|
+
"session capture the screen, and it forbids client sessions from making " +
|
|
41
|
+
"HTTP requests, so no session that can be reached is allowed to take the " +
|
|
42
|
+
"picture: the playtest server refuses outright and the editor session " +
|
|
43
|
+
"times out, because the window is no longer rendering its data model. " +
|
|
44
|
+
"Stop the playtest and screenshot in edit mode, or read the running game " +
|
|
45
|
+
"through `character`, `console` and `find` instead.",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
width: z
|
|
48
|
+
.number()
|
|
49
|
+
.int()
|
|
50
|
+
.min(160)
|
|
51
|
+
.max(1600)
|
|
52
|
+
.default(800)
|
|
53
|
+
.describe("Width to scale the image down to, in pixels; height follows the " +
|
|
54
|
+
"viewport's aspect ratio. Larger is sharper and costs more — raise " +
|
|
55
|
+
"it only when you need to read small text."),
|
|
56
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
57
|
+
},
|
|
58
|
+
readOnly: true,
|
|
59
|
+
}, async (args) => {
|
|
60
|
+
const response = await bridge.call("capture.screenshot", { width: args.width },
|
|
61
|
+
// Capturing, reading the pixels back and encoding a PNG in Luau all
|
|
62
|
+
// happen before the reply, and none of them is instant on a big viewport.
|
|
63
|
+
{ studioId: args.studioId, timeoutMs: 60_000 });
|
|
64
|
+
const png = toPngBase64(response);
|
|
65
|
+
// The device is named in the caption rather than left to be inferred: an
|
|
66
|
+
// emulated phone makes every screenshot tall and narrow until it is
|
|
67
|
+
// switched off, and a caller who did not set it has no way to know why.
|
|
68
|
+
const emulating = response.device
|
|
69
|
+
? ` Emulating ${response.device} — call \`device op="stop"\` for the normal viewport.`
|
|
70
|
+
: "";
|
|
71
|
+
return image(png, `Studio viewport (${response.context}), ${response.width}x${response.height}` +
|
|
72
|
+
` scaled from ${response.sourceWidth}x${response.sourceHeight}.${emulating}`);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,EAAmB,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAoB,MAAM,gBAAgB,CAAC;AAiB9D;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,QAA4B;IAC/C,IAAI,QAAQ,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IACD,MAAM,GAAG,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACrE,OAAO,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAoB;IAC1D,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3B,UAAU,CACR,OAAO,EACP;QACE,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,yBAAyB;QAChC,WAAW,EACT,wEAAwE;YACxE,2BAA2B;YAC3B,kEAAkE;YAClE,wEAAwE;YACxE,wEAAwE;YACxE,sEAAsE;YACtE,qEAAqE;YACrE,+BAA+B;YAC/B,sEAAsE;YACtE,wEAAwE;YACxE,oEAAoE;YACpE,oBAAoB;YACpB,uEAAuE;YACvE,yEAAyE;YACzE,0EAA0E;YAC1E,uEAAuE;YACvE,uEAAuE;YACvE,0EAA0E;YAC1E,oDAAoD;QACtD,WAAW,EAAE;YACX,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,GAAG,CAAC;iBACR,GAAG,CAAC,IAAI,CAAC;iBACT,OAAO,CAAC,GAAG,CAAC;iBACZ,QAAQ,CACP,kEAAkE;gBAChE,oEAAoE;gBACpE,2CAA2C,CAC9C;YACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;SACpF;QACD,QAAQ,EAAE,IAAI;KACf,EACD,KAAK,EAAE,IAAI,EAAuB,EAAE;QAClC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAChC,oBAAoB,EACpB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;QACrB,oEAAoE;QACpE,0EAA0E;QAC1E,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAC/C,CAAC;QAEF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAElC,yEAAyE;QACzE,oEAAoE;QACpE,wEAAwE;QACxE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM;YAC/B,CAAC,CAAC,cAAc,QAAQ,CAAC,MAAM,uDAAuD;YACtF,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO,KAAK,CACV,GAAG,EACH,oBAAoB,QAAQ,CAAC,OAAO,MAAM,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE;YAC3E,gBAAgB,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,YAAY,IAAI,SAAS,EAAE,CAC/E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { body, cursorSchema, decodeCursor, encodeCursor, limitSchema, table, text, } from "../lib/format.js";
|
|
3
|
+
import { defineTool } from "../lib/tool.js";
|
|
4
|
+
/**
|
|
5
|
+
* Prefixes each line with its number, right-aligned to the widest one.
|
|
6
|
+
*
|
|
7
|
+
* The numbers are not decoration: `script_edit` addresses lines by these exact
|
|
8
|
+
* values, so an agent that reads a window can write back to it without counting
|
|
9
|
+
* newlines itself.
|
|
10
|
+
*/
|
|
11
|
+
function numbered(source, startLine) {
|
|
12
|
+
const lines = source.length === 0 ? [] : source.split("\n");
|
|
13
|
+
const width = String(startLine + lines.length - 1).length;
|
|
14
|
+
return lines
|
|
15
|
+
.map((line, index) => `${String(startLine + index).padStart(width)}│ ${line}`)
|
|
16
|
+
.join("\n");
|
|
17
|
+
}
|
|
18
|
+
export function registerScriptTools(context) {
|
|
19
|
+
const { bridge } = context;
|
|
20
|
+
defineTool(context, {
|
|
21
|
+
name: "script_read",
|
|
22
|
+
title: "Read scripts",
|
|
23
|
+
description: "Reads Luau source from one or more scripts, with line numbers that " +
|
|
24
|
+
"`script_edit` accepts back verbatim.\n\n" +
|
|
25
|
+
"Source comes from the Studio script editor's live buffer, so anything the " +
|
|
26
|
+
"user has typed but not yet saved is included. Reading the saved property " +
|
|
27
|
+
"instead would hand you stale code and you would 'fix' the change they just " +
|
|
28
|
+
"made.\n\n" +
|
|
29
|
+
"Pass every script you need in one call. `startLine`/`endLine` apply to all " +
|
|
30
|
+
"of them, so use them when following one range across several files and " +
|
|
31
|
+
"read whole files otherwise.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
paths: z
|
|
34
|
+
.array(z.string())
|
|
35
|
+
.min(1)
|
|
36
|
+
.max(20)
|
|
37
|
+
.describe('Script paths, e.g. ["ServerScriptService.Systems.Combat"].'),
|
|
38
|
+
startLine: z
|
|
39
|
+
.number()
|
|
40
|
+
.int()
|
|
41
|
+
.min(1)
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("First line to return, 1-based and inclusive. Omit to start at the top."),
|
|
44
|
+
endLine: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.min(1)
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("Last line to return, inclusive. Omit to read to the end."),
|
|
50
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
51
|
+
},
|
|
52
|
+
readOnly: true,
|
|
53
|
+
}, async (args) => {
|
|
54
|
+
const response = await bridge.call("script.read", { paths: args.paths, startLine: args.startLine, endLine: args.endLine }, { studioId: args.studioId });
|
|
55
|
+
const blocks = response.items.map((item) => {
|
|
56
|
+
const shown = item.source.length === 0 ? 0 : item.source.split("\n").length;
|
|
57
|
+
// An empty window means the requested range sits past the end of the
|
|
58
|
+
// file, or runs backwards. Reporting it as "lines 50-49 of 9" alongside
|
|
59
|
+
// no content reads as a broken tool rather than a bad argument.
|
|
60
|
+
if (shown === 0) {
|
|
61
|
+
if (item.lineCount === 0) {
|
|
62
|
+
return `${item.path} (${item.className}) is empty.`;
|
|
63
|
+
}
|
|
64
|
+
const asked = args.endLine !== undefined
|
|
65
|
+
? `Lines ${item.startLine}-${args.endLine}`
|
|
66
|
+
: `Line ${item.startLine} onwards`;
|
|
67
|
+
return (`${item.path} (${item.className}, ${item.lineCount} lines)\n` +
|
|
68
|
+
`${asked} is empty — the file ends at line ${item.lineCount}.`);
|
|
69
|
+
}
|
|
70
|
+
const range = shown === item.lineCount
|
|
71
|
+
? `${item.lineCount} lines`
|
|
72
|
+
: `lines ${item.startLine}-${item.startLine + shown - 1} of ${item.lineCount}`;
|
|
73
|
+
return `${item.path} (${item.className}, ${range})\n${numbered(item.source, item.startLine)}`;
|
|
74
|
+
});
|
|
75
|
+
if (response.failures.length > 0) {
|
|
76
|
+
blocks.push(`Could not read ${response.failures.length} path(s):\n` +
|
|
77
|
+
response.failures.map((failure) => ` - ${failure}`).join("\n"));
|
|
78
|
+
}
|
|
79
|
+
if (blocks.length === 0)
|
|
80
|
+
return text("No scripts read.");
|
|
81
|
+
return body(blocks.join("\n\n"), "read fewer scripts per call, or narrow with startLine/endLine");
|
|
82
|
+
});
|
|
83
|
+
defineTool(context, {
|
|
84
|
+
name: "script_edit",
|
|
85
|
+
title: "Edit scripts",
|
|
86
|
+
description: "Edits Luau source through the Studio script editor. This is the tool to " +
|
|
87
|
+
"use for any change to existing code.\n\n" +
|
|
88
|
+
"Every edit in one call is all-or-nothing: the whole batch is resolved " +
|
|
89
|
+
"against current source before anything is written, so if one edit cannot " +
|
|
90
|
+
"be applied nothing is. Batch related changes together, even across " +
|
|
91
|
+
"different scripts.\n\n" +
|
|
92
|
+
"Each edit picks exactly one mode:\n" +
|
|
93
|
+
" find/replace — literal text, not a pattern. Preferred: it survives line " +
|
|
94
|
+
"numbers shifting. Fails if the text is not unique, unless you set " +
|
|
95
|
+
"`replaceAll`, so include enough surrounding lines to pin it down.\n" +
|
|
96
|
+
" startLine/endLine + replacement — for line ranges from `script_read`. " +
|
|
97
|
+
"Numbers refer to the file as you read it; several line edits to one script " +
|
|
98
|
+
"are applied bottom-up so they do not shift each other.\n" +
|
|
99
|
+
" source — replaces the whole script. Only for small files or a rewrite; " +
|
|
100
|
+
"it discards anything the user changed since you read it.\n\n" +
|
|
101
|
+
"Writes go through `ScriptEditorService:UpdateSourceAsync`, so an open " +
|
|
102
|
+
"editor tab updates in place and unsaved work is preserved. Undo for " +
|
|
103
|
+
"source changes is the script editor's own, per script — Ctrl+Z in a " +
|
|
104
|
+
"script tab reverts that script, not the whole batch.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
edits: z
|
|
107
|
+
.array(z.object({
|
|
108
|
+
path: z
|
|
109
|
+
.string()
|
|
110
|
+
.describe('Script to edit, e.g. "ServerScriptService.Systems.Combat".'),
|
|
111
|
+
find: z
|
|
112
|
+
.string()
|
|
113
|
+
.optional()
|
|
114
|
+
.describe("Exact text to replace, whitespace included. Literal, not a regex " +
|
|
115
|
+
"or Lua pattern."),
|
|
116
|
+
replace: z
|
|
117
|
+
.string()
|
|
118
|
+
.optional()
|
|
119
|
+
.describe("Text to put in its place. Required with `find`; empty string deletes."),
|
|
120
|
+
replaceAll: z
|
|
121
|
+
.boolean()
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Replace every occurrence. Without this a non-unique `find` is " +
|
|
124
|
+
"refused rather than guessing which one you meant."),
|
|
125
|
+
startLine: z
|
|
126
|
+
.number()
|
|
127
|
+
.int()
|
|
128
|
+
.min(1)
|
|
129
|
+
.optional()
|
|
130
|
+
.describe("First line to replace, 1-based and inclusive."),
|
|
131
|
+
endLine: z
|
|
132
|
+
.number()
|
|
133
|
+
.int()
|
|
134
|
+
.min(0)
|
|
135
|
+
.optional()
|
|
136
|
+
.describe("Last line to replace, inclusive. Defaults to `startLine`. Set it " +
|
|
137
|
+
"one below `startLine` to insert without replacing anything."),
|
|
138
|
+
replacement: z
|
|
139
|
+
.string()
|
|
140
|
+
.optional()
|
|
141
|
+
.describe("New text for that line range. Required with `startLine`."),
|
|
142
|
+
source: z
|
|
143
|
+
.string()
|
|
144
|
+
.optional()
|
|
145
|
+
.describe("Complete new source for the script, replacing everything."),
|
|
146
|
+
}))
|
|
147
|
+
.min(1)
|
|
148
|
+
.max(50)
|
|
149
|
+
.describe("Edits to apply together as one undoable step."),
|
|
150
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
151
|
+
},
|
|
152
|
+
destructive: true,
|
|
153
|
+
}, async (args) => {
|
|
154
|
+
const response = await bridge.call("script.edit", { edits: args.edits }, { studioId: args.studioId, timeoutMs: 30_000 });
|
|
155
|
+
return table(["path", "className", "edits", "lineCount", "lineDelta"], response.items);
|
|
156
|
+
});
|
|
157
|
+
defineTool(context, {
|
|
158
|
+
name: "script_grep",
|
|
159
|
+
title: "Search script source",
|
|
160
|
+
description: "Searches inside Luau source across the place and returns matching lines " +
|
|
161
|
+
"with their paths and line numbers.\n\n" +
|
|
162
|
+
"Use this to find where something is defined or used before editing it — " +
|
|
163
|
+
"it is far cheaper than reading whole scripts to look for one call.\n\n" +
|
|
164
|
+
"Patterns are Lua patterns, which are not regular expressions: `%` escapes " +
|
|
165
|
+
"instead of backslash, there is no alternation, and `-` means a lazy " +
|
|
166
|
+
"quantifier. Set `literal` to search for text exactly as written, which is " +
|
|
167
|
+
"usually what you want for identifiers.\n\n" +
|
|
168
|
+
"Matches come from the script editor's live buffer, so unsaved edits are " +
|
|
169
|
+
"searched too.",
|
|
170
|
+
inputSchema: {
|
|
171
|
+
pattern: z
|
|
172
|
+
.string()
|
|
173
|
+
.describe('Lua pattern, or exact text when `literal` is set, e.g. "PlayerAdded".'),
|
|
174
|
+
path: z
|
|
175
|
+
.string()
|
|
176
|
+
.optional()
|
|
177
|
+
.describe('Limit to this subtree, e.g. "ServerScriptService". Omit to search everywhere.'),
|
|
178
|
+
literal: z
|
|
179
|
+
.boolean()
|
|
180
|
+
.default(false)
|
|
181
|
+
.describe("Treat `pattern` as plain text rather than a Lua pattern."),
|
|
182
|
+
ignoreCase: z
|
|
183
|
+
.boolean()
|
|
184
|
+
.default(false)
|
|
185
|
+
.describe("Case-insensitive. Both sides are lowercased, so pattern classes like " +
|
|
186
|
+
"%u stop being meaningful — combine with `literal`."),
|
|
187
|
+
contextLines: z
|
|
188
|
+
.number()
|
|
189
|
+
.int()
|
|
190
|
+
.min(0)
|
|
191
|
+
.max(10)
|
|
192
|
+
.default(0)
|
|
193
|
+
.describe("Lines of context to show either side of each match."),
|
|
194
|
+
className: z
|
|
195
|
+
.string()
|
|
196
|
+
.optional()
|
|
197
|
+
.describe('Restrict to one script class: "Script", "LocalScript" or "ModuleScript".'),
|
|
198
|
+
limit: limitSchema,
|
|
199
|
+
cursor: cursorSchema,
|
|
200
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
201
|
+
},
|
|
202
|
+
readOnly: true,
|
|
203
|
+
}, async (args) => {
|
|
204
|
+
const offset = decodeCursor(args.cursor);
|
|
205
|
+
const response = await bridge.call("script.grep", {
|
|
206
|
+
pattern: args.pattern,
|
|
207
|
+
path: args.path,
|
|
208
|
+
literal: args.literal,
|
|
209
|
+
ignoreCase: args.ignoreCase,
|
|
210
|
+
contextLines: args.contextLines,
|
|
211
|
+
className: args.className,
|
|
212
|
+
limit: args.limit,
|
|
213
|
+
offset,
|
|
214
|
+
}, { studioId: args.studioId, timeoutMs: 30_000 });
|
|
215
|
+
if (response.total === 0) {
|
|
216
|
+
if (response.searched === 0) {
|
|
217
|
+
return text(args.path
|
|
218
|
+
? `No scripts under "${args.path}" to search.`
|
|
219
|
+
: "This place contains no scripts.");
|
|
220
|
+
}
|
|
221
|
+
// Suggesting `literal` to someone who already set it reads as though the
|
|
222
|
+
// tool did not register the argument.
|
|
223
|
+
// `|` is called out by name because it is the one difference that fails
|
|
224
|
+
// silently. A regex habit writes `foo|bar`, Lua reads it as the literal
|
|
225
|
+
// characters, nothing matches, and the empty result looks like an
|
|
226
|
+
// answer rather than like a malformed pattern.
|
|
227
|
+
const alternation = !args.literal && args.pattern.includes("|");
|
|
228
|
+
return text(`No matches in ${response.searched} script(s).\n` +
|
|
229
|
+
(alternation
|
|
230
|
+
? "This pattern contains `|`, which Lua patterns do not support — " +
|
|
231
|
+
"there is no alternation, so `|` matched as a literal character. " +
|
|
232
|
+
"Search one alternative per call, or set `literal`."
|
|
233
|
+
: args.literal
|
|
234
|
+
? "The match is literal and case-sensitive unless you set `ignoreCase`."
|
|
235
|
+
: "Check case, and remember patterns are Lua patterns — set `literal` " +
|
|
236
|
+
"to search for the text exactly as written."));
|
|
237
|
+
}
|
|
238
|
+
const lines = [];
|
|
239
|
+
let previousPath = "";
|
|
240
|
+
for (const match of response.items) {
|
|
241
|
+
// Context blocks get a separator; a flat list of adjacent lines is
|
|
242
|
+
// otherwise impossible to tell apart from a run of separate matches.
|
|
243
|
+
if (match.path !== previousPath) {
|
|
244
|
+
if (previousPath !== "")
|
|
245
|
+
lines.push("");
|
|
246
|
+
previousPath = match.path;
|
|
247
|
+
}
|
|
248
|
+
for (const [index, before] of (match.before ?? []).entries()) {
|
|
249
|
+
lines.push(`${match.path}-${match.line - (match.before?.length ?? 0) + index}- ${before}`);
|
|
250
|
+
}
|
|
251
|
+
lines.push(`${match.path}:${match.line}: ${match.text}`);
|
|
252
|
+
for (const [index, after] of (match.after ?? []).entries()) {
|
|
253
|
+
lines.push(`${match.path}-${match.line + index + 1}- ${after}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const trailer = [`[searched ${response.searched} scripts]`];
|
|
257
|
+
const nextOffset = offset + response.items.length;
|
|
258
|
+
if (nextOffset < response.total) {
|
|
259
|
+
trailer.unshift(`[showing ${response.items.length} of ${response.total} matches — call again ` +
|
|
260
|
+
`with cursor: "${encodeCursor(nextOffset)}"]`);
|
|
261
|
+
}
|
|
262
|
+
return body([...lines, "", ...trailer].join("\n"), "re-run with a smaller `limit` or a narrower `path`");
|
|
263
|
+
});
|
|
264
|
+
defineTool(context, {
|
|
265
|
+
name: "script_create",
|
|
266
|
+
title: "Create scripts",
|
|
267
|
+
description: "Creates Script, LocalScript or ModuleScript instances with their source.\n\n" +
|
|
268
|
+
"Batch related scripts into one call: they are created inside one " +
|
|
269
|
+
"ChangeHistoryService recording, so the user can drop a whole generated " +
|
|
270
|
+
"system in a single undo. The response says whether that recording was " +
|
|
271
|
+
"actually opened — Studio refuses while another one is in progress.\n\n" +
|
|
272
|
+
"Prefer `Script` with `runContext: \"Client\"` over `LocalScript` in new " +
|
|
273
|
+
"work — a Script with an explicit RunContext runs wherever you parent it, " +
|
|
274
|
+
"while LocalScript only runs under a player's character, backpack or " +
|
|
275
|
+
"PlayerGui. Use `script_edit` to change a script that already exists.",
|
|
276
|
+
inputSchema: {
|
|
277
|
+
scripts: z
|
|
278
|
+
.array(z.object({
|
|
279
|
+
parent: z
|
|
280
|
+
.string()
|
|
281
|
+
.describe('Path of the parent instance, e.g. "ServerScriptService.Systems".'),
|
|
282
|
+
name: z.string().describe("Name for the new script."),
|
|
283
|
+
className: z
|
|
284
|
+
.enum(["Script", "LocalScript", "ModuleScript"])
|
|
285
|
+
.describe("Which kind of script to create."),
|
|
286
|
+
source: z
|
|
287
|
+
.string()
|
|
288
|
+
.optional()
|
|
289
|
+
.describe("Initial Luau source. Omit for Roblox's default stub."),
|
|
290
|
+
runContext: z
|
|
291
|
+
.enum(["Legacy", "Server", "Client"])
|
|
292
|
+
.optional()
|
|
293
|
+
.describe("Where a `Script` runs. 'Legacy' means server-only and only under " +
|
|
294
|
+
"a server container. Ignored for the other classes."),
|
|
295
|
+
disabled: z
|
|
296
|
+
.boolean()
|
|
297
|
+
.optional()
|
|
298
|
+
.describe("Create it disabled, so it does not run on the next playtest."),
|
|
299
|
+
}))
|
|
300
|
+
.min(1)
|
|
301
|
+
.max(50)
|
|
302
|
+
.describe("Scripts to create together as one undoable step."),
|
|
303
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
304
|
+
},
|
|
305
|
+
}, async (args) => {
|
|
306
|
+
const response = await bridge.call("script.create", { scripts: args.scripts }, { studioId: args.studioId });
|
|
307
|
+
return table(["path", "className"], response.items, {
|
|
308
|
+
more: response.undoStep
|
|
309
|
+
? `undoable as one step, "${response.undoStep}" — Ctrl+Z with focus ` +
|
|
310
|
+
"outside the script editor"
|
|
311
|
+
: "Studio would not open an undo recording, so this is not undoable " +
|
|
312
|
+
"as a single step",
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/tools/scripts.ts"],"names":[],"mappings":"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"}
|