dominus-cli 0.5.0 → 0.5.2
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 +144 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +57 -0
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
- package/plugin/Dominus.rbxm +0 -0
- package/plugin/src/UIBuilder.lua +27 -9
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import { randomBytes } from 'crypto';
|
|
|
19
19
|
import Spinner from 'ink-spinner';
|
|
20
20
|
import OpenAI from 'openai';
|
|
21
21
|
import https from 'https';
|
|
22
|
+
import { fileURLToPath } from 'url';
|
|
22
23
|
|
|
23
24
|
var __defProp = Object.defineProperty;
|
|
24
25
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -628,6 +629,66 @@ var init_ws_client = __esm({
|
|
|
628
629
|
}
|
|
629
630
|
});
|
|
630
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
|
+
- Adjusting an existing instance \u2192 \`set_properties\` (not \`run_code\`)
|
|
682
|
+
- Anything exotic or procedural \u2192 \`run_code\` as last resort
|
|
683
|
+
|
|
684
|
+
### Verification habits
|
|
685
|
+
- After a build, call \`get_explorer\` or \`get_selection\` to confirm the tree looks right.
|
|
686
|
+
- After editing a script, read it back.
|
|
687
|
+
- After \`run_code\`, check \`get_output\` for errors.
|
|
688
|
+
`;
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
|
|
631
692
|
// src/memory/store.ts
|
|
632
693
|
var store_exports = {};
|
|
633
694
|
__export(store_exports, {
|
|
@@ -1517,7 +1578,7 @@ var init_create_ui = __esm({
|
|
|
1517
1578
|
},
|
|
1518
1579
|
tree: {
|
|
1519
1580
|
type: "object",
|
|
1520
|
-
description: 'The root UI node. Each node has: ClassName (string), Name (string),
|
|
1581
|
+
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.'
|
|
1521
1582
|
},
|
|
1522
1583
|
animate: {
|
|
1523
1584
|
type: "boolean",
|
|
@@ -2498,6 +2559,8 @@ async function startMcpServer() {
|
|
|
2498
2559
|
const mcp = new McpServer({
|
|
2499
2560
|
name: "dominus",
|
|
2500
2561
|
version: "0.2.1"
|
|
2562
|
+
}, {
|
|
2563
|
+
instructions: INTERNAL_MEMORY
|
|
2501
2564
|
});
|
|
2502
2565
|
mcp.tool(
|
|
2503
2566
|
"read_script",
|
|
@@ -2950,6 +3013,7 @@ var init_server = __esm({
|
|
|
2950
3013
|
init_protocol();
|
|
2951
3014
|
init_store();
|
|
2952
3015
|
init_config();
|
|
3016
|
+
init_internal_memory();
|
|
2953
3017
|
}
|
|
2954
3018
|
});
|
|
2955
3019
|
var CROWN_ART = ` \u25C6 \u25C6 \u25C6
|
|
@@ -4131,6 +4195,7 @@ function toolToOpenAI(tool29) {
|
|
|
4131
4195
|
}
|
|
4132
4196
|
|
|
4133
4197
|
// src/agent/system-prompt.ts
|
|
4198
|
+
init_internal_memory();
|
|
4134
4199
|
function buildSystemPrompt(opts) {
|
|
4135
4200
|
const parts = [];
|
|
4136
4201
|
parts.push(`You are Dominus, an expert AI agent for Roblox Studio development.
|
|
@@ -4289,7 +4354,9 @@ The \`get_class_info\` tool queries Roblox's ReflectionService to return the com
|
|
|
4289
4354
|
- All events with parameter types
|
|
4290
4355
|
- Superclass, creatability, serialization info
|
|
4291
4356
|
|
|
4292
|
-
Use it whenever you're unsure about property names or types. It's fast and cached
|
|
4357
|
+
Use it whenever you're unsure about property names or types. It's fast and cached.
|
|
4358
|
+
|
|
4359
|
+
${INTERNAL_MEMORY}`);
|
|
4293
4360
|
return parts.join("\n");
|
|
4294
4361
|
}
|
|
4295
4362
|
|
|
@@ -4751,7 +4818,62 @@ function formatUpdateMessage(info) {
|
|
|
4751
4818
|
""
|
|
4752
4819
|
].join("\n");
|
|
4753
4820
|
}
|
|
4754
|
-
|
|
4821
|
+
async function autoUpdate(currentVersion) {
|
|
4822
|
+
const info = await checkForUpdate(currentVersion);
|
|
4823
|
+
if (!info?.updateAvailable) {
|
|
4824
|
+
return { success: true, from: currentVersion, to: currentVersion };
|
|
4825
|
+
}
|
|
4826
|
+
const managers = [
|
|
4827
|
+
{ name: "pnpm", check: "pnpm list -g dominus-cli", cmd: "pnpm add -g dominus-cli@latest" },
|
|
4828
|
+
{ name: "npm", check: "npm list -g dominus-cli", cmd: "npm install -g dominus-cli@latest" },
|
|
4829
|
+
{ name: "yarn", check: "yarn global list --pattern dominus-cli", cmd: "yarn global add dominus-cli@latest" }
|
|
4830
|
+
];
|
|
4831
|
+
let installCmd = null;
|
|
4832
|
+
for (const mgr of managers) {
|
|
4833
|
+
try {
|
|
4834
|
+
const out = execSync(mgr.check, { stdio: "pipe", timeout: 1e4 }).toString();
|
|
4835
|
+
if (out.includes("dominus-cli")) {
|
|
4836
|
+
installCmd = mgr.cmd;
|
|
4837
|
+
break;
|
|
4838
|
+
}
|
|
4839
|
+
} catch {
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
if (!installCmd) {
|
|
4843
|
+
try {
|
|
4844
|
+
const out = execSync("pnpm list -g dominus-cli", { stdio: "pipe", timeout: 1e4 }).toString();
|
|
4845
|
+
if (out.includes("link:")) {
|
|
4846
|
+
const pkgPath = path4.resolve(__dirname$1, "..");
|
|
4847
|
+
if (fs5.existsSync(path4.join(pkgPath, ".git"))) {
|
|
4848
|
+
try {
|
|
4849
|
+
execSync("git pull", { cwd: pkgPath, stdio: "pipe", timeout: 3e4 });
|
|
4850
|
+
execSync("pnpm install", { cwd: pkgPath, stdio: "pipe", timeout: 6e4 });
|
|
4851
|
+
execSync("pnpm build", { cwd: pkgPath, stdio: "pipe", timeout: 6e4 });
|
|
4852
|
+
execSync("pnpm build:plugin", { cwd: pkgPath, stdio: "pipe", timeout: 3e4 });
|
|
4853
|
+
return { success: true, from: currentVersion, to: info.latestVersion };
|
|
4854
|
+
} catch (err) {
|
|
4855
|
+
return { success: false, from: currentVersion, to: info.latestVersion, error: `Git pull/rebuild failed: ${err}` };
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
return { success: false, from: currentVersion, to: info.latestVersion, error: 'Linked install without git \u2014 run "pnpm build" manually in the repo' };
|
|
4859
|
+
}
|
|
4860
|
+
} catch {
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
if (!installCmd) {
|
|
4864
|
+
installCmd = `npm install -g ${NPM_PACKAGE}@latest`;
|
|
4865
|
+
}
|
|
4866
|
+
try {
|
|
4867
|
+
execSync(installCmd, { stdio: "pipe", timeout: 12e4 });
|
|
4868
|
+
writeCache({ lastCheck: 0, latestVersion: null });
|
|
4869
|
+
return { success: true, from: currentVersion, to: info.latestVersion };
|
|
4870
|
+
} catch (err) {
|
|
4871
|
+
return { success: false, from: currentVersion, to: info.latestVersion, error: `Update command failed: ${err}` };
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
var __dirname$1 = path4.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, "$1"));
|
|
4875
|
+
var __dirname2 = path4.dirname(fileURLToPath(import.meta.url));
|
|
4876
|
+
var VERSION = JSON.parse(fs5.readFileSync(path4.join(__dirname2, "..", "package.json"), "utf-8")).version;
|
|
4755
4877
|
var program = new Command();
|
|
4756
4878
|
program.name("dominus").description("AI-powered autonomous agent for Roblox Studio development").version(VERSION);
|
|
4757
4879
|
program.command("start", { isDefault: true }).description("Launch the Dominus TUI agent").option("-p, --port <port>", "WebSocket server port", "18088").action(async (opts) => {
|
|
@@ -4863,9 +4985,24 @@ rulesCmd.command("list").description("List all rules").action(() => {
|
|
|
4863
4985
|
}
|
|
4864
4986
|
console.log("");
|
|
4865
4987
|
});
|
|
4988
|
+
program.command("update").description("Auto-update Dominus to the latest version").action(async () => {
|
|
4989
|
+
console.log(` Current version: ${VERSION}`);
|
|
4990
|
+
console.log(" Checking for updates...");
|
|
4991
|
+
const result = await autoUpdate(VERSION);
|
|
4992
|
+
if (result.from === result.to && result.success) {
|
|
4993
|
+
console.log(" Already on the latest version.");
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
if (result.success) {
|
|
4997
|
+
console.log(` \u2714 Updated: ${result.from} \u2192 ${result.to}`);
|
|
4998
|
+
console.log(" Restart dominus to use the new version.");
|
|
4999
|
+
} else {
|
|
5000
|
+
console.error(` \u2718 Update failed: ${result.error}`);
|
|
5001
|
+
}
|
|
5002
|
+
});
|
|
4866
5003
|
program.command("install-plugin").description("Build & install the Dominus plugin into Roblox Studio").action(async () => {
|
|
4867
|
-
const { execSync:
|
|
4868
|
-
const packageRoot = path4.resolve(import.meta.dirname ??
|
|
5004
|
+
const { execSync: execSync3 } = await import('child_process');
|
|
5005
|
+
const packageRoot = path4.resolve(import.meta.dirname ?? __dirname2, "..");
|
|
4869
5006
|
const pluginDir = path4.join(packageRoot, "plugin");
|
|
4870
5007
|
const pluginProject = path4.join(pluginDir, "default.project.json");
|
|
4871
5008
|
const studioPlugins = path4.join(
|
|
@@ -4886,14 +5023,14 @@ program.command("install-plugin").description("Build & install the Dominus plugi
|
|
|
4886
5023
|
}
|
|
4887
5024
|
let rojoAvailable = false;
|
|
4888
5025
|
try {
|
|
4889
|
-
|
|
5026
|
+
execSync3("rojo --version", { stdio: "pipe" });
|
|
4890
5027
|
rojoAvailable = true;
|
|
4891
5028
|
} catch {
|
|
4892
5029
|
}
|
|
4893
5030
|
if (rojoAvailable) {
|
|
4894
5031
|
try {
|
|
4895
5032
|
console.log(" Building plugin with Rojo...");
|
|
4896
|
-
|
|
5033
|
+
execSync3(`rojo build "${pluginDir}" -o "${destFile}"`, { stdio: "pipe" });
|
|
4897
5034
|
console.log(` \u2714 Plugin built and installed to: ${destFile}`);
|
|
4898
5035
|
console.log(" Restart Roblox Studio to load the plugin.");
|
|
4899
5036
|
} catch (err) {
|