uloop-cli 0.55.2 → 0.57.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.
- package/dist/cli.bundle.cjs +731 -17
- package/dist/cli.bundle.cjs.map +4 -4
- package/package.json +7 -6
- package/src/__tests__/cli-e2e.test.ts +40 -0
- package/src/cli.ts +64 -2
- package/src/commands/launch.ts +125 -0
- package/src/default-tools.json +6 -1
- package/src/direct-unity-client.ts +1 -1
- package/src/execute-tool.ts +3 -1
- package/src/skills/skill-definitions/cli-only/uloop-launch/Skill/SKILL.md +51 -0
- package/src/tool-cache.ts +21 -0
- package/src/version.ts +1 -1
package/dist/cli.bundle.cjs
CHANGED
|
@@ -5384,7 +5384,7 @@ var require_semver2 = __commonJS({
|
|
|
5384
5384
|
|
|
5385
5385
|
// src/cli.ts
|
|
5386
5386
|
var import_fs6 = require("fs");
|
|
5387
|
-
var
|
|
5387
|
+
var import_path7 = 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((
|
|
5489
|
+
return new Promise((resolve5, 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
|
-
|
|
5495
|
+
resolve5();
|
|
5496
5496
|
});
|
|
5497
5497
|
});
|
|
5498
5498
|
}
|
|
@@ -5508,12 +5508,12 @@ var DirectUnityClient = class {
|
|
|
5508
5508
|
};
|
|
5509
5509
|
const requestJson = JSON.stringify(request);
|
|
5510
5510
|
const framedMessage = createFrame(requestJson);
|
|
5511
|
-
return new Promise((
|
|
5511
|
+
return new Promise((resolve5, reject) => {
|
|
5512
5512
|
const socket = this.socket;
|
|
5513
5513
|
const timeoutId = setTimeout(() => {
|
|
5514
5514
|
reject(
|
|
5515
5515
|
new Error(
|
|
5516
|
-
`Request timed out after ${NETWORK_TIMEOUT_MS}ms. Unity may be frozen or busy. Please report this to the user and ask how to proceed. Do NOT kill Unity processes without user permission.`
|
|
5516
|
+
`Request timed out after ${NETWORK_TIMEOUT_MS}ms. Unity may be frozen or busy. [For AI] Please report this to the user and ask how to proceed. Do NOT kill Unity processes without user permission.`
|
|
5517
5517
|
)
|
|
5518
5518
|
);
|
|
5519
5519
|
}, NETWORK_TIMEOUT_MS);
|
|
@@ -5539,7 +5539,7 @@ var DirectUnityClient = class {
|
|
|
5539
5539
|
reject(new Error(`Unity error: ${response.error.message}`));
|
|
5540
5540
|
return;
|
|
5541
5541
|
}
|
|
5542
|
-
|
|
5542
|
+
resolve5(response.result);
|
|
5543
5543
|
};
|
|
5544
5544
|
socket.on("data", onData);
|
|
5545
5545
|
socket.write(framedMessage);
|
|
@@ -5763,7 +5763,7 @@ var import_path3 = require("path");
|
|
|
5763
5763
|
|
|
5764
5764
|
// src/default-tools.json
|
|
5765
5765
|
var default_tools_default = {
|
|
5766
|
-
version: "0.
|
|
5766
|
+
version: "0.57.0",
|
|
5767
5767
|
tools: [
|
|
5768
5768
|
{
|
|
5769
5769
|
name: "compile",
|
|
@@ -5906,6 +5906,11 @@ var default_tools_default = {
|
|
|
5906
5906
|
IncludePaths: {
|
|
5907
5907
|
type: "boolean",
|
|
5908
5908
|
description: "Include path information"
|
|
5909
|
+
},
|
|
5910
|
+
UseSelection: {
|
|
5911
|
+
type: "boolean",
|
|
5912
|
+
description: "Use selected GameObject(s) as root(s). When true, RootPath is ignored.",
|
|
5913
|
+
default: false
|
|
5909
5914
|
}
|
|
5910
5915
|
}
|
|
5911
5916
|
}
|
|
@@ -6195,9 +6200,22 @@ function hasCacheFile() {
|
|
|
6195
6200
|
function getCacheFilePath() {
|
|
6196
6201
|
return getCachePath();
|
|
6197
6202
|
}
|
|
6203
|
+
function getCachedServerVersion() {
|
|
6204
|
+
const cachePath = getCachePath();
|
|
6205
|
+
if (!(0, import_fs3.existsSync)(cachePath)) {
|
|
6206
|
+
return void 0;
|
|
6207
|
+
}
|
|
6208
|
+
try {
|
|
6209
|
+
const content = (0, import_fs3.readFileSync)(cachePath, "utf-8");
|
|
6210
|
+
const cache = JSON.parse(content);
|
|
6211
|
+
return typeof cache.serverVersion === "string" ? cache.serverVersion : void 0;
|
|
6212
|
+
} catch {
|
|
6213
|
+
return void 0;
|
|
6214
|
+
}
|
|
6215
|
+
}
|
|
6198
6216
|
|
|
6199
6217
|
// src/version.ts
|
|
6200
|
-
var VERSION = "0.
|
|
6218
|
+
var VERSION = "0.57.0";
|
|
6201
6219
|
|
|
6202
6220
|
// src/spinner.ts
|
|
6203
6221
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -6260,7 +6278,7 @@ function suppressStdinEcho() {
|
|
|
6260
6278
|
var RETRY_DELAY_MS = 500;
|
|
6261
6279
|
var MAX_RETRIES = 3;
|
|
6262
6280
|
function sleep(ms) {
|
|
6263
|
-
return new Promise((
|
|
6281
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
6264
6282
|
}
|
|
6265
6283
|
function isRetryableError(error) {
|
|
6266
6284
|
if (!(error instanceof Error)) {
|
|
@@ -6441,6 +6459,7 @@ async function syncTools(globalOptions) {
|
|
|
6441
6459
|
}
|
|
6442
6460
|
const cache = {
|
|
6443
6461
|
version: VERSION,
|
|
6462
|
+
serverVersion: result.Ver,
|
|
6444
6463
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6445
6464
|
tools: result.Tools.map((tool) => ({
|
|
6446
6465
|
name: tool.name,
|
|
@@ -7231,8 +7250,671 @@ Uninstalling uloop skills (${location})...`);
|
|
|
7231
7250
|
}
|
|
7232
7251
|
}
|
|
7233
7252
|
|
|
7253
|
+
// src/commands/launch.ts
|
|
7254
|
+
var import_path6 = require("path");
|
|
7255
|
+
|
|
7256
|
+
// node_modules/launch-unity/dist/lib.js
|
|
7257
|
+
var import_node_child_process = require("node:child_process");
|
|
7258
|
+
var import_node_fs2 = require("node:fs");
|
|
7259
|
+
var import_promises3 = require("node:fs/promises");
|
|
7260
|
+
var import_node_path2 = require("node:path");
|
|
7261
|
+
var import_node_util = require("node:util");
|
|
7262
|
+
|
|
7263
|
+
// node_modules/launch-unity/dist/unityHub.js
|
|
7264
|
+
var import_promises2 = require("node:fs/promises");
|
|
7265
|
+
var import_node_fs = require("node:fs");
|
|
7266
|
+
var import_node_path = require("node:path");
|
|
7267
|
+
var resolveUnityHubProjectFiles = () => {
|
|
7268
|
+
if (process.platform === "darwin") {
|
|
7269
|
+
const home = process.env.HOME;
|
|
7270
|
+
if (!home) {
|
|
7271
|
+
return [];
|
|
7272
|
+
}
|
|
7273
|
+
const base = (0, import_node_path.join)(home, "Library", "Application Support", "UnityHub");
|
|
7274
|
+
return [(0, import_node_path.join)(base, "projects-v1.json"), (0, import_node_path.join)(base, "projects.json")];
|
|
7275
|
+
}
|
|
7276
|
+
if (process.platform === "win32") {
|
|
7277
|
+
const appData = process.env.APPDATA;
|
|
7278
|
+
if (!appData) {
|
|
7279
|
+
return [];
|
|
7280
|
+
}
|
|
7281
|
+
const base = (0, import_node_path.join)(appData, "UnityHub");
|
|
7282
|
+
return [(0, import_node_path.join)(base, "projects-v1.json"), (0, import_node_path.join)(base, "projects.json")];
|
|
7283
|
+
}
|
|
7284
|
+
return [];
|
|
7285
|
+
};
|
|
7286
|
+
var removeTrailingSeparators = (target) => {
|
|
7287
|
+
let trimmed = target;
|
|
7288
|
+
while (trimmed.length > 1 && (trimmed.endsWith("/") || trimmed.endsWith("\\"))) {
|
|
7289
|
+
trimmed = trimmed.slice(0, -1);
|
|
7290
|
+
}
|
|
7291
|
+
return trimmed;
|
|
7292
|
+
};
|
|
7293
|
+
var normalizePath = (target) => {
|
|
7294
|
+
const resolvedPath = (0, import_node_path.resolve)(target);
|
|
7295
|
+
return removeTrailingSeparators(resolvedPath);
|
|
7296
|
+
};
|
|
7297
|
+
var resolvePathWithActualCase = (target) => {
|
|
7298
|
+
try {
|
|
7299
|
+
return removeTrailingSeparators(import_node_fs.realpathSync.native(target));
|
|
7300
|
+
} catch {
|
|
7301
|
+
return normalizePath(target);
|
|
7302
|
+
}
|
|
7303
|
+
};
|
|
7304
|
+
var toComparablePath = (value) => {
|
|
7305
|
+
return value.replace(/\\/g, "/").toLocaleLowerCase();
|
|
7306
|
+
};
|
|
7307
|
+
var pathsEqual = (left, right) => {
|
|
7308
|
+
return toComparablePath(normalizePath(left)) === toComparablePath(normalizePath(right));
|
|
7309
|
+
};
|
|
7310
|
+
var safeParseProjectsJson = (content) => {
|
|
7311
|
+
try {
|
|
7312
|
+
return JSON.parse(content);
|
|
7313
|
+
} catch {
|
|
7314
|
+
return void 0;
|
|
7315
|
+
}
|
|
7316
|
+
};
|
|
7317
|
+
var logDebug = (message) => {
|
|
7318
|
+
if (process.env["LAUNCH_UNITY_DEBUG"] === "1") {
|
|
7319
|
+
console.log(`[unityHub] ${message}`);
|
|
7320
|
+
}
|
|
7321
|
+
};
|
|
7322
|
+
var ensureProjectEntryAndUpdate = async (projectPath, version, when, setFavorite = false) => {
|
|
7323
|
+
const canonicalProjectPath = resolvePathWithActualCase(projectPath);
|
|
7324
|
+
const projectTitle = (0, import_node_path.basename)(canonicalProjectPath);
|
|
7325
|
+
const containingFolderPath = (0, import_node_path.dirname)(canonicalProjectPath);
|
|
7326
|
+
const candidates = resolveUnityHubProjectFiles();
|
|
7327
|
+
if (candidates.length === 0) {
|
|
7328
|
+
logDebug("No Unity Hub project files found.");
|
|
7329
|
+
return;
|
|
7330
|
+
}
|
|
7331
|
+
for (const path of candidates) {
|
|
7332
|
+
logDebug(`Trying Unity Hub file: ${path}`);
|
|
7333
|
+
const content = await (0, import_promises2.readFile)(path, "utf8").catch(() => void 0);
|
|
7334
|
+
if (!content) {
|
|
7335
|
+
logDebug("Read failed or empty content, skipping.");
|
|
7336
|
+
continue;
|
|
7337
|
+
}
|
|
7338
|
+
const json = safeParseProjectsJson(content);
|
|
7339
|
+
if (!json) {
|
|
7340
|
+
logDebug("Parse failed, skipping.");
|
|
7341
|
+
continue;
|
|
7342
|
+
}
|
|
7343
|
+
const data = { ...json.data ?? {} };
|
|
7344
|
+
const existingKey = Object.keys(data).find((key) => {
|
|
7345
|
+
const entryPath = data[key]?.path;
|
|
7346
|
+
return entryPath ? pathsEqual(entryPath, projectPath) : false;
|
|
7347
|
+
});
|
|
7348
|
+
const targetKey = existingKey ?? canonicalProjectPath;
|
|
7349
|
+
const existingEntry = existingKey ? data[existingKey] : void 0;
|
|
7350
|
+
logDebug(existingKey ? `Found existing entry for project (key=${existingKey}). Updating lastModified.` : `No existing entry. Adding new entry (key=${targetKey}).`);
|
|
7351
|
+
const updatedEntry = {
|
|
7352
|
+
...existingEntry,
|
|
7353
|
+
path: existingEntry?.path ?? canonicalProjectPath,
|
|
7354
|
+
containingFolderPath: existingEntry?.containingFolderPath ?? containingFolderPath,
|
|
7355
|
+
version: existingEntry?.version ?? version,
|
|
7356
|
+
title: existingEntry?.title ?? projectTitle,
|
|
7357
|
+
lastModified: when.getTime(),
|
|
7358
|
+
isFavorite: setFavorite ? true : existingEntry?.isFavorite ?? false
|
|
7359
|
+
};
|
|
7360
|
+
const updatedJson = {
|
|
7361
|
+
...json,
|
|
7362
|
+
data: {
|
|
7363
|
+
...data,
|
|
7364
|
+
[targetKey]: updatedEntry
|
|
7365
|
+
}
|
|
7366
|
+
};
|
|
7367
|
+
try {
|
|
7368
|
+
await (0, import_promises2.writeFile)(path, JSON.stringify(updatedJson, void 0, 2), "utf8");
|
|
7369
|
+
logDebug("Write succeeded.");
|
|
7370
|
+
} catch (error) {
|
|
7371
|
+
logDebug(`Write failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
7372
|
+
}
|
|
7373
|
+
return;
|
|
7374
|
+
}
|
|
7375
|
+
};
|
|
7376
|
+
var updateLastModifiedIfExists = async (projectPath, when) => {
|
|
7377
|
+
const candidates = resolveUnityHubProjectFiles();
|
|
7378
|
+
if (candidates.length === 0) {
|
|
7379
|
+
return;
|
|
7380
|
+
}
|
|
7381
|
+
for (const path of candidates) {
|
|
7382
|
+
let content;
|
|
7383
|
+
let json;
|
|
7384
|
+
try {
|
|
7385
|
+
content = await (0, import_promises2.readFile)(path, "utf8");
|
|
7386
|
+
} catch {
|
|
7387
|
+
continue;
|
|
7388
|
+
}
|
|
7389
|
+
try {
|
|
7390
|
+
json = JSON.parse(content);
|
|
7391
|
+
} catch {
|
|
7392
|
+
continue;
|
|
7393
|
+
}
|
|
7394
|
+
if (!json.data) {
|
|
7395
|
+
return;
|
|
7396
|
+
}
|
|
7397
|
+
const projectKey = Object.keys(json.data).find((key) => {
|
|
7398
|
+
const entryPath = json.data?.[key]?.path;
|
|
7399
|
+
return entryPath ? pathsEqual(entryPath, projectPath) : false;
|
|
7400
|
+
});
|
|
7401
|
+
if (!projectKey) {
|
|
7402
|
+
return;
|
|
7403
|
+
}
|
|
7404
|
+
const original = json.data[projectKey];
|
|
7405
|
+
if (!original) {
|
|
7406
|
+
return;
|
|
7407
|
+
}
|
|
7408
|
+
json.data[projectKey] = {
|
|
7409
|
+
...original,
|
|
7410
|
+
lastModified: when.getTime()
|
|
7411
|
+
};
|
|
7412
|
+
try {
|
|
7413
|
+
await (0, import_promises2.writeFile)(path, JSON.stringify(json, void 0, 2), "utf8");
|
|
7414
|
+
} catch {
|
|
7415
|
+
}
|
|
7416
|
+
return;
|
|
7417
|
+
}
|
|
7418
|
+
};
|
|
7419
|
+
|
|
7420
|
+
// node_modules/launch-unity/dist/lib.js
|
|
7421
|
+
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
7422
|
+
var UNITY_EXECUTABLE_PATTERN_MAC = /Unity\.app\/Contents\/MacOS\/Unity/i;
|
|
7423
|
+
var UNITY_EXECUTABLE_PATTERN_WINDOWS = /Unity\.exe/i;
|
|
7424
|
+
var PROJECT_PATH_PATTERN = /-(?:projectPath|projectpath)(?:=|\s+)("[^"]+"|'[^']+'|[^\s"']+)/i;
|
|
7425
|
+
var PROCESS_LIST_COMMAND_MAC = "ps";
|
|
7426
|
+
var PROCESS_LIST_ARGS_MAC = ["-axo", "pid=,command=", "-ww"];
|
|
7427
|
+
var WINDOWS_POWERSHELL = "powershell";
|
|
7428
|
+
var UNITY_LOCKFILE_NAME = "UnityLockfile";
|
|
7429
|
+
var TEMP_DIRECTORY_NAME = "Temp";
|
|
7430
|
+
function getUnityVersion(projectPath) {
|
|
7431
|
+
const versionFile = (0, import_node_path2.join)(projectPath, "ProjectSettings", "ProjectVersion.txt");
|
|
7432
|
+
if (!(0, import_node_fs2.existsSync)(versionFile)) {
|
|
7433
|
+
throw new Error(`ProjectVersion.txt not found at ${versionFile}. This does not appear to be a Unity project.`);
|
|
7434
|
+
}
|
|
7435
|
+
const content = (0, import_node_fs2.readFileSync)(versionFile, "utf8");
|
|
7436
|
+
const version = content.match(/m_EditorVersion:\s*([^\s\n]+)/)?.[1];
|
|
7437
|
+
if (!version) {
|
|
7438
|
+
throw new Error(`Could not extract Unity version from ${versionFile}`);
|
|
7439
|
+
}
|
|
7440
|
+
return version;
|
|
7441
|
+
}
|
|
7442
|
+
function getUnityPathWindows(version) {
|
|
7443
|
+
const candidates = [];
|
|
7444
|
+
const programFiles = process.env["PROGRAMFILES"];
|
|
7445
|
+
const programFilesX86 = process.env["PROGRAMFILES(X86)"];
|
|
7446
|
+
const localAppData = process.env["LOCALAPPDATA"];
|
|
7447
|
+
const addCandidate = (base) => {
|
|
7448
|
+
if (!base) {
|
|
7449
|
+
return;
|
|
7450
|
+
}
|
|
7451
|
+
candidates.push((0, import_node_path2.join)(base, "Unity", "Hub", "Editor", version, "Editor", "Unity.exe"));
|
|
7452
|
+
};
|
|
7453
|
+
addCandidate(programFiles);
|
|
7454
|
+
addCandidate(programFilesX86);
|
|
7455
|
+
addCandidate(localAppData);
|
|
7456
|
+
candidates.push((0, import_node_path2.join)("C:\\", "Program Files", "Unity", "Hub", "Editor", version, "Editor", "Unity.exe"));
|
|
7457
|
+
for (const candidate of candidates) {
|
|
7458
|
+
if ((0, import_node_fs2.existsSync)(candidate)) {
|
|
7459
|
+
return candidate;
|
|
7460
|
+
}
|
|
7461
|
+
}
|
|
7462
|
+
return candidates[0] ?? (0, import_node_path2.join)("C:\\", "Program Files", "Unity", "Hub", "Editor", version, "Editor", "Unity.exe");
|
|
7463
|
+
}
|
|
7464
|
+
function getUnityPath(version) {
|
|
7465
|
+
if (process.platform === "darwin") {
|
|
7466
|
+
return `/Applications/Unity/Hub/Editor/${version}/Unity.app/Contents/MacOS/Unity`;
|
|
7467
|
+
}
|
|
7468
|
+
if (process.platform === "win32") {
|
|
7469
|
+
return getUnityPathWindows(version);
|
|
7470
|
+
}
|
|
7471
|
+
return `/Applications/Unity/Hub/Editor/${version}/Unity.app/Contents/MacOS/Unity`;
|
|
7472
|
+
}
|
|
7473
|
+
var removeTrailingSeparators2 = (target) => {
|
|
7474
|
+
let trimmed = target;
|
|
7475
|
+
while (trimmed.length > 1 && (trimmed.endsWith("/") || trimmed.endsWith("\\"))) {
|
|
7476
|
+
trimmed = trimmed.slice(0, -1);
|
|
7477
|
+
}
|
|
7478
|
+
return trimmed;
|
|
7479
|
+
};
|
|
7480
|
+
var normalizePath2 = (target) => {
|
|
7481
|
+
const resolvedPath = (0, import_node_path2.resolve)(target);
|
|
7482
|
+
const trimmed = removeTrailingSeparators2(resolvedPath);
|
|
7483
|
+
return trimmed;
|
|
7484
|
+
};
|
|
7485
|
+
var toComparablePath2 = (value) => {
|
|
7486
|
+
return value.replace(/\\/g, "/").toLocaleLowerCase();
|
|
7487
|
+
};
|
|
7488
|
+
var pathsEqual2 = (left, right) => {
|
|
7489
|
+
return toComparablePath2(normalizePath2(left)) === toComparablePath2(normalizePath2(right));
|
|
7490
|
+
};
|
|
7491
|
+
function extractProjectPath(command) {
|
|
7492
|
+
const match = command.match(PROJECT_PATH_PATTERN);
|
|
7493
|
+
if (!match) {
|
|
7494
|
+
return void 0;
|
|
7495
|
+
}
|
|
7496
|
+
const raw = match[1];
|
|
7497
|
+
if (!raw) {
|
|
7498
|
+
return void 0;
|
|
7499
|
+
}
|
|
7500
|
+
const trimmed = raw.trim();
|
|
7501
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
7502
|
+
return trimmed.slice(1, -1);
|
|
7503
|
+
}
|
|
7504
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
7505
|
+
return trimmed.slice(1, -1);
|
|
7506
|
+
}
|
|
7507
|
+
return trimmed;
|
|
7508
|
+
}
|
|
7509
|
+
var isUnityAuxiliaryProcess = (command) => {
|
|
7510
|
+
const normalizedCommand = command.toLowerCase();
|
|
7511
|
+
if (normalizedCommand.includes("-batchmode")) {
|
|
7512
|
+
return true;
|
|
7513
|
+
}
|
|
7514
|
+
return normalizedCommand.includes("assetimportworker");
|
|
7515
|
+
};
|
|
7516
|
+
async function listUnityProcessesMac() {
|
|
7517
|
+
let stdout = "";
|
|
7518
|
+
try {
|
|
7519
|
+
const result = await execFileAsync(PROCESS_LIST_COMMAND_MAC, PROCESS_LIST_ARGS_MAC);
|
|
7520
|
+
stdout = result.stdout;
|
|
7521
|
+
} catch (error) {
|
|
7522
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7523
|
+
console.error(`Failed to retrieve Unity process list: ${message}`);
|
|
7524
|
+
return [];
|
|
7525
|
+
}
|
|
7526
|
+
const lines = stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
7527
|
+
const processes = [];
|
|
7528
|
+
for (const line of lines) {
|
|
7529
|
+
const match = line.match(/^(\d+)\s+(.*)$/);
|
|
7530
|
+
if (!match) {
|
|
7531
|
+
continue;
|
|
7532
|
+
}
|
|
7533
|
+
const pidValue = Number.parseInt(match[1] ?? "", 10);
|
|
7534
|
+
if (!Number.isFinite(pidValue)) {
|
|
7535
|
+
continue;
|
|
7536
|
+
}
|
|
7537
|
+
const command = match[2] ?? "";
|
|
7538
|
+
if (!UNITY_EXECUTABLE_PATTERN_MAC.test(command)) {
|
|
7539
|
+
continue;
|
|
7540
|
+
}
|
|
7541
|
+
if (isUnityAuxiliaryProcess(command)) {
|
|
7542
|
+
continue;
|
|
7543
|
+
}
|
|
7544
|
+
const projectArgument = extractProjectPath(command);
|
|
7545
|
+
if (!projectArgument) {
|
|
7546
|
+
continue;
|
|
7547
|
+
}
|
|
7548
|
+
processes.push({
|
|
7549
|
+
pid: pidValue,
|
|
7550
|
+
projectPath: normalizePath2(projectArgument)
|
|
7551
|
+
});
|
|
7552
|
+
}
|
|
7553
|
+
return processes;
|
|
7554
|
+
}
|
|
7555
|
+
async function listUnityProcessesWindows() {
|
|
7556
|
+
const scriptLines = [
|
|
7557
|
+
"$ErrorActionPreference = 'Stop'",
|
|
7558
|
+
`$processes = Get-CimInstance Win32_Process -Filter "Name = 'Unity.exe'" | Where-Object { $_.CommandLine }`,
|
|
7559
|
+
"foreach ($process in $processes) {",
|
|
7560
|
+
` $commandLine = $process.CommandLine -replace "\`r", ' ' -replace "\`n", ' '`,
|
|
7561
|
+
' Write-Output ("{0}|{1}" -f $process.ProcessId, $commandLine)',
|
|
7562
|
+
"}"
|
|
7563
|
+
];
|
|
7564
|
+
let stdout = "";
|
|
7565
|
+
try {
|
|
7566
|
+
const result = await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
7567
|
+
stdout = result.stdout ?? "";
|
|
7568
|
+
} catch (error) {
|
|
7569
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7570
|
+
console.error(`Failed to retrieve Unity process list on Windows: ${message}`);
|
|
7571
|
+
return [];
|
|
7572
|
+
}
|
|
7573
|
+
const lines = stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
7574
|
+
const processes = [];
|
|
7575
|
+
for (const line of lines) {
|
|
7576
|
+
const delimiterIndex = line.indexOf("|");
|
|
7577
|
+
if (delimiterIndex < 0) {
|
|
7578
|
+
continue;
|
|
7579
|
+
}
|
|
7580
|
+
const pidText = line.slice(0, delimiterIndex).trim();
|
|
7581
|
+
const command = line.slice(delimiterIndex + 1).trim();
|
|
7582
|
+
const pidValue = Number.parseInt(pidText, 10);
|
|
7583
|
+
if (!Number.isFinite(pidValue)) {
|
|
7584
|
+
continue;
|
|
7585
|
+
}
|
|
7586
|
+
if (!UNITY_EXECUTABLE_PATTERN_WINDOWS.test(command)) {
|
|
7587
|
+
continue;
|
|
7588
|
+
}
|
|
7589
|
+
if (isUnityAuxiliaryProcess(command)) {
|
|
7590
|
+
continue;
|
|
7591
|
+
}
|
|
7592
|
+
const projectArgument = extractProjectPath(command);
|
|
7593
|
+
if (!projectArgument) {
|
|
7594
|
+
continue;
|
|
7595
|
+
}
|
|
7596
|
+
processes.push({
|
|
7597
|
+
pid: pidValue,
|
|
7598
|
+
projectPath: normalizePath2(projectArgument)
|
|
7599
|
+
});
|
|
7600
|
+
}
|
|
7601
|
+
return processes;
|
|
7602
|
+
}
|
|
7603
|
+
async function listUnityProcesses() {
|
|
7604
|
+
if (process.platform === "darwin") {
|
|
7605
|
+
return await listUnityProcessesMac();
|
|
7606
|
+
}
|
|
7607
|
+
if (process.platform === "win32") {
|
|
7608
|
+
return await listUnityProcessesWindows();
|
|
7609
|
+
}
|
|
7610
|
+
return [];
|
|
7611
|
+
}
|
|
7612
|
+
async function findRunningUnityProcess(projectPath) {
|
|
7613
|
+
const normalizedTarget = normalizePath2(projectPath);
|
|
7614
|
+
const processes = await listUnityProcesses();
|
|
7615
|
+
return processes.find((candidate) => pathsEqual2(candidate.projectPath, normalizedTarget));
|
|
7616
|
+
}
|
|
7617
|
+
async function focusUnityProcess(pid) {
|
|
7618
|
+
if (process.platform === "darwin") {
|
|
7619
|
+
await focusUnityProcessMac(pid);
|
|
7620
|
+
return;
|
|
7621
|
+
}
|
|
7622
|
+
if (process.platform === "win32") {
|
|
7623
|
+
await focusUnityProcessWindows(pid);
|
|
7624
|
+
}
|
|
7625
|
+
}
|
|
7626
|
+
async function focusUnityProcessMac(pid) {
|
|
7627
|
+
const script = `tell application "System Events" to set frontmost of (first process whose unix id is ${pid}) to true`;
|
|
7628
|
+
try {
|
|
7629
|
+
await execFileAsync("osascript", ["-e", script]);
|
|
7630
|
+
console.log("Brought existing Unity to the front.");
|
|
7631
|
+
} catch (error) {
|
|
7632
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7633
|
+
console.warn(`Failed to bring Unity to front: ${message}`);
|
|
7634
|
+
}
|
|
7635
|
+
}
|
|
7636
|
+
async function focusUnityProcessWindows(pid) {
|
|
7637
|
+
const addTypeLines = [
|
|
7638
|
+
'Add-Type -TypeDefinition @"',
|
|
7639
|
+
"using System;",
|
|
7640
|
+
"using System.Runtime.InteropServices;",
|
|
7641
|
+
"public static class Win32Interop {",
|
|
7642
|
+
' [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);',
|
|
7643
|
+
' [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);',
|
|
7644
|
+
"}",
|
|
7645
|
+
'"@'
|
|
7646
|
+
];
|
|
7647
|
+
const scriptLines = [
|
|
7648
|
+
"$ErrorActionPreference = 'Stop'",
|
|
7649
|
+
...addTypeLines,
|
|
7650
|
+
`try { $process = Get-Process -Id ${pid} -ErrorAction Stop } catch { return }`,
|
|
7651
|
+
"$handle = $process.MainWindowHandle",
|
|
7652
|
+
"if ($handle -eq 0) { return }",
|
|
7653
|
+
"[Win32Interop]::ShowWindowAsync($handle, 9) | Out-Null",
|
|
7654
|
+
"[Win32Interop]::SetForegroundWindow($handle) | Out-Null"
|
|
7655
|
+
];
|
|
7656
|
+
try {
|
|
7657
|
+
await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
7658
|
+
console.log("Brought existing Unity to the front.");
|
|
7659
|
+
} catch (error) {
|
|
7660
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7661
|
+
console.warn(`Failed to bring Unity to front on Windows: ${message}`);
|
|
7662
|
+
}
|
|
7663
|
+
}
|
|
7664
|
+
async function handleStaleLockfile(projectPath) {
|
|
7665
|
+
const tempDirectoryPath = (0, import_node_path2.join)(projectPath, TEMP_DIRECTORY_NAME);
|
|
7666
|
+
const lockfilePath = (0, import_node_path2.join)(tempDirectoryPath, UNITY_LOCKFILE_NAME);
|
|
7667
|
+
if (!(0, import_node_fs2.existsSync)(lockfilePath)) {
|
|
7668
|
+
return;
|
|
7669
|
+
}
|
|
7670
|
+
console.log(`UnityLockfile found without active Unity process: ${lockfilePath}`);
|
|
7671
|
+
console.log("Assuming previous crash. Cleaning Temp directory and continuing launch.");
|
|
7672
|
+
try {
|
|
7673
|
+
await (0, import_promises3.rm)(tempDirectoryPath, { recursive: true, force: true });
|
|
7674
|
+
console.log("Deleted Temp directory.");
|
|
7675
|
+
} catch (error) {
|
|
7676
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7677
|
+
console.warn(`Failed to delete Temp directory: ${message}`);
|
|
7678
|
+
}
|
|
7679
|
+
try {
|
|
7680
|
+
await (0, import_promises3.rm)(lockfilePath, { force: true });
|
|
7681
|
+
console.log("Deleted UnityLockfile.");
|
|
7682
|
+
} catch (error) {
|
|
7683
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7684
|
+
console.warn(`Failed to delete UnityLockfile: ${message}`);
|
|
7685
|
+
}
|
|
7686
|
+
}
|
|
7687
|
+
var KILL_POLL_INTERVAL_MS = 100;
|
|
7688
|
+
var KILL_TIMEOUT_MS = 1e4;
|
|
7689
|
+
function isProcessAlive(pid) {
|
|
7690
|
+
try {
|
|
7691
|
+
process.kill(pid, 0);
|
|
7692
|
+
return true;
|
|
7693
|
+
} catch {
|
|
7694
|
+
return false;
|
|
7695
|
+
}
|
|
7696
|
+
}
|
|
7697
|
+
function killProcess(pid) {
|
|
7698
|
+
try {
|
|
7699
|
+
process.kill(pid, "SIGKILL");
|
|
7700
|
+
} catch {
|
|
7701
|
+
}
|
|
7702
|
+
}
|
|
7703
|
+
async function waitForProcessExit(pid) {
|
|
7704
|
+
const start = Date.now();
|
|
7705
|
+
while (Date.now() - start < KILL_TIMEOUT_MS) {
|
|
7706
|
+
if (!isProcessAlive(pid)) {
|
|
7707
|
+
return true;
|
|
7708
|
+
}
|
|
7709
|
+
await new Promise((resolve5) => setTimeout(resolve5, KILL_POLL_INTERVAL_MS));
|
|
7710
|
+
}
|
|
7711
|
+
return false;
|
|
7712
|
+
}
|
|
7713
|
+
async function killRunningUnity(projectPath) {
|
|
7714
|
+
const processInfo = await findRunningUnityProcess(projectPath);
|
|
7715
|
+
if (!processInfo) {
|
|
7716
|
+
console.log("No running Unity process found for this project.");
|
|
7717
|
+
return;
|
|
7718
|
+
}
|
|
7719
|
+
const pid = processInfo.pid;
|
|
7720
|
+
console.log(`Killing Unity (PID: ${pid})...`);
|
|
7721
|
+
killProcess(pid);
|
|
7722
|
+
const exited = await waitForProcessExit(pid);
|
|
7723
|
+
if (!exited) {
|
|
7724
|
+
throw new Error(`Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1e3}s.`);
|
|
7725
|
+
}
|
|
7726
|
+
console.log("Unity killed.");
|
|
7727
|
+
}
|
|
7728
|
+
function hasBuildTargetArg(unityArgs) {
|
|
7729
|
+
for (const arg of unityArgs) {
|
|
7730
|
+
if (arg === "-buildTarget") {
|
|
7731
|
+
return true;
|
|
7732
|
+
}
|
|
7733
|
+
if (arg.startsWith("-buildTarget=")) {
|
|
7734
|
+
return true;
|
|
7735
|
+
}
|
|
7736
|
+
}
|
|
7737
|
+
return false;
|
|
7738
|
+
}
|
|
7739
|
+
var EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
7740
|
+
"library",
|
|
7741
|
+
"temp",
|
|
7742
|
+
"logs",
|
|
7743
|
+
"obj",
|
|
7744
|
+
".git",
|
|
7745
|
+
"node_modules",
|
|
7746
|
+
".idea",
|
|
7747
|
+
".vscode",
|
|
7748
|
+
".vs"
|
|
7749
|
+
]);
|
|
7750
|
+
function isUnityProjectRoot(candidateDir) {
|
|
7751
|
+
const versionFile = (0, import_node_path2.join)(candidateDir, "ProjectSettings", "ProjectVersion.txt");
|
|
7752
|
+
return (0, import_node_fs2.existsSync)(versionFile);
|
|
7753
|
+
}
|
|
7754
|
+
function listSubdirectoriesSorted(dir) {
|
|
7755
|
+
let entries = [];
|
|
7756
|
+
try {
|
|
7757
|
+
const dirents = (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true });
|
|
7758
|
+
const subdirs = dirents.filter((d) => d.isDirectory()).map((d) => d.name).filter((name) => !EXCLUDED_DIR_NAMES.has(name.toLocaleLowerCase()));
|
|
7759
|
+
subdirs.sort((a, b) => a.localeCompare(b));
|
|
7760
|
+
entries = subdirs.map((name) => (0, import_node_path2.join)(dir, name));
|
|
7761
|
+
} catch {
|
|
7762
|
+
entries = [];
|
|
7763
|
+
}
|
|
7764
|
+
return entries;
|
|
7765
|
+
}
|
|
7766
|
+
function findUnityProjectBfs(rootDir, maxDepth) {
|
|
7767
|
+
const queue = [];
|
|
7768
|
+
let rootCanonical;
|
|
7769
|
+
try {
|
|
7770
|
+
rootCanonical = (0, import_node_fs2.realpathSync)(rootDir);
|
|
7771
|
+
} catch {
|
|
7772
|
+
rootCanonical = rootDir;
|
|
7773
|
+
}
|
|
7774
|
+
queue.push({ dir: rootCanonical, depth: 0 });
|
|
7775
|
+
const visited = /* @__PURE__ */ new Set([toComparablePath2(normalizePath2(rootCanonical))]);
|
|
7776
|
+
while (queue.length > 0) {
|
|
7777
|
+
const current = queue.shift();
|
|
7778
|
+
if (!current) {
|
|
7779
|
+
continue;
|
|
7780
|
+
}
|
|
7781
|
+
const { dir, depth } = current;
|
|
7782
|
+
if (isUnityProjectRoot(dir)) {
|
|
7783
|
+
return normalizePath2(dir);
|
|
7784
|
+
}
|
|
7785
|
+
const canDescend = maxDepth === -1 || depth < maxDepth;
|
|
7786
|
+
if (!canDescend) {
|
|
7787
|
+
continue;
|
|
7788
|
+
}
|
|
7789
|
+
const children = listSubdirectoriesSorted(dir);
|
|
7790
|
+
for (const child of children) {
|
|
7791
|
+
let childCanonical = child;
|
|
7792
|
+
try {
|
|
7793
|
+
const stat = (0, import_node_fs2.lstatSync)(child);
|
|
7794
|
+
if (stat.isSymbolicLink()) {
|
|
7795
|
+
try {
|
|
7796
|
+
childCanonical = (0, import_node_fs2.realpathSync)(child);
|
|
7797
|
+
} catch {
|
|
7798
|
+
continue;
|
|
7799
|
+
}
|
|
7800
|
+
}
|
|
7801
|
+
} catch {
|
|
7802
|
+
continue;
|
|
7803
|
+
}
|
|
7804
|
+
const key = toComparablePath2(normalizePath2(childCanonical));
|
|
7805
|
+
if (visited.has(key)) {
|
|
7806
|
+
continue;
|
|
7807
|
+
}
|
|
7808
|
+
visited.add(key);
|
|
7809
|
+
queue.push({ dir: childCanonical, depth: depth + 1 });
|
|
7810
|
+
}
|
|
7811
|
+
}
|
|
7812
|
+
return void 0;
|
|
7813
|
+
}
|
|
7814
|
+
function launch(opts) {
|
|
7815
|
+
const { projectPath, platform, unityArgs, unityVersion } = opts;
|
|
7816
|
+
const unityPath = getUnityPath(unityVersion);
|
|
7817
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
7818
|
+
if (!(0, import_node_fs2.existsSync)(unityPath)) {
|
|
7819
|
+
throw new Error(`Unity ${unityVersion} not found at ${unityPath}. Please install Unity through Unity Hub.`);
|
|
7820
|
+
}
|
|
7821
|
+
console.log("Opening Unity...");
|
|
7822
|
+
console.log(`Project Path: ${projectPath}`);
|
|
7823
|
+
const args = ["-projectPath", projectPath];
|
|
7824
|
+
const unityArgsContainBuildTarget = hasBuildTargetArg(unityArgs);
|
|
7825
|
+
if (platform && platform.length > 0 && !unityArgsContainBuildTarget) {
|
|
7826
|
+
args.push("-buildTarget", platform);
|
|
7827
|
+
}
|
|
7828
|
+
if (unityArgs.length > 0) {
|
|
7829
|
+
args.push(...unityArgs);
|
|
7830
|
+
}
|
|
7831
|
+
const child = (0, import_node_child_process.spawn)(unityPath, args, { stdio: "ignore", detached: true });
|
|
7832
|
+
child.unref();
|
|
7833
|
+
}
|
|
7834
|
+
|
|
7835
|
+
// src/commands/launch.ts
|
|
7836
|
+
function registerLaunchCommand(program3) {
|
|
7837
|
+
program3.command("launch").description("Launch Unity project with matching Editor version").argument("[project-path]", "Path to Unity project").option("-r, --restart", "Kill running Unity and restart").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) => {
|
|
7838
|
+
await runLaunchCommand(projectPath, options);
|
|
7839
|
+
});
|
|
7840
|
+
}
|
|
7841
|
+
function parseMaxDepth(value) {
|
|
7842
|
+
if (value === void 0) {
|
|
7843
|
+
return 3;
|
|
7844
|
+
}
|
|
7845
|
+
const parsed = parseInt(value, 10);
|
|
7846
|
+
if (Number.isNaN(parsed)) {
|
|
7847
|
+
console.error(`Error: Invalid --max-depth value: "${value}". Must be an integer.`);
|
|
7848
|
+
process.exit(1);
|
|
7849
|
+
}
|
|
7850
|
+
return parsed;
|
|
7851
|
+
}
|
|
7852
|
+
async function runLaunchCommand(projectPath, options) {
|
|
7853
|
+
const maxDepth = parseMaxDepth(options.maxDepth);
|
|
7854
|
+
let resolvedProjectPath = projectPath ? (0, import_path6.resolve)(projectPath) : void 0;
|
|
7855
|
+
if (!resolvedProjectPath) {
|
|
7856
|
+
const searchRoot = process.cwd();
|
|
7857
|
+
const depthInfo = maxDepth === -1 ? "unlimited" : String(maxDepth);
|
|
7858
|
+
console.log(
|
|
7859
|
+
`No project-path provided. Searching under ${searchRoot} (max-depth: ${depthInfo})...`
|
|
7860
|
+
);
|
|
7861
|
+
const found = findUnityProjectBfs(searchRoot, maxDepth);
|
|
7862
|
+
if (!found) {
|
|
7863
|
+
console.error(`Error: Unity project not found under ${searchRoot}.`);
|
|
7864
|
+
process.exit(1);
|
|
7865
|
+
}
|
|
7866
|
+
console.log(`Selected project: ${found}`);
|
|
7867
|
+
resolvedProjectPath = found;
|
|
7868
|
+
}
|
|
7869
|
+
const unityVersion = getUnityVersion(resolvedProjectPath);
|
|
7870
|
+
const unityHubOnlyMode = options.addUnityHub === true || options.favorite === true;
|
|
7871
|
+
if (unityHubOnlyMode) {
|
|
7872
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
7873
|
+
console.log(`Project Path: ${resolvedProjectPath}`);
|
|
7874
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
7875
|
+
await ensureProjectEntryAndUpdate(
|
|
7876
|
+
resolvedProjectPath,
|
|
7877
|
+
unityVersion,
|
|
7878
|
+
now2,
|
|
7879
|
+
options.favorite === true
|
|
7880
|
+
);
|
|
7881
|
+
console.log("Unity Hub entry updated.");
|
|
7882
|
+
return;
|
|
7883
|
+
}
|
|
7884
|
+
if (options.restart === true) {
|
|
7885
|
+
await killRunningUnity(resolvedProjectPath);
|
|
7886
|
+
} else {
|
|
7887
|
+
const runningProcess = await findRunningUnityProcess(resolvedProjectPath);
|
|
7888
|
+
if (runningProcess) {
|
|
7889
|
+
console.log(
|
|
7890
|
+
`Unity process already running for project: ${resolvedProjectPath} (PID: ${runningProcess.pid})`
|
|
7891
|
+
);
|
|
7892
|
+
await focusUnityProcess(runningProcess.pid);
|
|
7893
|
+
return;
|
|
7894
|
+
}
|
|
7895
|
+
}
|
|
7896
|
+
await handleStaleLockfile(resolvedProjectPath);
|
|
7897
|
+
const resolved = {
|
|
7898
|
+
projectPath: resolvedProjectPath,
|
|
7899
|
+
platform: options.platform,
|
|
7900
|
+
unityArgs: [],
|
|
7901
|
+
unityVersion
|
|
7902
|
+
};
|
|
7903
|
+
launch(resolved);
|
|
7904
|
+
const now = /* @__PURE__ */ new Date();
|
|
7905
|
+
await updateLastModifiedIfExists(resolvedProjectPath, now);
|
|
7906
|
+
}
|
|
7907
|
+
|
|
7234
7908
|
// src/cli.ts
|
|
7235
|
-
var BUILTIN_COMMANDS = [
|
|
7909
|
+
var BUILTIN_COMMANDS = [
|
|
7910
|
+
"list",
|
|
7911
|
+
"sync",
|
|
7912
|
+
"completion",
|
|
7913
|
+
"update",
|
|
7914
|
+
"fix",
|
|
7915
|
+
"skills",
|
|
7916
|
+
"launch"
|
|
7917
|
+
];
|
|
7236
7918
|
var program2 = new Command();
|
|
7237
7919
|
program2.name("uloop").description("Unity MCP CLI - Direct communication with Unity Editor").version(VERSION, "-v, --version", "Output the version number");
|
|
7238
7920
|
program2.option("--list-commands", "List all command names (for shell completion)");
|
|
@@ -7253,6 +7935,7 @@ program2.command("fix").description("Clean up stale lock files that may prevent
|
|
|
7253
7935
|
cleanupLockFiles();
|
|
7254
7936
|
});
|
|
7255
7937
|
registerSkillsCommand(program2);
|
|
7938
|
+
registerLaunchCommand(program2);
|
|
7256
7939
|
function registerToolCommand(tool) {
|
|
7257
7940
|
const cmd = program2.command(tool.name).description(tool.description);
|
|
7258
7941
|
const properties = tool.inputSchema.properties;
|
|
@@ -7386,6 +8069,30 @@ function printConnectionError() {
|
|
|
7386
8069
|
console.error("");
|
|
7387
8070
|
console.error("[For AI] Please report the above to the user.");
|
|
7388
8071
|
}
|
|
8072
|
+
function printVersionMismatchDiagnostic() {
|
|
8073
|
+
const serverVersion = getCachedServerVersion();
|
|
8074
|
+
if (serverVersion === void 0) {
|
|
8075
|
+
return;
|
|
8076
|
+
}
|
|
8077
|
+
if (serverVersion === VERSION) {
|
|
8078
|
+
return;
|
|
8079
|
+
}
|
|
8080
|
+
const isCliOlder = isVersionOlder(VERSION, serverVersion);
|
|
8081
|
+
const action = isCliOlder ? "Update" : "Downgrade";
|
|
8082
|
+
const updateCommand = `npm install -g uloop-cli@${serverVersion}`;
|
|
8083
|
+
console.error("");
|
|
8084
|
+
console.error("\x1B[33m\u2501\u2501\u2501 Version Mismatch Diagnostic \u2501\u2501\u2501\x1B[0m");
|
|
8085
|
+
console.error("");
|
|
8086
|
+
console.error(` CLI version: ${VERSION}`);
|
|
8087
|
+
console.error(` Unity package: ${serverVersion}`);
|
|
8088
|
+
console.error(" Version mismatch may cause communication errors.");
|
|
8089
|
+
console.error("");
|
|
8090
|
+
console.error(` To fix: ${action} CLI to match Unity package version`);
|
|
8091
|
+
console.error(` ${updateCommand}`);
|
|
8092
|
+
console.error("");
|
|
8093
|
+
console.error("[For AI] Please ask the user if they would like to run this command.");
|
|
8094
|
+
console.error("\x1B[33m\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\x1B[0m");
|
|
8095
|
+
}
|
|
7389
8096
|
async function runWithErrorHandling(fn) {
|
|
7390
8097
|
try {
|
|
7391
8098
|
await fn();
|
|
@@ -7409,10 +8116,17 @@ async function runWithErrorHandling(fn) {
|
|
|
7409
8116
|
if (message === "UNITY_NO_RESPONSE") {
|
|
7410
8117
|
console.error("\x1B[33m\u23F3 Unity is busy (no response received).\x1B[0m");
|
|
7411
8118
|
console.error("Unity may be compiling, reloading, or starting. Please wait and try again.");
|
|
8119
|
+
printVersionMismatchDiagnostic();
|
|
7412
8120
|
process.exit(1);
|
|
7413
8121
|
}
|
|
7414
8122
|
if (isConnectionError(message)) {
|
|
7415
8123
|
printConnectionError();
|
|
8124
|
+
printVersionMismatchDiagnostic();
|
|
8125
|
+
process.exit(1);
|
|
8126
|
+
}
|
|
8127
|
+
if (message.includes("Request timed out")) {
|
|
8128
|
+
console.error(`\x1B[31mError: ${message}\x1B[0m`);
|
|
8129
|
+
printVersionMismatchDiagnostic();
|
|
7416
8130
|
process.exit(1);
|
|
7417
8131
|
}
|
|
7418
8132
|
console.error(`\x1B[31mError: ${message}\x1B[0m`);
|
|
@@ -7421,7 +8135,7 @@ async function runWithErrorHandling(fn) {
|
|
|
7421
8135
|
}
|
|
7422
8136
|
function detectShell() {
|
|
7423
8137
|
const shell = process.env["SHELL"] || "";
|
|
7424
|
-
const shellName = (0,
|
|
8138
|
+
const shellName = (0, import_path7.basename)(shell).replace(/\.exe$/i, "");
|
|
7425
8139
|
if (shellName === "zsh") {
|
|
7426
8140
|
return "zsh";
|
|
7427
8141
|
}
|
|
@@ -7436,12 +8150,12 @@ function detectShell() {
|
|
|
7436
8150
|
function getShellConfigPath(shell) {
|
|
7437
8151
|
const home = (0, import_os2.homedir)();
|
|
7438
8152
|
if (shell === "zsh") {
|
|
7439
|
-
return (0,
|
|
8153
|
+
return (0, import_path7.join)(home, ".zshrc");
|
|
7440
8154
|
}
|
|
7441
8155
|
if (shell === "powershell") {
|
|
7442
|
-
return (0,
|
|
8156
|
+
return (0, import_path7.join)(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
7443
8157
|
}
|
|
7444
|
-
return (0,
|
|
8158
|
+
return (0, import_path7.join)(home, ".bashrc");
|
|
7445
8159
|
}
|
|
7446
8160
|
function getCompletionScript(shell) {
|
|
7447
8161
|
if (shell === "bash") {
|
|
@@ -7578,10 +8292,10 @@ function cleanupLockFiles() {
|
|
|
7578
8292
|
console.error("Could not find Unity project root.");
|
|
7579
8293
|
process.exit(1);
|
|
7580
8294
|
}
|
|
7581
|
-
const tempDir = (0,
|
|
8295
|
+
const tempDir = (0, import_path7.join)(projectRoot, "Temp");
|
|
7582
8296
|
let cleaned = 0;
|
|
7583
8297
|
for (const lockFile of LOCK_FILES) {
|
|
7584
|
-
const lockPath = (0,
|
|
8298
|
+
const lockPath = (0, import_path7.join)(tempDir, lockFile);
|
|
7585
8299
|
if ((0, import_fs6.existsSync)(lockPath)) {
|
|
7586
8300
|
(0, import_fs6.unlinkSync)(lockPath);
|
|
7587
8301
|
console.log(`Removed: ${lockFile}`);
|
|
@@ -7618,7 +8332,7 @@ function handleCompletion(install, shellOverride) {
|
|
|
7618
8332
|
return;
|
|
7619
8333
|
}
|
|
7620
8334
|
const configPath = getShellConfigPath(shell);
|
|
7621
|
-
const configDir = (0,
|
|
8335
|
+
const configDir = (0, import_path7.dirname)(configPath);
|
|
7622
8336
|
if (!(0, import_fs6.existsSync)(configDir)) {
|
|
7623
8337
|
(0, import_fs6.mkdirSync)(configDir, { recursive: true });
|
|
7624
8338
|
}
|