uloop-cli 0.65.0 → 0.66.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.
@@ -5486,13 +5486,13 @@ var DirectUnityClient = class {
5486
5486
  requestId = 0;
5487
5487
  receiveBuffer = Buffer.alloc(0);
5488
5488
  async connect() {
5489
- return new Promise((resolve5, reject) => {
5489
+ return new Promise((resolve6, reject) => {
5490
5490
  this.socket = new net.Socket();
5491
5491
  this.socket.on("error", (error) => {
5492
5492
  reject(new Error(`Connection error: ${error.message}`));
5493
5493
  });
5494
5494
  this.socket.connect(this.port, this.host, () => {
5495
- resolve5();
5495
+ resolve6();
5496
5496
  });
5497
5497
  });
5498
5498
  }
@@ -5508,7 +5508,7 @@ var DirectUnityClient = class {
5508
5508
  };
5509
5509
  const requestJson = JSON.stringify(request);
5510
5510
  const framedMessage = createFrame(requestJson);
5511
- return new Promise((resolve5, reject) => {
5511
+ return new Promise((resolve6, reject) => {
5512
5512
  const socket = this.socket;
5513
5513
  const cleanup = () => {
5514
5514
  clearTimeout(timeoutId);
@@ -5545,7 +5545,7 @@ var DirectUnityClient = class {
5545
5545
  reject(new Error(`Unity error: ${response.error.message}`));
5546
5546
  return;
5547
5547
  }
5548
- resolve5(response.result);
5548
+ resolve6(response.result);
5549
5549
  };
5550
5550
  const onError = (error) => {
5551
5551
  cleanup();
@@ -5759,13 +5759,41 @@ function resolvePortFromUnitySettings(settings) {
5759
5759
  }
5760
5760
  return null;
5761
5761
  }
5762
- async function resolveUnityPort(explicitPort) {
5762
+ function validateProjectPath(projectPath) {
5763
+ const resolved = (0, import_path2.resolve)(projectPath);
5764
+ if (!(0, import_fs2.existsSync)(resolved)) {
5765
+ throw new Error(`Path does not exist: ${resolved}`);
5766
+ }
5767
+ if (!isUnityProject(resolved)) {
5768
+ throw new Error(`Not a Unity project (Assets/ or ProjectSettings/ not found): ${resolved}`);
5769
+ }
5770
+ if (!hasUloopInstalled(resolved)) {
5771
+ throw new Error(
5772
+ `uLoopMCP is not installed in this project (UserSettings/UnityMcpSettings.json not found): ${resolved}`
5773
+ );
5774
+ }
5775
+ return resolved;
5776
+ }
5777
+ async function resolveUnityPort(explicitPort, projectPath) {
5778
+ if (explicitPort !== void 0 && projectPath !== void 0) {
5779
+ throw new Error("Cannot specify both --port and --project-path. Use one or the other.");
5780
+ }
5763
5781
  if (explicitPort !== void 0) {
5764
5782
  return explicitPort;
5765
5783
  }
5784
+ if (projectPath !== void 0) {
5785
+ const resolved = validateProjectPath(projectPath);
5786
+ const settingsPort2 = await readPortFromSettings(resolved);
5787
+ if (settingsPort2 !== null) {
5788
+ return settingsPort2;
5789
+ }
5790
+ return DEFAULT_PORT;
5791
+ }
5766
5792
  const projectRoot = findUnityProjectRoot();
5767
5793
  if (projectRoot === null) {
5768
- throw new Error("Unity project not found. Use --port option to specify the port explicitly.");
5794
+ throw new Error(
5795
+ "Unity project not found. Use --port or --project-path option to specify the target."
5796
+ );
5769
5797
  }
5770
5798
  const settingsPort = await readPortFromSettings(projectRoot);
5771
5799
  if (settingsPort !== null) {
@@ -5799,7 +5827,7 @@ var import_path3 = require("path");
5799
5827
 
5800
5828
  // src/default-tools.json
5801
5829
  var default_tools_default = {
5802
- version: "0.65.0",
5830
+ version: "0.66.0",
5803
5831
  tools: [
5804
5832
  {
5805
5833
  name: "compile",
@@ -6247,7 +6275,7 @@ function getCachedServerVersion() {
6247
6275
  }
6248
6276
 
6249
6277
  // src/version.ts
6250
- var VERSION = "0.65.0";
6278
+ var VERSION = "0.66.0";
6251
6279
 
6252
6280
  // src/spinner.ts
6253
6281
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -6383,11 +6411,11 @@ function tryReadCompileResult(projectRoot, requestId) {
6383
6411
  }
6384
6412
  }
6385
6413
  function canSendRequestToUnity(port) {
6386
- return new Promise((resolve5) => {
6414
+ return new Promise((resolve6) => {
6387
6415
  const socket = new net2.Socket();
6388
6416
  const timer = setTimeout(() => {
6389
6417
  socket.destroy();
6390
- resolve5(false);
6418
+ resolve6(false);
6391
6419
  }, READINESS_CHECK_TIMEOUT_MS);
6392
6420
  const cleanup = () => {
6393
6421
  clearTimeout(timer);
@@ -6410,21 +6438,21 @@ function canSendRequestToUnity(port) {
6410
6438
  const sepIndex = buffer.indexOf(HEADER_SEPARATOR2);
6411
6439
  if (sepIndex !== -1) {
6412
6440
  cleanup();
6413
- resolve5(true);
6441
+ resolve6(true);
6414
6442
  }
6415
6443
  });
6416
6444
  socket.on("error", () => {
6417
6445
  cleanup();
6418
- resolve5(false);
6446
+ resolve6(false);
6419
6447
  });
6420
6448
  socket.on("close", () => {
6421
6449
  clearTimeout(timer);
6422
- resolve5(false);
6450
+ resolve6(false);
6423
6451
  });
6424
6452
  });
6425
6453
  }
6426
6454
  function sleep(ms) {
6427
- return new Promise((resolve5) => setTimeout(resolve5, ms));
6455
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
6428
6456
  }
6429
6457
  async function waitForCompileCompletion(options) {
6430
6458
  const startTime = Date.now();
@@ -6565,8 +6593,8 @@ function checkServerVersion(result) {
6565
6593
  printVersionWarning(VERSION, serverVersion);
6566
6594
  }
6567
6595
  }
6568
- function checkUnityBusyState() {
6569
- const projectRoot = findUnityProjectRoot();
6596
+ function checkUnityBusyState(projectPath) {
6597
+ const projectRoot = projectPath !== void 0 ? validateProjectPath(projectPath) : findUnityProjectRoot();
6570
6598
  if (projectRoot === null) {
6571
6599
  return;
6572
6600
  }
@@ -6592,7 +6620,7 @@ async function executeToolCommand(toolName, params, globalOptions) {
6592
6620
  }
6593
6621
  portNumber = parsed;
6594
6622
  }
6595
- const port = await resolveUnityPort(portNumber);
6623
+ const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
6596
6624
  const compileOptions = getCompileExecutionOptions(toolName, params);
6597
6625
  const shouldWaitForDomainReload = compileOptions.waitForDomainReload;
6598
6626
  const compileRequestId = shouldWaitForDomainReload ? ensureCompileRequestId(params) : void 0;
@@ -6600,10 +6628,10 @@ async function executeToolCommand(toolName, params, globalOptions) {
6600
6628
  const spinner = createSpinner("Connecting to Unity...");
6601
6629
  let lastError;
6602
6630
  let immediateResult;
6603
- const projectRoot = findUnityProjectRoot();
6631
+ const projectRoot = globalOptions.projectPath !== void 0 ? validateProjectPath(globalOptions.projectPath) : findUnityProjectRoot();
6604
6632
  let requestDispatched = false;
6605
6633
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6606
- checkUnityBusyState();
6634
+ checkUnityBusyState(globalOptions.projectPath);
6607
6635
  const client = new DirectUnityClient(port);
6608
6636
  try {
6609
6637
  await client.connect();
@@ -6717,12 +6745,12 @@ async function listAvailableTools(globalOptions) {
6717
6745
  }
6718
6746
  portNumber = parsed;
6719
6747
  }
6720
- const port = await resolveUnityPort(portNumber);
6748
+ const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
6721
6749
  const restoreStdin = suppressStdinEcho();
6722
6750
  const spinner = createSpinner("Connecting to Unity...");
6723
6751
  let lastError;
6724
6752
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6725
- checkUnityBusyState();
6753
+ checkUnityBusyState(globalOptions.projectPath);
6726
6754
  const client = new DirectUnityClient(port);
6727
6755
  try {
6728
6756
  await client.connect();
@@ -6774,12 +6802,12 @@ async function syncTools(globalOptions) {
6774
6802
  }
6775
6803
  portNumber = parsed;
6776
6804
  }
6777
- const port = await resolveUnityPort(portNumber);
6805
+ const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
6778
6806
  const restoreStdin = suppressStdinEcho();
6779
6807
  const spinner = createSpinner("Connecting to Unity...");
6780
6808
  let lastError;
6781
6809
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6782
- checkUnityBusyState();
6810
+ checkUnityBusyState(globalOptions.projectPath);
6783
6811
  const client = new DirectUnityClient(port);
6784
6812
  try {
6785
6813
  await client.connect();
@@ -8212,7 +8240,7 @@ async function waitForProcessExit(pid, timeoutMs) {
8212
8240
  if (!isProcessAlive(pid)) {
8213
8241
  return true;
8214
8242
  }
8215
- await new Promise((resolve5) => setTimeout(resolve5, KILL_POLL_INTERVAL_MS));
8243
+ await new Promise((resolve6) => setTimeout(resolve6, KILL_POLL_INTERVAL_MS));
8216
8244
  }
8217
8245
  return false;
8218
8246
  }
@@ -8381,7 +8409,7 @@ async function waitForLockfile(projectPath) {
8381
8409
  if ((0, import_node_fs2.existsSync)(lockfilePath)) {
8382
8410
  return;
8383
8411
  }
8384
- await new Promise((resolve5) => setTimeout(resolve5, LOCKFILE_POLL_INTERVAL_MS));
8412
+ await new Promise((resolve6) => setTimeout(resolve6, LOCKFILE_POLL_INTERVAL_MS));
8385
8413
  }
8386
8414
  console.warn("Unity launched, but UnityLockfile was not detected within 5s.");
8387
8415
  }
@@ -8412,7 +8440,7 @@ async function launch(opts) {
8412
8440
  if (unityArgs.length > 0) {
8413
8441
  args.push(...unityArgs);
8414
8442
  }
8415
- return new Promise((resolve5, reject) => {
8443
+ return new Promise((resolve6, reject) => {
8416
8444
  const child = (0, import_node_child_process.spawn)(unityPath, args, {
8417
8445
  stdio: "ignore",
8418
8446
  detached: true,
@@ -8429,7 +8457,7 @@ async function launch(opts) {
8429
8457
  const handleSpawn = () => {
8430
8458
  child.removeListener("error", handleError);
8431
8459
  child.unref();
8432
- resolve5();
8460
+ resolve6();
8433
8461
  };
8434
8462
  child.once("error", handleError);
8435
8463
  child.once("spawn", handleSpawn);
@@ -8537,8 +8565,24 @@ async function runLaunchCommand(projectPath, options) {
8537
8565
 
8538
8566
  // src/commands/focus-window.ts
8539
8567
  function registerFocusWindowCommand(program3) {
8540
- program3.command("focus-window").description("Bring Unity Editor window to front using OS-level commands").action(async () => {
8541
- const projectRoot = findUnityProjectRoot();
8568
+ program3.command("focus-window").description("Bring Unity Editor window to front using OS-level commands").option("--project-path <path>", "Unity project path").action(async (options) => {
8569
+ let projectRoot;
8570
+ if (options.projectPath !== void 0) {
8571
+ try {
8572
+ projectRoot = validateProjectPath(options.projectPath);
8573
+ } catch (error) {
8574
+ console.error(
8575
+ JSON.stringify({
8576
+ Success: false,
8577
+ Message: error instanceof Error ? error.message : String(error)
8578
+ })
8579
+ );
8580
+ process.exit(1);
8581
+ return;
8582
+ }
8583
+ } else {
8584
+ projectRoot = findUnityProjectRoot();
8585
+ }
8542
8586
  if (projectRoot === null) {
8543
8587
  console.error(
8544
8588
  JSON.stringify({
@@ -8596,11 +8640,11 @@ var program2 = new Command();
8596
8640
  program2.name("uloop").description("Unity MCP CLI - Direct communication with Unity Editor").version(VERSION, "-v, --version", "Output the version number");
8597
8641
  program2.option("--list-commands", "List all command names (for shell completion)");
8598
8642
  program2.option("--list-options <cmd>", "List options for a command (for shell completion)");
8599
- program2.command("list").description("List all available tools from Unity").option("-p, --port <port>", "Unity TCP port").action(async (options) => {
8600
- await runWithErrorHandling(() => listAvailableTools(options));
8643
+ program2.command("list").description("List all available tools from Unity").option("-p, --port <port>", "Unity TCP port").option("--project-path <path>", "Unity project path").action(async (options) => {
8644
+ await runWithErrorHandling(() => listAvailableTools(extractGlobalOptions(options)));
8601
8645
  });
8602
- program2.command("sync").description("Sync tool definitions from Unity to local cache").option("-p, --port <port>", "Unity TCP port").action(async (options) => {
8603
- await runWithErrorHandling(() => syncTools(options));
8646
+ program2.command("sync").description("Sync tool definitions from Unity to local cache").option("-p, --port <port>", "Unity TCP port").option("--project-path <path>", "Unity project path").action(async (options) => {
8647
+ await runWithErrorHandling(() => syncTools(extractGlobalOptions(options)));
8604
8648
  });
8605
8649
  program2.command("completion").description("Setup shell completion").option("--install", "Install completion to shell config file").option("--shell <type>", "Shell type: bash, zsh, or powershell").action((options) => {
8606
8650
  handleCompletion(options.install ?? false, options.shell);
@@ -8608,8 +8652,11 @@ program2.command("completion").description("Setup shell completion").option("--i
8608
8652
  program2.command("update").description("Update uloop CLI to the latest version").action(() => {
8609
8653
  updateCli();
8610
8654
  });
8611
- program2.command("fix").description("Clean up stale lock files that may prevent CLI from connecting").action(() => {
8612
- cleanupLockFiles();
8655
+ program2.command("fix").description("Clean up stale lock files that may prevent CLI from connecting").option("--project-path <path>", "Unity project path").action(async (options) => {
8656
+ await runWithErrorHandling(() => {
8657
+ cleanupLockFiles(options.projectPath);
8658
+ return Promise.resolve();
8659
+ });
8613
8660
  });
8614
8661
  registerSkillsCommand(program2);
8615
8662
  registerLaunchCommand(program2);
@@ -8632,6 +8679,7 @@ function registerToolCommand(tool) {
8632
8679
  }
8633
8680
  }
8634
8681
  cmd.option("-p, --port <port>", "Unity TCP port");
8682
+ cmd.option("--project-path <path>", "Unity project path");
8635
8683
  cmd.action(async (options) => {
8636
8684
  const params = buildParams(options, properties);
8637
8685
  if (tool.name === "execute-dynamic-code" && params["Code"]) {
@@ -8738,7 +8786,8 @@ function convertValue(value, propInfo) {
8738
8786
  }
8739
8787
  function extractGlobalOptions(options) {
8740
8788
  return {
8741
- port: options["port"]
8789
+ port: options["port"],
8790
+ projectPath: options["projectPath"]
8742
8791
  };
8743
8792
  }
8744
8793
  function isConnectionError(message) {
@@ -8973,8 +9022,8 @@ function updateCli() {
8973
9022
  });
8974
9023
  }
8975
9024
  var LOCK_FILES = ["compiling.lock", "domainreload.lock", "serverstarting.lock"];
8976
- function cleanupLockFiles() {
8977
- const projectRoot = findUnityProjectRoot();
9025
+ function cleanupLockFiles(projectPath) {
9026
+ const projectRoot = projectPath !== void 0 ? validateProjectPath(projectPath) : findUnityProjectRoot();
8978
9027
  if (projectRoot === null) {
8979
9028
  console.error("Could not find Unity project root.");
8980
9029
  process.exit(1);
@@ -9102,20 +9151,33 @@ function shouldSkipAutoSync(cmdName, args) {
9102
9151
  return args.some((arg) => NO_SYNC_FLAGS.includes(arg));
9103
9152
  }
9104
9153
  function extractSyncGlobalOptions(args) {
9154
+ const options = {};
9105
9155
  for (let i = 0; i < args.length; i++) {
9106
9156
  const arg = args[i];
9107
9157
  if (arg === "--port" || arg === "-p") {
9108
9158
  const nextArg = args[i + 1];
9109
9159
  if (nextArg !== void 0 && !nextArg.startsWith("-")) {
9110
- return { port: nextArg };
9160
+ options.port = nextArg;
9111
9161
  }
9112
9162
  continue;
9113
9163
  }
9114
9164
  if (arg.startsWith("--port=")) {
9115
- return { port: arg.slice("--port=".length) };
9165
+ options.port = arg.slice("--port=".length);
9166
+ continue;
9167
+ }
9168
+ if (arg === "--project-path") {
9169
+ const nextArg = args[i + 1];
9170
+ if (nextArg !== void 0 && !nextArg.startsWith("-")) {
9171
+ options.projectPath = nextArg;
9172
+ }
9173
+ continue;
9174
+ }
9175
+ if (arg.startsWith("--project-path=")) {
9176
+ options.projectPath = arg.slice("--project-path=".length);
9177
+ continue;
9116
9178
  }
9117
9179
  }
9118
- return {};
9180
+ return options;
9119
9181
  }
9120
9182
  async function main() {
9121
9183
  if (handleCompletionOptions()) {