dominus-cli 0.5.4 → 0.5.6
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/dist/index.js +50 -46
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +43 -44
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
- package/plugin/Dominus.rbxm +0 -0
- package/plugin/src/Properties.lua +9 -2
- package/plugin/src/init.server.lua +5 -1
package/dist/index.js
CHANGED
|
@@ -1180,13 +1180,17 @@ var init_get_properties = __esm({
|
|
|
1180
1180
|
init_protocol();
|
|
1181
1181
|
tool5 = {
|
|
1182
1182
|
name: "get_properties",
|
|
1183
|
-
description: "Get all properties of
|
|
1183
|
+
description: "Get all properties of a single instance in Roblox Studio. By default uses compact mode which strips read-only, nil, deprecated, and default-valued properties. For inspecting UI trees, prefer serialize_ui or get_descendants_properties.",
|
|
1184
1184
|
parameters: {
|
|
1185
1185
|
type: "object",
|
|
1186
1186
|
properties: {
|
|
1187
1187
|
path: {
|
|
1188
1188
|
type: "string",
|
|
1189
1189
|
description: 'Full instance path (e.g., "Workspace.Part")'
|
|
1190
|
+
},
|
|
1191
|
+
compact: {
|
|
1192
|
+
type: "boolean",
|
|
1193
|
+
description: "Strip read-only, nil, deprecated, and default-valued properties (default true). Set false for full dump."
|
|
1190
1194
|
}
|
|
1191
1195
|
},
|
|
1192
1196
|
required: ["path"]
|
|
@@ -1195,9 +1199,10 @@ var init_get_properties = __esm({
|
|
|
1195
1199
|
if (!ctx.isStudioConnected()) {
|
|
1196
1200
|
return { success: false, error: "Studio is not connected" };
|
|
1197
1201
|
}
|
|
1202
|
+
const compact = params.compact !== false;
|
|
1198
1203
|
const response = await ctx.sendToStudio(
|
|
1199
1204
|
CliMsg.GET_PROPERTIES,
|
|
1200
|
-
{ path: params.path }
|
|
1205
|
+
{ path: params.path, compact }
|
|
1201
1206
|
);
|
|
1202
1207
|
return { success: true, data: response.payload };
|
|
1203
1208
|
}
|
|
@@ -2581,10 +2586,19 @@ async function startMcpServer() {
|
|
|
2581
2586
|
}
|
|
2582
2587
|
const mcp = new McpServer({
|
|
2583
2588
|
name: "dominus",
|
|
2584
|
-
version: "0.
|
|
2589
|
+
version: "0.5.5"
|
|
2585
2590
|
}, {
|
|
2586
2591
|
instructions: INTERNAL_MEMORY
|
|
2587
2592
|
});
|
|
2593
|
+
function luaStr(s) {
|
|
2594
|
+
return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`;
|
|
2595
|
+
}
|
|
2596
|
+
function resolvePath(dotPath) {
|
|
2597
|
+
const parts = dotPath.split(".");
|
|
2598
|
+
let r = "game";
|
|
2599
|
+
for (const p of parts) r += `[${luaStr(p)}]`;
|
|
2600
|
+
return r;
|
|
2601
|
+
}
|
|
2588
2602
|
mcp.tool(
|
|
2589
2603
|
"read_script",
|
|
2590
2604
|
"Read the source code of a script in Roblox Studio",
|
|
@@ -2636,11 +2650,14 @@ async function startMcpServer() {
|
|
|
2636
2650
|
);
|
|
2637
2651
|
mcp.tool(
|
|
2638
2652
|
"get_properties",
|
|
2639
|
-
"Get all properties of
|
|
2640
|
-
{
|
|
2641
|
-
|
|
2653
|
+
"Get all properties of a single instance in Roblox Studio. Returns property name, value, type, and category. For inspecting UI trees, prefer serialize_ui (structured tree) or get_descendants_properties (flat list with compact filtering).",
|
|
2654
|
+
{
|
|
2655
|
+
path: z.string().describe('Full instance path (e.g. "Workspace.Part", "StarterGui.MyUI.Frame")'),
|
|
2656
|
+
compact: z.boolean().optional().default(true).describe("Strip read-only, nil, deprecated, and default-valued properties (default true). Set false for full dump.")
|
|
2657
|
+
},
|
|
2658
|
+
async ({ path: path5, compact }) => {
|
|
2642
2659
|
assertConnected();
|
|
2643
|
-
const res = await bridge.sendRequest(CliMsg.GET_PROPERTIES, { path: path5 });
|
|
2660
|
+
const res = await bridge.sendRequest(CliMsg.GET_PROPERTIES, { path: path5, compact });
|
|
2644
2661
|
return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
|
|
2645
2662
|
}
|
|
2646
2663
|
);
|
|
@@ -2856,16 +2873,10 @@ async function startMcpServer() {
|
|
|
2856
2873
|
},
|
|
2857
2874
|
async (params) => {
|
|
2858
2875
|
assertConnected();
|
|
2859
|
-
const
|
|
2860
|
-
|
|
2861
|
-
for (const p of parts) resolve += `["${p}"]`;
|
|
2862
|
-
const lines = [`local orig = ${resolve}`, `local clone = orig:Clone()`];
|
|
2863
|
-
if (params.newName) lines.push(`clone.Name = "${params.newName}"`);
|
|
2876
|
+
const lines = [`local orig = ${resolvePath(params.path)}`, `local clone = orig:Clone()`];
|
|
2877
|
+
if (params.newName) lines.push(`clone.Name = ${luaStr(params.newName)}`);
|
|
2864
2878
|
if (params.newParent) {
|
|
2865
|
-
|
|
2866
|
-
let pr = "game";
|
|
2867
|
-
for (const p of pp) pr += `["${p}"]`;
|
|
2868
|
-
lines.push(`clone.Parent = ${pr}`);
|
|
2879
|
+
lines.push(`clone.Parent = ${resolvePath(params.newParent)}`);
|
|
2869
2880
|
} else {
|
|
2870
2881
|
lines.push(`clone.Parent = orig.Parent`);
|
|
2871
2882
|
}
|
|
@@ -2881,7 +2892,7 @@ async function startMcpServer() {
|
|
|
2881
2892
|
);
|
|
2882
2893
|
mcp.tool(
|
|
2883
2894
|
"group_instances",
|
|
2884
|
-
"Group multiple instances into a Model or Folder",
|
|
2895
|
+
"Group multiple instances into a Model or Folder. All listed instances become children of the new group.",
|
|
2885
2896
|
{
|
|
2886
2897
|
paths: z.array(z.string()).describe("Array of instance paths to group"),
|
|
2887
2898
|
groupName: z.string().describe("Name for the group"),
|
|
@@ -2892,20 +2903,11 @@ async function startMcpServer() {
|
|
|
2892
2903
|
assertConnected();
|
|
2893
2904
|
const gc = params.groupClass ?? "Model";
|
|
2894
2905
|
const parent = params.parent ?? "Workspace";
|
|
2895
|
-
const parentParts = parent.split(".");
|
|
2896
|
-
let parentResolve = "game";
|
|
2897
|
-
for (const p of parentParts) parentResolve += `["${p}"]`;
|
|
2898
|
-
const resolves = params.paths.map((path5) => {
|
|
2899
|
-
const parts = path5.split(".");
|
|
2900
|
-
let r = "game";
|
|
2901
|
-
for (const part of parts) r += `["${part}"]`;
|
|
2902
|
-
return r;
|
|
2903
|
-
});
|
|
2904
2906
|
const code = [
|
|
2905
|
-
`local group = Instance.new(
|
|
2906
|
-
`group.Name =
|
|
2907
|
-
`group.Parent = ${
|
|
2908
|
-
...
|
|
2907
|
+
`local group = Instance.new(${luaStr(gc)})`,
|
|
2908
|
+
`group.Name = ${luaStr(params.groupName)}`,
|
|
2909
|
+
`group.Parent = ${resolvePath(parent)}`,
|
|
2910
|
+
...params.paths.map((p) => `${resolvePath(p)}.Parent = group`),
|
|
2909
2911
|
`print("Grouped ${params.paths.length} instances into: " .. group:GetFullName())`
|
|
2910
2912
|
].join("\n");
|
|
2911
2913
|
const res = await bridge.sendRequest(CliMsg.RUN_CODE, { code });
|
|
@@ -2914,7 +2916,7 @@ async function startMcpServer() {
|
|
|
2914
2916
|
);
|
|
2915
2917
|
mcp.tool(
|
|
2916
2918
|
"build_multiple",
|
|
2917
|
-
"Create many parts/instances in one batch. Send an array of specs \u2014 all created in a single round-trip. Ideal for building trees, houses, vehicles.",
|
|
2919
|
+
"Create many parts/instances in one batch. Send an array of specs \u2014 all created in a single round-trip. Ideal for building trees, houses, vehicles. Supports hex colors, rgb() colors, and BrickColor names.",
|
|
2918
2920
|
{
|
|
2919
2921
|
parts: z.array(z.object({
|
|
2920
2922
|
name: z.string(),
|
|
@@ -2922,10 +2924,11 @@ async function startMcpServer() {
|
|
|
2922
2924
|
parent: z.string().optional(),
|
|
2923
2925
|
position: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),
|
|
2924
2926
|
size: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),
|
|
2925
|
-
color: z.string().optional().describe('Hex "#RRGGBB" or BrickColor name'),
|
|
2926
|
-
material: z.string().optional(),
|
|
2927
|
+
color: z.string().optional().describe('Hex "#RRGGBB", "rgb(r,g,b)", or BrickColor name'),
|
|
2928
|
+
material: z.string().optional().describe("Enum.Material name: Plastic, Wood, Neon, Glass, etc."),
|
|
2927
2929
|
transparency: z.number().optional(),
|
|
2928
2930
|
anchored: z.boolean().optional(),
|
|
2931
|
+
canCollide: z.boolean().optional(),
|
|
2929
2932
|
shape: z.enum(["Block", "Ball", "Cylinder", "Wedge"]).optional()
|
|
2930
2933
|
})).describe("Array of part specifications"),
|
|
2931
2934
|
groupName: z.string().optional().describe("Group all parts into a Model with this name"),
|
|
@@ -2936,35 +2939,36 @@ async function startMcpServer() {
|
|
|
2936
2939
|
const parts = params.parts;
|
|
2937
2940
|
const groupName = params.groupName;
|
|
2938
2941
|
const groupParent = params.groupParent ?? "Workspace";
|
|
2939
|
-
function resolveP(path5) {
|
|
2940
|
-
const segs = path5.split(".");
|
|
2941
|
-
let r = "game";
|
|
2942
|
-
for (const s of segs) r += `["${s}"]`;
|
|
2943
|
-
return r;
|
|
2944
|
-
}
|
|
2945
2942
|
const lines = [];
|
|
2946
2943
|
if (groupName) {
|
|
2947
2944
|
lines.push(`local _group = Instance.new("Model")`);
|
|
2948
|
-
lines.push(`_group.Name =
|
|
2949
|
-
lines.push(`_group.Parent = ${
|
|
2945
|
+
lines.push(`_group.Name = ${luaStr(groupName)}`);
|
|
2946
|
+
lines.push(`_group.Parent = ${resolvePath(groupParent)}`);
|
|
2950
2947
|
}
|
|
2951
2948
|
for (let i = 0; i < parts.length; i++) {
|
|
2952
2949
|
const p = parts[i];
|
|
2953
2950
|
const v = `_p${i}`;
|
|
2954
2951
|
const cn = p.className ?? (p.shape === "Wedge" ? "WedgePart" : "Part");
|
|
2955
|
-
lines.push(`local ${v} = Instance.new(
|
|
2956
|
-
lines.push(`${v}.Name =
|
|
2952
|
+
lines.push(`local ${v} = Instance.new(${luaStr(cn)})`);
|
|
2953
|
+
lines.push(`${v}.Name = ${luaStr(p.name)}`);
|
|
2957
2954
|
if (p.position) lines.push(`${v}.Position = Vector3.new(${p.position.x}, ${p.position.y}, ${p.position.z})`);
|
|
2958
2955
|
if (p.size) lines.push(`${v}.Size = Vector3.new(${p.size.x}, ${p.size.y}, ${p.size.z})`);
|
|
2959
2956
|
if (p.color) {
|
|
2960
|
-
if (p.color.startsWith("#"))
|
|
2961
|
-
|
|
2957
|
+
if (p.color.startsWith("#")) {
|
|
2958
|
+
lines.push(`${v}.Color = Color3.fromHex(${luaStr(p.color)})`);
|
|
2959
|
+
} else if (p.color.startsWith("rgb(")) {
|
|
2960
|
+
const m = p.color.match(/rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);
|
|
2961
|
+
if (m) lines.push(`${v}.Color = Color3.fromRGB(${m[1]}, ${m[2]}, ${m[3]})`);
|
|
2962
|
+
} else {
|
|
2963
|
+
lines.push(`${v}.BrickColor = BrickColor.new(${luaStr(p.color)})`);
|
|
2964
|
+
}
|
|
2962
2965
|
}
|
|
2963
2966
|
if (p.material) lines.push(`${v}.Material = Enum.Material.${p.material}`);
|
|
2964
2967
|
if (p.transparency !== void 0) lines.push(`${v}.Transparency = ${p.transparency}`);
|
|
2965
2968
|
lines.push(`${v}.Anchored = ${p.anchored ?? true}`);
|
|
2969
|
+
if (p.canCollide !== void 0) lines.push(`${v}.CanCollide = ${p.canCollide}`);
|
|
2966
2970
|
if (p.shape && p.shape !== "Block" && cn === "Part") lines.push(`${v}.Shape = Enum.PartType.${p.shape}`);
|
|
2967
|
-
lines.push(`${v}.Parent = ${groupName ? "_group" :
|
|
2971
|
+
lines.push(`${v}.Parent = ${groupName ? "_group" : resolvePath(p.parent ?? "Workspace")}`);
|
|
2968
2972
|
}
|
|
2969
2973
|
lines.push(`print("Built ${parts.length} parts${groupName ? ` in ${groupName}` : ""}")`);
|
|
2970
2974
|
const res = await bridge.sendRequest(CliMsg.RUN_CODE, { code: lines.join("\n") });
|