@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":"debug.js","sourceRoot":"","sources":["../../src/tools/debug.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { json, table, text } from "../lib/format.js";
|
|
3
|
+
import { defineTool } from "../lib/tool.js";
|
|
4
|
+
export function registerDeviceTools(context) {
|
|
5
|
+
const { bridge } = context;
|
|
6
|
+
defineTool(context, {
|
|
7
|
+
name: "device",
|
|
8
|
+
title: "Emulate a phone, tablet or console",
|
|
9
|
+
description: "Resizes the Studio viewport to a real device, so you can see what a " +
|
|
10
|
+
"player on that device sees.\n\n" +
|
|
11
|
+
"Most Roblox players are on a phone and most UI is built on a desktop " +
|
|
12
|
+
"monitor, which is where interfaces break: a button under the notch, a " +
|
|
13
|
+
"menu off the bottom of a 393-pixel-tall screen, text sized for a " +
|
|
14
|
+
"display three times larger. None of that is visible in the data model " +
|
|
15
|
+
"— every one of those instances has perfectly correct properties — so " +
|
|
16
|
+
"this is the only way to find it short of owning the hardware.\n\n" +
|
|
17
|
+
"The workflow is: `set` a device, `screenshot`, look. Pair it with " +
|
|
18
|
+
"`playtest` to check a running game's HUD rather than the editor.\n\n" +
|
|
19
|
+
"`list` gives the ids, each with its real name, form factor and " +
|
|
20
|
+
"resolution — ids look like \"iphone_16\", \"ipad_a16\", " +
|
|
21
|
+
"\"samsung_galaxy_s25_ultra\", \"xbox\", \"meta_quest_3\".\n\n" +
|
|
22
|
+
"`stop` returns Studio to the normal editor viewport. Do that when you " +
|
|
23
|
+
"are finished: a left-over emulated device makes every later screenshot " +
|
|
24
|
+
"the wrong shape, and nothing on screen obviously says why.",
|
|
25
|
+
inputSchema: {
|
|
26
|
+
op: z
|
|
27
|
+
.enum(["list", "set", "stop", "state"])
|
|
28
|
+
.default("state")
|
|
29
|
+
.describe("'list' shows the available devices, 'set' switches to one, 'stop' " +
|
|
30
|
+
"returns to the normal viewport, 'state' only reports."),
|
|
31
|
+
device: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('set only: the device id, e.g. "iphone_16". See `list`.'),
|
|
35
|
+
orientation: z
|
|
36
|
+
.enum(["LandscapeLeft", "LandscapeRight", "Portrait", "Sensor"])
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("set only: which way up. Portrait is worth testing separately — " +
|
|
39
|
+
"most mobile players hold the phone upright and most UI is only " +
|
|
40
|
+
"ever checked in landscape."),
|
|
41
|
+
form: z
|
|
42
|
+
.enum(["Phone", "Tablet", "Console", "Desktop", "VR"])
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("list only: show only devices of this form factor."),
|
|
45
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
46
|
+
},
|
|
47
|
+
readOnly: false,
|
|
48
|
+
destructive: false,
|
|
49
|
+
}, async (args) => {
|
|
50
|
+
if (args.op === "list") {
|
|
51
|
+
const response = await bridge.call("device.list", {},
|
|
52
|
+
// One GetDeviceInfoAsync per device, and there are around forty.
|
|
53
|
+
{ studioId: args.studioId, timeoutMs: 45_000 });
|
|
54
|
+
const rows = response.devices.filter((entry) => args.form === undefined || entry.form === args.form);
|
|
55
|
+
if (rows.length === 0) {
|
|
56
|
+
return text(`No ${args.form} devices are available. Studio offers ${response.count} in total; ` +
|
|
57
|
+
"call again without `form` to see them.");
|
|
58
|
+
}
|
|
59
|
+
return table(["id", "name", "form", "resolution"], rows, {
|
|
60
|
+
more: `${rows.length} of ${response.count} devices; ` +
|
|
61
|
+
`currently ${JSON.stringify(response.current["device"] ?? "default")}`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (args.op === "set" && (args.device === undefined || args.device === "")) {
|
|
65
|
+
return text('set needs a `device` id. Call `device op="list"` to see them.');
|
|
66
|
+
}
|
|
67
|
+
const command = args.op === "set" ? "device.set" : args.op === "stop" ? "device.stop" : "device.state";
|
|
68
|
+
const response = await bridge.call(command, { device: args.device, orientation: args.orientation }, { studioId: args.studioId, timeoutMs: 30_000 });
|
|
69
|
+
return json(response, args.op === "set"
|
|
70
|
+
? "Take a `screenshot` to see it. Call `device op=\"stop\"` when finished, or every later screenshot stays this shape."
|
|
71
|
+
: undefined);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/tools/device.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { propertiesOf, standardProperties } from "../lib/apidump.js";
|
|
3
|
+
import { cursorSchema, decodeCursor, detailSchema, encodeCursor, json, limitSchema, table, text, } from "../lib/format.js";
|
|
4
|
+
import { defineTool } from "../lib/tool.js";
|
|
5
|
+
/**
|
|
6
|
+
* Renders a hierarchy page as a table. `concise` drops the child count, which
|
|
7
|
+
* is the only column a pure scan does not need.
|
|
8
|
+
*/
|
|
9
|
+
function pageOf(response, detail, more) {
|
|
10
|
+
const columns = detail === "concise" ? ["path", "className"] : ["path", "className", "childCount"];
|
|
11
|
+
const nextOffset = response.offset + response.items.length;
|
|
12
|
+
return table(columns, response.items, {
|
|
13
|
+
total: response.total,
|
|
14
|
+
...(nextOffset < response.total ? { nextCursor: encodeCursor(nextOffset) } : {}),
|
|
15
|
+
...(more ? { more } : {}),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Sorts property and attribute keys alphabetically.
|
|
20
|
+
*
|
|
21
|
+
* Luau table iteration order is unspecified, so the same instance inspected
|
|
22
|
+
* twice comes back with its keys shuffled. That defeats prompt caching, makes
|
|
23
|
+
* two inspects impossible to diff, and reads as though something changed when
|
|
24
|
+
* nothing did.
|
|
25
|
+
*/
|
|
26
|
+
function withSortedProperties(item) {
|
|
27
|
+
const sortKeys = (record) => record
|
|
28
|
+
? Object.fromEntries(Object.entries(record).sort(([a], [b]) => a.localeCompare(b)))
|
|
29
|
+
: undefined;
|
|
30
|
+
// `requested` exists so callers can correlate an answer with the path they
|
|
31
|
+
// asked about; it is redundant next to the canonical path and only costs
|
|
32
|
+
// tokens here.
|
|
33
|
+
const { requested: _requested, ...rest } = item;
|
|
34
|
+
return {
|
|
35
|
+
...rest,
|
|
36
|
+
properties: sortKeys(item.properties) ?? {},
|
|
37
|
+
...(item.attributes ? { attributes: sortKeys(item.attributes) } : {}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function registerDiscoverTools(context) {
|
|
41
|
+
const { bridge } = context;
|
|
42
|
+
defineTool(context, {
|
|
43
|
+
name: "tree",
|
|
44
|
+
title: "Browse hierarchy",
|
|
45
|
+
description: "Lists the instance hierarchy under a path, breadth-first to a given depth. " +
|
|
46
|
+
"Returns a flat array of paths — flat is both cheaper and easier to act on " +
|
|
47
|
+
"than nested JSON, since every entry is directly usable as a path.\n\n" +
|
|
48
|
+
"Use this to orient yourself in an unfamiliar place. Use `find` instead " +
|
|
49
|
+
"when you already know what you are looking for; a deep `tree` over a " +
|
|
50
|
+
"whole place wastes context on instances you will never touch.\n\n" +
|
|
51
|
+
"With `path` omitted it lists only the containers a place is authored in " +
|
|
52
|
+
"— Workspace, ReplicatedStorage, ServerScriptService and friends. Roblox " +
|
|
53
|
+
"exposes ~120 services at the root, almost all engine internals; those are " +
|
|
54
|
+
"hidden and the response says how many. Pass an explicit `path` to look " +
|
|
55
|
+
"inside one of them anyway.",
|
|
56
|
+
inputSchema: {
|
|
57
|
+
path: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe('Dot-notation root, e.g. "Workspace.Map". Omit to list services from the root.'),
|
|
61
|
+
depth: z
|
|
62
|
+
.number()
|
|
63
|
+
.int()
|
|
64
|
+
.min(1)
|
|
65
|
+
.max(10)
|
|
66
|
+
.default(2)
|
|
67
|
+
.describe("Levels below `path` to walk. Keep low; each level multiplies the result."),
|
|
68
|
+
className: z
|
|
69
|
+
.string()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Only include instances of this class or a subclass, e.g. "BasePart".'),
|
|
72
|
+
nameContains: z
|
|
73
|
+
.string()
|
|
74
|
+
.optional()
|
|
75
|
+
.describe("Only include instances whose name contains this text (case-insensitive)."),
|
|
76
|
+
detail: detailSchema,
|
|
77
|
+
limit: limitSchema,
|
|
78
|
+
cursor: cursorSchema,
|
|
79
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
80
|
+
},
|
|
81
|
+
readOnly: true,
|
|
82
|
+
}, async (args) => {
|
|
83
|
+
const response = await bridge.call("discover.tree", {
|
|
84
|
+
path: args.path,
|
|
85
|
+
depth: args.depth,
|
|
86
|
+
className: args.className,
|
|
87
|
+
nameContains: args.nameContains,
|
|
88
|
+
limit: args.limit,
|
|
89
|
+
offset: decodeCursor(args.cursor),
|
|
90
|
+
}, { studioId: args.studioId });
|
|
91
|
+
// Say what was withheld at the root, so an agent that genuinely needs an
|
|
92
|
+
// engine service knows it can ask for one by path.
|
|
93
|
+
const hidden = response.hiddenServices ?? 0;
|
|
94
|
+
return pageOf(response, args.detail, hidden > 0
|
|
95
|
+
? `${hidden} engine services hidden — pass an explicit \`path\` to inspect one`
|
|
96
|
+
: undefined);
|
|
97
|
+
});
|
|
98
|
+
defineTool(context, {
|
|
99
|
+
name: "inspect",
|
|
100
|
+
title: "Inspect instances",
|
|
101
|
+
description: "Reads properties, attributes, tags and children of one or more instances. " +
|
|
102
|
+
"Pass every path you care about in a single call — batching costs one " +
|
|
103
|
+
"round trip instead of N.\n\n" +
|
|
104
|
+
"Property selection comes from the live Roblox API dump for each " +
|
|
105
|
+
"instance's actual class, so it stays correct across engine updates:\n" +
|
|
106
|
+
" concise — class and child count only\n" +
|
|
107
|
+
" standard — the properties that characterise the class (Part gets Size, " +
|
|
108
|
+
"Position, CFrame, Anchored, Material...)\n" +
|
|
109
|
+
" full — every readable property; expensive, use on one or two " +
|
|
110
|
+
"instances at most\n\n" +
|
|
111
|
+
"Bad paths do not fail the call: they come back under `failures` while the " +
|
|
112
|
+
"valid ones still return, so one typo does not cost you the whole batch.",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
paths: z
|
|
115
|
+
.array(z.string())
|
|
116
|
+
.min(1)
|
|
117
|
+
.max(50)
|
|
118
|
+
.describe('Instance paths, e.g. ["Workspace.Baseplate", "Lighting"].'),
|
|
119
|
+
detail: detailSchema,
|
|
120
|
+
properties: z
|
|
121
|
+
.array(z.string())
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Read exactly these properties instead of the detail-level default. " +
|
|
124
|
+
"Use when you want one specific value across many instances."),
|
|
125
|
+
includeChildren: z
|
|
126
|
+
.boolean()
|
|
127
|
+
.default(true)
|
|
128
|
+
.describe("Include a name/class listing of direct children."),
|
|
129
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
130
|
+
},
|
|
131
|
+
readOnly: true,
|
|
132
|
+
}, async (args) => {
|
|
133
|
+
// Classes are not known until the plugin answers, so resolve the property
|
|
134
|
+
// set in two passes: a cheap probe for class names, then the real read.
|
|
135
|
+
let requested = args.properties;
|
|
136
|
+
if (!requested && args.detail !== "concise") {
|
|
137
|
+
const probe = await bridge.call("discover.inspect", { paths: args.paths, includeChildren: false }, { studioId: args.studioId });
|
|
138
|
+
const names = new Set();
|
|
139
|
+
for (const item of probe.items) {
|
|
140
|
+
const list = args.detail === "full"
|
|
141
|
+
? (await propertiesOf(item.className)).map((property) => property.name)
|
|
142
|
+
: await standardProperties(item.className);
|
|
143
|
+
for (const name of list)
|
|
144
|
+
names.add(name);
|
|
145
|
+
}
|
|
146
|
+
requested = [...names];
|
|
147
|
+
}
|
|
148
|
+
const response = await bridge.call("discover.inspect", {
|
|
149
|
+
paths: args.paths,
|
|
150
|
+
properties: requested,
|
|
151
|
+
includeChildren: args.includeChildren,
|
|
152
|
+
}, { studioId: args.studioId });
|
|
153
|
+
const note = response.failures.length > 0
|
|
154
|
+
? `Could not resolve ${response.failures.length} path(s):\n` +
|
|
155
|
+
response.failures.map((failure) => ` - ${failure}`).join("\n")
|
|
156
|
+
: undefined;
|
|
157
|
+
return json(response.items.map(withSortedProperties), note);
|
|
158
|
+
});
|
|
159
|
+
defineTool(context, {
|
|
160
|
+
name: "find",
|
|
161
|
+
title: "Find instances",
|
|
162
|
+
description: "Searches the data model by name, class, property value and/or tag. Every " +
|
|
163
|
+
"filter you supply must match, so one call answers questions that would " +
|
|
164
|
+
'otherwise take several: "anchored BaseParts under Workspace.Map whose ' +
|
|
165
|
+
'name contains door" is a single request.\n\n' +
|
|
166
|
+
"This replaces separate name / class / property / tag search tools. " +
|
|
167
|
+
"Prefer it over `tree` whenever you know what you are looking for.\n\n" +
|
|
168
|
+
"Tag searches are answered from CollectionService's index rather than by " +
|
|
169
|
+
"walking the tree, so they stay fast on large places. Narrow with `path` " +
|
|
170
|
+
"if a search reports TOO_BROAD.",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
path: z
|
|
173
|
+
.string()
|
|
174
|
+
.optional()
|
|
175
|
+
.describe('Limit the search to this subtree, e.g. "Workspace.Map". Omit for everything.'),
|
|
176
|
+
nameContains: z.string().optional().describe("Substring of the instance name, case-insensitive."),
|
|
177
|
+
className: z.string().optional().describe('Class or superclass, e.g. "BasePart", "Script".'),
|
|
178
|
+
tag: z.string().optional().describe("CollectionService tag the instance must carry."),
|
|
179
|
+
propertyName: z
|
|
180
|
+
.string()
|
|
181
|
+
.optional()
|
|
182
|
+
.describe('Property that must exist, e.g. "Anchored". Combine with propertyValue.'),
|
|
183
|
+
propertyValue: z
|
|
184
|
+
.string()
|
|
185
|
+
.optional()
|
|
186
|
+
.describe('Required value of `propertyName`, compared as text — "true", "0, 5, 0", ' +
|
|
187
|
+
'"Enum.Material.Neon". Omit to match any instance that has the property.'),
|
|
188
|
+
detail: detailSchema,
|
|
189
|
+
limit: limitSchema,
|
|
190
|
+
cursor: cursorSchema,
|
|
191
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
192
|
+
},
|
|
193
|
+
readOnly: true,
|
|
194
|
+
}, async (args) => {
|
|
195
|
+
if (!args.nameContains && !args.className && !args.tag && !args.propertyName) {
|
|
196
|
+
return text("find needs at least one filter (nameContains, className, tag or propertyName).\n" +
|
|
197
|
+
"To list everything under a path, use `tree` instead.");
|
|
198
|
+
}
|
|
199
|
+
const response = await bridge.call("discover.find", {
|
|
200
|
+
path: args.path,
|
|
201
|
+
nameContains: args.nameContains,
|
|
202
|
+
className: args.className,
|
|
203
|
+
tag: args.tag,
|
|
204
|
+
propertyName: args.propertyName,
|
|
205
|
+
propertyValue: args.propertyValue,
|
|
206
|
+
limit: args.limit,
|
|
207
|
+
offset: decodeCursor(args.cursor),
|
|
208
|
+
}, { studioId: args.studioId, timeoutMs: 30_000 });
|
|
209
|
+
if (response.total === 0) {
|
|
210
|
+
return text(`No matches (searched ${response.searched ?? 0} instances).\n` +
|
|
211
|
+
"Check spelling and case — names and class names are case-sensitive. " +
|
|
212
|
+
"Try a shorter `nameContains`, or drop a filter to widen the search.");
|
|
213
|
+
}
|
|
214
|
+
return pageOf(response, args.detail, `searched ${response.searched ?? 0} instances`);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/tools/discover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { json, table, text } from "../lib/format.js";
|
|
3
|
+
import { defineTool } from "../lib/tool.js";
|
|
4
|
+
export function registerExecTools(context) {
|
|
5
|
+
const { bridge } = context;
|
|
6
|
+
defineTool(context, {
|
|
7
|
+
name: "execute_luau",
|
|
8
|
+
title: "Run Luau in Studio",
|
|
9
|
+
description: "Runs Luau in Studio's plugin context and returns whatever it printed, " +
|
|
10
|
+
"returned, or threw.\n\n" +
|
|
11
|
+
"This is the escape hatch. Reach for it only when no dedicated tool " +
|
|
12
|
+
"fits — `create`, `modify`, `delete`, `move`, `script_edit` and `find` " +
|
|
13
|
+
"validate their input, type values from the live API dump, and wrap " +
|
|
14
|
+
"writes in an undo recording. Code run here does none of that, so a typo " +
|
|
15
|
+
"becomes a runtime error instead of a suggestion, and changes it makes " +
|
|
16
|
+
"may not be undoable as one step.\n\n" +
|
|
17
|
+
"Good uses: reading something no tool exposes, a one-off calculation " +
|
|
18
|
+
"over many instances, or calling an engine API the tools do not cover.\n\n" +
|
|
19
|
+
"Output printed while it runs is captured and returned, so `print` is a " +
|
|
20
|
+
"reasonable way to get values out. `return` works too, including " +
|
|
21
|
+
"returning a table — it comes back as a structure, not a summary. There " +
|
|
22
|
+
"is no timeout: an infinite loop will hang Studio until it is " +
|
|
23
|
+
"force-quit.\n\n" +
|
|
24
|
+
"Against a running playtest server, Studio disables `loadstring`, so the " +
|
|
25
|
+
"code is compiled through a ModuleScript instead and runs at script " +
|
|
26
|
+
"identity — plugin-only APIs are unavailable there. When that happens it " +
|
|
27
|
+
"is stated in the result rather than left to be inferred from a failure.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
source: z
|
|
30
|
+
.string()
|
|
31
|
+
.min(1)
|
|
32
|
+
.describe("Luau to run. In an editor session this has plugin permissions, so " +
|
|
33
|
+
"`game`, `workspace` and plugin-only APIs are all reachable."),
|
|
34
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
35
|
+
},
|
|
36
|
+
destructive: true,
|
|
37
|
+
}, async (args) => {
|
|
38
|
+
const response = await bridge.call("exec.run", { source: args.source }, { studioId: args.studioId, timeoutMs: 60_000 });
|
|
39
|
+
const parts = [];
|
|
40
|
+
if (response.output.length > 0) {
|
|
41
|
+
parts.push("Output:\n" +
|
|
42
|
+
response.output.map((line) => ` [${line.level}] ${line.message}`).join("\n"));
|
|
43
|
+
}
|
|
44
|
+
if (response.ok) {
|
|
45
|
+
if (response.returned && response.returned.length > 0) {
|
|
46
|
+
// Indented, because returned values are now whole structures rather
|
|
47
|
+
// than one-line summaries and a single-line dump of a nested table is
|
|
48
|
+
// no more readable than the "<table with 5 entries>" it replaced.
|
|
49
|
+
const single = response.returned.length === 1 ? response.returned[0] : response.returned;
|
|
50
|
+
parts.push(`Returned:\n${JSON.stringify(single, null, 2)}`);
|
|
51
|
+
}
|
|
52
|
+
if (parts.length === 0) {
|
|
53
|
+
parts.push("Ran successfully. Nothing was printed or returned.");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// A thrown error is reported as content rather than a tool failure: the
|
|
58
|
+
// output captured before the throw is usually what explains it.
|
|
59
|
+
parts.push(`Error: ${response.error ?? "unknown"}`);
|
|
60
|
+
}
|
|
61
|
+
if (response.note)
|
|
62
|
+
parts.push(`Note: ${response.note}`);
|
|
63
|
+
parts.push(`(${response.milliseconds}ms)`);
|
|
64
|
+
return text(parts.join("\n\n"));
|
|
65
|
+
});
|
|
66
|
+
defineTool(context, {
|
|
67
|
+
name: "viewport",
|
|
68
|
+
title: "Viewport and selection",
|
|
69
|
+
description: "Works with the 3D view and the Studio selection.\n\n" +
|
|
70
|
+
"`select` sets, extends or shrinks what is highlighted in Studio. Select " +
|
|
71
|
+
"what you just built or changed — it shows the user the result, and puts " +
|
|
72
|
+
"the instance under Studio's own move and scale handles. `studio_status` " +
|
|
73
|
+
"reports the current selection; this sets it.\n\n" +
|
|
74
|
+
"`focus` aims the Studio camera at an instance and frames it so the " +
|
|
75
|
+
"whole thing is on screen. This is what makes `screenshot` worth having: " +
|
|
76
|
+
"a picture of wherever the camera happened to be answers nothing, while " +
|
|
77
|
+
"a picture of the thing you just built answers 'does it look right', " +
|
|
78
|
+
"which no amount of reading properties can. Build, focus, screenshot.\n\n" +
|
|
79
|
+
"The distance is computed from the subject's size and the camera's field " +
|
|
80
|
+
"of view, so a doorway and a whole map both arrive filling a similar " +
|
|
81
|
+
"share of the frame. `from` changes the angle you view it from, and " +
|
|
82
|
+
"`padding` how tightly it is framed.\n\n" +
|
|
83
|
+
"`camera` sets or reads the camera directly, for shots framing cannot " +
|
|
84
|
+
"express — standing inside a room, or looking along a corridor.\n\n" +
|
|
85
|
+
"`raycast` fires a ray through the world and reports the first thing it " +
|
|
86
|
+
"hits, with position, surface normal, distance and material. This answers " +
|
|
87
|
+
"'what occupies this space', which the data model alone cannot: use it to " +
|
|
88
|
+
"find the ground under a spawn point, or check whether a gap is clear " +
|
|
89
|
+
"before placing something.",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
op: z
|
|
92
|
+
.enum(["select", "raycast", "focus", "camera"])
|
|
93
|
+
.describe("'focus' points the camera at something and frames it, 'camera' sets " +
|
|
94
|
+
"it explicitly, 'select' changes the Studio selection, 'raycast' " +
|
|
95
|
+
"queries the world."),
|
|
96
|
+
path: z
|
|
97
|
+
.string()
|
|
98
|
+
.optional()
|
|
99
|
+
.describe("focus only: the instance to look at. A model, part, or folder containing them."),
|
|
100
|
+
at: z
|
|
101
|
+
.string()
|
|
102
|
+
.optional()
|
|
103
|
+
.describe('focus only: look at this point instead of an instance, e.g. "0, 10, 0".'),
|
|
104
|
+
from: z
|
|
105
|
+
.string()
|
|
106
|
+
.optional()
|
|
107
|
+
.describe('focus only: direction to view from, e.g. "0, 1, 0" for directly above ' +
|
|
108
|
+
'or "1, 0, 0" from the side. Defaults to a raised three-quarter view.'),
|
|
109
|
+
padding: z
|
|
110
|
+
.number()
|
|
111
|
+
.min(1)
|
|
112
|
+
.max(5)
|
|
113
|
+
.default(1.5)
|
|
114
|
+
.describe("focus only: how much room to leave around the subject. 1 is tight."),
|
|
115
|
+
position: z.string().optional().describe('camera only: where to put the camera, e.g. "0, 20, 30".'),
|
|
116
|
+
lookAt: z.string().optional().describe("camera only: the point to aim at."),
|
|
117
|
+
fieldOfView: z
|
|
118
|
+
.number()
|
|
119
|
+
.min(1)
|
|
120
|
+
.max(120)
|
|
121
|
+
.optional()
|
|
122
|
+
.describe("camera only: field of view in degrees. Lower is more zoomed in."),
|
|
123
|
+
paths: z
|
|
124
|
+
.array(z.string())
|
|
125
|
+
.optional()
|
|
126
|
+
.describe("select only: instances to select. An empty array clears the selection."),
|
|
127
|
+
mode: z
|
|
128
|
+
.enum(["set", "add", "remove"])
|
|
129
|
+
.default("set")
|
|
130
|
+
.describe("select only: replace the selection, extend it, or remove from it."),
|
|
131
|
+
origin: z
|
|
132
|
+
.string()
|
|
133
|
+
.optional()
|
|
134
|
+
.describe('raycast only: where the ray starts, e.g. "0, 50, 0".'),
|
|
135
|
+
direction: z
|
|
136
|
+
.string()
|
|
137
|
+
.optional()
|
|
138
|
+
.describe('raycast only: which way it points, e.g. "0, -1, 0" for straight down.'),
|
|
139
|
+
maxDistance: z
|
|
140
|
+
.number()
|
|
141
|
+
.positive()
|
|
142
|
+
.default(1000)
|
|
143
|
+
.describe("raycast only: how far to look, in studs."),
|
|
144
|
+
ignore: z
|
|
145
|
+
.array(z.string())
|
|
146
|
+
.optional()
|
|
147
|
+
.describe("raycast only: instances the ray passes through."),
|
|
148
|
+
studioId: z.string().optional().describe("Target Studio; omit for the active one."),
|
|
149
|
+
},
|
|
150
|
+
destructive: false,
|
|
151
|
+
idempotent: true,
|
|
152
|
+
}, async (args) => {
|
|
153
|
+
if (args.op === "focus") {
|
|
154
|
+
if (!args.path && !args.at) {
|
|
155
|
+
return text("focus needs a `path` to look at, or an `at` position.");
|
|
156
|
+
}
|
|
157
|
+
const response = await bridge.call("viewport.focus", { path: args.path, at: args.at, from: args.from, padding: args.padding }, { studioId: args.studioId });
|
|
158
|
+
return json(response, "Take a `screenshot` to see it.");
|
|
159
|
+
}
|
|
160
|
+
if (args.op === "camera") {
|
|
161
|
+
const response = await bridge.call("viewport.camera", { position: args.position, lookAt: args.lookAt, fieldOfView: args.fieldOfView }, { studioId: args.studioId });
|
|
162
|
+
return json(response);
|
|
163
|
+
}
|
|
164
|
+
if (args.op === "raycast") {
|
|
165
|
+
if (!args.origin || !args.direction) {
|
|
166
|
+
return text("raycast needs `origin` and `direction`.\n" +
|
|
167
|
+
'For example origin "0, 100, 0" and direction "0, -1, 0" to find the ' +
|
|
168
|
+
"ground below a point.");
|
|
169
|
+
}
|
|
170
|
+
const response = await bridge.call("viewport.raycast", {
|
|
171
|
+
origin: args.origin,
|
|
172
|
+
direction: args.direction,
|
|
173
|
+
maxDistance: args.maxDistance,
|
|
174
|
+
ignore: args.ignore,
|
|
175
|
+
}, { studioId: args.studioId });
|
|
176
|
+
if (!response.hit) {
|
|
177
|
+
return text(`Nothing within ${args.maxDistance} studs along that ray.\n` +
|
|
178
|
+
"Check the direction points the way you expect, or raise `maxDistance`.");
|
|
179
|
+
}
|
|
180
|
+
return json(response);
|
|
181
|
+
}
|
|
182
|
+
const response = await bridge.call("viewport.select", { paths: args.paths ?? [], mode: args.mode }, { studioId: args.studioId });
|
|
183
|
+
if (response.count === 0)
|
|
184
|
+
return text("Selection cleared.");
|
|
185
|
+
return table(["path", "className"], response.items, {
|
|
186
|
+
total: response.count,
|
|
187
|
+
more: `${response.count} selected in Studio`,
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/tools/exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { json } from "../lib/format.js";
|
|
3
|
+
import { defineTool } from "../lib/tool.js";
|
|
4
|
+
export function registerInputTools(context) {
|
|
5
|
+
const { bridge } = context;
|
|
6
|
+
defineTool(context, {
|
|
7
|
+
name: "input",
|
|
8
|
+
title: "Send keyboard and mouse input",
|
|
9
|
+
description: "Sends real keyboard and mouse input to a running playtest — the same " +
|
|
10
|
+
"events a person pressing the keys would produce.\n\n" +
|
|
11
|
+
"This is how to test what `character` cannot reach. `character` drives " +
|
|
12
|
+
"the Humanoid directly, which answers 'can it get to the door'; this " +
|
|
13
|
+
"answers 'does pressing E open it', 'does the sprint key work', 'does " +
|
|
14
|
+
"the menu close on Escape' — anything bound to input rather than to " +
|
|
15
|
+
"movement. Use `character` for going places and this for controls.\n\n" +
|
|
16
|
+
"Steps run in order, so a sequence is one call: tap E, wait, click at a " +
|
|
17
|
+
"point, type a name. `hold` is how long a key or button stays down, " +
|
|
18
|
+
"`after` is how long to wait before the next step — a jump held for a " +
|
|
19
|
+
"second is a different test from a tapped one.\n\n" +
|
|
20
|
+
"REQUIRES A RUNNING PLAYTEST, and must be addressed to the playtest's " +
|
|
21
|
+
"studioId from `list_studios`, not the editor's.\n\n" +
|
|
22
|
+
"How it works, because it explains the one thing that will surprise " +
|
|
23
|
+
"you: input belongs to the data model that creates it, and the " +
|
|
24
|
+
"character is driven by the CLIENT. Sending from the playtest's server " +
|
|
25
|
+
"succeeds and moves nothing. So this parents a short script into the " +
|
|
26
|
+
"player's PlayerGui, which runs on their client, and that reports back " +
|
|
27
|
+
"when the input has actually been delivered. Nothing is reported as " +
|
|
28
|
+
"sent until the client confirms it. If confirmation never arrives you " +
|
|
29
|
+
"get an error, not a success — check where things really are with " +
|
|
30
|
+
"`character op=\"state\"`.\n\n" +
|
|
31
|
+
"Mouse coordinates are viewport pixels from the top-left, so pair this " +
|
|
32
|
+
"with `screenshot` to see what is where before clicking it.",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
steps: z
|
|
35
|
+
.array(z
|
|
36
|
+
.object({
|
|
37
|
+
kind: z
|
|
38
|
+
.enum(["key", "click", "move", "text"])
|
|
39
|
+
.default("key")
|
|
40
|
+
.describe("'key' presses a keyboard key, 'click' a mouse button at a " +
|
|
41
|
+
"point, 'move' just moves the pointer, 'text' types a string."),
|
|
42
|
+
key: z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe('key only: an Enum.KeyCode name — "W", "Space", "E", "LeftShift", "Escape".'),
|
|
46
|
+
action: z
|
|
47
|
+
.enum(["tap", "press", "release"])
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("'tap' presses and releases (the default), 'press' holds it " +
|
|
50
|
+
"down until a later 'release', 'release' lets go. Use " +
|
|
51
|
+
"press/release across steps to hold a key while doing " +
|
|
52
|
+
"something else."),
|
|
53
|
+
button: z
|
|
54
|
+
.enum(["MouseButton1", "MouseButton2", "MouseButton3"])
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("click only: which button. Defaults to left."),
|
|
57
|
+
x: z.number().optional().describe("click/move only: viewport pixels from the left."),
|
|
58
|
+
y: z.number().optional().describe("click/move only: viewport pixels from the top."),
|
|
59
|
+
text: z.string().optional().describe("text only: the string to type."),
|
|
60
|
+
hold: z
|
|
61
|
+
.number()
|
|
62
|
+
.min(0)
|
|
63
|
+
.max(10)
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Seconds to hold the key or button down before releasing it."),
|
|
66
|
+
after: z
|
|
67
|
+
.number()
|
|
68
|
+
.min(0)
|
|
69
|
+
.max(10)
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("Seconds to wait after this step before the next one."),
|
|
72
|
+
})
|
|
73
|
+
.strict())
|
|
74
|
+
.min(1)
|
|
75
|
+
.max(40)
|
|
76
|
+
.describe("Input steps, delivered in order."),
|
|
77
|
+
player: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe("Which player, by name. Omit for the only one; needed in a multiplayer test."),
|
|
81
|
+
studioId: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe("The PLAYTEST session's id — not the editor's. See list_studios."),
|
|
85
|
+
},
|
|
86
|
+
readOnly: false,
|
|
87
|
+
destructive: false,
|
|
88
|
+
}, async (args) => {
|
|
89
|
+
const response = await bridge.call("input.send", { steps: args.steps, player: args.player },
|
|
90
|
+
// The plugin waits for the client's acknowledgement, and the steps
|
|
91
|
+
// themselves can hold keys for seconds, so the deadline must outlast both.
|
|
92
|
+
{ studioId: args.studioId, timeoutMs: 90_000 });
|
|
93
|
+
return json(response, "Delivered on the client and confirmed back. Read the result with `character op=\"state\"`, `console`, or `screenshot`.");
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/tools/input.ts"],"names":[],"mappings":"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"}
|