uloop-cli 0.68.1 → 0.68.2
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 +28 -10
- package/dist/cli.bundle.cjs.map +2 -2
- package/package.json +1 -1
- package/src/__tests__/cli-e2e.test.ts +51 -0
- package/src/cli.ts +34 -22
- package/src/default-tools.json +1 -1
- package/src/version.ts +1 -1
- /package/src/skills/skill-definitions/cli-only/uloop-focus-window/{SKILL.md → Skill/SKILL.md} +0 -0
- /package/src/skills/skill-definitions/cli-only/uloop-get-project-info/{SKILL.md → Skill/SKILL.md} +0 -0
- /package/src/skills/skill-definitions/cli-only/uloop-get-version/{SKILL.md → Skill/SKILL.md} +0 -0
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
spawnSync,
|
|
14
14
|
SpawnSyncOptionsWithStringEncoding,
|
|
15
15
|
} from 'child_process';
|
|
16
|
+
import { readFileSync, writeFileSync, unlinkSync } from 'fs';
|
|
16
17
|
import { join } from 'path';
|
|
17
18
|
|
|
18
19
|
const CLI_PATH = join(__dirname, '../..', 'dist/cli.bundle.cjs');
|
|
@@ -666,6 +667,56 @@ describe('CLI E2E Tests (requires running Unity)', () => {
|
|
|
666
667
|
});
|
|
667
668
|
});
|
|
668
669
|
|
|
670
|
+
describe('tool-settings', () => {
|
|
671
|
+
const settingsPath: string = join(UNITY_PROJECT_ROOT, '.uloop', 'settings.tools.json');
|
|
672
|
+
let originalSettings: string | null;
|
|
673
|
+
|
|
674
|
+
beforeAll(() => {
|
|
675
|
+
try {
|
|
676
|
+
originalSettings = readFileSync(settingsPath, 'utf-8');
|
|
677
|
+
} catch (error) {
|
|
678
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
679
|
+
originalSettings = null;
|
|
680
|
+
} else {
|
|
681
|
+
throw error;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
writeFileSync(settingsPath, JSON.stringify({ disabledTools: ['get-logs'] }));
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
afterAll(() => {
|
|
688
|
+
if (originalSettings !== null) {
|
|
689
|
+
writeFileSync(settingsPath, originalSettings);
|
|
690
|
+
} else {
|
|
691
|
+
unlinkSync(settingsPath);
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it('should not display disabled tools in --help', () => {
|
|
696
|
+
const { stdout, exitCode } = runCli('--help');
|
|
697
|
+
|
|
698
|
+
expect(exitCode).toBe(0);
|
|
699
|
+
expect(stdout).toContain('compile');
|
|
700
|
+
expect(stdout).not.toContain('get-logs');
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
it('should not include disabled tools in --list-commands', () => {
|
|
704
|
+
const { stdout, exitCode } = runCli('--list-commands');
|
|
705
|
+
|
|
706
|
+
expect(exitCode).toBe(0);
|
|
707
|
+
const commands: string[] = stdout.trim().split('\n').filter(Boolean);
|
|
708
|
+
expect(commands).toContain('compile');
|
|
709
|
+
expect(commands).not.toContain('get-logs');
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
it('should output nothing for --list-options on disabled tool', () => {
|
|
713
|
+
const { stdout, exitCode } = runCli('--list-options get-logs');
|
|
714
|
+
|
|
715
|
+
expect(exitCode).toBe(0);
|
|
716
|
+
expect(stdout.trim()).toBe('');
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
|
|
669
720
|
// Domain Reload tests must run last to avoid affecting other tests
|
|
670
721
|
describe('compile --force-recompile (Domain Reload)', () => {
|
|
671
722
|
it('should support --force-recompile option', () => {
|
package/src/cli.ts
CHANGED
|
@@ -41,6 +41,7 @@ interface CliOptions extends GlobalOptions {
|
|
|
41
41
|
[key: string]: unknown;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
const FOCUS_WINDOW_COMMAND = 'focus-window' as const;
|
|
44
45
|
const LAUNCH_COMMAND = 'launch' as const;
|
|
45
46
|
const UPDATE_COMMAND = 'update' as const;
|
|
46
47
|
|
|
@@ -55,7 +56,7 @@ const BUILTIN_COMMANDS = [
|
|
|
55
56
|
'fix',
|
|
56
57
|
'skills',
|
|
57
58
|
LAUNCH_COMMAND,
|
|
58
|
-
|
|
59
|
+
FOCUS_WINDOW_COMMAND,
|
|
59
60
|
] as const;
|
|
60
61
|
|
|
61
62
|
const program = new Command();
|
|
@@ -64,7 +65,8 @@ program
|
|
|
64
65
|
.name('uloop')
|
|
65
66
|
.description('Unity MCP CLI - Direct communication with Unity Editor')
|
|
66
67
|
.version(VERSION, '-v, --version', 'Output the version number')
|
|
67
|
-
.showHelpAfterError('(run with -h for available options)')
|
|
68
|
+
.showHelpAfterError('(run with -h for available options)')
|
|
69
|
+
.configureHelp({ sortSubcommands: true });
|
|
68
70
|
|
|
69
71
|
// --list-commands: Output command names for shell completion
|
|
70
72
|
program.option('--list-commands', 'List all command names (for shell completion)');
|
|
@@ -124,8 +126,8 @@ registerSkillsCommand(program);
|
|
|
124
126
|
// Register launch subcommand
|
|
125
127
|
registerLaunchCommand(program);
|
|
126
128
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
+
// focus-window is registered conditionally in main() based on tool settings,
|
|
130
|
+
// since it corresponds to an MCP tool that can be disabled via Tool Settings UI
|
|
129
131
|
|
|
130
132
|
/**
|
|
131
133
|
* Register a tool as a CLI command dynamically.
|
|
@@ -717,12 +719,14 @@ function handleCompletionOptions(): boolean {
|
|
|
717
719
|
|
|
718
720
|
if (args.includes('--list-commands')) {
|
|
719
721
|
const tools = loadToolsCache();
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
722
|
+
const enabledTools: ToolDefinition[] = filterEnabledTools(tools.tools, projectPath);
|
|
723
|
+
const allCommands = [
|
|
724
|
+
...BUILTIN_COMMANDS.filter(
|
|
725
|
+
(cmd) => cmd !== FOCUS_WINDOW_COMMAND || isToolEnabled(cmd, projectPath),
|
|
726
|
+
),
|
|
727
|
+
...enabledTools.map((t) => t.name),
|
|
728
|
+
];
|
|
729
|
+
console.log(allCommands.sort().join('\n'));
|
|
726
730
|
return true;
|
|
727
731
|
}
|
|
728
732
|
|
|
@@ -746,13 +750,10 @@ function listOptionsForCommand(cmdName: string, projectPath?: string): void {
|
|
|
746
750
|
}
|
|
747
751
|
|
|
748
752
|
// Tool commands - only output tool-specific options
|
|
749
|
-
// Only filter disabled tools when --project-path is explicitly provided;
|
|
750
|
-
// without it, loadDisabledTools would trigger findUnityProjectRoot() scanning
|
|
751
753
|
const tools = loadToolsCache();
|
|
752
|
-
const tool: ToolDefinition | undefined =
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
: tools.tools.find((t) => t.name === cmdName);
|
|
754
|
+
const tool: ToolDefinition | undefined = filterEnabledTools(tools.tools, projectPath).find(
|
|
755
|
+
(t) => t.name === cmdName,
|
|
756
|
+
);
|
|
756
757
|
if (!tool) {
|
|
757
758
|
return;
|
|
758
759
|
}
|
|
@@ -770,6 +771,9 @@ function listOptionsForCommand(cmdName: string, projectPath?: string): void {
|
|
|
770
771
|
* Check if a command exists in the current program.
|
|
771
772
|
*/
|
|
772
773
|
function commandExists(cmdName: string, projectPath?: string): boolean {
|
|
774
|
+
if (cmdName === FOCUS_WINDOW_COMMAND) {
|
|
775
|
+
return isToolEnabled(FOCUS_WINDOW_COMMAND, projectPath);
|
|
776
|
+
}
|
|
773
777
|
if (BUILTIN_COMMANDS.includes(cmdName as (typeof BUILTIN_COMMANDS)[number])) {
|
|
774
778
|
return true;
|
|
775
779
|
}
|
|
@@ -838,12 +842,17 @@ async function main(): Promise<void> {
|
|
|
838
842
|
|
|
839
843
|
if (skipProjectDetection) {
|
|
840
844
|
const defaultTools = getDefaultTools();
|
|
841
|
-
// Only filter disabled tools
|
|
842
|
-
//
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
845
|
+
// Only filter disabled tools for top-level help (uloop --help); subcommand help
|
|
846
|
+
// (e.g. uloop completion --help) does not list dynamic tools, so scanning is unnecessary
|
|
847
|
+
const isTopLevelHelp: boolean =
|
|
848
|
+
cmdName === undefined && (args.includes('-h') || args.includes('--help'));
|
|
849
|
+
const shouldFilter: boolean = syncGlobalOptions.projectPath !== undefined || isTopLevelHelp;
|
|
850
|
+
const tools: ToolDefinition[] = shouldFilter
|
|
851
|
+
? filterEnabledTools(defaultTools.tools, syncGlobalOptions.projectPath)
|
|
852
|
+
: defaultTools.tools;
|
|
853
|
+
if (!shouldFilter || isToolEnabled(FOCUS_WINDOW_COMMAND, syncGlobalOptions.projectPath)) {
|
|
854
|
+
registerFocusWindowCommand(program);
|
|
855
|
+
}
|
|
847
856
|
for (const tool of tools) {
|
|
848
857
|
registerToolCommand(tool);
|
|
849
858
|
}
|
|
@@ -878,6 +887,9 @@ async function main(): Promise<void> {
|
|
|
878
887
|
// Register tool commands from cache (after potential auto-sync)
|
|
879
888
|
const toolsCache = loadToolsCache();
|
|
880
889
|
const projectPath: string | undefined = syncGlobalOptions.projectPath;
|
|
890
|
+
if (isToolEnabled(FOCUS_WINDOW_COMMAND, projectPath)) {
|
|
891
|
+
registerFocusWindowCommand(program);
|
|
892
|
+
}
|
|
881
893
|
for (const tool of filterEnabledTools(toolsCache.tools, projectPath)) {
|
|
882
894
|
registerToolCommand(tool);
|
|
883
895
|
}
|
package/src/default-tools.json
CHANGED
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.68.
|
|
7
|
+
export const VERSION = '0.68.2'; // x-release-please-version
|
/package/src/skills/skill-definitions/cli-only/uloop-focus-window/{SKILL.md → Skill/SKILL.md}
RENAMED
|
File without changes
|
/package/src/skills/skill-definitions/cli-only/uloop-get-project-info/{SKILL.md → Skill/SKILL.md}
RENAMED
|
File without changes
|
/package/src/skills/skill-definitions/cli-only/uloop-get-version/{SKILL.md → Skill/SKILL.md}
RENAMED
|
File without changes
|