dominus-cli 0.5.1 → 0.5.3
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 +177 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +101 -4
- package/dist/mcp.js.map +1 -1
- package/package.json +17 -16
- package/plugin/Dominus.rbxm +0 -0
- package/plugin/src/Properties.lua +117 -8
- package/plugin/src/UIBuilder.lua +27 -9
- package/plugin/src/init.server.lua +5 -1
package/dist/index.js
CHANGED
|
@@ -629,6 +629,84 @@ var init_ws_client = __esm({
|
|
|
629
629
|
}
|
|
630
630
|
});
|
|
631
631
|
|
|
632
|
+
// src/agent/internal-memory.ts
|
|
633
|
+
var INTERNAL_MEMORY;
|
|
634
|
+
var init_internal_memory = __esm({
|
|
635
|
+
"src/agent/internal-memory.ts"() {
|
|
636
|
+
INTERNAL_MEMORY = `## Internal Memory \u2014 Known Quirks & Lessons
|
|
637
|
+
|
|
638
|
+
These are built-in lessons that ship with Dominus. Follow them exactly.
|
|
639
|
+
|
|
640
|
+
### create_ui \u2014 property format
|
|
641
|
+
- Each node accepts properties in **either** of two shapes:
|
|
642
|
+
- **Flattened (preferred)**: props as top-level keys next to \`ClassName\`, \`Name\`, \`Children\`.
|
|
643
|
+
\`\`\`json
|
|
644
|
+
{ "ClassName": "TextButton", "Name": "Btn", "Text": "OK", "Size": [0, 100, 0, 40] }
|
|
645
|
+
\`\`\`
|
|
646
|
+
- **Nested bag**: props grouped under \`properties\` / \`Properties\` / \`props\` / \`Props\`.
|
|
647
|
+
\`\`\`json
|
|
648
|
+
{ "ClassName": "TextButton", "Name": "Btn",
|
|
649
|
+
"properties": { "Text": "OK", "Size": [0, 100, 0, 40] } }
|
|
650
|
+
\`\`\`
|
|
651
|
+
- Do NOT mix a nested \`properties\` bag with flattened props of the same name \u2014 the bag wins.
|
|
652
|
+
- Reserved keys (never treated as instance properties): \`ClassName\`, \`className\`, \`Name\`, \`name\`, \`Children\`, \`children\`, \`properties\`, \`Properties\`, \`props\`, \`Props\`.
|
|
653
|
+
|
|
654
|
+
### build_multiple \u2014 schema is strict
|
|
655
|
+
- Top-level keys only: \`name\`, \`className\`, \`position\`, \`size\`, \`color\`, \`material\`, \`anchored\`, \`shape\`, \`transparency\`, \`parent\`, \`canCollide\`.
|
|
656
|
+
- Does NOT accept a nested \`properties\` bag. For anything outside those fields use \`insert_instance\` + \`set_properties\`.
|
|
657
|
+
- \`shape\` values: \`Block\`, \`Ball\`, \`Cylinder\`, \`Wedge\`.
|
|
658
|
+
|
|
659
|
+
### Color formats (accepted everywhere)
|
|
660
|
+
- Hex: \`"#RRGGBB"\`
|
|
661
|
+
- RGB string: \`"rgb(255, 128, 0)"\`
|
|
662
|
+
- BrickColor name: \`"Bright red"\`, \`"Institutional white"\`, \`"Really black"\`, etc.
|
|
663
|
+
- Array: \`[r, g, b]\` (0\u20131 floats) or \`[255, 128, 0]\` (auto-detected if any value > 1)
|
|
664
|
+
|
|
665
|
+
### UDim2 / UDim / Vector2 / Color3 coercion (create_ui)
|
|
666
|
+
- UDim2: \`[xScale, xOffset, yScale, yOffset]\` or \`{XScale, XOffset, YScale, YOffset}\`.
|
|
667
|
+
- UDim: \`[scale, offset]\` or a plain number (treated as pixels).
|
|
668
|
+
- Vector2 (e.g. \`AnchorPoint\`): \`[x, y]\` or \`{x, y}\`.
|
|
669
|
+
- 2-element arrays are auto-disambiguated by property name (\`AnchorPoint\` \u2192 Vector2, \`CornerRadius\` \u2192 UDim).
|
|
670
|
+
|
|
671
|
+
### Common GUI property names
|
|
672
|
+
- GUI uses \`Size\`/\`Position\` as **UDim2** \u2014 never Vector3.
|
|
673
|
+
- \`BackgroundColor3\`, \`TextColor3\`, \`BorderColor3\`, \`ImageColor3\` \u2192 Color3.
|
|
674
|
+
- \`Font\` accepts a string enum name like \`"GothamBold"\`, \`"SourceSans"\`.
|
|
675
|
+
- Enum properties take the string name: \`"Center"\`, \`"Left"\`, \`"Fit"\`.
|
|
676
|
+
|
|
677
|
+
### Tool selection cheat-sheet
|
|
678
|
+
- Single 3D part \u2192 \`create_part\`
|
|
679
|
+
- Many 3D parts (tree, building, vehicle) \u2192 \`build_multiple\` with \`groupName\`
|
|
680
|
+
- Full UI tree \u2192 \`create_ui\` (one call, never loop \`insert_instance\` for UI)
|
|
681
|
+
- **Convert/export existing UI \u2192 \`serialize_ui\`** (NOT get_descendants_properties)
|
|
682
|
+
- Adjusting an existing instance \u2192 \`set_properties\` (not \`run_code\`)
|
|
683
|
+
- Anything exotic or procedural \u2192 \`run_code\` as last resort
|
|
684
|
+
|
|
685
|
+
### Verification habits
|
|
686
|
+
- After a build, call \`get_explorer\` or \`get_selection\` to confirm the tree looks right.
|
|
687
|
+
- After editing a script, read it back.
|
|
688
|
+
- After \`run_code\`, check \`get_output\` for errors.
|
|
689
|
+
|
|
690
|
+
### serialize_ui \u2014 the RIGHT tool for UI conversion
|
|
691
|
+
- **Use \`serialize_ui\` when converting existing UI to Roact/React/Fusion components.** It returns a minimal JSON tree with only non-default properties, already in JSON-friendly formats.
|
|
692
|
+
- **Do NOT use \`get_descendants_properties\` for UI conversion** \u2014 it returns a flat list with ~50+ properties per instance (including read-only, deprecated, nil, and default values), which bloats context and confuses conversion.
|
|
693
|
+
- \`serialize_ui\` output maps 1:1 to \`create_ui\` input \u2014 you can round-trip UI through it.
|
|
694
|
+
- The tree structure preserves parent-child hierarchy, so Roact/React children mapping is direct.
|
|
695
|
+
|
|
696
|
+
### UI \u2192 Roact/React conversion cheat-sheet
|
|
697
|
+
- \`serialize_ui\` path \u2192 JSON tree \u2192 map each node to \`Roact.createElement(ClassName, props, childrenDict)\`
|
|
698
|
+
- UDim2 arrays \`[xS, xO, yS, yO]\` \u2192 \`UDim2.new(xS, xO, yS, yO)\`
|
|
699
|
+
- Color3 hex strings \u2192 \`Color3.fromHex("#RRGGBB")\`
|
|
700
|
+
- Vector2 arrays \u2192 \`Vector2.new(x, y)\`
|
|
701
|
+
- UDim arrays \u2192 \`UDim.new(s, o)\`
|
|
702
|
+
- Enum strings like \`"Center"\` \u2192 \`Enum.TextXAlignment.Center\`
|
|
703
|
+
- FontFace \u2192 \`Font.new(family, weight, style)\`
|
|
704
|
+
- UI modifiers (UICorner, UIStroke, UIGradient, UIListLayout, UIPadding) are CHILDREN not props
|
|
705
|
+
- Use instance Name as dictionary key in children table
|
|
706
|
+
`;
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
632
710
|
// src/memory/store.ts
|
|
633
711
|
var store_exports = {};
|
|
634
712
|
__export(store_exports, {
|
|
@@ -1138,7 +1216,7 @@ var init_get_descendants_properties = __esm({
|
|
|
1138
1216
|
init_protocol();
|
|
1139
1217
|
tool6 = {
|
|
1140
1218
|
name: "get_descendants_properties",
|
|
1141
|
-
description: "Easily get all descendants of a UI instance (or any instance) and all of their properties.",
|
|
1219
|
+
description: "Easily get all descendants of a UI instance (or any instance) and all of their properties. By default uses compact mode which strips read-only, nil, deprecated, and default-valued properties to keep responses small.",
|
|
1142
1220
|
parameters: {
|
|
1143
1221
|
type: "object",
|
|
1144
1222
|
properties: {
|
|
@@ -1146,6 +1224,10 @@ var init_get_descendants_properties = __esm({
|
|
|
1146
1224
|
type: "string",
|
|
1147
1225
|
description: 'Full instance path (e.g., "Workspace.Part", "StarterGui.ScreenGui")'
|
|
1148
1226
|
},
|
|
1227
|
+
compact: {
|
|
1228
|
+
type: "boolean",
|
|
1229
|
+
description: "When true (default), strips read-only, nil, deprecated, and default-valued properties to massively reduce response size. Set to false for full property dump."
|
|
1230
|
+
},
|
|
1149
1231
|
outputFile: {
|
|
1150
1232
|
type: "string",
|
|
1151
1233
|
description: "Optional file path to write the JSON result to, useful for very large trees where context limits apply."
|
|
@@ -1157,9 +1239,10 @@ var init_get_descendants_properties = __esm({
|
|
|
1157
1239
|
if (!ctx.isStudioConnected()) {
|
|
1158
1240
|
return { success: false, error: "Studio is not connected" };
|
|
1159
1241
|
}
|
|
1242
|
+
const compact = params.compact !== false;
|
|
1160
1243
|
const response = await ctx.sendToStudio(
|
|
1161
1244
|
CliMsg.GET_DESCENDANTS_PROPERTIES,
|
|
1162
|
-
{ path: params.path },
|
|
1245
|
+
{ path: params.path, compact },
|
|
1163
1246
|
1e3 * 60 * 5
|
|
1164
1247
|
// 5 minute timeout since getting ALL descendants can take a very long time
|
|
1165
1248
|
);
|
|
@@ -1518,7 +1601,7 @@ var init_create_ui = __esm({
|
|
|
1518
1601
|
},
|
|
1519
1602
|
tree: {
|
|
1520
1603
|
type: "object",
|
|
1521
|
-
description: 'The root UI node. Each node has: ClassName (string), Name (string),
|
|
1604
|
+
description: 'The root UI node. Each node has: ClassName (string), Name (string), Children (array of child nodes), and properties. Properties may be specified either flattened at the top level of the node, OR nested under a "properties" / "Properties" / "props" key \u2014 both work. Property values are auto-coerced:\n UDim2: [xScale, xOffset, yScale, yOffset] or {XScale, XOffset, YScale, YOffset}\n Color3: "#hex", "rgb(r,g,b)", [r,g,b], or BrickColor name\n UDim: [scale, offset] or number\n Vector2: [x, y] or {x, y} (auto-disambiguated from UDim by property name)\n NumberRange: [min, max] or number\n Rect: [minX, minY, maxX, maxY] or {MinX, MinY, MaxX, MaxY}\n Font: "GothamBold", "SourceSans", etc. (Enum.Font names)\n Enums: string name like "Center", "Left", "Fit"\n FontFace: {Family, Weight, Style}\n 2-element arrays are auto-disambiguated: AnchorPoint\u2192Vector2, CornerRadius/Padding\u2192UDim, etc.'
|
|
1522
1605
|
},
|
|
1523
1606
|
animate: {
|
|
1524
1607
|
type: "boolean",
|
|
@@ -2499,6 +2582,8 @@ async function startMcpServer() {
|
|
|
2499
2582
|
const mcp = new McpServer({
|
|
2500
2583
|
name: "dominus",
|
|
2501
2584
|
version: "0.2.1"
|
|
2585
|
+
}, {
|
|
2586
|
+
instructions: INTERNAL_MEMORY
|
|
2502
2587
|
});
|
|
2503
2588
|
mcp.tool(
|
|
2504
2589
|
"read_script",
|
|
@@ -2561,14 +2646,15 @@ async function startMcpServer() {
|
|
|
2561
2646
|
);
|
|
2562
2647
|
mcp.tool(
|
|
2563
2648
|
"get_descendants_properties",
|
|
2564
|
-
"Easily get all descendants of a UI instance (or any instance) and all of their properties.",
|
|
2649
|
+
"Easily get all descendants of a UI instance (or any instance) and all of their properties. By default uses compact mode which strips read-only, nil, deprecated, and default-valued properties to keep responses small.",
|
|
2565
2650
|
{
|
|
2566
2651
|
path: z.string().describe('Full instance path (e.g., "Workspace.Part", "StarterGui.ScreenGui")'),
|
|
2652
|
+
compact: z.boolean().optional().default(true).describe("Strip noisy/default properties (default true). Set false for full dump."),
|
|
2567
2653
|
outputFile: z.string().optional().describe("Optional file path to write to prevent limit errors/timeouts")
|
|
2568
2654
|
},
|
|
2569
|
-
async ({ path: path5, outputFile }) => {
|
|
2655
|
+
async ({ path: path5, compact, outputFile }) => {
|
|
2570
2656
|
assertConnected();
|
|
2571
|
-
const res = await bridge.sendRequest(CliMsg.GET_DESCENDANTS_PROPERTIES, { path: path5, outputFile }, 1e3 * 60 * 5);
|
|
2657
|
+
const res = await bridge.sendRequest(CliMsg.GET_DESCENDANTS_PROPERTIES, { path: path5, compact, outputFile }, 1e3 * 60 * 5);
|
|
2572
2658
|
return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
|
|
2573
2659
|
}
|
|
2574
2660
|
);
|
|
@@ -2885,6 +2971,26 @@ async function startMcpServer() {
|
|
|
2885
2971
|
return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
|
|
2886
2972
|
}
|
|
2887
2973
|
);
|
|
2974
|
+
mcp.tool(
|
|
2975
|
+
"serialize_ui",
|
|
2976
|
+
"Serialize an existing Roblox UI tree into a compact, create_ui-compatible JSON tree. This is the reverse of create_ui \u2014 reads any GUI instance and returns a declarative JSON tree with ClassName, Name, non-default properties (Color3 as hex, UDim2 as arrays, etc.), and Children. Perfect for: converting existing UI to Roact/React components, cloning/templating, understanding UI structure, or refactoring. Use this INSTEAD of get_descendants_properties when you need to recreate or convert UI.",
|
|
2977
|
+
{
|
|
2978
|
+
path: z.string().describe('Instance path to serialize (e.g. "StarterGui.MyScreenGui")'),
|
|
2979
|
+
maxDepth: z.number().optional().default(50).describe("Maximum tree depth (default 50)")
|
|
2980
|
+
},
|
|
2981
|
+
async ({ path: path5, maxDepth }) => {
|
|
2982
|
+
assertConnected();
|
|
2983
|
+
const res = await bridge.sendRequest(
|
|
2984
|
+
CliMsg.SERIALIZE_UI,
|
|
2985
|
+
{ path: path5, maxDepth },
|
|
2986
|
+
1e3 * 60 * 2
|
|
2987
|
+
);
|
|
2988
|
+
if (!res.payload.success) {
|
|
2989
|
+
return { content: [{ type: "text", text: `Error: ${res.payload.error ?? "Serialization failed"}` }] };
|
|
2990
|
+
}
|
|
2991
|
+
return { content: [{ type: "text", text: JSON.stringify(res.payload.tree, null, 2) }] };
|
|
2992
|
+
}
|
|
2993
|
+
);
|
|
2888
2994
|
mcp.tool(
|
|
2889
2995
|
"recall_memory",
|
|
2890
2996
|
"Search persistent memory for facts about the current Roblox project",
|
|
@@ -2951,6 +3057,7 @@ var init_server = __esm({
|
|
|
2951
3057
|
init_protocol();
|
|
2952
3058
|
init_store();
|
|
2953
3059
|
init_config();
|
|
3060
|
+
init_internal_memory();
|
|
2954
3061
|
}
|
|
2955
3062
|
});
|
|
2956
3063
|
var CROWN_ART = ` \u25C6 \u25C6 \u25C6
|
|
@@ -4132,6 +4239,7 @@ function toolToOpenAI(tool29) {
|
|
|
4132
4239
|
}
|
|
4133
4240
|
|
|
4134
4241
|
// src/agent/system-prompt.ts
|
|
4242
|
+
init_internal_memory();
|
|
4135
4243
|
function buildSystemPrompt(opts) {
|
|
4136
4244
|
const parts = [];
|
|
4137
4245
|
parts.push(`You are Dominus, an expert AI agent for Roblox Studio development.
|
|
@@ -4283,6 +4391,66 @@ GUI classes use DIFFERENT property types than 3D parts:
|
|
|
4283
4391
|
- All enum properties from string names
|
|
4284
4392
|
- Color3 from hex "#RRGGBB", "rgb(r,g,b)", or BrickColor name strings
|
|
4285
4393
|
|
|
4394
|
+
## Serializing & Converting Existing UI
|
|
4395
|
+
When the user asks to convert, export, recreate, or turn an existing UI into a React/Roact component:
|
|
4396
|
+
|
|
4397
|
+
**Use \`serialize_ui\` \u2014 NOT \`get_descendants_properties\`.**
|
|
4398
|
+
\`serialize_ui\` returns a clean, minimal JSON tree with only non-default properties, values already in JSON-friendly formats (hex colors, UDim2 arrays, enum names), and a proper parent-child hierarchy. It's purpose-built for this exact workflow.
|
|
4399
|
+
|
|
4400
|
+
\`get_descendants_properties\` returns a flat list with ALL properties (including read-only, defaults, deprecated) \u2014 it's much larger and harder to convert.
|
|
4401
|
+
|
|
4402
|
+
### Roblox UI \u2192 Roact/React Conversion Workflow
|
|
4403
|
+
1. Call \`serialize_ui\` with the path (e.g. \`StarterGui.MyScreenGui.MyFrame\`)
|
|
4404
|
+
2. The result is a tree like:
|
|
4405
|
+
\`\`\`json
|
|
4406
|
+
{
|
|
4407
|
+
"ClassName": "Frame", "Name": "MyFrame",
|
|
4408
|
+
"Size": [0.5, 0, 0.3, 0], "BackgroundColor3": "#1a1a2e",
|
|
4409
|
+
"Children": [
|
|
4410
|
+
{ "ClassName": "UICorner", "CornerRadius": [0, 8] },
|
|
4411
|
+
{ "ClassName": "TextLabel", "Name": "Title", "Text": "Hello",
|
|
4412
|
+
"Size": [1, 0, 0.2, 0], "TextColor3": "#ffffff", "BackgroundTransparency": 1 }
|
|
4413
|
+
]
|
|
4414
|
+
}
|
|
4415
|
+
\`\`\`
|
|
4416
|
+
3. Convert to Roact/React-lua using these mappings:
|
|
4417
|
+
- Each JSON node \u2192 \`Roact.createElement(ClassName, props, children)\` or \`React.createElement\`
|
|
4418
|
+
- \`UDim2\` arrays \`[xS, xO, yS, yO]\` \u2192 \`UDim2.new(xS, xO, yS, yO)\`
|
|
4419
|
+
- \`Color3\` hex \`"#RRGGBB"\` \u2192 \`Color3.fromHex("#RRGGBB")\`
|
|
4420
|
+
- \`Vector2\` arrays \`[x, y]\` \u2192 \`Vector2.new(x, y)\`
|
|
4421
|
+
- \`UDim\` arrays \`[s, o]\` \u2192 \`UDim.new(s, o)\`
|
|
4422
|
+
- Enum strings \`"Center"\` \u2192 \`Enum.TextXAlignment.Center\` (resolve the full enum path)
|
|
4423
|
+
- \`Children\` array \u2192 child elements table
|
|
4424
|
+
- UI modifiers (UICorner, UIStroke, UIGradient, UIListLayout, UIPadding, UIScale) \u2192 children of the parent element
|
|
4425
|
+
|
|
4426
|
+
### Example Roact output:
|
|
4427
|
+
\`\`\`lua
|
|
4428
|
+
local function MyFrame()
|
|
4429
|
+
return Roact.createElement("Frame", {
|
|
4430
|
+
Size = UDim2.new(0.5, 0, 0.3, 0),
|
|
4431
|
+
BackgroundColor3 = Color3.fromHex("#1a1a2e"),
|
|
4432
|
+
}, {
|
|
4433
|
+
Corner = Roact.createElement("UICorner", {
|
|
4434
|
+
CornerRadius = UDim.new(0, 8),
|
|
4435
|
+
}),
|
|
4436
|
+
Title = Roact.createElement("TextLabel", {
|
|
4437
|
+
Size = UDim2.new(1, 0, 0.2, 0),
|
|
4438
|
+
Text = "Hello",
|
|
4439
|
+
TextColor3 = Color3.fromHex("#ffffff"),
|
|
4440
|
+
BackgroundTransparency = 1,
|
|
4441
|
+
}),
|
|
4442
|
+
})
|
|
4443
|
+
end
|
|
4444
|
+
\`\`\`
|
|
4445
|
+
|
|
4446
|
+
### Key rules for conversion:
|
|
4447
|
+
- Use the instance \`Name\` as the dictionary key in the children table
|
|
4448
|
+
- UI modifiers (UICorner, UIStroke, etc.) are CHILDREN, not props
|
|
4449
|
+
- Keep the exact property values from serialize_ui \u2014 don't guess or approximate
|
|
4450
|
+
- For Fusion: \`New "Frame" { Size = UDim2.new(...), [Children] = { ... } }\`
|
|
4451
|
+
- Preserve ZIndex ordering when relevant
|
|
4452
|
+
- FontFace objects \u2192 \`Font.new("rbxasset://fonts/families/...", Enum.FontWeight.Bold)\`
|
|
4453
|
+
|
|
4286
4454
|
## ReflectionService
|
|
4287
4455
|
The \`get_class_info\` tool queries Roblox's ReflectionService to return the complete API surface for any class:
|
|
4288
4456
|
- All properties with their exact ValueType
|
|
@@ -4290,7 +4458,9 @@ The \`get_class_info\` tool queries Roblox's ReflectionService to return the com
|
|
|
4290
4458
|
- All events with parameter types
|
|
4291
4459
|
- Superclass, creatability, serialization info
|
|
4292
4460
|
|
|
4293
|
-
Use it whenever you're unsure about property names or types. It's fast and cached
|
|
4461
|
+
Use it whenever you're unsure about property names or types. It's fast and cached.
|
|
4462
|
+
|
|
4463
|
+
${INTERNAL_MEMORY}`);
|
|
4294
4464
|
return parts.join("\n");
|
|
4295
4465
|
}
|
|
4296
4466
|
|