uloop-cli 0.64.1 → 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.
@@ -5383,8 +5383,8 @@ var require_semver2 = __commonJS({
5383
5383
  });
5384
5384
 
5385
5385
  // src/cli.ts
5386
- var import_fs6 = require("fs");
5387
- var import_path7 = require("path");
5386
+ var import_fs7 = require("fs");
5387
+ var import_path8 = require("path");
5388
5388
  var import_os2 = require("os");
5389
5389
  var import_child_process = require("child_process");
5390
5390
 
@@ -5407,8 +5407,8 @@ var {
5407
5407
 
5408
5408
  // src/execute-tool.ts
5409
5409
  var readline = __toESM(require("readline"), 1);
5410
- var import_fs4 = require("fs");
5411
- var import_path4 = require("path");
5410
+ var import_fs5 = require("fs");
5411
+ var import_path5 = require("path");
5412
5412
  var semver = __toESM(require_semver2(), 1);
5413
5413
 
5414
5414
  // src/direct-unity-client.ts
@@ -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,9 +5508,16 @@ 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
+ const cleanup = () => {
5514
+ clearTimeout(timeoutId);
5515
+ socket.off("data", onData);
5516
+ socket.off("error", onError);
5517
+ socket.off("close", onClose);
5518
+ };
5513
5519
  const timeoutId = setTimeout(() => {
5520
+ cleanup();
5514
5521
  reject(
5515
5522
  new Error(
5516
5523
  `Request timed out after ${NETWORK_TIMEOUT_MS}ms. Unity may be frozen or busy. [For AI] Run 'uloop focus-window' to bring Unity to the front, then retry the tool. If the issue persists, report this to the user and ask how to proceed. Do NOT kill Unity processes without user permission.`
@@ -5531,17 +5538,26 @@ var DirectUnityClient = class {
5531
5538
  if (extractResult.jsonContent === null) {
5532
5539
  return;
5533
5540
  }
5534
- clearTimeout(timeoutId);
5535
- socket.off("data", onData);
5541
+ cleanup();
5536
5542
  this.receiveBuffer = extractResult.remainingData;
5537
5543
  const response = JSON.parse(extractResult.jsonContent);
5538
5544
  if (response.error) {
5539
5545
  reject(new Error(`Unity error: ${response.error.message}`));
5540
5546
  return;
5541
5547
  }
5542
- resolve5(response.result);
5548
+ resolve6(response.result);
5549
+ };
5550
+ const onError = (error) => {
5551
+ cleanup();
5552
+ reject(new Error(`Connection lost: ${error.message}`));
5553
+ };
5554
+ const onClose = () => {
5555
+ cleanup();
5556
+ reject(new Error("UNITY_NO_RESPONSE"));
5543
5557
  };
5544
5558
  socket.on("data", onData);
5559
+ socket.on("error", onError);
5560
+ socket.on("close", onClose);
5545
5561
  socket.write(framedMessage);
5546
5562
  });
5547
5563
  }
@@ -5743,13 +5759,41 @@ function resolvePortFromUnitySettings(settings) {
5743
5759
  }
5744
5760
  return null;
5745
5761
  }
5746
- 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
+ }
5747
5781
  if (explicitPort !== void 0) {
5748
5782
  return explicitPort;
5749
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
+ }
5750
5792
  const projectRoot = findUnityProjectRoot();
5751
5793
  if (projectRoot === null) {
5752
- 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
+ );
5753
5797
  }
5754
5798
  const settingsPort = await readPortFromSettings(projectRoot);
