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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uloop-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"//version": "x-release-please-version",
|
|
5
5
|
"description": "CLI tool for Unity Editor communication via uLoopMCP",
|
|
6
6
|
"main": "dist/cli.bundle.cjs",
|
|
@@ -41,23 +41,24 @@
|
|
|
41
41
|
"provenance": true
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"commander": "
|
|
45
|
-
"
|
|
44
|
+
"commander": "14.0.2",
|
|
45
|
+
"launch-unity": "0.12.0",
|
|
46
|
+
"semver": "7.7.3"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@eslint/js": "9.39.2",
|
|
49
|
-
"tsx": "4.21.0",
|
|
50
50
|
"@types/jest": "30.0.0",
|
|
51
51
|
"@types/node": "25.0.2",
|
|
52
|
-
"@types/semver": "
|
|
52
|
+
"@types/semver": "7.7.1",
|
|
53
53
|
"esbuild": "0.27.1",
|
|
54
54
|
"eslint": "9.39.2",
|
|
55
|
-
"eslint-config-prettier": "
|
|
55
|
+
"eslint-config-prettier": "10.1.8",
|
|
56
56
|
"eslint-plugin-prettier": "5.5.4",
|
|
57
57
|
"eslint-plugin-security": "3.0.1",
|
|
58
58
|
"jest": "30.2.0",
|
|
59
59
|
"prettier": "3.7.4",
|
|
60
60
|
"ts-jest": "29.4.6",
|
|
61
|
+
"tsx": "4.21.0",
|
|
61
62
|
"typescript": "5.9.3",
|
|
62
63
|
"typescript-eslint": "8.49.0"
|
|
63
64
|
}
|
|
@@ -482,6 +482,46 @@ describe('CLI E2E Tests (requires running Unity)', () => {
|
|
|
482
482
|
});
|
|
483
483
|
});
|
|
484
484
|
|
|
485
|
+
describe('launch', () => {
|
|
486
|
+
it('should display launch command help', () => {
|
|
487
|
+
const { stdout, exitCode } = runCli('launch --help');
|
|
488
|
+
|
|
489
|
+
expect(exitCode).toBe(0);
|
|
490
|
+
expect(stdout).toContain('Launch Unity project');
|
|
491
|
+
expect(stdout).toContain('--restart');
|
|
492
|
+
expect(stdout).toContain('--platform');
|
|
493
|
+
expect(stdout).toContain('--max-depth');
|
|
494
|
+
expect(stdout).toContain('--add-unity-hub');
|
|
495
|
+
expect(stdout).toContain('--favorite');
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
it('should detect already running Unity and focus window', () => {
|
|
499
|
+
// Unity is already running for this test suite, so launch should detect it
|
|
500
|
+
const { stdout, exitCode } = runCli(`launch "${UNITY_PROJECT_ROOT}"`);
|
|
501
|
+
|
|
502
|
+
expect(exitCode).toBe(0);
|
|
503
|
+
expect(stdout).toContain('Unity process already running');
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
it('should fail gracefully when project not found', () => {
|
|
507
|
+
const { stdout, stderr, exitCode } = runCli('launch /nonexistent/path/to/project');
|
|
508
|
+
|
|
509
|
+
expect(exitCode).not.toBe(0);
|
|
510
|
+
// Error message should mention project not found or version file not found
|
|
511
|
+
const output = stderr || stdout;
|
|
512
|
+
expect(output).toMatch(/not found|does not appear to be a Unity project/i);
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
it('should search for Unity project from current directory', () => {
|
|
516
|
+
// This test runs from Unity project root, so it should find the project
|
|
517
|
+
const { stdout, exitCode } = runCli('launch');
|
|
518
|
+
|
|
519
|
+
expect(exitCode).toBe(0);
|
|
520
|
+
// Should either find and focus existing Unity or report no Unity found
|
|
521
|
+
expect(stdout).toMatch(/Unity process already running|Selected project/);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
|
|
485
525
|
// Domain Reload tests must run last to avoid affecting other tests
|
|
486
526
|
describe('compile --force-recompile (Domain Reload)', () => {
|
|
487
527
|
it('should support --force-recompile option', () => {
|
package/src/cli.ts
CHANGED
|
@@ -18,10 +18,18 @@ import {
|
|
|
18
18
|
listAvailableTools,
|
|
19
19
|
GlobalOptions,
|
|
20
20
|
syncTools,
|
|
21
|
+
isVersionOlder,
|
|
21
22
|
} from './execute-tool.js';
|
|
22
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
loadToolsCache,
|
|
25
|
+
hasCacheFile,
|
|
26
|
+
ToolDefinition,
|
|
27
|
+
ToolProperty,
|
|
28
|
+
getCachedServerVersion,
|
|
29
|
+
} from './tool-cache.js';
|
|
23
30
|
import { pascalToKebabCase } from './arg-parser.js';
|
|
24
31
|
import { registerSkillsCommand } from './skills/skills-command.js';
|
|
32
|
+
import { registerLaunchCommand } from './commands/launch.js';
|
|
25
33
|
import { VERSION } from './version.js';
|
|
26
34
|
import { findUnityProjectRoot } from './project-root.js';
|
|
27
35
|
|
|
@@ -29,7 +37,15 @@ interface CliOptions extends GlobalOptions {
|
|
|
29
37
|
[key: string]: unknown;
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
const BUILTIN_COMMANDS = [
|
|
40
|
+
const BUILTIN_COMMANDS = [
|
|
41
|
+
'list',
|
|
42
|
+
'sync',
|
|
43
|
+
'completion',
|
|
44
|
+
'update',
|
|
45
|
+
'fix',
|
|
46
|
+
'skills',
|
|
47
|
+
'launch',
|
|
48
|
+
] as const;
|
|
33
49
|
|
|
34
50
|
const program = new Command();
|
|
35
51
|
|
|
@@ -87,6 +103,9 @@ program
|
|
|
87
103
|
// Register skills subcommand
|
|
88
104
|
registerSkillsCommand(program);
|
|
89
105
|
|
|
106
|
+
// Register launch subcommand
|
|
107
|
+
registerLaunchCommand(program);
|
|
108
|
+
|
|
90
109
|
/**
|
|
91
110
|
* Register a tool as a CLI command dynamically.
|
|
92
111
|
*/
|
|
@@ -274,12 +293,45 @@ function printConnectionError(): void {
|
|
|
274
293
|
console.error('[For AI] Please report the above to the user.');
|
|
275
294
|
}
|
|
276
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Print version mismatch diagnostic information when errors occur.
|
|
298
|
+
* Only prints if versions are mismatched.
|
|
299
|
+
*/
|
|
300
|
+
function printVersionMismatchDiagnostic(): void {
|
|
301
|
+
const serverVersion = getCachedServerVersion();
|
|
302
|
+
if (serverVersion === undefined) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (serverVersion === VERSION) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const isCliOlder = isVersionOlder(VERSION, serverVersion);
|
|
311
|
+
const action = isCliOlder ? 'Update' : 'Downgrade';
|
|
312
|
+
const updateCommand = `npm install -g uloop-cli@${serverVersion}`;
|
|
313
|
+
|
|
314
|
+
console.error('');
|
|
315
|
+
console.error('\x1b[33m━━━ Version Mismatch Diagnostic ━━━\x1b[0m');
|
|
316
|
+
console.error('');
|
|
317
|
+
console.error(` CLI version: ${VERSION}`);
|
|
318
|
+
console.error(` Unity package: ${serverVersion}`);
|
|
319
|
+
console.error(' Version mismatch may cause communication errors.');
|
|
320
|
+
console.error('');
|
|
321
|
+
console.error(` To fix: ${action} CLI to match Unity package version`);
|
|
322
|
+
console.error(` ${updateCommand}`);
|
|
323
|
+
console.error('');
|
|
324
|
+
console.error('[For AI] Please ask the user if they would like to run this command.');
|
|
325
|
+
console.error('\x1b[33m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m');
|
|
326
|
+
}
|
|
327
|
+
|
|
277
328
|
async function runWithErrorHandling(fn: () => Promise<void>): Promise<void> {
|
|
278
329
|
try {
|
|
279
330
|
await fn();
|
|
280
331
|
} catch (error) {
|
|
281
332
|
const message = error instanceof Error ? error.message : String(error);
|
|
282
333
|
|
|
334
|
+
// Unity busy states have clear causes - no version diagnostic needed
|
|
283
335
|
if (message === 'UNITY_COMPILING') {
|
|
284
336
|
console.error('\x1b[33m⏳ Unity is compiling scripts.\x1b[0m');
|
|
285
337
|
console.error('Please wait for compilation to finish and try again.');
|
|
@@ -298,14 +350,24 @@ async function runWithErrorHandling(fn: () => Promise<void>): Promise<void> {
|
|
|
298
350
|
process.exit(1);
|
|
299
351
|
}
|
|
300
352
|
|
|
353
|
+
// Errors that may be caused by version mismatch - show diagnostic
|
|
301
354
|
if (message === 'UNITY_NO_RESPONSE') {
|
|
302
355
|
console.error('\x1b[33m⏳ Unity is busy (no response received).\x1b[0m');
|
|
303
356
|
console.error('Unity may be compiling, reloading, or starting. Please wait and try again.');
|
|
357
|
+
printVersionMismatchDiagnostic();
|
|
304
358
|
process.exit(1);
|
|
305
359
|
}
|
|
306
360
|
|
|
307
361
|
if (isConnectionError(message)) {
|
|
308
362
|
printConnectionError();
|
|
363
|
+
printVersionMismatchDiagnostic();
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Timeout errors
|
|
368
|
+
if (message.includes('Request timed out')) {
|
|
369
|
+
console.error(`\x1b[31mError: ${message}\x1b[0m`);
|
|
370
|
+
printVersionMismatchDiagnostic();
|
|
309
371
|
process.exit(1);
|
|
310
372
|
}
|
|
311
373
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command for launching Unity projects.
|
|
3
|
+
* Integrates launch-unity library into uloop CLI.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// CLI commands output to console by design
|
|
7
|
+
/* eslint-disable no-console */
|
|
8
|
+
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
import { resolve } from 'path';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
findUnityProjectBfs,
|
|
14
|
+
getUnityVersion,
|
|
15
|
+
launch,
|
|
16
|
+
findRunningUnityProcess,
|
|
17
|
+
focusUnityProcess,
|
|
18
|
+
killRunningUnity,
|
|
19
|
+
handleStaleLockfile,
|
|
20
|
+
ensureProjectEntryAndUpdate,
|
|
21
|
+
updateLastModifiedIfExists,
|
|
22
|
+
LaunchResolvedOptions,
|
|
23
|
+
} from 'launch-unity';
|
|
24
|
+
|
|
25
|
+
interface LaunchCommandOptions {
|
|
26
|
+
restart?: boolean;
|
|
27
|
+
platform?: string;
|
|
28
|
+
maxDepth?: string;
|
|
29
|
+
addUnityHub?: boolean;
|
|
30
|
+
favorite?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function registerLaunchCommand(program: Command): void {
|
|
34
|
+
program
|
|
35
|
+
.command('launch')
|
|
36
|
+
.description('Launch Unity project with matching Editor version')
|
|
37
|
+
.argument('[project-path]', 'Path to Unity project')
|
|
38
|
+
.option('-r, --restart', 'Kill running Unity and restart')
|
|
39
|
+
.option('-p, --platform <platform>', 'Build target (e.g., Android, iOS)')
|
|
40
|
+
.option('--max-depth <n>', 'Search depth when project-path is omitted', '3')
|
|
41
|
+
.option('-a, --add-unity-hub', 'Add to Unity Hub (does not launch)')
|
|
42
|
+
.option('-f, --favorite', 'Add to Unity Hub as favorite (does not launch)')
|
|
43
|
+
.action(async (projectPath: string | undefined, options: LaunchCommandOptions) => {
|
|
44
|
+
await runLaunchCommand(projectPath, options);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function parseMaxDepth(value: string | undefined): number {
|
|
49
|
+
if (value === undefined) {
|
|
50
|
+
return 3;
|
|
51
|
+
}
|
|
52
|
+
const parsed = parseInt(value, 10);
|
|
53
|
+
if (Number.isNaN(parsed)) {
|
|
54
|
+
console.error(`Error: Invalid --max-depth value: "${value}". Must be an integer.`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function runLaunchCommand(
|
|
61
|
+
projectPath: string | undefined,
|
|
62
|
+
options: LaunchCommandOptions,
|
|
63
|
+
): Promise<void> {
|
|
64
|
+
const maxDepth = parseMaxDepth(options.maxDepth);
|
|
65
|
+
|
|
66
|
+
let resolvedProjectPath: string | undefined = projectPath ? resolve(projectPath) : undefined;
|
|
67
|
+
|
|
68
|
+
if (!resolvedProjectPath) {
|
|
69
|
+
const searchRoot = process.cwd();
|
|
70
|
+
const depthInfo = maxDepth === -1 ? 'unlimited' : String(maxDepth);
|
|
71
|
+
console.log(
|
|
72
|
+
`No project-path provided. Searching under ${searchRoot} (max-depth: ${depthInfo})...`,
|
|
73
|
+
);
|
|
74
|
+
const found = findUnityProjectBfs(searchRoot, maxDepth);
|
|
75
|
+
if (!found) {
|
|
76
|
+
console.error(`Error: Unity project not found under ${searchRoot}.`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
console.log(`Selected project: ${found}`);
|
|
80
|
+
resolvedProjectPath = found;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const unityVersion = getUnityVersion(resolvedProjectPath);
|
|
84
|
+
|
|
85
|
+
const unityHubOnlyMode = options.addUnityHub === true || options.favorite === true;
|
|
86
|
+
if (unityHubOnlyMode) {
|
|
87
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
88
|
+
console.log(`Project Path: ${resolvedProjectPath}`);
|
|
89
|
+
const now = new Date();
|
|
90
|
+
await ensureProjectEntryAndUpdate(
|
|
91
|
+
resolvedProjectPath,
|
|
92
|
+
unityVersion,
|
|
93
|
+
now,
|
|
94
|
+
options.favorite === true,
|
|
95
|
+
);
|
|
96
|
+
console.log('Unity Hub entry updated.');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (options.restart === true) {
|
|
101
|
+
await killRunningUnity(resolvedProjectPath);
|
|
102
|
+
} else {
|
|
103
|
+
const runningProcess = await findRunningUnityProcess(resolvedProjectPath);
|
|
104
|
+
if (runningProcess) {
|
|
105
|
+
console.log(
|
|
106
|
+
`Unity process already running for project: ${resolvedProjectPath} (PID: ${runningProcess.pid})`,
|
|
107
|
+
);
|
|
108
|
+
await focusUnityProcess(runningProcess.pid);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await handleStaleLockfile(resolvedProjectPath);
|
|
114
|
+
|
|
115
|
+
const resolved: LaunchResolvedOptions = {
|
|
116
|
+
projectPath: resolvedProjectPath,
|
|
117
|
+
platform: options.platform,
|
|
118
|
+
unityArgs: [],
|
|
119
|
+
unityVersion,
|
|
120
|
+
};
|
|
121
|
+
launch(resolved);
|
|
122
|
+
|
|
123
|
+
const now = new Date();
|
|
124
|
+
await updateLastModifiedIfExists(resolvedProjectPath, now);
|
|
125
|
+
}
|
package/src/default-tools.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.57.0",
|
|
3
3
|
"tools": [
|
|
4
4
|
{
|
|
5
5
|
"name": "compile",
|
|
@@ -142,6 +142,11 @@
|
|
|
142
142
|
"IncludePaths": {
|
|
143
143
|
"type": "boolean",
|
|
144
144
|
"description": "Include path information"
|
|
145
|
+
},
|
|
146
|
+
"UseSelection": {
|
|
147
|
+
"type": "boolean",
|
|
148
|
+
"description": "Use selected GameObject(s) as root(s). When true, RootPath is ignored.",
|
|
149
|
+
"default": false
|
|
145
150
|
}
|
|
146
151
|
}
|
|
147
152
|
}
|
|
@@ -75,7 +75,7 @@ export class DirectUnityClient {
|
|
|
75
75
|
const timeoutId = setTimeout(() => {
|
|
76
76
|
reject(
|
|
77
77
|
new Error(
|
|
78
|
-
`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.`,
|
|
78
|
+
`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.`,
|
|
79
79
|
),
|
|
80
80
|
);
|
|
81
81
|
}, NETWORK_TIMEOUT_MS);
|
package/src/execute-tool.ts
CHANGED
|
@@ -80,7 +80,7 @@ function isRetryableError(error: unknown): boolean {
|
|
|
80
80
|
* Returns true if v1 < v2, false otherwise.
|
|
81
81
|
* Falls back to string comparison if versions are invalid.
|
|
82
82
|
*/
|
|
83
|
-
function isVersionOlder(v1: string, v2: string): boolean {
|
|
83
|
+
export function isVersionOlder(v1: string, v2: string): boolean {
|
|
84
84
|
const parsed1 = semver.valid(v1);
|
|
85
85
|
const parsed2 = semver.valid(v2);
|
|
86
86
|
|
|
@@ -321,6 +321,7 @@ export async function syncTools(globalOptions: GlobalOptions): Promise<void> {
|
|
|
321
321
|
spinner.update('Syncing tools...');
|
|
322
322
|
const result = await client.sendRequest<{
|
|
323
323
|
Tools: UnityToolInfo[];
|
|
324
|
+
Ver?: string;
|
|
324
325
|
}>('get-tool-details', { IncludeDevelopmentOnly: false });
|
|
325
326
|
|
|
326
327
|
spinner.stop();
|
|
@@ -331,6 +332,7 @@ export async function syncTools(globalOptions: GlobalOptions): Promise<void> {
|
|
|
331
332
|
|
|
332
333
|
const cache: ToolsCache = {
|
|
333
334
|
version: VERSION,
|
|
335
|
+
serverVersion: result.Ver,
|
|
334
336
|
updatedAt: new Date().toISOString(),
|
|
335
337
|
tools: result.Tools.map((tool) => ({
|
|
336
338
|
name: tool.name,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: uloop-launch
|
|
3
|
+
description: "Launch Unity project with matching Editor version via uloop CLI. Use when you need to: (1) Open a Unity project with the correct Editor version, (2) Restart Unity to apply changes, (3) Switch build target when launching."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# uloop launch
|
|
7
|
+
|
|
8
|
+
Launch Unity Editor with the correct version for a project.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
uloop launch [project-path] [options]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Parameters
|
|
17
|
+
|
|
18
|
+
| Parameter | Type | Description |
|
|
19
|
+
|-----------|------|-------------|
|
|
20
|
+
| `project-path` | string | Path to Unity project (optional, searches current directory if omitted) |
|
|
21
|
+
| `-r, --restart` | boolean | Kill running Unity and restart |
|
|
22
|
+
| `-p, --platform <P>` | string | Build target (e.g., StandaloneOSX, Android, iOS) |
|
|
23
|
+
| `--max-depth <N>` | number | Search depth when project-path is omitted (default: 3, -1 for unlimited) |
|
|
24
|
+
| `-a, --add-unity-hub` | boolean | Add to Unity Hub only (does not launch) |
|
|
25
|
+
| `-f, --favorite` | boolean | Add to Unity Hub as favorite (does not launch) |
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Search for Unity project in current directory and launch
|
|
31
|
+
uloop launch
|
|
32
|
+
|
|
33
|
+
# Launch specific project
|
|
34
|
+
uloop launch /path/to/project
|
|
35
|
+
|
|
36
|
+
# Restart Unity (kill existing and relaunch)
|
|
37
|
+
uloop launch -r
|
|
38
|
+
|
|
39
|
+
# Launch with build target
|
|
40
|
+
uloop launch -p Android
|
|
41
|
+
|
|
42
|
+
# Add project to Unity Hub without launching
|
|
43
|
+
uloop launch -a
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Output
|
|
47
|
+
|
|
48
|
+
- Prints detected Unity version
|
|
49
|
+
- Prints project path
|
|
50
|
+
- If Unity is already running, focuses the existing window
|
|
51
|
+
- If launching, opens Unity in background
|
package/src/tool-cache.ts
CHANGED
|
@@ -33,6 +33,7 @@ export interface ToolDefinition {
|
|
|
33
33
|
|
|
34
34
|
export interface ToolsCache {
|
|
35
35
|
version: string;
|
|
36
|
+
serverVersion?: string;
|
|
36
37
|
updatedAt?: string;
|
|
37
38
|
tools: ToolDefinition[];
|
|
38
39
|
}
|
|
@@ -105,3 +106,23 @@ export function hasCacheFile(): boolean {
|
|
|
105
106
|
export function getCacheFilePath(): string {
|
|
106
107
|
return getCachePath();
|
|
107
108
|
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get the Unity server version from cache file.
|
|
112
|
+
* Returns undefined if cache doesn't exist, is corrupted, or serverVersion is missing.
|
|
113
|
+
*/
|
|
114
|
+
export function getCachedServerVersion(): string | undefined {
|
|
115
|
+
const cachePath = getCachePath();
|
|
116
|
+
|
|
117
|
+
if (!existsSync(cachePath)) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const content = readFileSync(cachePath, 'utf-8');
|
|
123
|
+
const cache = JSON.parse(content) as Partial<ToolsCache>;
|
|
124
|
+
return typeof cache.serverVersion === 'string' ? cache.serverVersion : undefined;
|
|
125
|
+
} catch {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* This file exists to avoid bundling the entire package.json into the CLI bundle.
|
|
5
5
|
* This version is automatically updated by release-please.
|
|
6
6
|
*/
|
|
7
|
-
export const VERSION = '0.
|
|
7
|
+
export const VERSION = '0.57.0'; // x-release-please-version
|