dominus-cli 0.2.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import fs4, { existsSync, readFileSync, unlinkSync } from 'fs';
3
- import path3, { join } from 'path';
4
- import os2, { tmpdir } from 'os';
2
+ import fs5, { existsSync, readFileSync, unlinkSync } from 'fs';
3
+ import path4, { join } from 'path';
4
+ import os3, { tmpdir } from 'os';
5
5
  import { nanoid } from 'nanoid';
6
6
  import { WebSocket, WebSocketServer } from 'ws';
7
7
  import { EventEmitter } from 'events';
@@ -18,6 +18,7 @@ import { execSync } from 'child_process';
18
18
  import { randomBytes } from 'crypto';
19
19
  import Spinner from 'ink-spinner';
20
20
  import OpenAI from 'openai';
21
+ import https from 'https';
21
22
 
22
23
  var __defProp = Object.defineProperty;
23
24
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -55,14 +56,14 @@ function resolveProviderSettings(config) {
55
56
  };
56
57
  }
57
58
  function ensureDir() {
58
- if (!fs4.existsSync(DOMINUS_DIR)) {
59
- fs4.mkdirSync(DOMINUS_DIR, { recursive: true });
59
+ if (!fs5.existsSync(DOMINUS_DIR)) {
60
+ fs5.mkdirSync(DOMINUS_DIR, { recursive: true });
60
61
  }
61
62
  }
62
63
  function readJson(filePath, defaults) {
63
64
  try {
64
- if (fs4.existsSync(filePath)) {
65
- const raw = fs4.readFileSync(filePath, "utf-8");
65
+ if (fs5.existsSync(filePath)) {
66
+ const raw = fs5.readFileSync(filePath, "utf-8");
66
67
  return { ...defaults, ...JSON.parse(raw) };
67
68
  }
68
69
  } catch {
@@ -71,7 +72,7 @@ function readJson(filePath, defaults) {
71
72
  }
72
73
  function writeJson(filePath, data) {
73
74
  ensureDir();
74
- fs4.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
75
+ fs5.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
75
76
  }
76
77
  function loadConfig() {
77
78
  ensureDir();
@@ -123,10 +124,10 @@ function createConfigAccess() {
123
124
  var DOMINUS_DIR, CONFIG_PATH, DB_PATH, RULES_PATH, PROVIDERS, DEFAULTS, DEFAULT_RULES;
124
125
  var init_config = __esm({
125
126
  "src/config/config.ts"() {
126
- DOMINUS_DIR = path3.join(os2.homedir(), ".dominus");
127
- CONFIG_PATH = path3.join(DOMINUS_DIR, "config.json");
128
- DB_PATH = path3.join(DOMINUS_DIR, "dominus.db");
129
- RULES_PATH = path3.join(DOMINUS_DIR, "rules.json");
127
+ DOMINUS_DIR = path4.join(os3.homedir(), ".dominus");
128
+ CONFIG_PATH = path4.join(DOMINUS_DIR, "config.json");
129
+ DB_PATH = path4.join(DOMINUS_DIR, "dominus.db");
130
+ RULES_PATH = path4.join(DOMINUS_DIR, "rules.json");
130
131
  PROVIDERS = {
131
132
  openai: {
132
133
  name: "OpenAI",
@@ -641,14 +642,14 @@ __export(store_exports, {
641
642
  function persist() {
642
643
  if (!db) return;
643
644
  const data = db.export();
644
- fs4.writeFileSync(dbPath, Buffer.from(data));
645
+ fs5.writeFileSync(dbPath, Buffer.from(data));
645
646
  }
646
647
  async function initMemoryStore() {
647
648
  if (db) return;
648
649
  dbPath = getDbPath();
649
650
  const SQL = await initSqlJs();
650
- if (fs4.existsSync(dbPath)) {
651
- const buffer = fs4.readFileSync(dbPath);
651
+ if (fs5.existsSync(dbPath)) {
652
+ const buffer = fs5.readFileSync(dbPath);
652
653
  db = new SQL.Database(buffer);
653
654
  } else {
654
655
  db = new SQL.Database();
@@ -939,10 +940,10 @@ var init_read_script = __esm({
939
940
  if (!ctx.isStudioConnected()) {
940
941
  return { success: false, error: "Studio is not connected" };
941
942
  }
942
- const path4 = params.path;
943
- const response = await ctx.sendToStudio(CliMsg.GET_SCRIPT, { path: path4 });
943
+ const path5 = params.path;
944
+ const response = await ctx.sendToStudio(CliMsg.GET_SCRIPT, { path: path5 });
944
945
  if (!response.payload) {
945
- return { success: false, error: `Script not found: ${path4}` };
946
+ return { success: false, error: `Script not found: ${path5}` };
946
947
  }
947
948
  return {
948
949
  success: true,
@@ -988,14 +989,14 @@ var init_edit_script = __esm({
988
989
  if (!ctx.isStudioConnected()) {
989
990
  return { success: false, error: "Studio is not connected" };
990
991
  }
991
- const path4 = params.path;
992
+ const path5 = params.path;
992
993
  const source = params.source;
993
- const response = await ctx.sendToStudio(CliMsg.SET_SCRIPT, { path: path4, source });
994
+ const response = await ctx.sendToStudio(CliMsg.SET_SCRIPT, { path: path5, source });
994
995
  const payload = response.payload;
995
996
  if (!payload.success) {
996
997
  return { success: false, error: payload.error ?? "Failed to edit script" };
997
998
  }
998
- return { success: true, data: { path: path4, linesWritten: source.split("\n").length } };
999
+ return { success: true, data: { path: path5, linesWritten: source.split("\n").length } };
999
1000
  }
1000
1001
  };
1001
1002
  }
@@ -1681,8 +1682,8 @@ __export(clone_instance_exports, {
1681
1682
  tool: () => tool18
1682
1683
  });
1683
1684
  function buildCloneCode(params) {
1684
- const path4 = params.path;
1685
- const parts = path4.split(".");
1685
+ const path5 = params.path;
1686
+ const parts = path5.split(".");
1686
1687
  let resolve = "game";
1687
1688
  for (const p of parts) {
1688
1689
  resolve += `["${p}"]`;
@@ -1823,8 +1824,8 @@ __export(build_multiple_exports, {
1823
1824
  });
1824
1825
  function generateBatchCode(parts, groupName, groupParent) {
1825
1826
  const lines = [];
1826
- function resolveParent(path4) {
1827
- const segs = path4.split(".");
1827
+ function resolveParent(path5) {
1828
+ const segs = path5.split(".");
1828
1829
  let r = "game";
1829
1830
  for (const s of segs) r += `["${s}"]`;
1830
1831
  return r;
@@ -2088,11 +2089,11 @@ var init_upload_asset = __esm({
2088
2089
  const assetType = params.assetType;
2089
2090
  const name = params.name;
2090
2091
  const description = params.description ?? "";
2091
- if (!fs4.existsSync(filePath)) {
2092
+ if (!fs5.existsSync(filePath)) {
2092
2093
  return { success: false, error: `File not found: ${filePath}` };
2093
2094
  }
2094
- const fileBuffer = fs4.readFileSync(filePath);
2095
- const fileName = path3.basename(filePath);
2095
+ const fileBuffer = fs5.readFileSync(filePath);
2096
+ const fileName = path4.basename(filePath);
2096
2097
  const typeMapping = {
2097
2098
  Image: "Decal",
2098
2099
  Audio: "Audio",
@@ -2166,15 +2167,15 @@ async function startMcpServer() {
2166
2167
  }
2167
2168
  const mcp = new McpServer({
2168
2169
  name: "dominus",
2169
- version: "0.2.0"
2170
+ version: "0.2.1"
2170
2171
  });
2171
2172
  mcp.tool(
2172
2173
  "read_script",
2173
2174
  "Read the source code of a script in Roblox Studio",
2174
2175
  { path: z.string().describe('Full instance path, e.g. "ServerScriptService.GameManager"') },
2175
- async ({ path: path4 }) => {
2176
+ async ({ path: path5 }) => {
2176
2177
  assertConnected();
2177
- const res = await bridge.sendRequest(CliMsg.GET_SCRIPT, { path: path4 });
2178
+ const res = await bridge.sendRequest(CliMsg.GET_SCRIPT, { path: path5 });
2178
2179
  return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
2179
2180
  }
2180
2181
  );
@@ -2185,9 +2186,9 @@ async function startMcpServer() {
2185
2186
  path: z.string().describe("Full instance path"),
2186
2187
  source: z.string().describe("New complete source code")
2187
2188
  },
2188
- async ({ path: path4, source }) => {
2189
+ async ({ path: path5, source }) => {
2189
2190
  assertConnected();
2190
- const res = await bridge.sendRequest(CliMsg.SET_SCRIPT, { path: path4, source });
2191
+ const res = await bridge.sendRequest(CliMsg.SET_SCRIPT, { path: path5, source });
2191
2192
  return { content: [{ type: "text", text: JSON.stringify(res.payload) }] };
2192
2193
  }
2193
2194
  );
@@ -2221,9 +2222,9 @@ async function startMcpServer() {
2221
2222
  "get_properties",
2222
2223
  "Get all properties of an instance in Roblox Studio",
2223
2224
  { path: z.string().describe("Full instance path") },
2224
- async ({ path: path4 }) => {
2225
+ async ({ path: path5 }) => {
2225
2226
  assertConnected();
2226
- const res = await bridge.sendRequest(CliMsg.GET_PROPERTIES, { path: path4 });
2227
+ const res = await bridge.sendRequest(CliMsg.GET_PROPERTIES, { path: path5 });
2227
2228
  return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
2228
2229
  }
2229
2230
  );
@@ -2234,9 +2235,9 @@ async function startMcpServer() {
2234
2235
  path: z.string().describe("Full instance path"),
2235
2236
  properties: z.record(z.unknown()).describe("Key-value pairs of properties to set")
2236
2237
  },
2237
- async ({ path: path4, properties }) => {
2238
+ async ({ path: path5, properties }) => {
2238
2239
  assertConnected();
2239
- const res = await bridge.sendRequest(CliMsg.SET_PROPERTIES, { path: path4, properties });
2240
+ const res = await bridge.sendRequest(CliMsg.SET_PROPERTIES, { path: path5, properties });
2240
2241
  return { content: [{ type: "text", text: JSON.stringify(res.payload) }] };
2241
2242
  }
2242
2243
  );
@@ -2264,9 +2265,9 @@ async function startMcpServer() {
2264
2265
  "delete_instance",
2265
2266
  "Delete an instance from the Roblox Studio DataModel",
2266
2267
  { path: z.string().describe("Full instance path to delete") },
2267
- async ({ path: path4 }) => {
2268
+ async ({ path: path5 }) => {
2268
2269
  assertConnected();
2269
- const res = await bridge.sendRequest(CliMsg.DELETE_INSTANCE, { path: path4 });
2270
+ const res = await bridge.sendRequest(CliMsg.DELETE_INSTANCE, { path: path5 });
2270
2271
  return { content: [{ type: "text", text: JSON.stringify(res.payload) }] };
2271
2272
  }
2272
2273
  );
@@ -2463,8 +2464,8 @@ async function startMcpServer() {
2463
2464
  const parentParts = parent.split(".");
2464
2465
  let parentResolve = "game";
2465
2466
  for (const p of parentParts) parentResolve += `["${p}"]`;
2466
- const resolves = params.paths.map((path4) => {
2467
- const parts = path4.split(".");
2467
+ const resolves = params.paths.map((path5) => {
2468
+ const parts = path5.split(".");
2468
2469
  let r = "game";
2469
2470
  for (const part of parts) r += `["${part}"]`;
2470
2471
  return r;
@@ -2504,8 +2505,8 @@ async function startMcpServer() {
2504
2505
  const parts = params.parts;
2505
2506
  const groupName = params.groupName;
2506
2507
  const groupParent = params.groupParent ?? "Workspace";
2507
- function resolveP(path4) {
2508
- const segs = path4.split(".");
2508
+ function resolveP(path5) {
2509
+ const segs = path5.split(".");
2509
2510
  let r = "game";
2510
2511
  for (const s of segs) r += `["${s}"]`;
2511
2512
  return r;
@@ -4306,7 +4307,98 @@ function createDefaultRegistry() {
4306
4307
  // src/index.tsx
4307
4308
  init_store();
4308
4309
  init_config();
4309
- var VERSION = "0.2.0";
4310
+ var CACHE_DIR = path4.join(os3.homedir(), ".dominus");
4311
+ var CACHE_FILE = path4.join(CACHE_DIR, "update-check.json");
4312
+ var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
4313
+ var NPM_PACKAGE = "dominus-cli";
4314
+ function readCache() {
4315
+ try {
4316
+ if (fs5.existsSync(CACHE_FILE)) {
4317
+ return JSON.parse(fs5.readFileSync(CACHE_FILE, "utf-8"));
4318
+ }
4319
+ } catch {
4320
+ }
4321
+ return { lastCheck: 0, latestVersion: null };
4322
+ }
4323
+ function writeCache(cache) {
4324
+ try {
4325
+ if (!fs5.existsSync(CACHE_DIR)) fs5.mkdirSync(CACHE_DIR, { recursive: true });
4326
+ fs5.writeFileSync(CACHE_FILE, JSON.stringify(cache), "utf-8");
4327
+ } catch {
4328
+ }
4329
+ }
4330
+ function fetchLatestVersion() {
4331
+ return new Promise((resolve) => {
4332
+ const req = https.get(
4333
+ `https://registry.npmjs.org/${NPM_PACKAGE}/latest`,
4334
+ { headers: { Accept: "application/json" }, timeout: 5e3 },
4335
+ (res) => {
4336
+ if (res.statusCode !== 200) {
4337
+ resolve(null);
4338
+ res.resume();
4339
+ return;
4340
+ }
4341
+ let body = "";
4342
+ res.on("data", (c) => body += c);
4343
+ res.on("end", () => {
4344
+ try {
4345
+ resolve(JSON.parse(body).version ?? null);
4346
+ } catch {
4347
+ resolve(null);
4348
+ }
4349
+ });
4350
+ }
4351
+ );
4352
+ req.on("error", () => resolve(null));
4353
+ req.on("timeout", () => {
4354
+ req.destroy();
4355
+ resolve(null);
4356
+ });
4357
+ });
4358
+ }
4359
+ function compareVersions(current, latest) {
4360
+ const a = current.split(".").map(Number);
4361
+ const b = latest.split(".").map(Number);
4362
+ for (let i = 0; i < 3; i++) {
4363
+ if ((b[i] ?? 0) > (a[i] ?? 0)) return 1;
4364
+ if ((b[i] ?? 0) < (a[i] ?? 0)) return -1;
4365
+ }
4366
+ return 0;
4367
+ }
4368
+ async function checkForUpdate(currentVersion) {
4369
+ try {
4370
+ const cache = readCache();
4371
+ const now = Date.now();
4372
+ if (now - cache.lastCheck < CHECK_INTERVAL_MS && cache.latestVersion) {
4373
+ if (compareVersions(currentVersion, cache.latestVersion) > 0) {
4374
+ return { updateAvailable: true, currentVersion, latestVersion: cache.latestVersion };
4375
+ }
4376
+ return null;
4377
+ }
4378
+ const latest = await fetchLatestVersion();
4379
+ writeCache({ lastCheck: now, latestVersion: latest });
4380
+ if (latest && compareVersions(currentVersion, latest) > 0) {
4381
+ return { updateAvailable: true, currentVersion, latestVersion: latest };
4382
+ }
4383
+ } catch {
4384
+ }
4385
+ return null;
4386
+ }
4387
+ function formatUpdateMessage(info) {
4388
+ const line1 = `Update available: ${info.currentVersion} \u2192 ${info.latestVersion}`;
4389
+ const line2 = `Run: npm i -g ${NPM_PACKAGE}`;
4390
+ const width = Math.max(line1.length, line2.length) + 4;
4391
+ const pad = (s) => ` \u2502 ${s}${" ".repeat(width - s.length - 4)} \u2502`;
4392
+ return [
4393
+ "",
4394
+ ` \u256D${"\u2500".repeat(width)}\u256E`,
4395
+ pad(line1),
4396
+ pad(line2),
4397
+ ` \u2570${"\u2500".repeat(width)}\u256F`,
4398
+ ""
4399
+ ].join("\n");
4400
+ }
4401
+ var VERSION = "0.2.1";
4310
4402
  var program = new Command();
4311
4403
  program.name("dominus").description("AI-powered autonomous agent for Roblox Studio development").version(VERSION);
4312
4404
  program.command("start", { isDefault: true }).description("Launch the Dominus TUI agent").option("-p, --port <port>", "WebSocket server port", "18088").action(async (opts) => {
@@ -4326,6 +4418,10 @@ program.command("start", { isDefault: true }).description("Launch the Dominus TU
4326
4418
  setConfigValue("userName", firstName);
4327
4419
  }
4328
4420
  }
4421
+ checkForUpdate(VERSION).then((info) => {
4422
+ if (info) process.stderr.write(formatUpdateMessage(info));
4423
+ }).catch(() => {
4424
+ });
4329
4425
  await launchApp(port);
4330
4426
  });
4331
4427
  var configCmd = program.command("config").description("Manage Dominus configuration");
@@ -4416,24 +4512,24 @@ rulesCmd.command("list").description("List all rules").action(() => {
4416
4512
  });
4417
4513
  program.command("install-plugin").description("Build & install the Dominus plugin into Roblox Studio").action(async () => {
4418
4514
  const { execSync: execSync2 } = await import('child_process');
4419
- const packageRoot = path3.resolve(import.meta.dirname ?? __dirname, "..");
4420
- const pluginDir = path3.join(packageRoot, "plugin");
4421
- const pluginProject = path3.join(pluginDir, "default.project.json");
4422
- const studioPlugins = path3.join(
4423
- os2.homedir(),
4515
+ const packageRoot = path4.resolve(import.meta.dirname ?? __dirname, "..");
4516
+ const pluginDir = path4.join(packageRoot, "plugin");
4517
+ const pluginProject = path4.join(pluginDir, "default.project.json");
4518
+ const studioPlugins = path4.join(
4519
+ os3.homedir(),
4424
4520
  "AppData",
4425
4521
  "Local",
4426
4522
  "Roblox",
4427
4523
  "Plugins"
4428
4524
  );
4429
- const destFile = path3.join(studioPlugins, "Dominus.rbxm");
4430
- if (!fs4.existsSync(pluginProject)) {
4525
+ const destFile = path4.join(studioPlugins, "Dominus.rbxm");
4526
+ if (!fs5.existsSync(pluginProject)) {
4431
4527
  console.log(" \u2716 Plugin source not found.");
4432
4528
  console.log(` Expected at: ${pluginDir}`);
4433
4529
  return;
4434
4530
  }
4435
- if (!fs4.existsSync(studioPlugins)) {
4436
- fs4.mkdirSync(studioPlugins, { recursive: true });
4531
+ if (!fs5.existsSync(studioPlugins)) {
4532
+ fs5.mkdirSync(studioPlugins, { recursive: true });
4437
4533
  }
4438
4534
  let rojoAvailable = false;
4439
4535
  try {
@@ -4460,49 +4556,49 @@ program.command("mcp").description("Start the Dominus MCP server (for Cursor, Cl
4460
4556
  await startMcpServer2();
4461
4557
  });
4462
4558
  function getMcpTargets() {
4463
- const home = os2.homedir();
4464
- const appData = process.env.APPDATA || path3.join(home, "AppData", "Roaming");
4465
- const localAppData = process.env.LOCALAPPDATA || path3.join(home, "AppData", "Local");
4559
+ const home = os3.homedir();
4560
+ const appData = process.env.APPDATA || path4.join(home, "AppData", "Roaming");
4561
+ const localAppData = process.env.LOCALAPPDATA || path4.join(home, "AppData", "Local");
4466
4562
  const cwd = process.cwd();
4467
4563
  return [
4468
4564
  {
4469
4565
  name: "Cursor (project)",
4470
- configPath: path3.join(cwd, ".cursor", "mcp.json"),
4566
+ configPath: path4.join(cwd, ".cursor", "mcp.json"),
4471
4567
  keyPath: ["mcpServers"]
4472
4568
  },
4473
4569
  {
4474
4570
  name: "Cursor (global)",
4475
- configPath: path3.join(home, ".cursor", "mcp.json"),
4571
+ configPath: path4.join(home, ".cursor", "mcp.json"),
4476
4572
  keyPath: ["mcpServers"]
4477
4573
  },
4478
4574
  {
4479
4575
  name: "Claude Desktop",
4480
- configPath: path3.join(appData, "Claude", "claude_desktop_config.json"),
4576
+ configPath: path4.join(appData, "Claude", "claude_desktop_config.json"),
4481
4577
  keyPath: ["mcpServers"]
4482
4578
  },
4483
4579
  {
4484
4580
  name: "Claude Code",
4485
- configPath: path3.join(home, ".claude.json"),
4581
+ configPath: path4.join(home, ".claude.json"),
4486
4582
  keyPath: ["mcpServers"]
4487
4583
  },
4488
4584
  {
4489
4585
  name: "Windsurf (project)",
4490
- configPath: path3.join(cwd, ".windsurf", "mcp.json"),
4586
+ configPath: path4.join(cwd, ".windsurf", "mcp.json"),
4491
4587
  keyPath: ["mcpServers"]
4492
4588
  },
4493
4589
  {
4494
4590
  name: "Windsurf (global)",
4495
- configPath: path3.join(home, ".codeium", "windsurf", "mcp_config.json"),
4591
+ configPath: path4.join(home, ".codeium", "windsurf", "mcp_config.json"),
4496
4592
  keyPath: ["mcpServers"]
4497
4593
  },
4498
4594
  {
4499
4595
  name: "VS Code (project)",
4500
- configPath: path3.join(cwd, ".vscode", "mcp.json"),
4596
+ configPath: path4.join(cwd, ".vscode", "mcp.json"),
4501
4597
  keyPath: ["servers"]
4502
4598
  },
4503
4599
  {
4504
4600
  name: "VS Code (global)",
4505
- configPath: path3.join(localAppData, "Code", "User", "settings.json"),
4601
+ configPath: path4.join(localAppData, "Code", "User", "settings.json"),
4506
4602
  keyPath: ["mcp", "servers"]
4507
4603
  }
4508
4604
  ];
@@ -4514,9 +4610,9 @@ var dominusEntry = {
4514
4610
  };
4515
4611
  function injectMcpConfig(target) {
4516
4612
  let config = {};
4517
- if (fs4.existsSync(target.configPath)) {
4613
+ if (fs5.existsSync(target.configPath)) {
4518
4614
  try {
4519
- config = JSON.parse(fs4.readFileSync(target.configPath, "utf-8"));
4615
+ config = JSON.parse(fs5.readFileSync(target.configPath, "utf-8"));
4520
4616
  } catch {
4521
4617
  config = {};
4522
4618
  }
@@ -4532,12 +4628,12 @@ function injectMcpConfig(target) {
4532
4628
  return { status: "already" };
4533
4629
  }
4534
4630
  obj["dominus"] = { ...dominusEntry };
4535
- const dir = path3.dirname(target.configPath);
4536
- if (!fs4.existsSync(dir)) {
4537
- fs4.mkdirSync(dir, { recursive: true });
4631
+ const dir = path4.dirname(target.configPath);
4632
+ if (!fs5.existsSync(dir)) {
4633
+ fs5.mkdirSync(dir, { recursive: true });
4538
4634
  }
4539
- fs4.writeFileSync(target.configPath, JSON.stringify(config, null, 2), "utf-8");
4540
- return { status: fs4.existsSync(target.configPath) ? "installed" : "created" };
4635
+ fs5.writeFileSync(target.configPath, JSON.stringify(config, null, 2), "utf-8");
4636
+ return { status: fs5.existsSync(target.configPath) ? "installed" : "created" };
4541
4637
  }
4542
4638
  program.command("mcp-install").description("Auto-install Dominus MCP into Cursor, VS Code, Claude Desktop, Windsurf, etc.").option("-a, --all", "Install to all detected editors").action(async (opts) => {
4543
4639
  const targets = getMcpTargets();
@@ -4559,7 +4655,7 @@ program.command("mcp-install").description("Auto-install Dominus MCP into Cursor
4559
4655
  }
4560
4656
  const detected = targets.map((t) => ({
4561
4657
  target: t,
4562
- exists: fs4.existsSync(path3.dirname(t.configPath))
4658
+ exists: fs5.existsSync(path4.dirname(t.configPath))
4563
4659
  }));
4564
4660
  const toInstall = detected.filter((d) => d.exists);
4565
4661
  if (toInstall.length === 0) {
@@ -4632,23 +4728,23 @@ program.command("mcp-setup").description("Print MCP configuration for manual set
4632
4728
  console.log("");
4633
4729
  });
4634
4730
  function buildPluginXml(pluginDir, destFile) {
4635
- const srcDir = path3.join(pluginDir, "src");
4636
- if (!fs4.existsSync(srcDir)) {
4731
+ const srcDir = path4.join(pluginDir, "src");
4732
+ if (!fs5.existsSync(srcDir)) {
4637
4733
  console.log(` \u2716 Plugin source directory not found: ${srcDir}`);
4638
4734
  return;
4639
4735
  }
4640
- const files = fs4.readdirSync(srcDir).filter((f) => f.endsWith(".lua"));
4736
+ const files = fs5.readdirSync(srcDir).filter((f) => f.endsWith(".lua"));
4641
4737
  const mainFile = files.find((f) => f === "init.server.lua");
4642
4738
  const moduleFiles = files.filter((f) => f !== "init.server.lua");
4643
4739
  if (!mainFile) {
4644
4740
  console.log(" \u2716 init.server.lua not found in plugin source");
4645
4741
  return;
4646
4742
  }
4647
- const mainSource = fs4.readFileSync(path3.join(srcDir, mainFile), "utf-8");
4743
+ const mainSource = fs5.readFileSync(path4.join(srcDir, mainFile), "utf-8");
4648
4744
  let moduleItems = "";
4649
4745
  for (const mf of moduleFiles) {
4650
4746
  const modName = mf.replace(".lua", "");
4651
- const modSource = fs4.readFileSync(path3.join(srcDir, mf), "utf-8");
4747
+ const modSource = fs5.readFileSync(path4.join(srcDir, mf), "utf-8");
4652
4748
  moduleItems += `
4653
4749
  <Item class="ModuleScript" referent="${modName}">
4654
4750
  <Properties>
@@ -4666,7 +4762,7 @@ function buildPluginXml(pluginDir, destFile) {
4666
4762
  </Properties>${moduleItems}
4667
4763
  </Item>
4668
4764
  </roblox>`;
4669
- fs4.writeFileSync(destFile, rbxmx, "utf-8");
4765
+ fs5.writeFileSync(destFile, rbxmx, "utf-8");
4670
4766
  console.log(` \u2714 Plugin installed to: ${destFile}`);
4671
4767
  console.log(" Restart Roblox Studio to load the plugin.");
4672
4768
  }