5755
5799
  if (settingsPort !== null) {
@@ -5783,7 +5827,7 @@ var import_path3 = require("path");
5783
5827
 
5784
5828
  // src/default-tools.json
5785
5829
  var default_tools_default = {
5786
- version: "0.64.1",
5830
+ version: "0.66.0",
5787
5831
  tools: [
5788
5832
  {
5789
5833
  name: "compile",
@@ -5794,6 +5838,10 @@ var default_tools_default = {
5794
5838
  ForceRecompile: {
5795
5839
  type: "boolean",
5796
5840
  description: "Force full recompilation"
5841
+ },
5842
+ WaitForDomainReload: {
5843
+ type: "boolean",
5844
+ description: "Wait for domain reload completion before returning"
5797
5845
  }
5798
5846
  }
5799
5847
  }
@@ -6227,7 +6275,7 @@ function getCachedServerVersion() {
6227
6275
  }
6228
6276
 
6229
6277
  // src/version.ts
6230
- var VERSION = "0.64.1";
6278
+ var VERSION = "0.66.0";
6231
6279
 
6232
6280
  // src/spinner.ts
6233
6281
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -6261,6 +6309,206 @@ function createSpinner(initialMessage) {
6261
6309
  };
6262
6310
  }
6263
6311
 
6312
+ // src/compile-helpers.ts
6313
+ var import_node_assert = __toESM(require("node:assert"), 1);
6314
+ var import_fs4 = require("fs");
6315
+ var net2 = __toESM(require("net"), 1);
6316
+ var import_path4 = require("path");
6317
+ var SAFE_REQUEST_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
6318
+ var COMPILE_FORCE_RECOMPILE_ARG_KEYS = [
6319
+ "ForceRecompile",
6320
+ "forceRecompile",
6321
+ "force_recompile",
6322
+ "force-recompile"
6323
+ ];
6324
+ var COMPILE_WAIT_FOR_DOMAIN_RELOAD_ARG_KEYS = [
6325
+ "WaitForDomainReload",
6326
+ "waitForDomainReload",
6327
+ "wait_for_domain_reload",
6328
+ "wait-for-domain-reload"
6329
+ ];
6330
+ var LOCK_GRACE_PERIOD_MS = 500;
6331
+ var READINESS_CHECK_TIMEOUT_MS = 3e3;
6332
+ var DEFAULT_HOST2 = "127.0.0.1";
6333
+ var CONTENT_LENGTH_HEADER2 = "Content-Length:";
6334
+ var HEADER_SEPARATOR2 = "\r\n\r\n";
6335
+ function toBoolean(value) {
6336
+ if (typeof value === "boolean") {
6337
+ return value;
6338
+ }
6339
+ if (typeof value === "string") {
6340
+ return value.toLowerCase() === "true";
6341
+ }
6342
+ return false;
6343
+ }
6344
+ function getCompileBooleanArg(args, keys) {
6345
+ for (const key of keys) {
6346
+ if (!(key in args)) {
6347
+ continue;
6348
+ }
6349
+ return toBoolean(args[key]);
6350
+ }
6351
+ return false;
6352
+ }
6353
+ function resolveCompileExecutionOptions(args) {
6354
+ return {
6355
+ forceRecompile: getCompileBooleanArg(args, COMPILE_FORCE_RECOMPILE_ARG_KEYS),
6356
+ waitForDomainReload: getCompileBooleanArg(args, COMPILE_WAIT_FOR_DOMAIN_RELOAD_ARG_KEYS)
6357
+ };
6358
+ }
6359
+ function createCompileRequestId() {
6360
+ const timestamp = Date.now();
6361
+ const randomToken = Math.floor(Math.random() * 1e6).toString().padStart(6, "0");
6362
+ return `compile_${timestamp}_${randomToken}`;
6363
+ }
6364
+ function ensureCompileRequestId(args) {
6365
+ const existingRequestId = args["RequestId"];
6366
+ if (typeof existingRequestId === "string" && existingRequestId.length > 0) {
6367
+ if (SAFE_REQUEST_ID_PATTERN.test(existingRequestId)) {
6368
+ return existingRequestId;
6369
+ }
6370
+ }
6371
+ const requestId = createCompileRequestId();
6372
+ args["RequestId"] = requestId;
6373
+ return requestId;
6374
+ }
6375
+ function getCompileResultFilePath(projectRoot, requestId) {
6376
+ (0, import_node_assert.default)(
6377
+ SAFE_REQUEST_ID_PATTERN.test(requestId),
6378
+ `requestId contains unsafe characters: '${requestId}'`
6379
+ );
6380
+ return (0, import_path4.join)(projectRoot, "Temp", "uLoopMCP", "compile-results", `${requestId}.json`);
6381
+ }
6382
+ function isUnityBusyByLockFiles(projectRoot) {
6383
+ const compilingLockPath = (0, import_path4.join)(projectRoot, "Temp", "compiling.lock");
6384
+ if ((0, import_fs4.existsSync)(compilingLockPath)) {
6385
+ return true;
6386
+ }
6387
+ const domainReloadLockPath = (0, import_path4.join)(projectRoot, "Temp", "domainreload.lock");
6388
+ if ((0, import_fs4.existsSync)(domainReloadLockPath)) {
6389
+ return true;
6390
+ }
6391
+ const serverStartingLockPath = (0, import_path4.join)(projectRoot, "Temp", "serverstarting.lock");
6392
+ return (0, import_fs4.existsSync)(serverStartingLockPath);
6393
+ }
6394
+ function stripUtf8Bom(content) {
6395
+ if (content.charCodeAt(0) === 65279) {
6396
+ return content.slice(1);
6397
+ }
6398
+ return content;
6399
+ }
6400
+ function tryReadCompileResult(projectRoot, requestId) {
6401
+ const resultFilePath = getCompileResultFilePath(projectRoot, requestId);
6402
+ if (!(0, import_fs4.existsSync)(resultFilePath)) {
6403
+ return void 0;
6404
+ }
6405
+ try {
6406
+ const content = (0, import_fs4.readFileSync)(resultFilePath, "utf-8");
6407
+ const parsed = JSON.parse(stripUtf8Bom(content));
6408
+ return parsed;
6409
+ } catch {
6410
+ return void 0;
6411
+ }
6412
+ }
6413
+ function canSendRequestToUnity(port) {
6414
+ return new Promise((resolve6) => {
6415
+ const socket = new net2.Socket();
6416
+ const timer = setTimeout(() => {
6417
+ socket.destroy();
6418
+ resolve6(false);
6419
+ }, READINESS_CHECK_TIMEOUT_MS);
6420
+ const cleanup = () => {
6421
+ clearTimeout(timer);
6422
+ socket.destroy();
6423
+ };
6424
+ socket.connect(port, DEFAULT_HOST2, () => {
6425
+ const rpcRequest = JSON.stringify({
6426
+ jsonrpc: "2.0",
6427
+ method: "get-tool-details",
6428
+ params: { IncludeDevelopmentOnly: false },
6429
+ id: 0
6430
+ });
6431
+ const contentLength = Buffer.byteLength(rpcRequest, "utf8");
6432
+ const frame = `${CONTENT_LENGTH_HEADER2} ${contentLength}${HEADER_SEPARATOR2}${rpcRequest}`;
6433
+ socket.write(frame);
6434
+ });
6435
+ let buffer = Buffer.alloc(0);
6436
+ socket.on("data", (chunk) => {
6437
+ buffer = Buffer.concat([buffer, chunk]);
6438
+ const sepIndex = buffer.indexOf(HEADER_SEPARATOR2);
6439
+ if (sepIndex !== -1) {
6440
+ cleanup();
6441
+ resolve6(true);
6442
+ }
6443
+ });
6444
+ socket.on("error", () => {
6445
+ cleanup();
6446
+ resolve6(false);
6447
+ });
6448
+ socket.on("close", () => {
6449
+ clearTimeout(timer);
6450
+ resolve6(false);
6451
+ });
6452
+ });
6453
+ }
6454
+ function sleep(ms) {
6455
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
6456
+ }
6457
+ async function waitForCompileCompletion(options) {
6458
+ const startTime = Date.now();
6459
+ let idleSinceTimestamp = null;
6460
+ while (Date.now() - startTime < options.timeoutMs) {
6461
+ const result = tryReadCompileResult(options.projectRoot, options.requestId);
6462
+ const isBusy = isUnityBusyByLockFiles(options.projectRoot);
6463
+ if (result !== void 0 && !isBusy) {
6464
+ const now = Date.now();
6465
+ if (idleSinceTimestamp === null) {
6466
+ idleSinceTimestamp = now;
6467
+ }
6468
+ const idleDuration = now - idleSinceTimestamp;
6469
+ if (idleDuration >= LOCK_GRACE_PERIOD_MS) {
6470
+ if (options.unityPort !== void 0) {
6471
+ const isReady = await canSendRequestToUnity(options.unityPort);
6472
+ if (isReady) {
6473
+ return { outcome: "completed", result };
6474
+ }
6475
+ } else if (options.isUnityReadyWhenIdle) {
6476
+ const isReady = await options.isUnityReadyWhenIdle();
6477
+ if (isReady) {
6478
+ return { outcome: "completed", result };
6479
+ }
6480
+ } else {
6481
+ return { outcome: "completed", result };
6482
+ }
6483
+ }
6484
+ } else {
6485
+ idleSinceTimestamp = null;
6486
+ }
6487
+ await sleep(options.pollIntervalMs);
6488
+ }
6489
+ const lastResult = tryReadCompileResult(options.projectRoot, options.requestId);
6490
+ if (lastResult !== void 0 && !isUnityBusyByLockFiles(options.projectRoot)) {
6491
+ await sleep(LOCK_GRACE_PERIOD_MS);
6492
+ if (isUnityBusyByLockFiles(options.projectRoot)) {
6493
+ return { outcome: "timed_out" };
6494
+ }
6495
+ if (options.unityPort !== void 0) {
6496
+ const isReady = await canSendRequestToUnity(options.unityPort);
6497
+ if (isReady) {
6498
+ return { outcome: "completed", result: lastResult };
6499
+ }
6500
+ } else if (options.isUnityReadyWhenIdle) {
6501
+ const isReady = await options.isUnityReadyWhenIdle();
6502
+ if (isReady) {
6503
+ return { outcome: "completed", result: lastResult };
6504
+ }
6505
+ } else {
6506
+ return { outcome: "completed", result: lastResult };
6507
+ }
6508
+ }
6509
+ return { outcome: "timed_out" };
6510
+ }
6511
+
6264
6512
  // src/execute-tool.ts
6265
6513
  function suppressStdinEcho() {
6266
6514
  if (!process.stdin.isTTY) {
@@ -6287,10 +6535,23 @@ function suppressStdinEcho() {
6287
6535
  rl.close();
6288
6536
  };
6289
6537
  }
6538
+ function stripInternalFields(result) {
6539
+ const cleaned = { ...result };
6540
+ delete cleaned["ProjectRoot"];
6541
+ return cleaned;
6542
+ }
6290
6543
  var RETRY_DELAY_MS = 500;
6291
6544
  var MAX_RETRIES = 3;
6292
- function sleep(ms) {
6293
- return new Promise((resolve5) => setTimeout(resolve5, ms));
6545
+ var COMPILE_WAIT_TIMEOUT_MS = 9e4;
6546
+ var COMPILE_WAIT_POLL_INTERVAL_MS = 100;
6547
+ function getCompileExecutionOptions(toolName, params) {
6548
+ if (toolName !== "compile") {
6549
+ return {
6550
+ forceRecompile: false,
6551
+ waitForDomainReload: false
6552
+ };
6553
+ }
6554
+ return resolveCompileExecutionOptions(params);
6294
6555
  }
6295
6556
  function isRetryableError(error) {
6296
6557
  if (!(error instanceof Error)) {
@@ -6299,6 +6560,13 @@ function isRetryableError(error) {
6299
6560
  const message = error.message;
6300
6561
  return message.includes("ECONNREFUSED") || message.includes("EADDRNOTAVAIL") || message === "UNITY_NO_RESPONSE";
6301
6562
  }
6563
+ function isTransportDisconnectError(error) {
6564
+ if (!(error instanceof Error)) {
6565
+ return false;
6566
+ }
6567
+ const message = error.message;
6568
+ return message === "UNITY_NO_RESPONSE" || message.startsWith("Connection lost:");
6569
+ }
6302
6570
  function isVersionOlder(v1, v2) {
6303
6571
  const parsed1 = semver.valid(v1);
6304
6572
  const parsed2 = semver.valid(v2);
@@ -6325,21 +6593,21 @@ function checkServerVersion(result) {
6325
6593
  printVersionWarning(VERSION, serverVersion);
6326
6594
  }
6327
6595
  }
6328
- function checkUnityBusyState() {
6329
- const projectRoot = findUnityProjectRoot();
6596
+ function checkUnityBusyState(projectPath) {
6597
+ const projectRoot = projectPath !== void 0 ? validateProjectPath(projectPath) : findUnityProjectRoot();
6330
6598
  if (projectRoot === null) {
6331
6599
  return;
6332
6600
  }
6333
- const compilingLock = (0, import_path4.join)(projectRoot, "Temp", "compiling.lock");
6334
- if ((0, import_fs4.existsSync)(compilingLock)) {
6601
+ const compilingLock = (0, import_path5.join)(projectRoot, "Temp", "compiling.lock");
6602
+ if ((0, import_fs5.existsSync)(compilingLock)) {
6335
6603
  throw new Error("UNITY_COMPILING");
6336
6604
  }
6337
- const domainReloadLock = (0, import_path4.join)(projectRoot, "Temp", "domainreload.lock");
6338
- if ((0, import_fs4.existsSync)(domainReloadLock)) {
6605
+ const domainReloadLock = (0, import_path5.join)(projectRoot, "Temp", "domainreload.lock");
6606
+ if ((0, import_fs5.existsSync)(domainReloadLock)) {
6339
6607
  throw new Error("UNITY_DOMAIN_RELOAD");
6340
6608
  }
6341
- const serverStartingLock = (0, import_path4.join)(projectRoot, "Temp", "serverstarting.lock");
6342
- if ((0, import_fs4.existsSync)(serverStartingLock)) {
6609
+ const serverStartingLock = (0, import_path5.join)(projectRoot, "Temp", "serverstarting.lock");
6610
+ if ((0, import_fs5.existsSync)(serverStartingLock)) {
6343
6611
  throw new Error("UNITY_SERVER_STARTING");
6344
6612
  }
6345
6613
  }
@@ -6352,28 +6620,48 @@ async function executeToolCommand(toolName, params, globalOptions) {
6352
6620
  }
6353
6621
  portNumber = parsed;
6354
6622
  }
6355
- const port = await resolveUnityPort(portNumber);
6623
+ const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
6624
+ const compileOptions = getCompileExecutionOptions(toolName, params);
6625
+ const shouldWaitForDomainReload = compileOptions.waitForDomainReload;
6626
+ const compileRequestId = shouldWaitForDomainReload ? ensureCompileRequestId(params) : void 0;
6356
6627
  const restoreStdin = suppressStdinEcho();
6357
6628
  const spinner = createSpinner("Connecting to Unity...");
6358
6629
  let lastError;
6630
+ let immediateResult;
6631
+ const projectRoot = globalOptions.projectPath !== void 0 ? validateProjectPath(globalOptions.projectPath) : findUnityProjectRoot();
6632
+ let requestDispatched = false;
6359
6633
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6360
- checkUnityBusyState();
6634
+ checkUnityBusyState(globalOptions.projectPath);
6361
6635
  const client = new DirectUnityClient(port);
6362
6636
  try {
6363
6637
  await client.connect();
6364
6638
  spinner.update(`Executing ${toolName}...`);
6639
+ requestDispatched = true;
6365
6640
  const result = await client.sendRequest(toolName, params);
6366
6641
  if (result === void 0 || result === null) {
6367
6642
  throw new Error("UNITY_NO_RESPONSE");
6368
6643
  }
6369
- spinner.stop();
6370
- restoreStdin();
6371
- checkServerVersion(result);
6372
- console.log(JSON.stringify(result, null, 2));
6373
- return;
6644
+ immediateResult = result;
6645
+ if (!shouldWaitForDomainReload) {
6646
+ spinner.stop();
6647
+ restoreStdin();
6648
+ checkServerVersion(result);
6649
+ console.log(JSON.stringify(stripInternalFields(result), null, 2));
6650
+ return;
6651
+ }
6652
+ break;
6374
6653
  } catch (error) {
6375
6654
  lastError = error;
6376
6655
  client.disconnect();
6656
+ if (requestDispatched && shouldWaitForDomainReload) {
6657
+ if (isTransportDisconnectError(error)) {
6658
+ spinner.update("Connection lost during compile. Waiting for result file...");
6659
+ break;
6660
+ }
6661
+ spinner.stop();
6662
+ restoreStdin();
6663
+ throw error instanceof Error ? error : new Error(String(error));
6664
+ }
6377
6665
  if (!isRetryableError(error) || attempt >= MAX_RETRIES) {
6378
6666
  break;
6379
6667
  }
@@ -6383,9 +6671,70 @@ async function executeToolCommand(toolName, params, globalOptions) {
6383
6671
  client.disconnect();
6384
6672
  }
6385
6673
  }
6674
+ if (shouldWaitForDomainReload && compileRequestId) {
6675
+ if (immediateResult === void 0 && !requestDispatched) {
6676
+ spinner.stop();
6677
+ restoreStdin();
6678
+ if (lastError instanceof Error) {
6679
+ throw lastError;
6680
+ }
6681
+ throw new Error(
6682
+ "Compile request never reached Unity. Check that Unity is running and retry."
6683
+ );
6684
+ }
6685
+ const projectRootFromUnity = immediateResult !== void 0 ? immediateResult["ProjectRoot"] : void 0;
6686
+ const effectiveProjectRoot = projectRootFromUnity ?? projectRoot;
6687
+ if (effectiveProjectRoot === null) {
6688
+ spinner.stop();
6689
+ restoreStdin();
6690
+ if (immediateResult !== void 0) {
6691
+ checkServerVersion(immediateResult);
6692
+ console.log(JSON.stringify(stripInternalFields(immediateResult), null, 2));
6693
+ return;
6694
+ }
6695
+ if (lastError instanceof Error) {
6696
+ throw lastError;
6697
+ }
6698
+ throw new Error(
6699
+ "Compile request failed and project root is unknown. Check connection and retry."
6700
+ );
6701
+ }
6702
+ spinner.update("Waiting for domain reload to complete...");
6703
+ const { outcome, result: storedResult } = await waitForCompileCompletion({
6704
+ projectRoot: effectiveProjectRoot,
6705
+ requestId: compileRequestId,
6706
+ timeoutMs: COMPILE_WAIT_TIMEOUT_MS,
6707
+ pollIntervalMs: COMPILE_WAIT_POLL_INTERVAL_MS,
6708
+ unityPort: port
6709
+ });
6710
+ if (outcome === "timed_out") {
6711
+ lastError = new Error(
6712
+ `Compile wait timed out after ${COMPILE_WAIT_TIMEOUT_MS}ms. Run 'uloop fix' and retry.`
6713
+ );
6714
+ } else {
6715
+ const finalResult = storedResult ?? immediateResult;
6716
+ if (finalResult !== void 0) {
6717
+ spinner.stop();
6718
+ restoreStdin();
6719
+ checkServerVersion(finalResult);
6720
+ console.log(JSON.stringify(stripInternalFields(finalResult), null, 2));
6721
+ return;
6722
+ }
6723
+ }
6724
+ }
6386
6725
  spinner.stop();
6387
6726
  restoreStdin();
6388
- throw lastError;
6727
+ if (lastError === void 0) {
6728
+ throw new Error("Tool execution failed without error details.");
6729
+ }
6730
+ if (lastError instanceof Error) {
6731
+ throw lastError;
6732
+ }
6733
+ if (typeof lastError === "string") {
6734
+ throw new Error(lastError);
6735
+ }
6736
+ const serializedError = JSON.stringify(lastError);
6737
+ throw new Error(serializedError ?? "Unknown error");
6389
6738
  }
6390
6739
  async function listAvailableTools(globalOptions) {
6391
6740
  let portNumber;
@@ -6396,12 +6745,12 @@ async function listAvailableTools(globalOptions) {
6396
6745
  }
6397
6746
  portNumber = parsed;
6398
6747
  }
6399
- const port = await resolveUnityPort(portNumber);
6748
+ const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
6400
6749
  const restoreStdin = suppressStdinEcho();
6401
6750
  const spinner = createSpinner("Connecting to Unity...");
6402
6751
  let lastError;
6403
6752
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6404
- checkUnityBusyState();
6753
+ checkUnityBusyState(globalOptions.projectPath);
6405
6754
  const client = new DirectUnityClient(port);
6406
6755
  try {
6407
6756
  await client.connect();
@@ -6453,12 +6802,12 @@ async function syncTools(globalOptions) {
6453
6802
  }
6454
6803
  portNumber = parsed;
6455
6804
  }
6456
- const port = await resolveUnityPort(portNumber);
6805
+ const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
6457
6806
  const restoreStdin = suppressStdinEcho();
6458
6807
  const spinner = createSpinner("Connecting to Unity...");
6459
6808
  let lastError;
6460
6809
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
6461
- checkUnityBusyState();
6810
+ checkUnityBusyState(globalOptions.projectPath);
6462
6811
  const client = new DirectUnityClient(port);
6463
6812
  try {
6464
6813
  await client.connect();
@@ -6515,8 +6864,8 @@ function pascalToKebabCase(pascal) {
6515
6864
  }
6516
6865
 
6517
6866
  // src/skills/skills-manager.ts
6518
- var import_fs5 = require("fs");
6519
- var import_path5 = require("path");
6867
+ var import_fs6 = require("fs");
6868
+ var import_path6 = require("path");
6520
6869
  var import_os = require("os");
6521
6870
 
6522
6871
  // src/skills/deprecated-skills.ts
@@ -6563,7 +6912,7 @@ var SkillsPathConstants = class _SkillsPathConstants {
6563
6912
  ];
6564
6913
  };
6565
6914
  function getGlobalSkillsDir(target) {
6566
- return (0, import_path5.join)((0, import_os.homedir)(), target.projectDir, "skills");
6915
+ return (0, import_path6.join)((0, import_os.homedir)(), target.projectDir, "skills");
6567
6916
  }
6568
6917
  function getProjectSkillsDir(target) {
6569
6918
  const status = getUnityProjectStatus();
@@ -6578,35 +6927,35 @@ function getProjectSkillsDir(target) {
6578
6927
  Please install uLoopMCP package first, then run this command again.`
6579
6928
  );
6580
6929
  }
6581
- return (0, import_path5.join)(status.path, target.projectDir, "skills");
6930
+ return (0, import_path6.join)(status.path, target.projectDir, "skills");
6582
6931
  }
6583
6932
  function getSkillPath(skillDirName, target, global) {
6584
6933
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6585
- return (0, import_path5.join)(baseDir, skillDirName, target.skillFileName);
6934
+ return (0, import_path6.join)(baseDir, skillDirName, target.skillFileName);
6586
6935
  }
6587
6936
  function isSkillInstalled(skill, target, global) {
6588
6937
  const skillPath = getSkillPath(skill.dirName, target, global);
6589
- return (0, import_fs5.existsSync)(skillPath);
6938
+ return (0, import_fs6.existsSync)(skillPath);
6590
6939
  }
6591
6940
  function isSkillOutdated(skill, target, global) {
6592
6941
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6593
- const skillDir = (0, import_path5.join)(baseDir, skill.dirName);
6594
- const skillPath = (0, import_path5.join)(skillDir, target.skillFileName);
6595
- if (!(0, import_fs5.existsSync)(skillPath)) {
6942
+ const skillDir = (0, import_path6.join)(baseDir, skill.dirName);
6943
+ const skillPath = (0, import_path6.join)(skillDir, target.skillFileName);
6944
+ if (!(0, import_fs6.existsSync)(skillPath)) {
6596
6945
  return false;
6597
6946
  }
6598
- const installedContent = (0, import_fs5.readFileSync)(skillPath, "utf-8");
6947
+ const installedContent = (0, import_fs6.readFileSync)(skillPath, "utf-8");
6599
6948
  if (installedContent !== skill.content) {
6600
6949
  return true;
6601
6950
  }
6602
6951
  if ("additionalFiles" in skill && skill.additionalFiles) {
6603
6952
  const additionalFiles = skill.additionalFiles;
6604
6953
  for (const [relativePath, expectedContent] of Object.entries(additionalFiles)) {
6605
- const filePath = (0, import_path5.join)(skillDir, relativePath);
6606
- if (!(0, import_fs5.existsSync)(filePath)) {
6954
+ const filePath = (0, import_path6.join)(skillDir, relativePath);
6955
+ if (!(0, import_fs6.existsSync)(filePath)) {
6607
6956
  return true;
6608
6957
  }
6609
- const installedFileContent = (0, import_fs5.readFileSync)(filePath);
6958
+ const installedFileContent = (0, import_fs6.readFileSync)(filePath);
6610
6959
  if (!installedFileContent.equals(expectedContent)) {
6611
6960
  return true;
6612
6961
  }
@@ -6670,24 +7019,24 @@ function warnLegacySkillStructure(toolPath, legacySkillMdPath) {
6670
7019
  console.error("");
6671
7020
  }
6672
7021
  function scanEditorFolderForSkills(editorPath, skills, sourceType, warnLegacy = true) {
6673
- if (!(0, import_fs5.existsSync)(editorPath)) {
7022
+ if (!(0, import_fs6.existsSync)(editorPath)) {
6674
7023
  return;
6675
7024
  }
6676
- const entries = (0, import_fs5.readdirSync)(editorPath, { withFileTypes: true });
7025
+ const entries = (0, import_fs6.readdirSync)(editorPath, { withFileTypes: true });
6677
7026
  for (const entry of entries) {
6678
7027
  if (EXCLUDED_DIRS2.has(entry.name)) {
6679
7028
  continue;
6680
7029
  }
6681
- const fullPath = (0, import_path5.join)(editorPath, entry.name);
7030
+ const fullPath = (0, import_path6.join)(editorPath, entry.name);
6682
7031
  if (entry.isDirectory()) {
6683
- const skillDir = (0, import_path5.join)(fullPath, SkillsPathConstants.SKILL_DIR);
6684
- const skillMdPath = (0, import_path5.join)(skillDir, SkillsPathConstants.SKILL_FILE);
6685
- const legacySkillMdPath = (0, import_path5.join)(fullPath, SkillsPathConstants.SKILL_FILE);
6686
- if (warnLegacy && !(0, import_fs5.existsSync)(skillMdPath) && (0, import_fs5.existsSync)(legacySkillMdPath)) {
7032
+ const skillDir = (0, import_path6.join)(fullPath, SkillsPathConstants.SKILL_DIR);
7033
+ const skillMdPath = (0, import_path6.join)(skillDir, SkillsPathConstants.SKILL_FILE);
7034
+ const legacySkillMdPath = (0, import_path6.join)(fullPath, SkillsPathConstants.SKILL_FILE);
7035
+ if (warnLegacy && !(0, import_fs6.existsSync)(skillMdPath) && (0, import_fs6.existsSync)(legacySkillMdPath)) {
6687
7036
  warnLegacySkillStructure(fullPath, legacySkillMdPath);
6688
7037
  }
6689
- if ((0, import_fs5.existsSync)(skillMdPath)) {
6690
- const content = (0, import_fs5.readFileSync)(skillMdPath, "utf-8");
7038
+ if ((0, import_fs6.existsSync)(skillMdPath)) {
7039
+ const content = (0, import_fs6.readFileSync)(skillMdPath, "utf-8");
6691
7040
  const frontmatter = parseFrontmatter(content);
6692
7041
  if (frontmatter.internal === true) {
6693
7042
  continue;
@@ -6710,15 +7059,15 @@ function scanEditorFolderForSkills(editorPath, skills, sourceType, warnLegacy =
6710
7059
  function findEditorFolders(basePath, maxDepth = 2) {
6711
7060
  const editorFolders = [];
6712
7061
  function scan(currentPath, depth) {
6713
- if (depth > maxDepth || !(0, import_fs5.existsSync)(currentPath)) {
7062
+ if (depth > maxDepth || !(0, import_fs6.existsSync)(currentPath)) {
6714
7063
  return;
6715
7064
  }
6716
- const entries = (0, import_fs5.readdirSync)(currentPath, { withFileTypes: true });
7065
+ const entries = (0, import_fs6.readdirSync)(currentPath, { withFileTypes: true });
6717
7066
  for (const entry of entries) {
6718
7067
  if (!entry.isDirectory() || EXCLUDED_DIRS2.has(entry.name)) {
6719
7068
  continue;
6720
7069
  }
6721
- const fullPath = (0, import_path5.join)(currentPath, entry.name);
7070
+ const fullPath = (0, import_path6.join)(currentPath, entry.name);
6722
7071
  if (entry.name === "Editor") {
6723
7072
  editorFolders.push(fullPath);
6724
7073
  } else {
@@ -6737,12 +7086,12 @@ function collectProjectSkills(excludedRoots = []) {
6737
7086
  const skills = [];
6738
7087
  const seenNames = /* @__PURE__ */ new Set();
6739
7088
  const searchPaths = [
6740
- (0, import_path5.join)(projectRoot, SkillsPathConstants.ASSETS_DIR),
6741
- (0, import_path5.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR),
6742
- (0, import_path5.join)(projectRoot, SkillsPathConstants.LIBRARY_DIR, SkillsPathConstants.PACKAGE_CACHE_DIR)
7089
+ (0, import_path6.join)(projectRoot, SkillsPathConstants.ASSETS_DIR),
7090
+ (0, import_path6.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR),
7091
+ (0, import_path6.join)(projectRoot, SkillsPathConstants.LIBRARY_DIR, SkillsPathConstants.PACKAGE_CACHE_DIR)
6743
7092
  ];
6744
7093
  for (const searchPath of searchPaths) {
6745
- if (!(0, import_fs5.existsSync)(searchPath)) {
7094
+ if (!(0, import_fs6.existsSync)(searchPath)) {
6746
7095
  continue;
6747
7096
  }
6748
7097
  const editorFolders = findEditorFolders(searchPath, 3);
@@ -6773,26 +7122,26 @@ function getAllSkillStatuses(target, global) {
6773
7122
  }
6774
7123
  function installSkill(skill, target, global) {
6775
7124
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6776
- const skillDir = (0, import_path5.join)(baseDir, skill.dirName);
6777
- const skillPath = (0, import_path5.join)(skillDir, target.skillFileName);
6778
- (0, import_fs5.mkdirSync)(skillDir, { recursive: true });
6779
- (0, import_fs5.writeFileSync)(skillPath, skill.content, "utf-8");
7125
+ const skillDir = (0, import_path6.join)(baseDir, skill.dirName);
7126
+ const skillPath = (0, import_path6.join)(skillDir, target.skillFileName);
7127
+ (0, import_fs6.mkdirSync)(skillDir, { recursive: true });
7128
+ (0, import_fs6.writeFileSync)(skillPath, skill.content, "utf-8");
6780
7129
  if ("additionalFiles" in skill && skill.additionalFiles) {
6781
7130
  const additionalFiles = skill.additionalFiles;
6782
7131
  for (const [relativePath, content] of Object.entries(additionalFiles)) {
6783
- const fullPath = (0, import_path5.join)(skillDir, relativePath);
6784
- (0, import_fs5.mkdirSync)((0, import_path5.dirname)(fullPath), { recursive: true });
6785
- (0, import_fs5.writeFileSync)(fullPath, content);
7132
+ const fullPath = (0, import_path6.join)(skillDir, relativePath);
7133
+ (0, import_fs6.mkdirSync)((0, import_path6.dirname)(fullPath), { recursive: true });
7134
+ (0, import_fs6.writeFileSync)(fullPath, content);
6786
7135
  }
6787
7136
  }
6788
7137
  }
6789
7138
  function uninstallSkill(skill, target, global) {
6790
7139
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6791
- const skillDir = (0, import_path5.join)(baseDir, skill.dirName);
6792
- if (!(0, import_fs5.existsSync)(skillDir)) {
7140
+ const skillDir = (0, import_path6.join)(baseDir, skill.dirName);
7141
+ if (!(0, import_fs6.existsSync)(skillDir)) {
6793
7142
  return false;
6794
7143
  }
6795
- (0, import_fs5.rmSync)(skillDir, { recursive: true, force: true });
7144
+ (0, import_fs6.rmSync)(skillDir, { recursive: true, force: true });
6796
7145
  return true;
6797
7146
  }
6798
7147
  function installAllSkills(target, global) {
@@ -6806,9 +7155,9 @@ function installAllSkills(target, global) {
6806
7155
  };
6807
7156
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6808
7157
  for (const deprecatedName of DEPRECATED_SKILLS) {
6809
- const deprecatedDir = (0, import_path5.join)(baseDir, deprecatedName);
6810
- if ((0, import_fs5.existsSync)(deprecatedDir)) {
6811
- (0, import_fs5.rmSync)(deprecatedDir, { recursive: true, force: true });
7158
+ const deprecatedDir = (0, import_path6.join)(baseDir, deprecatedName);
7159
+ if ((0, import_fs6.existsSync)(deprecatedDir)) {
7160
+ (0, import_fs6.rmSync)(deprecatedDir, { recursive: true, force: true });
6812
7161
  result.deprecatedRemoved++;
6813
7162
  }
6814
7163
  }
@@ -6835,9 +7184,9 @@ function uninstallAllSkills(target, global) {
6835
7184
  const result = { removed: 0, notFound: 0 };
6836
7185
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6837
7186
  for (const deprecatedName of DEPRECATED_SKILLS) {
6838
- const deprecatedDir = (0, import_path5.join)(baseDir, deprecatedName);
6839
- if ((0, import_fs5.existsSync)(deprecatedDir)) {
6840
- (0, import_fs5.rmSync)(deprecatedDir, { recursive: true, force: true });
7187
+ const deprecatedDir = (0, import_path6.join)(baseDir, deprecatedName);
7188
+ if ((0, import_fs6.existsSync)(deprecatedDir)) {
7189
+ (0, import_fs6.rmSync)(deprecatedDir, { recursive: true, force: true });
6841
7190
  result.removed++;
6842
7191
  }
6843
7192
  }
@@ -6866,13 +7215,13 @@ function collectAllSkills() {
6866
7215
  return dedupeSkillsByName([packageSkills, cliOnlySkills, projectSkills]);
6867
7216
  }
6868
7217
  function collectPackageSkillsFromRoot(packageRoot) {
6869
- const mcpToolsRoot = (0, import_path5.join)(
7218
+ const mcpToolsRoot = (0, import_path6.join)(
6870
7219
  packageRoot,
6871
7220
  SkillsPathConstants.EDITOR_DIR,
6872
7221
  SkillsPathConstants.API_DIR,
6873
7222
  SkillsPathConstants.MCP_TOOLS_DIR
6874
7223
  );
6875
- if (!(0, import_fs5.existsSync)(mcpToolsRoot)) {
7224
+ if (!(0, import_fs6.existsSync)(mcpToolsRoot)) {
6876
7225
  return [];
6877
7226
  }
6878
7227
  const skills = [];
@@ -6880,7 +7229,7 @@ function collectPackageSkillsFromRoot(packageRoot) {
6880
7229
  return skills;
6881
7230
  }
6882
7231
  function collectCliOnlySkills() {
6883
- const cliOnlyRoot = (0, import_path5.resolve)(
7232
+ const cliOnlyRoot = (0, import_path6.resolve)(
6884
7233
  __dirname,
6885
7234
  SkillsPathConstants.DIST_PARENT_DIR,
6886
7235
  SkillsPathConstants.SRC_DIR,
@@ -6888,7 +7237,7 @@ function collectCliOnlySkills() {
6888
7237
  SkillsPathConstants.CLI_ONLY_DIR,
6889
7238
  SkillsPathConstants.CLI_ONLY_SUBDIR
6890
7239
  );
6891
- if (!(0, import_fs5.existsSync)(cliOnlyRoot)) {
7240
+ if (!(0, import_fs6.existsSync)(cliOnlyRoot)) {
6892
7241
  return [];
6893
7242
  }
6894
7243
  const skills = [];
@@ -6907,12 +7256,12 @@ function isExcludedFile(fileName) {
6907
7256
  return false;
6908
7257
  }
6909
7258
  function collectSkillFolderFilesRecursive(baseDir, currentDir, additionalFiles) {
6910
- const entries = (0, import_fs5.readdirSync)(currentDir, { withFileTypes: true });
7259
+ const entries = (0, import_fs6.readdirSync)(currentDir, { withFileTypes: true });
6911
7260
  for (const entry of entries) {
6912
7261
  if (isExcludedFile(entry.name)) {
6913
7262
  continue;
6914
7263
  }
6915
- const fullPath = (0, import_path5.join)(currentDir, entry.name);
7264
+ const fullPath = (0, import_path6.join)(currentDir, entry.name);
6916
7265
  const relativePath = fullPath.slice(baseDir.length + 1);
6917
7266
  if (entry.isDirectory()) {
6918
7267
  if (EXCLUDED_DIRS2.has(entry.name)) {
@@ -6923,12 +7272,12 @@ function collectSkillFolderFilesRecursive(baseDir, currentDir, additionalFiles)
6923
7272
  if (entry.name === SkillsPathConstants.SKILL_FILE) {
6924
7273
  continue;
6925
7274
  }
6926
- additionalFiles[relativePath] = (0, import_fs5.readFileSync)(fullPath);
7275
+ additionalFiles[relativePath] = (0, import_fs6.readFileSync)(fullPath);
6927
7276
  }
6928
7277
  }
6929
7278
  }
6930
7279
  function collectSkillFolderFiles(skillDir) {
6931
- if (!(0, import_fs5.existsSync)(skillDir)) {
7280
+ if (!(0, import_fs6.existsSync)(skillDir)) {
6932
7281
  return void 0;
6933
7282
  }
6934
7283
  const additionalFiles = {};
@@ -6951,13 +7300,13 @@ function dedupeSkillsByName(skillGroups) {
6951
7300
  }
6952
7301
  function resolvePackageRoot(projectRoot) {
6953
7302
  const candidates = [];
6954
- candidates.push((0, import_path5.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR));
7303
+ candidates.push((0, import_path6.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR));
6955
7304
  const manifestPaths = resolveManifestPackagePaths(projectRoot);
6956
7305
  for (const manifestPath of manifestPaths) {
6957
7306
  candidates.push(manifestPath);
6958
7307
  }
6959
7308
  for (const packageName of SkillsPathConstants.PACKAGE_NAMES) {
6960
- candidates.push((0, import_path5.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, packageName));
7309
+ candidates.push((0, import_path6.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, packageName));
6961
7310
  }
6962
7311
  const directRoot = resolveFirstPackageRoot(candidates);
6963
7312
  if (directRoot) {
@@ -6966,15 +7315,15 @@ function resolvePackageRoot(projectRoot) {
6966
7315
  return resolvePackageCacheRoot(projectRoot);
6967
7316
  }
6968
7317
  function resolveManifestPackagePaths(projectRoot) {
6969
- const manifestPath = (0, import_path5.join)(
7318
+ const manifestPath = (0, import_path6.join)(
6970
7319
  projectRoot,
6971
7320
  SkillsPathConstants.PACKAGES_DIR,
6972
7321
  SkillsPathConstants.MANIFEST_FILE
6973
7322
  );
6974
- if (!(0, import_fs5.existsSync)(manifestPath)) {
7323
+ if (!(0, import_fs6.existsSync)(manifestPath)) {
6975
7324
  return [];
6976
7325
  }
6977
- const manifestContent = (0, import_fs5.readFileSync)(manifestPath, "utf-8");
7326
+ const manifestContent = (0, import_fs6.readFileSync)(manifestPath, "utf-8");
6978
7327
  let manifestJson;
6979
7328
  try {
6980
7329
  manifestJson = JSON.parse(manifestContent);
@@ -7018,10 +7367,10 @@ function resolveDependencyPath(rawPath, projectRoot) {
7018
7367
  if (normalizedPath.startsWith("//")) {
7019
7368
  normalizedPath = normalizedPath.slice(2);
7020
7369
  }
7021
- if ((0, import_path5.isAbsolute)(normalizedPath)) {
7370
+ if ((0, import_path6.isAbsolute)(normalizedPath)) {
7022
7371
  return normalizedPath;
7023
7372
  }
7024
- return (0, import_path5.resolve)(projectRoot, normalizedPath);
7373
+ return (0, import_path6.resolve)(projectRoot, normalizedPath);
7025
7374
  }
7026
7375
  function resolveFirstPackageRoot(candidates) {
7027
7376
  for (const candidate of candidates) {
@@ -7033,15 +7382,15 @@ function resolveFirstPackageRoot(candidates) {
7033
7382
  return null;
7034
7383
  }
7035
7384
  function resolvePackageCacheRoot(projectRoot) {
7036
- const packageCacheDir = (0, import_path5.join)(
7385
+ const packageCacheDir = (0, import_path6.join)(
7037
7386
  projectRoot,
7038
7387
  SkillsPathConstants.LIBRARY_DIR,
7039
7388
  SkillsPathConstants.PACKAGE_CACHE_DIR
7040
7389
  );
7041
- if (!(0, import_fs5.existsSync)(packageCacheDir)) {
7390
+ if (!(0, import_fs6.existsSync)(packageCacheDir)) {
7042
7391
  return null;
7043
7392
  }
7044
- const entries = (0, import_fs5.readdirSync)(packageCacheDir, { withFileTypes: true });
7393
+ const entries = (0, import_fs6.readdirSync)(packageCacheDir, { withFileTypes: true });
7045
7394
  for (const entry of entries) {
7046
7395
  if (!entry.isDirectory()) {
7047
7396
  continue;
@@ -7049,7 +7398,7 @@ function resolvePackageCacheRoot(projectRoot) {
7049
7398
  if (!isTargetPackageCacheDir(entry.name)) {
7050
7399
  continue;
7051
7400
  }
7052
- const candidate = (0, import_path5.join)(packageCacheDir, entry.name);
7401
+ const candidate = (0, import_path6.join)(packageCacheDir, entry.name);
7053
7402
  const resolvedRoot = resolvePackageRootCandidate(candidate);
7054
7403
  if (resolvedRoot) {
7055
7404
  return resolvedRoot;
@@ -7058,26 +7407,26 @@ function resolvePackageCacheRoot(projectRoot) {
7058
7407
  return null;
7059
7408
  }
7060
7409
  function resolvePackageRootCandidate(candidate) {
7061
- if (!(0, import_fs5.existsSync)(candidate)) {
7410
+ if (!(0, import_fs6.existsSync)(candidate)) {
7062
7411
  return null;
7063
7412
  }
7064
- const directToolsPath = (0, import_path5.join)(
7413
+ const directToolsPath = (0, import_path6.join)(
7065
7414
  candidate,
7066
7415
  SkillsPathConstants.EDITOR_DIR,
7067
7416
  SkillsPathConstants.API_DIR,
7068
7417
  SkillsPathConstants.MCP_TOOLS_DIR
7069
7418
  );
7070
- if ((0, import_fs5.existsSync)(directToolsPath)) {
7419
+ if ((0, import_fs6.existsSync)(directToolsPath)) {
7071
7420
  return candidate;
7072
7421
  }
7073
- const nestedRoot = (0, import_path5.join)(candidate, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR);
7074
- const nestedToolsPath = (0, import_path5.join)(
7422
+ const nestedRoot = (0, import_path6.join)(candidate, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR);
7423
+ const nestedToolsPath = (0, import_path6.join)(
7075
7424
  nestedRoot,
7076
7425
  SkillsPathConstants.EDITOR_DIR,
7077
7426
  SkillsPathConstants.API_DIR,
7078
7427
  SkillsPathConstants.MCP_TOOLS_DIR
7079
7428
  );
7080
- if ((0, import_fs5.existsSync)(nestedToolsPath)) {
7429
+ if ((0, import_fs6.existsSync)(nestedToolsPath)) {
7081
7430
  return nestedRoot;
7082
7431
  }
7083
7432
  return null;
@@ -7103,12 +7452,12 @@ function isUnderExcludedRoots(targetPath, excludedRoots) {
7103
7452
  return false;
7104
7453
  }
7105
7454
  function isPathUnder(childPath, parentPath) {
7106
- const resolvedChild = (0, import_path5.resolve)(childPath);
7107
- const resolvedParent = (0, import_path5.resolve)(parentPath);
7455
+ const resolvedChild = (0, import_path6.resolve)(childPath);
7456
+ const resolvedParent = (0, import_path6.resolve)(parentPath);
7108
7457
  if (resolvedChild === resolvedParent) {
7109
7458
  return true;
7110
7459
  }
7111
- return resolvedChild.startsWith(resolvedParent + import_path5.sep);
7460
+ return resolvedChild.startsWith(resolvedParent + import_path6.sep);
7112
7461
  }
7113
7462
 
7114
7463
  // src/skills/target-config.ts
@@ -7263,7 +7612,7 @@ Uninstalling uloop skills (${location})...`);
7263
7612
  }
7264
7613
 
7265
7614
  // src/commands/launch.ts
7266
- var import_path6 = require("path");
7615
+ var import_path7 = require("path");
7267
7616
 
7268
7617
  // node_modules/launch-unity/dist/lib.js
7269
7618
  var import_node_child_process = require("node:child_process");
@@ -7276,7 +7625,7 @@ var import_node_util = require("node:util");
7276
7625
  var import_promises2 = require("node:fs/promises");
7277
7626
  var import_node_fs = require("node:fs");
7278
7627
  var import_node_path = require("node:path");
7279
- var import_node_assert = __toESM(require("node:assert"), 1);
7628
+ var import_node_assert2 = __toESM(require("node:assert"), 1);
7280
7629
  var resolveUnityHubProjectFiles = () => {
7281
7630
  if (process.platform === "darwin") {
7282
7631
  const home = process.env.HOME;
@@ -7447,7 +7796,7 @@ var resolveUnityHubProjectsInfoFile = () => {
7447
7796
  return void 0;
7448
7797
  };
7449
7798
  var parseCliArgs = (cliArgsString) => {
7450
- (0, import_node_assert.default)(cliArgsString !== null && cliArgsString !== void 0, "cliArgsString must not be null");
7799
+ (0, import_node_assert2.default)(cliArgsString !== null && cliArgsString !== void 0, "cliArgsString must not be null");
7451
7800
  const trimmed = cliArgsString.trim();
7452
7801
  if (trimmed.length === 0) {
7453
7802
  return [];
@@ -7503,7 +7852,7 @@ var groupCliArgs = (args) => {
7503
7852
  return groups;
7504
7853
  };
7505
7854
  var getProjectCliArgs = async (projectPath) => {
7506
- (0, import_node_assert.default)(projectPath !== null && projectPath !== void 0, "projectPath must not be null");
7855
+ (0, import_node_assert2.default)(projectPath !== null && projectPath !== void 0, "projectPath must not be null");
7507
7856
  const infoFilePath = resolveUnityHubProjectsInfoFile();
7508
7857
  if (!infoFilePath) {
7509
7858
  logDebug("projectsInfo.json path could not be resolved.");
@@ -7551,6 +7900,8 @@ var PROCESS_LIST_ARGS_MAC = ["-axo", "pid=,command=", "-ww"];
7551
7900
  var WINDOWS_POWERSHELL = "powershell";
7552
7901
  var UNITY_LOCKFILE_NAME = "UnityLockfile";
7553
7902
  var TEMP_DIRECTORY_NAME = "Temp";
7903
+ var ASSETS_DIRECTORY_NAME = "Assets";
7904
+ var RECOVERY_DIRECTORY_NAME = "_Recovery";
7554
7905
  function getUnityVersion(projectPath) {
7555
7906
  const versionFile = (0, import_node_path2.join)(projectPath, "ProjectSettings", "ProjectVersion.txt");
7556
7907
  if (!(0, import_node_fs2.existsSync)(versionFile)) {
@@ -7850,6 +8201,20 @@ async function handleStaleLockfile(projectPath) {
7850
8201
  }
7851
8202
  console.log();
7852
8203
  }
8204
+ async function deleteRecoveryDirectory(projectPath) {
8205
+ const recoveryPath = (0, import_node_path2.join)(projectPath, ASSETS_DIRECTORY_NAME, RECOVERY_DIRECTORY_NAME);
8206
+ if (!(0, import_node_fs2.existsSync)(recoveryPath)) {
8207
+ return;
8208
+ }
8209
+ console.log(`Deleting recovery directory: ${recoveryPath}`);
8210
+ try {
8211
+ await (0, import_promises3.rm)(recoveryPath, { recursive: true, force: true });
8212
+ console.log("Deleted recovery directory.");
8213
+ } catch (error) {
8214
+ const message = error instanceof Error ? error.message : String(error);
8215
+ console.warn(`Failed to delete recovery directory: ${message}`);
8216
+ }
8217
+ }
7853
8218
  var LOCKFILE_POLL_INTERVAL_MS = 100;
7854
8219
  var LOCKFILE_WAIT_TIMEOUT_MS = 5e3;
7855
8220
  var KILL_POLL_INTERVAL_MS = 100;
@@ -7875,7 +8240,7 @@ async function waitForProcessExit(pid, timeoutMs) {
7875
8240
  if (!isProcessAlive(pid)) {
7876
8241
  return true;
7877
8242
  }
7878
- await new Promise((resolve5) => setTimeout(resolve5, KILL_POLL_INTERVAL_MS));
8243
+ await new Promise((resolve6) => setTimeout(resolve6, KILL_POLL_INTERVAL_MS));
7879
8244
  }
7880
8245
  return false;
7881
8246
  }
@@ -8044,7 +8409,7 @@ async function waitForLockfile(projectPath) {
8044
8409
  if ((0, import_node_fs2.existsSync)(lockfilePath)) {
8045
8410
  return;
8046
8411
  }
8047
- await new Promise((resolve5) => setTimeout(resolve5, LOCKFILE_POLL_INTERVAL_MS));
8412
+ await new Promise((resolve6) => setTimeout(resolve6, LOCKFILE_POLL_INTERVAL_MS));
8048
8413
  }
8049
8414
  console.warn("Unity launched, but UnityLockfile was not detected within 5s.");
8050
8415
  }
@@ -8075,7 +8440,7 @@ async function launch(opts) {
8075
8440
  if (unityArgs.length > 0) {
8076
8441
  args.push(...unityArgs);
8077
8442
  }
8078
- return new Promise((resolve5, reject) => {
8443
+ return new Promise((resolve6, reject) => {
8079
8444
  const child = (0, import_node_child_process.spawn)(unityPath, args, {
8080
8445
  stdio: "ignore",
8081
8446
  detached: true,
@@ -8092,7 +8457,7 @@ async function launch(opts) {
8092
8457
  const handleSpawn = () => {
8093
8458
  child.removeListener("error", handleError);
8094
8459
  child.unref();
8095
- resolve5();
8460
+ resolve6();
8096
8461
  };
8097
8462
  child.once("error", handleError);
8098
8463
  child.once("spawn", handleSpawn);
@@ -8140,6 +8505,9 @@ async function orchestrateLaunch(options) {
8140
8505
  return { action: "focused", projectPath: resolvedProjectPath, pid: runningProcess.pid };
8141
8506
  }
8142
8507
  }
8508
+ if (options.deleteRecovery) {
8509
+ await deleteRecoveryDirectory(resolvedProjectPath);
8510
+ }
8143
8511
  await handleStaleLockfile(resolvedProjectPath);
8144
8512
  const resolved = {
8145
8513
  projectPath: resolvedProjectPath,
@@ -8164,7 +8532,7 @@ async function orchestrateLaunch(options) {
8164
8532
  function registerLaunchCommand(program3) {
8165
8533
  program3.command("launch").description(
8166
8534
  "Open a Unity project with the matching Editor version installed by Unity Hub.\nAuto-detects project path and Unity version from ProjectSettings/ProjectVersion.txt.\nRun 'uloop launch -h' for all options. Details: https://github.com/hatayama/LaunchUnityCommand"
8167
- ).argument("[project-path]", "Path to Unity project").option("-r, --restart", "Kill running Unity and restart").option("-q, --quit", "Gracefully quit running Unity").option("-p, --platform <platform>", "Build target (e.g., Android, iOS)").option("--max-depth <n>", "Search depth when project-path is omitted", "3").option("-a, --add-unity-hub", "Add to Unity Hub (does not launch)").option("-f, --favorite", "Add to Unity Hub as favorite (does not launch)").action(async (projectPath, options) => {
8535
+ ).argument("[project-path]", "Path to Unity project").option("-r, --restart", "Kill running Unity and restart").option("-d, --delete-recovery", "Delete Assets/_Recovery before launch").option("-q, --quit", "Gracefully quit running Unity").option("-p, --platform <platform>", "Build target (e.g., Android, iOS)").option("--max-depth <n>", "Search depth when project-path is omitted", "3").option("-a, --add-unity-hub", "Add to Unity Hub (does not launch)").option("-f, --favorite", "Add to Unity Hub as favorite (does not launch)").action(async (projectPath, options) => {
8168
8536
  await runLaunchCommand(projectPath, options);
8169
8537
  });
8170
8538
  }
@@ -8182,13 +8550,14 @@ function parseMaxDepth(value) {
8182
8550
  async function runLaunchCommand(projectPath, options) {
8183
8551
  const maxDepth = parseMaxDepth(options.maxDepth);
8184
8552
  await orchestrateLaunch({
8185
- projectPath: projectPath ? (0, import_path6.resolve)(projectPath) : void 0,
8553
+ projectPath: projectPath ? (0, import_path7.resolve)(projectPath) : void 0,
8186
8554
  searchRoot: process.cwd(),
8187
8555
  searchMaxDepth: maxDepth,
8188
8556
  platform: options.platform,
8189
8557
  unityArgs: [],
8190
8558
  restart: options.restart === true,
8191
8559
  quit: options.quit === true,
8560
+ deleteRecovery: options.deleteRecovery === true,
8192
8561
  addUnityHub: options.addUnityHub === true,
8193
8562
  favoriteUnityHub: options.favorite === true
8194
8563
  });
@@ -8196,8 +8565,24 @@ async function runLaunchCommand(projectPath, options) {
8196
8565
 
8197
8566
  // src/commands/focus-window.ts
8198
8567
  function registerFocusWindowCommand(program3) {
8199
- program3.command("focus-window").description("Bring Unity Editor window to front using OS-level commands").action(async () => {
8200
- 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
+ }
8201
8586
  if (projectRoot === null) {
8202
8587
  console.error(
8203
8588
  JSON.stringify({
@@ -8255,11 +8640,11 @@ var program2 = new Command();
8255
8640
  program2.name("uloop").description("Unity MCP CLI - Direct communication with Unity Editor").version(VERSION, "-v, --version", "Output the version number");
8256
8641
  program2.option("--list-commands", "List all command names (for shell completion)");
8257
8642
  program2.option("--list-options <cmd>", "List options for a command (for shell completion)");
8258
- program2.command("list").description("List all available tools from Unity").option("-p, --port <port>", "Unity TCP port").action(async (options) => {
8259
- 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)));
8260
8645
  });
8261
- program2.command("sync").description("Sync tool definitions from Unity to local cache").option("-p, --port <port>", "Unity TCP port").action(async (options) => {
8262
- 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)));
8263
8648
  });
8264
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) => {
8265
8650
  handleCompletion(options.install ?? false, options.shell);
@@ -8267,8 +8652,11 @@ program2.command("completion").description("Setup shell completion").option("--i
8267
8652
  program2.command("update").description("Update uloop CLI to the latest version").action(() => {
8268
8653
  updateCli();
8269
8654
  });
8270
- program2.command("fix").description("Clean up stale lock files that may prevent CLI from connecting").action(() => {
8271
- 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
+ });
8272
8660
  });
8273
8661
  registerSkillsCommand(program2);
8274
8662
  registerLaunchCommand(program2);
@@ -8291,6 +8679,7 @@ function registerToolCommand(tool) {
8291
8679
  }
8292
8680
  }
8293
8681
  cmd.option("-p, --port <port>", "Unity TCP port");
8682
+ cmd.option("--project-path <path>", "Unity project path");
8294
8683
  cmd.action(async (options) => {
8295
8684
  const params = buildParams(options, properties);
8296
8685
  if (tool.name === "execute-dynamic-code" && params["Code"]) {
@@ -8397,7 +8786,8 @@ function convertValue(value, propInfo) {
8397
8786
  }
8398
8787
  function extractGlobalOptions(options) {
8399
8788
  return {
8400
- port: options["port"]
8789
+ port: options["port"],
8790
+ projectPath: options["projectPath"]
8401
8791
  };
8402
8792
  }
8403
8793
  function isConnectionError(message) {
@@ -8481,7 +8871,7 @@ async function runWithErrorHandling(fn) {
8481
8871
  }
8482
8872
  function detectShell() {
8483
8873
  const shell = process.env["SHELL"] || "";
8484
- const shellName = (0, import_path7.basename)(shell).replace(/\.exe$/i, "");
8874
+ const shellName = (0, import_path8.basename)(shell).replace(/\.exe$/i, "");
8485
8875
  if (shellName === "zsh") {
8486
8876
  return "zsh";
8487
8877
  }
@@ -8496,12 +8886,12 @@ function detectShell() {
8496
8886
  function getShellConfigPath(shell) {
8497
8887
  const home = (0, import_os2.homedir)();
8498
8888
  if (shell === "zsh") {
8499
- return (0, import_path7.join)(home, ".zshrc");
8889
+ return (0, import_path8.join)(home, ".zshrc");
8500
8890
  }
8501
8891
  if (shell === "powershell") {
8502
- return (0, import_path7.join)(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
8892
+ return (0, import_path8.join)(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
8503
8893
  }
8504
- return (0, import_path7.join)(home, ".bashrc");
8894
+ return (0, import_path8.join)(home, ".bashrc");
8505
8895
  }
8506
8896
  function getCompletionScript(shell) {
8507
8897
  if (shell === "bash") {
@@ -8632,18 +9022,18 @@ function updateCli() {
8632
9022
  });
8633
9023
  }
8634
9024
  var LOCK_FILES = ["compiling.lock", "domainreload.lock", "serverstarting.lock"];
8635
- function cleanupLockFiles() {
8636
- const projectRoot = findUnityProjectRoot();
9025
+ function cleanupLockFiles(projectPath) {
9026
+ const projectRoot = projectPath !== void 0 ? validateProjectPath(projectPath) : findUnityProjectRoot();
8637
9027
  if (projectRoot === null) {
8638
9028
  console.error("Could not find Unity project root.");
8639
9029
  process.exit(1);
8640
9030
  }
8641
- const tempDir = (0, import_path7.join)(projectRoot, "Temp");
9031
+ const tempDir = (0, import_path8.join)(projectRoot, "Temp");
8642
9032
  let cleaned = 0;
8643
9033
  for (const lockFile of LOCK_FILES) {
8644
- const lockPath = (0, import_path7.join)(tempDir, lockFile);
8645
- if ((0, import_fs6.existsSync)(lockPath)) {
8646
- (0, import_fs6.unlinkSync)(lockPath);
9034
+ const lockPath = (0, import_path8.join)(tempDir, lockFile);
9035
+ if ((0, import_fs7.existsSync)(lockPath)) {
9036
+ (0, import_fs7.unlinkSync)(lockPath);
8647
9037
  console.log(`Removed: ${lockFile}`);
8648
9038
  cleaned++;
8649
9039
  }
@@ -8678,13 +9068,13 @@ function handleCompletion(install, shellOverride) {
8678
9068
  return;
8679
9069
  }
8680
9070
  const configPath = getShellConfigPath(shell);
8681
- const configDir = (0, import_path7.dirname)(configPath);
8682
- if (!(0, import_fs6.existsSync)(configDir)) {
8683
- (0, import_fs6.mkdirSync)(configDir, { recursive: true });
9071
+ const configDir = (0, import_path8.dirname)(configPath);
9072
+ if (!(0, import_fs7.existsSync)(configDir)) {
9073
+ (0, import_fs7.mkdirSync)(configDir, { recursive: true });
8684
9074
  }
8685
9075
  let content = "";
8686
- if ((0, import_fs6.existsSync)(configPath)) {
8687
- content = (0, import_fs6.readFileSync)(configPath, "utf-8");
9076
+ if ((0, import_fs7.existsSync)(configPath)) {
9077
+ content = (0, import_fs7.readFileSync)(configPath, "utf-8");
8688
9078
  content = content.replace(
8689
9079
  /\n?# >>> uloop completion >>>[\s\S]*?# <<< uloop completion <<<\n?/g,
8690
9080
  ""
@@ -8698,7 +9088,7 @@ ${startMarker}
8698
9088
  ${script}
8699
9089
  ${endMarker}
8700
9090
  `;
8701
- (0, import_fs6.writeFileSync)(configPath, content + lineToAdd, "utf-8");
9091
+ (0, import_fs7.writeFileSync)(configPath, content + lineToAdd, "utf-8");
8702
9092
  } else {
8703
9093
  const evalLine = `eval "$(uloop completion --shell ${shell})"`;
8704
9094
  const lineToAdd = `
@@ -8706,7 +9096,7 @@ ${startMarker}
8706
9096
  ${evalLine}
8707
9097
  ${endMarker}
8708
9098
  `;
8709
- (0, import_fs6.writeFileSync)(configPath, content + lineToAdd, "utf-8");
9099
+ (0, import_fs7.writeFileSync)(configPath, content + lineToAdd, "utf-8");
8710
9100
  }
8711
9101
  console.log(`Completion installed to ${configPath}`);
8712
9102
  if (shell === "powershell") {
@@ -8760,12 +9150,42 @@ function shouldSkipAutoSync(cmdName, args) {
8760
9150
  }
8761
9151
  return args.some((arg) => NO_SYNC_FLAGS.includes(arg));
8762
9152
  }
9153
+ function extractSyncGlobalOptions(args) {
9154
+ const options = {};
9155
+ for (let i = 0; i < args.length; i++) {
9156
+ const arg = args[i];
9157
+ if (arg === "--port" || arg === "-p") {
9158
+ const nextArg = args[i + 1];
9159
+ if (nextArg !== void 0 && !nextArg.startsWith("-")) {
9160
+ options.port = nextArg;
9161
+ }
9162
+ continue;
9163
+ }
9164
+ if (arg.startsWith("--port=")) {
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;
9178
+ }
9179
+ }
9180
+ return options;
9181
+ }
8763
9182
  async function main() {
8764
9183
  if (handleCompletionOptions()) {
8765
9184
  return;
8766
9185
  }
8767
9186
  const args = process.argv.slice(2);
8768
9187
  const cmdName = args.find((arg) => !arg.startsWith("-"));
9188
+ const syncGlobalOptions = extractSyncGlobalOptions(args);
8769
9189
  if (!shouldSkipAutoSync(cmdName, args)) {
8770
9190
  const cachedVersion = loadToolsCache().version;
8771
9191
  if (hasCacheFile() && cachedVersion !== VERSION) {
@@ -8773,7 +9193,7 @@ async function main() {
8773
9193
  `\x1B[33mCache outdated (${cachedVersion} \u2192 ${VERSION}). Syncing tools from Unity...\x1B[0m`
8774
9194
  );
8775
9195
  try {
8776
- await syncTools({});
9196
+ await syncTools(syncGlobalOptions);
8777
9197
  console.log("\x1B[32m\u2713 Tools synced successfully.\x1B[0m\n");
8778
9198
  } catch (error) {
8779
9199
  const message = error instanceof Error ? error.message : String(error);
@@ -8795,7 +9215,7 @@ async function main() {
8795
9215
  if (cmdName && !commandExists(cmdName)) {
8796
9216
  console.log(`\x1B[33mUnknown command '${cmdName}'. Syncing tools from Unity...\x1B[0m`);
8797
9217
  try {
8798
- await syncTools({});
9218
+ await syncTools(syncGlobalOptions);
8799
9219
  const newCache = loadToolsCache();
8800
9220
  const tool = newCache.tools.find((t) => t.name === cmdName);
8801
9221
  if (tool) {