uloop-cli 0.67.5 → 0.68.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.
@@ -5383,8 +5383,8 @@ var require_semver2 = __commonJS({
5383
5383
  });
5384
5384
 
5385
5385
  // src/cli.ts
5386
- var import_fs7 = require("fs");
5387
- var import_path8 = require("path");
5386
+ var import_fs8 = require("fs");
5387
+ var import_path9 = require("path");
5388
5388
  var import_os2 = require("os");
5389
5389
  var import_child_process = require("child_process");
5390
5390
 
@@ -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((resolve6, reject) => {
5489
+ return new Promise((resolve7, 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
- resolve6();
5495
+ resolve7();
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((resolve6, reject) => {
5511
+ return new Promise((resolve7, 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
- resolve6(response.result);
5548
+ resolve7(response.result);
5549
5549
  };
5550
5550
  const onError = (error) => {
5551
5551
  cleanup();
@@ -5824,7 +5824,7 @@ var import_path3 = require("path");
5824
5824
 
5825
5825
  // src/default-tools.json
5826
5826
  var default_tools_default = {
5827
- version: "0.67.5",
5827
+ version: "0.68.1",
5828
5828
  tools: [
5829
5829
  {
5830
5830
  name: "compile",
@@ -6168,8 +6168,8 @@ var default_tools_default = {
6168
6168
  }
6169
6169
  },
6170
6170
  {
6171
- name: "capture-window",
6172
- description: "Capture Unity EditorWindow and save as PNG",
6171
+ name: "screenshot",
6172
+ description: "Take a screenshot of Unity EditorWindow and save as PNG",
6173
6173
  inputSchema: {
6174
6174
  type: "object",
6175
6175
  properties: {
@@ -6192,6 +6192,11 @@ var default_tools_default = {
6192
6192
  "contains"
6193
6193
  ],
6194
6194
  default: "exact"
6195
+ },
6196
+ OutputDirectory: {
6197
+ type: "string",
6198
+ description: "Output directory path for saving screenshots. When empty, uses default path (.uloop/outputs/Screenshots/). Accepts absolute paths.",
6199
+ default: ""
6195
6200
  }
6196
6201
  }
6197
6202
  }
@@ -6217,33 +6222,6 @@ var default_tools_default = {
6217
6222
  }
6218
6223
  }
6219
6224
  },
6220
- {
6221
- name: "get-provider-details",
6222
- description: "Get Unity Search provider details",
6223
- inputSchema: {
6224
- type: "object",
6225
- properties: {
6226
- ProviderId: {
6227
- type: "string",
6228
- description: "Specific provider ID"
6229
- },
6230
- ActiveOnly: {
6231
- type: "boolean",
6232
- description: "Only active providers"
6233
- },
6234
- IncludeDescriptions: {
6235
- type: "boolean",
6236
- description: "Include descriptions",
6237
- default: true
6238
- },
6239
- SortByPriority: {
6240
- type: "boolean",
6241
- description: "Sort by priority",
6242
- default: true
6243
- }
6244
- }
6245
- }
6246
- },
6247
6225
  {
6248
6226
  name: "get-project-info",
6249
6227
  description: "Get Unity project information",
@@ -6340,7 +6318,7 @@ function getCachedServerVersion() {
6340
6318
  }
6341
6319
 
6342
6320
  // src/version.ts
6343
- var VERSION = "0.67.5";
6321
+ var VERSION = "0.68.1";
6344
6322
 
6345
6323
  // src/spinner.ts
6346
6324
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -6476,11 +6454,11 @@ function tryReadCompileResult(projectRoot, requestId) {
6476
6454
  }
6477
6455
  }
6478
6456
  function canSendRequestToUnity(port) {
6479
- return new Promise((resolve6) => {
6457
+ return new Promise((resolve7) => {
6480
6458
  const socket = new net2.Socket();
6481
6459
  const timer = setTimeout(() => {
6482
6460
  socket.destroy();
6483
- resolve6(false);
6461
+ resolve7(false);
6484
6462
  }, READINESS_CHECK_TIMEOUT_MS);
6485
6463
  const cleanup = () => {
6486
6464
  clearTimeout(timer);
@@ -6503,21 +6481,21 @@ function canSendRequestToUnity(port) {
6503
6481
  const sepIndex = buffer.indexOf(HEADER_SEPARATOR2);
6504
6482
  if (sepIndex !== -1) {
6505
6483
  cleanup();
6506
- resolve6(true);
6484
+ resolve7(true);
6507
6485
  }
6508
6486
  });
6509
6487
  socket.on("error", () => {
6510
6488
  cleanup();
6511
- resolve6(false);
6489
+ resolve7(false);
6512
6490
  });
6513
6491
  socket.on("close", () => {
6514
6492
  clearTimeout(timer);
6515
- resolve6(false);
6493
+ resolve7(false);
6516
6494
  });
6517
6495
  });
6518
6496
  }
6519
6497
  function sleep(ms) {
6520
- return new Promise((resolve6) => setTimeout(resolve6, ms));
6498
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
6521
6499
  }
6522
6500
  async function waitForCompileCompletion(options) {
6523
6501
  const startTime = Date.now();
@@ -6929,16 +6907,65 @@ function pascalToKebabCase(pascal) {
6929
6907
  }
6930
6908
 
6931
6909
  // src/skills/skills-manager.ts
6932
- var import_fs6 = require("fs");
6933
- var import_path6 = require("path");
6910
+ var import_fs7 = require("fs");
6911
+ var import_path7 = require("path");
6934
6912
  var import_os = require("os");
6935
6913
 
6936
6914
  // src/skills/deprecated-skills.ts
6937
6915
  var DEPRECATED_SKILLS = [
6938
- "uloop-capture-window"
6916
+ "uloop-capture-window",
6939
6917
  // renamed to uloop-screenshot in v0.54.0
6918
+ "uloop-get-provider-details"
6919
+ // internal development-only tool, not for end users
6940
6920
  ];
6941
6921
 
6922
+ // src/tool-settings-loader.ts
6923
+ var import_fs6 = require("fs");
6924
+ var import_path6 = require("path");
6925
+ var ULOOP_DIR = ".uloop";
6926
+ var TOOL_SETTINGS_FILE = "settings.tools.json";
6927
+ function loadDisabledTools(projectPath) {
6928
+ const projectRoot = projectPath !== void 0 ? (0, import_path6.resolve)(projectPath) : findUnityProjectRoot();
6929
+ if (projectRoot === null) {
6930
+ return [];
6931
+ }
6932
+ const settingsPath = (0, import_path6.join)(projectRoot, ULOOP_DIR, TOOL_SETTINGS_FILE);
6933
+ let content;
6934
+ try {
6935
+ content = (0, import_fs6.readFileSync)(settingsPath, "utf-8");
6936
+ } catch {
6937
+ return [];
6938
+ }
6939
+ if (!content.trim()) {
6940
+ return [];
6941
+ }
6942
+ let parsed;
6943
+ try {
6944
+ parsed = JSON.parse(content);
6945
+ } catch {
6946
+ return [];
6947
+ }
6948
+ if (typeof parsed !== "object" || parsed === null) {
6949
+ return [];
6950
+ }
6951
+ const data = parsed;
6952
+ if (!Array.isArray(data.disabledTools)) {
6953
+ return [];
6954
+ }
6955
+ return data.disabledTools;
6956
+ }
6957
+ function isToolEnabled(toolName, projectPath) {
6958
+ const disabledTools = loadDisabledTools(projectPath);
6959
+ return !disabledTools.includes(toolName);
6960
+ }
6961
+ function filterEnabledTools(tools, projectPath) {
6962
+ const disabledTools = loadDisabledTools(projectPath);
6963
+ if (disabledTools.length === 0) {
6964
+ return tools;
6965
+ }
6966
+ return tools.filter((tool) => !disabledTools.includes(tool.name));
6967
+ }
6968
+
6942
6969
  // src/skills/skills-manager.ts
6943
6970
  var EXCLUDED_DIRS2 = /* @__PURE__ */ new Set([
6944
6971
  "node_modules",
@@ -6977,7 +7004,7 @@ var SkillsPathConstants = class _SkillsPathConstants {
6977
7004
  ];
6978
7005
  };
6979
7006
  function getGlobalSkillsDir(target) {
6980
- return (0, import_path6.join)((0, import_os.homedir)(), target.projectDir, "skills");
7007
+ return (0, import_path7.join)((0, import_os.homedir)(), target.projectDir, "skills");
6981
7008
  }
6982
7009
  function getProjectSkillsDir(target) {
6983
7010
  const status = getUnityProjectStatus();
@@ -6992,35 +7019,35 @@ function getProjectSkillsDir(target) {
6992
7019
  Please install uLoopMCP package first, then run this command again.`
6993
7020
  );
6994
7021
  }
6995
- return (0, import_path6.join)(status.path, target.projectDir, "skills");
7022
+ return (0, import_path7.join)(status.path, target.projectDir, "skills");
6996
7023
  }
6997
7024
  function getSkillPath(skillDirName, target, global) {
6998
7025
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6999
- return (0, import_path6.join)(baseDir, skillDirName, target.skillFileName);
7026
+ return (0, import_path7.join)(baseDir, skillDirName, target.skillFileName);
7000
7027
  }
7001
7028
  function isSkillInstalled(skill, target, global) {
7002
7029
  const skillPath = getSkillPath(skill.dirName, target, global);
7003
- return (0, import_fs6.existsSync)(skillPath);
7030
+ return (0, import_fs7.existsSync)(skillPath);
7004
7031
  }
7005
7032
  function isSkillOutdated(skill, target, global) {
7006
7033
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
7007
- const skillDir = (0, import_path6.join)(baseDir, skill.dirName);
7008
- const skillPath = (0, import_path6.join)(skillDir, target.skillFileName);
7009
- if (!(0, import_fs6.existsSync)(skillPath)) {
7034
+ const skillDir = (0, import_path7.join)(baseDir, skill.dirName);
7035
+ const skillPath = (0, import_path7.join)(skillDir, target.skillFileName);
7036
+ if (!(0, import_fs7.existsSync)(skillPath)) {
7010
7037
  return false;
7011
7038
  }
7012
- const installedContent = (0, import_fs6.readFileSync)(skillPath, "utf-8");
7039
+ const installedContent = (0, import_fs7.readFileSync)(skillPath, "utf-8");
7013
7040
  if (installedContent !== skill.content) {
7014
7041
  return true;
7015
7042
  }
7016
7043
  if ("additionalFiles" in skill && skill.additionalFiles) {
7017
7044
  const additionalFiles = skill.additionalFiles;
7018
7045
  for (const [relativePath, expectedContent] of Object.entries(additionalFiles)) {
7019
- const filePath = (0, import_path6.join)(skillDir, relativePath);
7020
- if (!(0, import_fs6.existsSync)(filePath)) {
7046
+ const filePath = (0, import_path7.join)(skillDir, relativePath);
7047
+ if (!(0, import_fs7.existsSync)(filePath)) {
7021
7048
  return true;
7022
7049
  }
7023
- const installedFileContent = (0, import_fs6.readFileSync)(filePath);
7050
+ const installedFileContent = (0, import_fs7.readFileSync)(filePath);
7024
7051
  if (!installedFileContent.equals(expectedContent)) {
7025
7052
  return true;
7026
7053
  }
@@ -7038,12 +7065,12 @@ function getSkillStatus(skill, target, global) {
7038
7065
  return "installed";
7039
7066
  }
7040
7067
  function parseFrontmatter(content) {
7041
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
7068
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
7042
7069
  if (!frontmatterMatch) {
7043
7070
  return {};
7044
7071
  }
7045
7072
  const frontmatterMap = /* @__PURE__ */ new Map();
7046
- const lines = frontmatterMatch[1].split("\n");
7073
+ const lines = frontmatterMatch[1].split(/\r?\n/);
7047
7074
  for (const line of lines) {
7048
7075
  const colonIndex = line.indexOf(":");
7049
7076
  if (colonIndex === -1) {
@@ -7084,32 +7111,34 @@ function warnLegacySkillStructure(toolPath, legacySkillMdPath) {
7084
7111
  console.error("");
7085
7112
  }
7086
7113
  function scanEditorFolderForSkills(editorPath, skills, sourceType, warnLegacy = true) {
7087
- if (!(0, import_fs6.existsSync)(editorPath)) {
7114
+ if (!(0, import_fs7.existsSync)(editorPath)) {
7088
7115
  return;
7089
7116
  }
7090
- const entries = (0, import_fs6.readdirSync)(editorPath, { withFileTypes: true });
7117
+ const entries = (0, import_fs7.readdirSync)(editorPath, { withFileTypes: true });
7091
7118
  for (const entry of entries) {
7092
7119
  if (EXCLUDED_DIRS2.has(entry.name)) {
7093
7120
  continue;
7094
7121
  }
7095
- const fullPath = (0, import_path6.join)(editorPath, entry.name);
7122
+ const fullPath = (0, import_path7.join)(editorPath, entry.name);
7096
7123
  if (entry.isDirectory()) {
7097
- const skillDir = (0, import_path6.join)(fullPath, SkillsPathConstants.SKILL_DIR);
7098
- const skillMdPath = (0, import_path6.join)(skillDir, SkillsPathConstants.SKILL_FILE);
7099
- const legacySkillMdPath = (0, import_path6.join)(fullPath, SkillsPathConstants.SKILL_FILE);
7100
- if (warnLegacy && !(0, import_fs6.existsSync)(skillMdPath) && (0, import_fs6.existsSync)(legacySkillMdPath)) {
7124
+ const skillDir = (0, import_path7.join)(fullPath, SkillsPathConstants.SKILL_DIR);
7125
+ const skillMdPath = (0, import_path7.join)(skillDir, SkillsPathConstants.SKILL_FILE);
7126
+ const legacySkillMdPath = (0, import_path7.join)(fullPath, SkillsPathConstants.SKILL_FILE);
7127
+ if (warnLegacy && !(0, import_fs7.existsSync)(skillMdPath) && (0, import_fs7.existsSync)(legacySkillMdPath)) {
7101
7128
  warnLegacySkillStructure(fullPath, legacySkillMdPath);
7102
7129
  }
7103
- if ((0, import_fs6.existsSync)(skillMdPath)) {
7104
- const content = (0, import_fs6.readFileSync)(skillMdPath, "utf-8");
7130
+ if ((0, import_fs7.existsSync)(skillMdPath)) {
7131
+ const content = (0, import_fs7.readFileSync)(skillMdPath, "utf-8");
7105
7132
  const frontmatter = parseFrontmatter(content);
7106
7133
  if (frontmatter.internal === true) {
7107
7134
  continue;
7108
7135
  }
7109
7136
  const name = typeof frontmatter.name === "string" ? frontmatter.name : entry.name;
7137
+ const toolName = typeof frontmatter.toolName === "string" ? frontmatter.toolName : void 0;
7110
7138
  const additionalFiles = collectSkillFolderFiles(skillDir);
7111
7139
  skills.push({
7112
7140
  name,
7141
+ toolName,
7113
7142
  dirName: name,
7114
7143
  content,
7115
7144
  sourcePath: skillMdPath,
@@ -7124,15 +7153,15 @@ function scanEditorFolderForSkills(editorPath, skills, sourceType, warnLegacy =
7124
7153
  function findEditorFolders(basePath, maxDepth = 2) {
7125
7154
  const editorFolders = [];
7126
7155
  function scan(currentPath, depth) {
7127
- if (depth > maxDepth || !(0, import_fs6.existsSync)(currentPath)) {
7156
+ if (depth > maxDepth || !(0, import_fs7.existsSync)(currentPath)) {
7128
7157
  return;
7129
7158
  }
7130
- const entries = (0, import_fs6.readdirSync)(currentPath, { withFileTypes: true });
7159
+ const entries = (0, import_fs7.readdirSync)(currentPath, { withFileTypes: true });
7131
7160
  for (const entry of entries) {
7132
7161
  if (!entry.isDirectory() || EXCLUDED_DIRS2.has(entry.name)) {
7133
7162
  continue;
7134
7163
  }
7135
- const fullPath = (0, import_path6.join)(currentPath, entry.name);
7164
+ const fullPath = (0, import_path7.join)(currentPath, entry.name);
7136
7165
  if (entry.name === "Editor") {
7137
7166
  editorFolders.push(fullPath);
7138
7167
  } else {
@@ -7151,12 +7180,12 @@ function collectProjectSkills(excludedRoots = []) {
7151
7180
  const skills = [];
7152
7181
  const seenNames = /* @__PURE__ */ new Set();
7153
7182
  const searchPaths = [
7154
- (0, import_path6.join)(projectRoot, SkillsPathConstants.ASSETS_DIR),
7155
- (0, import_path6.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR),
7156
- (0, import_path6.join)(projectRoot, SkillsPathConstants.LIBRARY_DIR, SkillsPathConstants.PACKAGE_CACHE_DIR)
7183
+ (0, import_path7.join)(projectRoot, SkillsPathConstants.ASSETS_DIR),
7184
+ (0, import_path7.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR),
7185
+ (0, import_path7.join)(projectRoot, SkillsPathConstants.LIBRARY_DIR, SkillsPathConstants.PACKAGE_CACHE_DIR)
7157
7186
  ];
7158
7187
  for (const searchPath of searchPaths) {
7159
- if (!(0, import_fs6.existsSync)(searchPath)) {
7188
+ if (!(0, import_fs7.existsSync)(searchPath)) {
7160
7189
  continue;
7161
7190
  }
7162
7191
  const editorFolders = findEditorFolders(searchPath, 3);
@@ -7187,26 +7216,26 @@ function getAllSkillStatuses(target, global) {
7187
7216
  }
7188
7217
  function installSkill(skill, target, global) {
7189
7218
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
7190
- const skillDir = (0, import_path6.join)(baseDir, skill.dirName);
7191
- const skillPath = (0, import_path6.join)(skillDir, target.skillFileName);
7192
- (0, import_fs6.mkdirSync)(skillDir, { recursive: true });
7193
- (0, import_fs6.writeFileSync)(skillPath, skill.content, "utf-8");
7219
+ const skillDir = (0, import_path7.join)(baseDir, skill.dirName);
7220
+ const skillPath = (0, import_path7.join)(skillDir, target.skillFileName);
7221
+ (0, import_fs7.mkdirSync)(skillDir, { recursive: true });
7222
+ (0, import_fs7.writeFileSync)(skillPath, skill.content, "utf-8");
7194
7223
  if ("additionalFiles" in skill && skill.additionalFiles) {
7195
7224
  const additionalFiles = skill.additionalFiles;
7196
7225
  for (const [relativePath, content] of Object.entries(additionalFiles)) {
7197
- const fullPath = (0, import_path6.join)(skillDir, relativePath);
7198
- (0, import_fs6.mkdirSync)((0, import_path6.dirname)(fullPath), { recursive: true });
7199
- (0, import_fs6.writeFileSync)(fullPath, content);
7226
+ const fullPath = (0, import_path7.join)(skillDir, relativePath);
7227
+ (0, import_fs7.mkdirSync)((0, import_path7.dirname)(fullPath), { recursive: true });
7228
+ (0, import_fs7.writeFileSync)(fullPath, content);
7200
7229
  }
7201
7230
  }
7202
7231
  }
7203
7232
  function uninstallSkill(skill, target, global) {
7204
7233
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
7205
- const skillDir = (0, import_path6.join)(baseDir, skill.dirName);
7206
- if (!(0, import_fs6.existsSync)(skillDir)) {
7234
+ const skillDir = (0, import_path7.join)(baseDir, skill.dirName);
7235
+ if (!(0, import_fs7.existsSync)(skillDir)) {
7207
7236
  return false;
7208
7237
  }
7209
- (0, import_fs6.rmSync)(skillDir, { recursive: true, force: true });
7238
+ (0, import_fs7.rmSync)(skillDir, { recursive: true, force: true });
7210
7239
  return true;
7211
7240
  }
7212
7241
  function installAllSkills(target, global) {
@@ -7220,16 +7249,21 @@ function installAllSkills(target, global) {
7220
7249
  };
7221
7250
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
7222
7251
  for (const deprecatedName of DEPRECATED_SKILLS) {
7223
- const deprecatedDir = (0, import_path6.join)(baseDir, deprecatedName);
7224
- if ((0, import_fs6.existsSync)(deprecatedDir)) {
7225
- (0, import_fs6.rmSync)(deprecatedDir, { recursive: true, force: true });
7252
+ const deprecatedDir = (0, import_path7.join)(baseDir, deprecatedName);
7253
+ if ((0, import_fs7.existsSync)(deprecatedDir)) {
7254
+ (0, import_fs7.rmSync)(deprecatedDir, { recursive: true, force: true });
7226
7255
  result.deprecatedRemoved++;
7227
7256
  }
7228
7257
  }
7258
+ const disabledTools = global ? [] : loadDisabledTools();
7229
7259
  const allSkills = collectAllSkills();
7230
7260
  const projectSkills = allSkills.filter((skill) => skill.sourceType === "project");
7231
7261
  const nonProjectSkills = allSkills.filter((skill) => skill.sourceType !== "project");
7232
7262
  for (const skill of allSkills) {
7263
+ if (isSkillDisabledByToolSettings(skill, disabledTools)) {
7264
+ uninstallSkill(skill, target, global);
7265
+ continue;
7266
+ }
7233
7267
  const status = getSkillStatus(skill, target, global);
7234
7268
  if (status === "not_installed") {
7235
7269
  installSkill(skill, target, global);
@@ -7245,13 +7279,23 @@ function installAllSkills(target, global) {
7245
7279
  result.projectCount = projectSkills.length;
7246
7280
  return result;
7247
7281
  }
7282
+ function isSkillDisabledByToolSettings(skill, disabledTools) {
7283
+ if (disabledTools.length === 0) {
7284
+ return false;
7285
+ }
7286
+ const toolName = skill.toolName ?? (skill.name.startsWith("uloop-") ? skill.name.slice("uloop-".length) : null);
7287
+ if (toolName === null) {
7288
+ return false;
7289
+ }
7290
+ return disabledTools.includes(toolName);
7291
+ }
7248
7292
  function uninstallAllSkills(target, global) {
7249
7293
  const result = { removed: 0, notFound: 0 };
7250
7294
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
7251
7295
  for (const deprecatedName of DEPRECATED_SKILLS) {
7252
- const deprecatedDir = (0, import_path6.join)(baseDir, deprecatedName);
7253
- if ((0, import_fs6.existsSync)(deprecatedDir)) {
7254
- (0, import_fs6.rmSync)(deprecatedDir, { recursive: true, force: true });
7296
+ const deprecatedDir = (0, import_path7.join)(baseDir, deprecatedName);
7297
+ if ((0, import_fs7.existsSync)(deprecatedDir)) {
7298
+ (0, import_fs7.rmSync)(deprecatedDir, { recursive: true, force: true });
7255
7299
  result.removed++;
7256
7300
  }
7257
7301
  }
@@ -7280,13 +7324,13 @@ function collectAllSkills() {
7280
7324
  return dedupeSkillsByName([packageSkills, cliOnlySkills, projectSkills]);
7281
7325
  }
7282
7326
  function collectPackageSkillsFromRoot(packageRoot) {
7283
- const mcpToolsRoot = (0, import_path6.join)(
7327
+ const mcpToolsRoot = (0, import_path7.join)(
7284
7328
  packageRoot,
7285
7329
  SkillsPathConstants.EDITOR_DIR,
7286
7330
  SkillsPathConstants.API_DIR,
7287
7331
  SkillsPathConstants.MCP_TOOLS_DIR
7288
7332
  );
7289
- if (!(0, import_fs6.existsSync)(mcpToolsRoot)) {
7333
+ if (!(0, import_fs7.existsSync)(mcpToolsRoot)) {
7290
7334
  return [];
7291
7335
  }
7292
7336
  const skills = [];
@@ -7294,7 +7338,7 @@ function collectPackageSkillsFromRoot(packageRoot) {
7294
7338
  return skills;
7295
7339
  }
7296
7340
  function collectCliOnlySkills() {
7297
- const cliOnlyRoot = (0, import_path6.resolve)(
7341
+ const cliOnlyRoot = (0, import_path7.resolve)(
7298
7342
  __dirname,
7299
7343
  SkillsPathConstants.DIST_PARENT_DIR,
7300
7344
  SkillsPathConstants.SRC_DIR,
@@ -7302,7 +7346,7 @@ function collectCliOnlySkills() {
7302
7346
  SkillsPathConstants.CLI_ONLY_DIR,
7303
7347
  SkillsPathConstants.CLI_ONLY_SUBDIR
7304
7348
  );
7305
- if (!(0, import_fs6.existsSync)(cliOnlyRoot)) {
7349
+ if (!(0, import_fs7.existsSync)(cliOnlyRoot)) {
7306
7350
  return [];
7307
7351
  }
7308
7352
  const skills = [];
@@ -7321,12 +7365,12 @@ function isExcludedFile(fileName) {
7321
7365
  return false;
7322
7366
  }
7323
7367
  function collectSkillFolderFilesRecursive(baseDir, currentDir, additionalFiles) {
7324
- const entries = (0, import_fs6.readdirSync)(currentDir, { withFileTypes: true });
7368
+ const entries = (0, import_fs7.readdirSync)(currentDir, { withFileTypes: true });
7325
7369
  for (const entry of entries) {
7326
7370
  if (isExcludedFile(entry.name)) {
7327
7371
  continue;
7328
7372
  }
7329
- const fullPath = (0, import_path6.join)(currentDir, entry.name);
7373
+ const fullPath = (0, import_path7.join)(currentDir, entry.name);
7330
7374
  const relativePath = fullPath.slice(baseDir.length + 1);
7331
7375
  if (entry.isDirectory()) {
7332
7376
  if (EXCLUDED_DIRS2.has(entry.name)) {
@@ -7337,12 +7381,12 @@ function collectSkillFolderFilesRecursive(baseDir, currentDir, additionalFiles)
7337
7381
  if (entry.name === SkillsPathConstants.SKILL_FILE) {
7338
7382
  continue;
7339
7383
  }
7340
- additionalFiles[relativePath] = (0, import_fs6.readFileSync)(fullPath);
7384
+ additionalFiles[relativePath] = (0, import_fs7.readFileSync)(fullPath);
7341
7385
  }
7342
7386
  }
7343
7387
  }
7344
7388
  function collectSkillFolderFiles(skillDir) {
7345
- if (!(0, import_fs6.existsSync)(skillDir)) {
7389
+ if (!(0, import_fs7.existsSync)(skillDir)) {
7346
7390
  return void 0;
7347
7391
  }
7348
7392
  const additionalFiles = {};
@@ -7365,13 +7409,13 @@ function dedupeSkillsByName(skillGroups) {
7365
7409
  }
7366
7410
  function resolvePackageRoot(projectRoot) {
7367
7411
  const candidates = [];
7368
- candidates.push((0, import_path6.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR));
7412
+ candidates.push((0, import_path7.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR));
7369
7413
  const manifestPaths = resolveManifestPackagePaths(projectRoot);
7370
7414
  for (const manifestPath of manifestPaths) {
7371
7415
  candidates.push(manifestPath);
7372
7416
  }
7373
7417
  for (const packageName of SkillsPathConstants.PACKAGE_NAMES) {
7374
- candidates.push((0, import_path6.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, packageName));
7418
+ candidates.push((0, import_path7.join)(projectRoot, SkillsPathConstants.PACKAGES_DIR, packageName));
7375
7419
  }
7376
7420
  const directRoot = resolveFirstPackageRoot(candidates);
7377
7421
  if (directRoot) {
@@ -7380,15 +7424,15 @@ function resolvePackageRoot(projectRoot) {
7380
7424
  return resolvePackageCacheRoot(projectRoot);
7381
7425
  }
7382
7426
  function resolveManifestPackagePaths(projectRoot) {
7383
- const manifestPath = (0, import_path6.join)(
7427
+ const manifestPath = (0, import_path7.join)(
7384
7428
  projectRoot,
7385
7429
  SkillsPathConstants.PACKAGES_DIR,
7386
7430
  SkillsPathConstants.MANIFEST_FILE
7387
7431
  );
7388
- if (!(0, import_fs6.existsSync)(manifestPath)) {
7432
+ if (!(0, import_fs7.existsSync)(manifestPath)) {
7389
7433
  return [];
7390
7434
  }
7391
- const manifestContent = (0, import_fs6.readFileSync)(manifestPath, "utf-8");
7435
+ const manifestContent = (0, import_fs7.readFileSync)(manifestPath, "utf-8");
7392
7436
  let manifestJson;
7393
7437
  try {
7394
7438
  manifestJson = JSON.parse(manifestContent);
@@ -7432,10 +7476,10 @@ function resolveDependencyPath(rawPath, projectRoot) {
7432
7476
  if (normalizedPath.startsWith("//")) {
7433
7477
  normalizedPath = normalizedPath.slice(2);
7434
7478
  }
7435
- if ((0, import_path6.isAbsolute)(normalizedPath)) {
7479
+ if ((0, import_path7.isAbsolute)(normalizedPath)) {
7436
7480
  return normalizedPath;
7437
7481
  }
7438
- return (0, import_path6.resolve)(projectRoot, normalizedPath);
7482
+ return (0, import_path7.resolve)(projectRoot, normalizedPath);
7439
7483
  }
7440
7484
  function resolveFirstPackageRoot(candidates) {
7441
7485
  for (const candidate of candidates) {
@@ -7447,15 +7491,15 @@ function resolveFirstPackageRoot(candidates) {
7447
7491
  return null;
7448
7492
  }
7449
7493
  function resolvePackageCacheRoot(projectRoot) {
7450
- const packageCacheDir = (0, import_path6.join)(
7494
+ const packageCacheDir = (0, import_path7.join)(
7451
7495
  projectRoot,
7452
7496
  SkillsPathConstants.LIBRARY_DIR,
7453
7497
  SkillsPathConstants.PACKAGE_CACHE_DIR
7454
7498
  );
7455
- if (!(0, import_fs6.existsSync)(packageCacheDir)) {
7499
+ if (!(0, import_fs7.existsSync)(packageCacheDir)) {
7456
7500
  return null;
7457
7501
  }
7458
- const entries = (0, import_fs6.readdirSync)(packageCacheDir, { withFileTypes: true });
7502
+ const entries = (0, import_fs7.readdirSync)(packageCacheDir, { withFileTypes: true });
7459
7503
  for (const entry of entries) {
7460
7504
  if (!entry.isDirectory()) {
7461
7505
  continue;
@@ -7463,7 +7507,7 @@ function resolvePackageCacheRoot(projectRoot) {
7463
7507
  if (!isTargetPackageCacheDir(entry.name)) {
7464
7508
  continue;
7465
7509
  }
7466
- const candidate = (0, import_path6.join)(packageCacheDir, entry.name);
7510
+ const candidate = (0, import_path7.join)(packageCacheDir, entry.name);
7467
7511
  const resolvedRoot = resolvePackageRootCandidate(candidate);
7468
7512
  if (resolvedRoot) {
7469
7513
  return resolvedRoot;
@@ -7472,26 +7516,26 @@ function resolvePackageCacheRoot(projectRoot) {
7472
7516
  return null;
7473
7517
  }
7474
7518
  function resolvePackageRootCandidate(candidate) {
7475
- if (!(0, import_fs6.existsSync)(candidate)) {
7519
+ if (!(0, import_fs7.existsSync)(candidate)) {
7476
7520
  return null;
7477
7521
  }
7478
- const directToolsPath = (0, import_path6.join)(
7522
+ const directToolsPath = (0, import_path7.join)(
7479
7523
  candidate,
7480
7524
  SkillsPathConstants.EDITOR_DIR,
7481
7525
  SkillsPathConstants.API_DIR,
7482
7526
  SkillsPathConstants.MCP_TOOLS_DIR
7483
7527
  );
7484
- if ((0, import_fs6.existsSync)(directToolsPath)) {
7528
+ if ((0, import_fs7.existsSync)(directToolsPath)) {
7485
7529
  return candidate;
7486
7530
  }
7487
- const nestedRoot = (0, import_path6.join)(candidate, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR);
7488
- const nestedToolsPath = (0, import_path6.join)(
7531
+ const nestedRoot = (0, import_path7.join)(candidate, SkillsPathConstants.PACKAGES_DIR, SkillsPathConstants.SRC_DIR);
7532
+ const nestedToolsPath = (0, import_path7.join)(
7489
7533
  nestedRoot,
7490
7534
  SkillsPathConstants.EDITOR_DIR,
7491
7535
  SkillsPathConstants.API_DIR,
7492
7536
  SkillsPathConstants.MCP_TOOLS_DIR
7493
7537
  );
7494
- if ((0, import_fs6.existsSync)(nestedToolsPath)) {
7538
+ if ((0, import_fs7.existsSync)(nestedToolsPath)) {
7495
7539
  return nestedRoot;
7496
7540
  }
7497
7541
  return null;
@@ -7517,12 +7561,12 @@ function isUnderExcludedRoots(targetPath, excludedRoots) {
7517
7561
  return false;
7518
7562
  }
7519
7563
  function isPathUnder(childPath, parentPath) {
7520
- const resolvedChild = (0, import_path6.resolve)(childPath);
7521
- const resolvedParent = (0, import_path6.resolve)(parentPath);
7564
+ const resolvedChild = (0, import_path7.resolve)(childPath);
7565
+ const resolvedParent = (0, import_path7.resolve)(parentPath);
7522
7566
  if (resolvedChild === resolvedParent) {
7523
7567
  return true;
7524
7568
  }
7525
- return resolvedChild.startsWith(resolvedParent + import_path6.sep);
7569
+ return resolvedChild.startsWith(resolvedParent + import_path7.sep);
7526
7570
  }
7527
7571
 
7528
7572
  // src/skills/target-config.ts
@@ -7707,7 +7751,7 @@ Uninstalling uloop skills (${location})...`);
7707
7751
  }
7708
7752
 
7709
7753
  // src/commands/launch.ts
7710
- var import_path7 = require("path");
7754
+ var import_path8 = require("path");
7711
7755
 
7712
7756
  // node_modules/launch-unity/dist/lib.js
7713
7757
  var import_node_child_process = require("node:child_process");
@@ -8335,7 +8379,7 @@ async function waitForProcessExit(pid, timeoutMs) {
8335
8379
  if (!isProcessAlive(pid)) {
8336
8380
  return true;
8337
8381
  }
8338
- await new Promise((resolve6) => setTimeout(resolve6, KILL_POLL_INTERVAL_MS));
8382
+ await new Promise((resolve7) => setTimeout(resolve7, KILL_POLL_INTERVAL_MS));
8339
8383
  }
8340
8384
  return false;
8341
8385
  }
@@ -8504,7 +8548,7 @@ async function waitForLockfile(projectPath) {
8504
8548
  if ((0, import_node_fs2.existsSync)(lockfilePath)) {
8505
8549
  return;
8506
8550
  }
8507
- await new Promise((resolve6) => setTimeout(resolve6, LOCKFILE_POLL_INTERVAL_MS));
8551
+ await new Promise((resolve7) => setTimeout(resolve7, LOCKFILE_POLL_INTERVAL_MS));
8508
8552
  }
8509
8553
  console.warn("Unity launched, but UnityLockfile was not detected within 5s.");
8510
8554
  }
@@ -8535,7 +8579,7 @@ async function launch(opts) {
8535
8579
  if (unityArgs.length > 0) {
8536
8580
  args.push(...unityArgs);
8537
8581
  }
8538
- return new Promise((resolve6, reject) => {
8582
+ return new Promise((resolve7, reject) => {
8539
8583
  const child = (0, import_node_child_process.spawn)(unityPath, args, {
8540
8584
  stdio: "ignore",
8541
8585
  detached: true,
@@ -8552,7 +8596,7 @@ async function launch(opts) {
8552
8596
  const handleSpawn = () => {
8553
8597
  child.removeListener("error", handleError);
8554
8598
  child.unref();
8555
- resolve6();
8599
+ resolve7();
8556
8600
  };
8557
8601
  child.once("error", handleError);
8558
8602
  child.once("spawn", handleSpawn);
@@ -8645,7 +8689,7 @@ function parseMaxDepth(value) {
8645
8689
  async function runLaunchCommand(projectPath, options) {
8646
8690
  const maxDepth = parseMaxDepth(options.maxDepth);
8647
8691
  await orchestrateLaunch({
8648
- projectPath: projectPath ? (0, import_path7.resolve)(projectPath) : void 0,
8692
+ projectPath: projectPath ? (0, import_path8.resolve)(projectPath) : void 0,
8649
8693
  searchRoot: process.cwd(),
8650
8694
  searchMaxDepth: maxDepth,
8651
8695
  platform: options.platform,
@@ -8888,6 +8932,10 @@ function extractGlobalOptions(options) {
8888
8932
  function isConnectionError(message) {
8889
8933
  return message.includes("ECONNREFUSED") || message.includes("EADDRNOTAVAIL");
8890
8934
  }
8935
+ function printToolDisabledError(cmdName) {
8936
+ console.error(`\x1B[33mTool '${cmdName}' is disabled.\x1B[0m`);
8937
+ console.error("You can enable it in Unity: Window > uLoop > Tool Settings");
8938
+ }
8891
8939
  function printConnectionError() {
8892
8940
  console.error("\x1B[31mError: Cannot connect to Unity.\x1B[0m");
8893
8941
  console.error("Make sure Unity Editor is open and uLoopMCP server is running.");
@@ -8966,7 +9014,7 @@ async function runWithErrorHandling(fn) {
8966
9014
  }
8967
9015
  function detectShell() {
8968
9016
  const shell = process.env["SHELL"] || "";
8969
- const shellName = (0, import_path8.basename)(shell).replace(/\.exe$/i, "");
9017
+ const shellName = (0, import_path9.basename)(shell).replace(/\.exe$/i, "");
8970
9018
  if (shellName === "zsh") {
8971
9019
  return "zsh";
8972
9020
  }
@@ -8981,12 +9029,12 @@ function detectShell() {
8981
9029
  function getShellConfigPath(shell) {
8982
9030
  const home = (0, import_os2.homedir)();
8983
9031
  if (shell === "zsh") {
8984
- return (0, import_path8.join)(home, ".zshrc");
9032
+ return (0, import_path9.join)(home, ".zshrc");
8985
9033
  }
8986
9034
  if (shell === "powershell") {
8987
- return (0, import_path8.join)(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
9035
+ return (0, import_path9.join)(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
8988
9036
  }
8989
- return (0, import_path8.join)(home, ".bashrc");
9037
+ return (0, import_path9.join)(home, ".bashrc");
8990
9038
  }
8991
9039
  function getCompletionScript(shell) {
8992
9040
  if (shell === "bash") {
@@ -9123,12 +9171,12 @@ function cleanupLockFiles(projectPath) {
9123
9171
  console.error("Could not find Unity project root.");
9124
9172
  process.exit(1);
9125
9173
  }
9126
- const tempDir = (0, import_path8.join)(projectRoot, "Temp");
9174
+ const tempDir = (0, import_path9.join)(projectRoot, "Temp");
9127
9175
  let cleaned = 0;
9128
9176
  for (const lockFile of LOCK_FILES) {
9129
- const lockPath = (0, import_path8.join)(tempDir, lockFile);
9130
- if ((0, import_fs7.existsSync)(lockPath)) {
9131
- (0, import_fs7.unlinkSync)(lockPath);
9177
+ const lockPath = (0, import_path9.join)(tempDir, lockFile);
9178
+ if ((0, import_fs8.existsSync)(lockPath)) {
9179
+ (0, import_fs8.unlinkSync)(lockPath);
9132
9180
  console.log(`Removed: ${lockFile}`);
9133
9181
  cleaned++;
9134
9182
  }
@@ -9163,13 +9211,13 @@ function handleCompletion(install, shellOverride) {
9163
9211
  return;
9164
9212
  }
9165
9213
  const configPath = getShellConfigPath(shell);
9166
- const configDir = (0, import_path8.dirname)(configPath);
9167
- if (!(0, import_fs7.existsSync)(configDir)) {
9168
- (0, import_fs7.mkdirSync)(configDir, { recursive: true });
9214
+ const configDir = (0, import_path9.dirname)(configPath);
9215
+ if (!(0, import_fs8.existsSync)(configDir)) {
9216
+ (0, import_fs8.mkdirSync)(configDir, { recursive: true });
9169
9217
  }
9170
9218
  let content = "";
9171
- if ((0, import_fs7.existsSync)(configPath)) {
9172
- content = (0, import_fs7.readFileSync)(configPath, "utf-8");
9219
+ if ((0, import_fs8.existsSync)(configPath)) {
9220
+ content = (0, import_fs8.readFileSync)(configPath, "utf-8");
9173
9221
  content = content.replace(
9174
9222
  /\n?# >>> uloop completion >>>[\s\S]*?# <<< uloop completion <<<\n?/g,
9175
9223
  ""
@@ -9183,7 +9231,7 @@ ${startMarker}
9183
9231
  ${script}
9184
9232
  ${endMarker}
9185
9233
  `;
9186
- (0, import_fs7.writeFileSync)(configPath, content + lineToAdd, "utf-8");
9234
+ (0, import_fs8.writeFileSync)(configPath, content + lineToAdd, "utf-8");
9187
9235
  } else {
9188
9236
  const evalLine = `eval "$(uloop completion --shell ${shell})"`;
9189
9237
  const lineToAdd = `
@@ -9191,7 +9239,7 @@ ${startMarker}
9191
9239
  ${evalLine}
9192
9240
  ${endMarker}
9193
9241
  `;
9194
- (0, import_fs7.writeFileSync)(configPath, content + lineToAdd, "utf-8");
9242
+ (0, import_fs8.writeFileSync)(configPath, content + lineToAdd, "utf-8");
9195
9243
  }
9196
9244
  console.log(`Completion installed to ${configPath}`);
9197
9245
  if (shell === "powershell") {
@@ -9202,26 +9250,28 @@ ${endMarker}
9202
9250
  }
9203
9251
  function handleCompletionOptions() {
9204
9252
  const args = process.argv.slice(2);
9253
+ const projectPath = extractSyncGlobalOptions(args).projectPath;
9205
9254
  if (args.includes("--list-commands")) {
9206
9255
  const tools = loadToolsCache();
9207
- const allCommands = [...BUILTIN_COMMANDS, ...tools.tools.map((t) => t.name)];
9256
+ const enabledTools = projectPath !== void 0 ? filterEnabledTools(tools.tools, projectPath) : tools.tools;
9257
+ const allCommands = [...BUILTIN_COMMANDS, ...enabledTools.map((t) => t.name)];
9208
9258
  console.log(allCommands.join("\n"));
9209
9259
  return true;
9210
9260
  }
9211
9261
  const listOptionsIdx = args.indexOf("--list-options");
9212
9262
  if (listOptionsIdx !== -1 && args[listOptionsIdx + 1]) {
9213
9263
  const cmdName = args[listOptionsIdx + 1];
9214
- listOptionsForCommand(cmdName);
9264
+ listOptionsForCommand(cmdName, projectPath);
9215
9265
  return true;
9216
9266
  }
9217
9267
  return false;
9218
9268
  }
9219
- function listOptionsForCommand(cmdName) {
9269
+ function listOptionsForCommand(cmdName, projectPath) {
9220
9270
  if (BUILTIN_COMMANDS.includes(cmdName)) {
9221
9271
  return;
9222
9272
  }
9223
9273
  const tools = loadToolsCache();
9224
- const tool = tools.tools.find((t) => t.name === cmdName);
9274
+ const tool = projectPath !== void 0 ? filterEnabledTools(tools.tools, projectPath).find((t) => t.name === cmdName) : tools.tools.find((t) => t.name === cmdName);
9225
9275
  if (!tool) {
9226
9276
  return;
9227
9277
  }
@@ -9232,12 +9282,12 @@ function listOptionsForCommand(cmdName) {
9232
9282
  }
9233
9283
  console.log(options.join("\n"));
9234
9284
  }
9235
- function commandExists(cmdName) {
9285
+ function commandExists(cmdName, projectPath) {
9236
9286
  if (BUILTIN_COMMANDS.includes(cmdName)) {
9237
9287
  return true;
9238
9288
  }
9239
9289
  const tools = loadToolsCache();
9240
- return tools.tools.some((t) => t.name === cmdName);
9290
+ return filterEnabledTools(tools.tools, projectPath).some((t) => t.name === cmdName);
9241
9291
  }
9242
9292
  function shouldSkipAutoSync(cmdName, args) {
9243
9293
  if (cmdName === LAUNCH_COMMAND || cmdName === UPDATE_COMMAND) {
@@ -9285,7 +9335,8 @@ async function main() {
9285
9335
  const skipProjectDetection = cmdName === void 0 || NO_PROJECT_COMMANDS.includes(cmdName);
9286
9336
  if (skipProjectDetection) {
9287
9337
  const defaultTools = getDefaultTools();
9288
- for (const tool of defaultTools.tools) {
9338
+ const tools = syncGlobalOptions.projectPath !== void 0 ? filterEnabledTools(defaultTools.tools, syncGlobalOptions.projectPath) : defaultTools.tools;
9339
+ for (const tool of tools) {
9289
9340
  registerToolCommand(tool);
9290
9341
  }
9291
9342
  program2.parse();
@@ -9314,15 +9365,20 @@ async function main() {
9314
9365
  }
9315
9366
  }
9316
9367
  const toolsCache = loadToolsCache();
9317
- for (const tool of toolsCache.tools) {
9368
+ const projectPath = syncGlobalOptions.projectPath;
9369
+ for (const tool of filterEnabledTools(toolsCache.tools, projectPath)) {
9318
9370
  registerToolCommand(tool);
9319
9371
  }
9320
- if (cmdName && !commandExists(cmdName)) {
9372
+ if (cmdName && !commandExists(cmdName, projectPath)) {
9373
+ if (!isToolEnabled(cmdName, projectPath)) {
9374
+ printToolDisabledError(cmdName);
9375
+ process.exit(1);
9376
+ }
9321
9377
  console.log(`\x1B[33mUnknown command '${cmdName}'. Syncing tools from Unity...\x1B[0m`);
9322
9378
  try {
9323
9379
  await syncTools(syncGlobalOptions);
9324
9380
  const newCache = loadToolsCache();
9325
- const tool = newCache.tools.find((t) => t.name === cmdName);
9381
+ const tool = filterEnabledTools(newCache.tools, projectPath).find((t) => t.name === cmdName);
9326
9382
  if (tool) {
9327
9383
  registerToolCommand(tool);
9328
9384
  console.log(`\x1B[32m\u2713 Found '${cmdName}' after sync.\x1B[0m