uloop-cli 0.50.2 → 0.52.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uloop-cli",
3
- "version": "0.50.2",
3
+ "version": "0.52.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",
@@ -1,12 +1,7 @@
1
1
  /**
2
- * Auto-generates bundled-skills.ts from multiple source directories.
3
- * Scans SKILL.md files from:
4
- * 1. Editor/Api/McpTools/SKILL.md (C# tool folders)
5
- * 2. skill-definitions/cli-only/SKILL.md (CLI-only skills)
6
- *
7
- * Skills with `internal: true` in frontmatter are excluded from generation.
8
- *
9
- * Usage: npx tsx scripts/generate-bundled-skills.ts
2
+ * Skills are scattered across multiple directories (McpTools, cli-only).
3
+ * Without this generator, we'd need manual synchronization between source
4
+ * SKILL.md files and the bundled output, which is error-prone and tedious.
10
5
  */
11
6
 
12
7
  import { readdirSync, readFileSync, writeFileSync, existsSync } from 'fs';
@@ -26,6 +21,7 @@ interface SkillMetadata {
26
21
  name: string;
27
22
  isInternal: boolean;
28
23
  importPath: string;
24
+ skillDirPath: string;
29
25
  }
30
26
 
31
27
  function parseFrontmatter(content: string): Record<string, string | boolean> {
@@ -75,8 +71,29 @@ function getSkillMetadataFromPath(
75
71
 
76
72
  const relativePath = relative(OUTPUT_DIR, skillMdPath).replace(/\\/g, '/');
77
73
  const importPath = relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
74
+ const skillDirPath = dirname(skillMdPath);
75
+
76
+ return { dirName, name, isInternal, importPath, skillDirPath };
77
+ }
78
+
79
+ function collectAdditionalFiles(skillDirPath: string): Record<string, string> {
80
+ const examplesDir = join(skillDirPath, 'examples');
81
+ if (!existsSync(examplesDir)) {
82
+ return {};
83
+ }
78
84
 
79
- return { dirName, name, isInternal, importPath };
85
+ const files: Record<string, string> = {};
86
+ const entries = readdirSync(examplesDir, { withFileTypes: true });
87
+
88
+ for (const entry of entries) {
89
+ if (entry.isFile() && entry.name.endsWith('.md')) {
90
+ const filePath = join(examplesDir, entry.name);
91
+ const relativePath = `examples/${entry.name}`;
92
+ files[relativePath] = readFileSync(filePath, 'utf-8');
93
+ }
94
+ }
95
+
96
+ return files;
80
97
  }
81
98
 
82
99
  function collectSkillsFromMcpTools(): SkillMetadata[] {
@@ -134,6 +151,13 @@ function toVariableName(dirName: string): string {
134
151
  .concat('Skill');
135
152
  }
136
153
 
154
+ function escapeStringForTemplate(str: string): string {
155
+ return str
156
+ .replace(/\\/g, '\\\\')
157
+ .replace(/`/g, '\\`')
158
+ .replace(/\$\{/g, '\\${');
159
+ }
160
+
137
161
  function generateBundledSkillsFile(skills: SkillMetadata[]): string {
138
162
  const imports = skills
139
163
  .map((skill) => {
@@ -145,10 +169,27 @@ function generateBundledSkillsFile(skills: SkillMetadata[]): string {
145
169
  const entries = skills
146
170
  .map((skill) => {
147
171
  const varName = toVariableName(skill.dirName);
172
+ const additionalFiles = collectAdditionalFiles(skill.skillDirPath);
173
+ const hasAdditionalFiles = Object.keys(additionalFiles).length > 0;
174
+
175
+ let additionalFilesCode = '';
176
+ if (hasAdditionalFiles) {
177
+ const fileEntries = Object.entries(additionalFiles)
178
+ .map(([path, content]) => {
179
+ const escapedContent = escapeStringForTemplate(content);
180
+ return ` '${path}': \`${escapedContent}\`,`;
181
+ })
182
+ .join('\n');
183
+ additionalFilesCode = `
184
+ additionalFiles: {
185
+ ${fileEntries}
186
+ },`;
187
+ }
188
+
148
189
  return ` {
149
190
  name: '${skill.name}',
150
191
  dirName: '${skill.dirName}',
151
- content: ${varName},
192
+ content: ${varName},${additionalFilesCode}
152
193
  },`;
153
194
  })
154
195
  .join('\n');
@@ -159,6 +200,7 @@ function generateBundledSkillsFile(skills: SkillMetadata[]): string {
159
200
  *
160
201
  * This file is automatically generated from:
161
202
  * - Editor/Api/McpTools/<ToolFolder>/SKILL.md
203
+ * - Editor/Api/McpTools/<ToolFolder>/examples/*.md (additional files)
162
204
  * - skill-definitions/cli-only/<SkillFolder>/SKILL.md
163
205
  *
164
206
  * To add a new skill, create a SKILL.md file in the appropriate location.
@@ -171,6 +213,7 @@ export interface BundledSkill {
171
213
  name: string;
172
214
  dirName: string;
173
215
  content: string;
216
+ additionalFiles?: Record<string, string>;
174
217
  }
175
218
 
176
219
  export const BUNDLED_SKILLS: BundledSkill[] = [
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.50.2",
2
+ "version": "0.52.0",
3
3
  "tools": [
4
4
  {
5
5
  "name": "compile",
@@ -274,8 +274,8 @@
274
274
  }
275
275
  },
276
276
  {
277
- "name": "capture-unity-window",
278
- "description": "Capture Unity EditorWindow and save as PNG image",
277
+ "name": "capture-window",
278
+ "description": "Capture Unity EditorWindow and save as PNG",
279
279
  "inputSchema": {
280
280
  "type": "object",
281
281
  "properties": {
@@ -288,6 +288,16 @@
288
288
  "type": "number",
289
289
  "description": "Resolution scale (0.1 to 1.0)",
290
290
  "default": 1
291
+ },
292
+ "MatchMode": {
293
+ "type": "string",
294
+ "description": "Window name matching mode (all case-insensitive)",
295
+ "enum": [
296
+ "exact",
297
+ "prefix",
298
+ "contains"
299
+ ],
300
+ "default": "exact"
291
301
  }
292
302
  }
293
303
  }