unity-agentic-tools 0.3.3 → 0.4.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.
- package/dist/cli.js +1233 -870
- package/dist/index.js +352 -37
- package/native/unity-file-tools.darwin-arm64.node +0 -0
- package/native/unity-file-tools.darwin-x64.node +0 -0
- package/native/unity-file-tools.linux-x64-gnu.node +0 -0
- package/native/unity-file-tools.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2299,7 +2299,7 @@ var require_package = __commonJS((exports2, module2) => {
|
|
|
2299
2299
|
module2.exports = {
|
|
2300
2300
|
name: "unity-agentic-tools",
|
|
2301
2301
|
packageManager: "bun@latest",
|
|
2302
|
-
version: "0.
|
|
2302
|
+
version: "0.4.1",
|
|
2303
2303
|
description: "Fast, token-efficient Unity YAML parser for AI agents",
|
|
2304
2304
|
exports: {
|
|
2305
2305
|
".": {
|
|
@@ -2595,18 +2595,10 @@ function removeDirectoryRecursive(dir) {
|
|
|
2595
2595
|
}
|
|
2596
2596
|
|
|
2597
2597
|
// src/cmd-create.ts
|
|
2598
|
-
var
|
|
2598
|
+
var import_fs17 = require("fs");
|
|
2599
2599
|
var import_path7 = require("path");
|
|
2600
2600
|
var import_crypto2 = require("crypto");
|
|
2601
2601
|
|
|
2602
|
-
// src/editor/create.ts
|
|
2603
|
-
var import_fs8 = require("fs");
|
|
2604
|
-
var path3 = __toESM(require("path"));
|
|
2605
|
-
|
|
2606
|
-
// src/guid-cache.ts
|
|
2607
|
-
var import_fs5 = require("fs");
|
|
2608
|
-
var import_path5 = require("path");
|
|
2609
|
-
|
|
2610
2602
|
// src/utils.ts
|
|
2611
2603
|
var import_fs4 = require("fs");
|
|
2612
2604
|
var import_path4 = require("path");
|
|
@@ -2627,6 +2619,12 @@ function find_unity_project_root(startDir) {
|
|
|
2627
2619
|
}
|
|
2628
2620
|
return null;
|
|
2629
2621
|
}
|
|
2622
|
+
function ensure_parent_dir(file_path) {
|
|
2623
|
+
const dir = import_path4.dirname(file_path);
|
|
2624
|
+
if (dir && dir !== "." && !import_fs4.existsSync(dir)) {
|
|
2625
|
+
import_fs4.mkdirSync(dir, { recursive: true });
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2630
2628
|
function atomicWrite(filePath, content) {
|
|
2631
2629
|
if (import_fs4.existsSync(filePath)) {
|
|
2632
2630
|
try {
|
|
@@ -2762,7 +2760,13 @@ function validate_file_path(file_path, operation) {
|
|
|
2762
2760
|
return null;
|
|
2763
2761
|
}
|
|
2764
2762
|
|
|
2763
|
+
// src/editor/create.ts
|
|
2764
|
+
var import_fs8 = require("fs");
|
|
2765
|
+
var path3 = __toESM(require("path"));
|
|
2766
|
+
|
|
2765
2767
|
// src/guid-cache.ts
|
|
2768
|
+
var import_fs5 = require("fs");
|
|
2769
|
+
var import_path5 = require("path");
|
|
2766
2770
|
var _cache_store = new Map;
|
|
2767
2771
|
function build_guid_cache(project_path, raw) {
|
|
2768
2772
|
return {
|
|
@@ -3164,6 +3168,7 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3164
3168
|
}
|
|
3165
3169
|
}
|
|
3166
3170
|
if (matches[0].filePath?.endsWith(".dll")) {
|
|
3171
|
+
const classNameLower = targetName.toLowerCase();
|
|
3167
3172
|
const dllBasename = path.basename(matches[0].filePath).toLowerCase();
|
|
3168
3173
|
for (const cacheName of ["package-cache.json", "local-package-cache.json"]) {
|
|
3169
3174
|
const cachePath = path.join(projectPath, ".unity-agentic", cacheName);
|
|
@@ -3171,6 +3176,11 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3171
3176
|
continue;
|
|
3172
3177
|
try {
|
|
3173
3178
|
const cache = JSON.parse(import_fs6.readFileSync(cachePath, "utf-8"));
|
|
3179
|
+
for (const [guid, assetPath] of Object.entries(cache)) {
|
|
3180
|
+
if (assetPath.endsWith(".cs") && path.basename(assetPath, ".cs").toLowerCase() === classNameLower) {
|
|
3181
|
+
return { guid, path: assetPath };
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3174
3184
|
for (const [guid, assetPath] of Object.entries(cache)) {
|
|
3175
3185
|
if (assetPath.toLowerCase().endsWith(".dll") && path.basename(assetPath).toLowerCase() === dllBasename) {
|
|
3176
3186
|
return { guid, path: assetPath };
|
|
@@ -3196,6 +3206,7 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3196
3206
|
}
|
|
3197
3207
|
}
|
|
3198
3208
|
if (!guid && m.filePath?.endsWith(".dll")) {
|
|
3209
|
+
const clsLower = (m.name ?? targetName).toLowerCase();
|
|
3199
3210
|
const dllBase = path.basename(m.filePath).toLowerCase();
|
|
3200
3211
|
for (const cn of ["package-cache.json", "local-package-cache.json"]) {
|
|
3201
3212
|
const cp = path.join(projectPath, ".unity-agentic", cn);
|
|
@@ -3204,11 +3215,19 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3204
3215
|
try {
|
|
3205
3216
|
const c = JSON.parse(import_fs6.readFileSync(cp, "utf-8"));
|
|
3206
3217
|
for (const [g, p] of Object.entries(c)) {
|
|
3207
|
-
if (p.
|
|
3218
|
+
if (p.endsWith(".cs") && path.basename(p, ".cs").toLowerCase() === clsLower) {
|
|
3208
3219
|
guid = g;
|
|
3209
3220
|
break;
|
|
3210
3221
|
}
|
|
3211
3222
|
}
|
|
3223
|
+
if (!guid) {
|
|
3224
|
+
for (const [g, p] of Object.entries(c)) {
|
|
3225
|
+
if (p.toLowerCase().endsWith(".dll") && path.basename(p).toLowerCase() === dllBase) {
|
|
3226
|
+
guid = g;
|
|
3227
|
+
break;
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3212
3231
|
} catch {}
|
|
3213
3232
|
if (guid)
|
|
3214
3233
|
break;
|
|
@@ -3239,7 +3258,11 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3239
3258
|
throw new Error(`Ambiguous type "${script}": found ${allResolved.length} matches (${paths}). ` + `Use a qualified name (e.g., "Namespace.${targetName}") or provide the full path.`);
|
|
3240
3259
|
}
|
|
3241
3260
|
}
|
|
3242
|
-
} catch {
|
|
3261
|
+
} catch (err) {
|
|
3262
|
+
if (err instanceof Error && err.message.startsWith("Ambiguous type")) {
|
|
3263
|
+
throw err;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3243
3266
|
}
|
|
3244
3267
|
const scriptNameLower = script.toLowerCase().replace(/\.cs$/, "");
|
|
3245
3268
|
const dotIdx = scriptNameLower.lastIndexOf(".");
|
|
@@ -3266,6 +3289,54 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3266
3289
|
}
|
|
3267
3290
|
return null;
|
|
3268
3291
|
}
|
|
3292
|
+
var ASSET_PPTR_MAP = {
|
|
3293
|
+
".inputactions": { fileID: 11400000, type: 2 },
|
|
3294
|
+
".asset": { fileID: 11400000, type: 2 },
|
|
3295
|
+
".mat": { fileID: 2100000, type: 2 },
|
|
3296
|
+
".prefab": { fileID: 100100000, type: 2 },
|
|
3297
|
+
".controller": { fileID: 9100000, type: 2 },
|
|
3298
|
+
".anim": { fileID: 7400000, type: 2 }
|
|
3299
|
+
};
|
|
3300
|
+
var ASSET_EXTENSIONS = new Set(Object.keys(ASSET_PPTR_MAP));
|
|
3301
|
+
function resolveAssetPathToPPtr(value, file_path, project_path) {
|
|
3302
|
+
if (value.startsWith("{fileID:") || value.startsWith("{"))
|
|
3303
|
+
return;
|
|
3304
|
+
const ext = path.extname(value).toLowerCase();
|
|
3305
|
+
if (!ASSET_EXTENSIONS.has(ext))
|
|
3306
|
+
return;
|
|
3307
|
+
const resolved_project = project_path || find_unity_project_root(path.dirname(file_path));
|
|
3308
|
+
if (!resolved_project)
|
|
3309
|
+
return null;
|
|
3310
|
+
const mapping = ASSET_PPTR_MAP[ext];
|
|
3311
|
+
let guid = null;
|
|
3312
|
+
const basename_val = path.basename(value, ext);
|
|
3313
|
+
if (value.includes("/") || value.includes("\\")) {
|
|
3314
|
+
const abs = path.isAbsolute(value) ? value : path.join(resolved_project, value);
|
|
3315
|
+
guid = extractGuidFromMeta(abs + ".meta");
|
|
3316
|
+
}
|
|
3317
|
+
if (!guid) {
|
|
3318
|
+
const cache = load_guid_cache_for_file(file_path, resolved_project);
|
|
3319
|
+
if (cache) {
|
|
3320
|
+
const found = cache.find_by_name(basename_val, ext);
|
|
3321
|
+
if (found)
|
|
3322
|
+
guid = found.guid;
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
if (!guid) {
|
|
3326
|
+
const candidates = [
|
|
3327
|
+
path.join(resolved_project, "Assets", value),
|
|
3328
|
+
path.join(resolved_project, value)
|
|
3329
|
+
];
|
|
3330
|
+
for (const candidate of candidates) {
|
|
3331
|
+
guid = extractGuidFromMeta(candidate + ".meta");
|
|
3332
|
+
if (guid)
|
|
3333
|
+
break;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
if (!guid)
|
|
3337
|
+
return null;
|
|
3338
|
+
return `{fileID: ${mapping.fileID}, guid: ${guid}, type: ${mapping.type}}`;
|
|
3339
|
+
}
|
|
3269
3340
|
function resolve_script_with_fields(script, project_path) {
|
|
3270
3341
|
const resolved = resolveScriptGuid(script, project_path);
|
|
3271
3342
|
if (!resolved)
|
|
@@ -3822,7 +3893,9 @@ ${element_indent2}- ${value}`);
|
|
|
3822
3893
|
if (!header) {
|
|
3823
3894
|
throw new Error(`Invalid Unity YAML block header in replacement text: "${new_text.slice(0, 80)}"`);
|
|
3824
3895
|
}
|
|
3825
|
-
this._raw = new_text
|
|
3896
|
+
this._raw = new_text.endsWith(`
|
|
3897
|
+
`) ? new_text : new_text + `
|
|
3898
|
+
`;
|
|
3826
3899
|
this._header = header;
|
|
3827
3900
|
this._dirty = true;
|
|
3828
3901
|
this._format_cache.clear();
|
|
@@ -3832,6 +3905,11 @@ ${element_indent2}- ${value}`);
|
|
|
3832
3905
|
}
|
|
3833
3906
|
_check_dirty(old_raw) {
|
|
3834
3907
|
if (this._raw !== old_raw) {
|
|
3908
|
+
if (!this._raw.endsWith(`
|
|
3909
|
+
`)) {
|
|
3910
|
+
this._raw += `
|
|
3911
|
+
`;
|
|
3912
|
+
}
|
|
3835
3913
|
this._dirty = true;
|
|
3836
3914
|
return true;
|
|
3837
3915
|
}
|
|
@@ -4914,14 +4992,82 @@ function get_project_info(projectPath) {
|
|
|
4914
4992
|
}
|
|
4915
4993
|
|
|
4916
4994
|
// src/editor/create.ts
|
|
4995
|
+
function md4(data) {
|
|
4996
|
+
function F(x, y, z) {
|
|
4997
|
+
return x & y | ~x & z;
|
|
4998
|
+
}
|
|
4999
|
+
function G(x, y, z) {
|
|
5000
|
+
return x & y | x & z | y & z;
|
|
5001
|
+
}
|
|
5002
|
+
function H(x, y, z) {
|
|
5003
|
+
return x ^ y ^ z;
|
|
5004
|
+
}
|
|
5005
|
+
function rotl(x, n) {
|
|
5006
|
+
return (x << n | x >>> 32 - n) >>> 0;
|
|
5007
|
+
}
|
|
5008
|
+
const len = data.length;
|
|
5009
|
+
const bitLen = len * 8;
|
|
5010
|
+
const padded_len = len + 9 + 63 & ~63;
|
|
5011
|
+
const buf = Buffer.alloc(padded_len);
|
|
5012
|
+
data.copy(buf);
|
|
5013
|
+
buf[len] = 128;
|
|
5014
|
+
buf.writeUInt32LE(bitLen >>> 0, padded_len - 8);
|
|
5015
|
+
buf.writeUInt32LE(Math.floor(bitLen / 4294967296) >>> 0, padded_len - 4);
|
|
5016
|
+
let a0 = 1732584193;
|
|
5017
|
+
let b0 = 4023233417;
|
|
5018
|
+
let c0 = 2562383102;
|
|
5019
|
+
let d0 = 271733878;
|
|
5020
|
+
const R1_K = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
5021
|
+
const R1_S = [3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19];
|
|
5022
|
+
const R2_K = [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15];
|
|
5023
|
+
const R2_S = [3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13];
|
|
5024
|
+
const R3_K = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];
|
|
5025
|
+
const R3_S = [3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15];
|
|
5026
|
+
for (let i = 0;i < padded_len; i += 64) {
|
|
5027
|
+
const X = [];
|
|
5028
|
+
for (let j = 0;j < 16; j++)
|
|
5029
|
+
X[j] = buf.readUInt32LE(i + j * 4);
|
|
5030
|
+
let a = a0, b = b0, c = c0, d = d0;
|
|
5031
|
+
for (let j = 0;j < 16; j++) {
|
|
5032
|
+
const t = a + F(b, c, d) + X[R1_K[j]] >>> 0;
|
|
5033
|
+
a = d;
|
|
5034
|
+
d = c;
|
|
5035
|
+
c = b;
|
|
5036
|
+
b = rotl(t, R1_S[j]);
|
|
5037
|
+
}
|
|
5038
|
+
for (let j = 0;j < 16; j++) {
|
|
5039
|
+
const t = a + G(b, c, d) + X[R2_K[j]] + 1518500249 >>> 0;
|
|
5040
|
+
a = d;
|
|
5041
|
+
d = c;
|
|
5042
|
+
c = b;
|
|
5043
|
+
b = rotl(t, R2_S[j]);
|
|
5044
|
+
}
|
|
5045
|
+
for (let j = 0;j < 16; j++) {
|
|
5046
|
+
const t = a + H(b, c, d) + X[R3_K[j]] + 1859775393 >>> 0;
|
|
5047
|
+
a = d;
|
|
5048
|
+
d = c;
|
|
5049
|
+
c = b;
|
|
5050
|
+
b = rotl(t, R3_S[j]);
|
|
5051
|
+
}
|
|
5052
|
+
a0 = a0 + a >>> 0;
|
|
5053
|
+
b0 = b0 + b >>> 0;
|
|
5054
|
+
c0 = c0 + c >>> 0;
|
|
5055
|
+
d0 = d0 + d >>> 0;
|
|
5056
|
+
}
|
|
5057
|
+
const result = Buffer.alloc(16);
|
|
5058
|
+
result.writeUInt32LE(a0, 0);
|
|
5059
|
+
result.writeUInt32LE(b0, 4);
|
|
5060
|
+
result.writeUInt32LE(c0, 8);
|
|
5061
|
+
result.writeUInt32LE(d0, 12);
|
|
5062
|
+
return result;
|
|
5063
|
+
}
|
|
4917
5064
|
function compute_dll_script_file_id(namespace, class_name) {
|
|
4918
|
-
const { createHash } = require("crypto");
|
|
4919
5065
|
const full_name = namespace ? `${namespace}.${class_name}` : class_name;
|
|
4920
5066
|
const name_bytes = Buffer.from(full_name, "utf-8");
|
|
4921
5067
|
const input = Buffer.alloc(4 + name_bytes.length);
|
|
4922
5068
|
input.writeInt32LE(114, 0);
|
|
4923
5069
|
name_bytes.copy(input, 4);
|
|
4924
|
-
const hash =
|
|
5070
|
+
const hash = md4(input);
|
|
4925
5071
|
const a = hash.readInt32LE(0);
|
|
4926
5072
|
const b = hash.readInt32LE(4);
|
|
4927
5073
|
const c = hash.readInt32LE(8);
|
|
@@ -4934,13 +5080,13 @@ function get_layer_from_parent(doc, parentTransformId) {
|
|
|
4934
5080
|
const parentTransform = doc.find_by_file_id(parentTransformId);
|
|
4935
5081
|
if (!parentTransform)
|
|
4936
5082
|
return 0;
|
|
4937
|
-
const goMatch = parentTransform.raw.match(/m_GameObject
|
|
5083
|
+
const goMatch = parentTransform.raw.match(/m_GameObject:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
4938
5084
|
if (!goMatch)
|
|
4939
5085
|
return 0;
|
|
4940
5086
|
const parentGo = doc.find_by_file_id(goMatch[1]);
|
|
4941
5087
|
if (!parentGo)
|
|
4942
5088
|
return 0;
|
|
4943
|
-
const layerMatch = parentGo.raw.match(/m_Layer
|
|
5089
|
+
const layerMatch = parentGo.raw.match(/m_Layer:[ \t]*(\d+)/);
|
|
4944
5090
|
return layerMatch ? parseInt(layerMatch[1], 10) : 0;
|
|
4945
5091
|
}
|
|
4946
5092
|
function createGameObjectYAML(gameObjectId, transformId, name, parentTransformId = "0", rootOrder = 0, layer = 0) {
|
|
@@ -5261,11 +5407,14 @@ ${defaults}`;
|
|
|
5261
5407
|
function addComponentToGameObject(doc, gameObjectId, componentId) {
|
|
5262
5408
|
const goBlock = doc.find_by_file_id(gameObjectId);
|
|
5263
5409
|
if (!goBlock)
|
|
5264
|
-
return;
|
|
5265
|
-
|
|
5266
|
-
|
|
5410
|
+
return false;
|
|
5411
|
+
const raw = goBlock.raw;
|
|
5412
|
+
const updated = raw.replace(/(m_Component:[ \t]*\n(?:[ \t]*-[ \t]*component:[ \t]*\{fileID:[ \t]*\d+\}[ \t]*\n)*)/, `$1 - component: {fileID: ${componentId}}
|
|
5267
5413
|
`);
|
|
5268
|
-
|
|
5414
|
+
if (updated === raw)
|
|
5415
|
+
return false;
|
|
5416
|
+
goBlock.replace_raw(updated);
|
|
5417
|
+
return true;
|
|
5269
5418
|
}
|
|
5270
5419
|
function createMonoBehaviourYAML(componentId, gameObjectId, scriptGuid, fields, version, scriptFileId = 11500000, type_lookup) {
|
|
5271
5420
|
const field_yaml = fields && fields.length > 0 ? generate_field_yaml(fields, version, " ", type_lookup) : `
|
|
@@ -5337,7 +5486,7 @@ function createGameObject(options) {
|
|
|
5337
5486
|
if (parentBlock.class_id === 4) {
|
|
5338
5487
|
parentTransformIdStr = parentIdStr;
|
|
5339
5488
|
} else if (parentBlock.class_id === 1) {
|
|
5340
|
-
const compMatch = parentBlock.raw.match(/m_Component
|
|
5489
|
+
const compMatch = parentBlock.raw.match(/m_Component:[ \t]*\n[ \t]*-[ \t]*component:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
5341
5490
|
if (compMatch) {
|
|
5342
5491
|
parentTransformIdStr = compMatch[1];
|
|
5343
5492
|
} else {
|
|
@@ -5751,6 +5900,7 @@ Light:
|
|
|
5751
5900
|
`;
|
|
5752
5901
|
}
|
|
5753
5902
|
try {
|
|
5903
|
+
ensure_parent_dir(output_path);
|
|
5754
5904
|
import_fs8.writeFileSync(output_path, yaml, "utf-8");
|
|
5755
5905
|
} catch (err) {
|
|
5756
5906
|
return {
|
|
@@ -5889,6 +6039,7 @@ PrefabInstance:
|
|
|
5889
6039
|
m_SourcePrefab: {fileID: 100100000, guid: ${sourceGuid}, type: 3}
|
|
5890
6040
|
`;
|
|
5891
6041
|
try {
|
|
6042
|
+
ensure_parent_dir(output_path);
|
|
5892
6043
|
import_fs8.writeFileSync(output_path, variantYaml, "utf-8");
|
|
5893
6044
|
} catch (err) {
|
|
5894
6045
|
return {
|
|
@@ -5979,7 +6130,7 @@ function createPrefabInstance(options) {
|
|
|
5979
6130
|
if (parentBlock.class_id === 4) {
|
|
5980
6131
|
parentTransformIdStr = parentIdStr;
|
|
5981
6132
|
} else if (parentBlock.class_id === 1) {
|
|
5982
|
-
const compMatch = parentBlock.raw.match(/m_Component
|
|
6133
|
+
const compMatch = parentBlock.raw.match(/m_Component:[ \t]*\n[ \t]*-[ \t]*component:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
5983
6134
|
if (compMatch) {
|
|
5984
6135
|
parentTransformIdStr = compMatch[1];
|
|
5985
6136
|
} else {
|
|
@@ -6213,6 +6364,7 @@ ${yaml_lines.join(`
|
|
|
6213
6364
|
}
|
|
6214
6365
|
}
|
|
6215
6366
|
try {
|
|
6367
|
+
ensure_parent_dir(output_path);
|
|
6216
6368
|
import_fs8.writeFileSync(output_path, assetYaml, "utf-8");
|
|
6217
6369
|
} catch (err) {
|
|
6218
6370
|
return { success: false, output_path, error: `Failed to write asset file: ${err instanceof Error ? err.message : String(err)}` };
|
|
@@ -6408,7 +6560,7 @@ function addComponent(options) {
|
|
|
6408
6560
|
let duplicateWarning;
|
|
6409
6561
|
const goBlock = doc.find_by_file_id(gameObjectIdStr);
|
|
6410
6562
|
if (goBlock && classId !== null) {
|
|
6411
|
-
const compRefs = [...goBlock.raw.matchAll(/component
|
|
6563
|
+
const compRefs = [...goBlock.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/g)].map((m) => m[1]);
|
|
6412
6564
|
for (const refId of compRefs) {
|
|
6413
6565
|
const compBlock = doc.find_by_file_id(refId);
|
|
6414
6566
|
if (compBlock && compBlock.class_id === classId) {
|
|
@@ -6440,12 +6592,16 @@ function addComponent(options) {
|
|
|
6440
6592
|
if (!resolved) {
|
|
6441
6593
|
const hints = [];
|
|
6442
6594
|
if (project_path) {
|
|
6595
|
+
const agenticDir = path3.join(project_path, ".unity-agentic");
|
|
6443
6596
|
const cacheExists = load_guid_cache(project_path) !== null;
|
|
6444
|
-
const registryExists = import_fs8.existsSync(path3.join(
|
|
6597
|
+
const registryExists = import_fs8.existsSync(path3.join(agenticDir, "type-registry.json"));
|
|
6598
|
+
const pkgCacheExists = import_fs8.existsSync(path3.join(agenticDir, "package-cache.json"));
|
|
6445
6599
|
if (!cacheExists && !registryExists) {
|
|
6446
|
-
hints.push(`No GUID cache or type registry found at ${
|
|
6600
|
+
hints.push(`No GUID cache or type registry found at ${agenticDir}/. Run "unity-agentic-tools setup" first.`);
|
|
6447
6601
|
} else if (!registryExists) {
|
|
6448
6602
|
hints.push('Type registry not found. Re-run "unity-agentic-tools setup" to rebuild.');
|
|
6603
|
+
} else if (!pkgCacheExists) {
|
|
6604
|
+
hints.push('Package cache not found. Re-run "unity-agentic-tools setup" to index package scripts.');
|
|
6449
6605
|
}
|
|
6450
6606
|
} else {
|
|
6451
6607
|
hints.push("No Unity project detected. Provide --project or run from inside a Unity project directory.");
|
|
@@ -6489,9 +6645,33 @@ function addComponent(options) {
|
|
|
6489
6645
|
if (variantInfo) {
|
|
6490
6646
|
appendToAddedComponents(doc, variantInfo.prefab_instance_id, variantInfo.source_ref, componentIdStr);
|
|
6491
6647
|
} else {
|
|
6492
|
-
addComponentToGameObject(doc, gameObjectIdStr, componentIdStr);
|
|
6648
|
+
const added = addComponentToGameObject(doc, gameObjectIdStr, componentIdStr);
|
|
6649
|
+
if (!added) {
|
|
6650
|
+
return {
|
|
6651
|
+
success: false,
|
|
6652
|
+
file_path,
|
|
6653
|
+
error: `Failed to add component reference to GameObject ${gameObjectIdStr}: m_Component array not found or malformed`
|
|
6654
|
+
};
|
|
6655
|
+
}
|
|
6493
6656
|
}
|
|
6494
6657
|
doc.append_raw(componentYAML);
|
|
6658
|
+
if (!doc.validate()) {
|
|
6659
|
+
return {
|
|
6660
|
+
success: false,
|
|
6661
|
+
file_path,
|
|
6662
|
+
error: "Validation failed after adding component. The generated YAML may be malformed."
|
|
6663
|
+
};
|
|
6664
|
+
}
|
|
6665
|
+
if (!variantInfo) {
|
|
6666
|
+
const goBlockAfter = doc.find_by_file_id(gameObjectIdStr);
|
|
6667
|
+
if (!goBlockAfter || !goBlockAfter.raw.includes(`component: {fileID: ${componentIdStr}}`)) {
|
|
6668
|
+
return {
|
|
6669
|
+
success: false,
|
|
6670
|
+
file_path,
|
|
6671
|
+
error: `Component block appended but reference not found in GameObject ${gameObjectIdStr}'s m_Component list`
|
|
6672
|
+
};
|
|
6673
|
+
}
|
|
6674
|
+
}
|
|
6495
6675
|
const saveResult = doc.save();
|
|
6496
6676
|
if (!saveResult.success) {
|
|
6497
6677
|
return {
|
|
@@ -6547,8 +6727,11 @@ function copyComponent(options) {
|
|
|
6547
6727
|
const newIdStr = doc.generate_file_id();
|
|
6548
6728
|
const newId = parseInt(newIdStr, 10);
|
|
6549
6729
|
let clonedBlock = sourceBlock.raw.replace(new RegExp(`^(--- !u!${sourceBlock.class_id} &)${source_file_id}`), `$1${newId}`);
|
|
6550
|
-
clonedBlock = clonedBlock.replace(/m_GameObject
|
|
6551
|
-
addComponentToGameObject(doc, targetGoIdStr, newIdStr);
|
|
6730
|
+
clonedBlock = clonedBlock.replace(/m_GameObject:[ \t]*\{fileID:[ \t]*\d+\}/, `m_GameObject: {fileID: ${targetGoId}}`);
|
|
6731
|
+
const added = addComponentToGameObject(doc, targetGoIdStr, newIdStr);
|
|
6732
|
+
if (!added) {
|
|
6733
|
+
return { success: false, file_path, error: `Failed to wire component to target GameObject ${targetGoIdStr}: m_Component array not found or malformed` };
|
|
6734
|
+
}
|
|
6552
6735
|
doc.append_raw(clonedBlock);
|
|
6553
6736
|
if (!doc.validate()) {
|
|
6554
6737
|
return { success: false, file_path, error: "Validation failed after copying component" };
|
|
@@ -7205,7 +7388,17 @@ function validate_value_type(current_value, new_value) {
|
|
|
7205
7388
|
const incoming = new_value.trim();
|
|
7206
7389
|
if (/^\{fileID:/.test(current)) {
|
|
7207
7390
|
if (/^\{fileID:[ \t]*0[ \t]*\}$/.test(current)) {
|
|
7208
|
-
|
|
7391
|
+
if (/^\{fileID:/.test(incoming))
|
|
7392
|
+
return null;
|
|
7393
|
+
if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(incoming))
|
|
7394
|
+
return null;
|
|
7395
|
+
if (/^(true|false|yes|no|on|off)$/i.test(incoming))
|
|
7396
|
+
return null;
|
|
7397
|
+
if (/^'[^']*'$/.test(incoming) || /^"[^"]*"$/.test(incoming))
|
|
7398
|
+
return null;
|
|
7399
|
+
if (/^\{.*:.*\}$/.test(incoming))
|
|
7400
|
+
return null;
|
|
7401
|
+
return `Current value is a null reference ({fileID: 0}). New value "${incoming}" is not a valid reference, number, boolean, quoted string, or compound value.`;
|
|
7209
7402
|
}
|
|
7210
7403
|
if (!/^\{fileID:/.test(incoming)) {
|
|
7211
7404
|
return `Expected a reference value ({fileID: ...}), got "${incoming}"`;
|
|
@@ -7415,7 +7608,19 @@ function editProperty(options) {
|
|
|
7415
7608
|
return result;
|
|
7416
7609
|
}
|
|
7417
7610
|
function editComponentByFileId(options) {
|
|
7418
|
-
const { file_path, file_id, property,
|
|
7611
|
+
const { file_path, file_id, property, project_path } = options;
|
|
7612
|
+
let { new_value } = options;
|
|
7613
|
+
const resolved = resolveAssetPathToPPtr(new_value, file_path, project_path);
|
|
7614
|
+
if (resolved === null) {
|
|
7615
|
+
return {
|
|
7616
|
+
success: false,
|
|
7617
|
+
file_path,
|
|
7618
|
+
error: `Could not resolve "${new_value}" to asset reference. Ensure GUID cache exists (run "setup <project>" first).`
|
|
7619
|
+
};
|
|
7620
|
+
}
|
|
7621
|
+
if (resolved !== undefined) {
|
|
7622
|
+
new_value = resolved;
|
|
7623
|
+
}
|
|
7419
7624
|
const pathError = validate_file_path(file_path, "write");
|
|
7420
7625
|
if (pathError) {
|
|
7421
7626
|
return { success: false, file_path, error: pathError };
|
|
@@ -8598,239 +8803,572 @@ ${fieldIndent} - rid: ${nextRid}`;
|
|
|
8598
8803
|
return { success: true, file_path, rid: nextRid, type_info: typeInfo };
|
|
8599
8804
|
}
|
|
8600
8805
|
// src/editor/delete.ts
|
|
8806
|
+
var import_fs13 = require("fs");
|
|
8807
|
+
|
|
8808
|
+
// src/project-search.ts
|
|
8809
|
+
init_scanner();
|
|
8601
8810
|
var import_fs12 = require("fs");
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8811
|
+
var path5 = __toESM(require("path"));
|
|
8812
|
+
var BINARY_EXTENSIONS = new Set([
|
|
8813
|
+
".png",
|
|
8814
|
+
".jpg",
|
|
8815
|
+
".jpeg",
|
|
8816
|
+
".gif",
|
|
8817
|
+
".bmp",
|
|
8818
|
+
".tga",
|
|
8819
|
+
".psd",
|
|
8820
|
+
".tif",
|
|
8821
|
+
".tiff",
|
|
8822
|
+
".fbx",
|
|
8823
|
+
".obj",
|
|
8824
|
+
".dae",
|
|
8825
|
+
".blend",
|
|
8826
|
+
".3ds",
|
|
8827
|
+
".max",
|
|
8828
|
+
".dll",
|
|
8829
|
+
".so",
|
|
8830
|
+
".dylib",
|
|
8831
|
+
".exe",
|
|
8832
|
+
".a",
|
|
8833
|
+
".lib",
|
|
8834
|
+
".mp3",
|
|
8835
|
+
".wav",
|
|
8836
|
+
".ogg",
|
|
8837
|
+
".aif",
|
|
8838
|
+
".aiff",
|
|
8839
|
+
".mp4",
|
|
8840
|
+
".mov",
|
|
8841
|
+
".avi",
|
|
8842
|
+
".wmv",
|
|
8843
|
+
".zip",
|
|
8844
|
+
".gz",
|
|
8845
|
+
".tar",
|
|
8846
|
+
".rar",
|
|
8847
|
+
".7z",
|
|
8848
|
+
".ttf",
|
|
8849
|
+
".otf",
|
|
8850
|
+
".woff",
|
|
8851
|
+
".woff2",
|
|
8852
|
+
".bank",
|
|
8853
|
+
".bytes",
|
|
8854
|
+
".db"
|
|
8855
|
+
]);
|
|
8856
|
+
var SKIP_DIRS = new Set(["Library", "Temp", "obj", "Logs", ".git", ".unity-agentic", "node_modules"]);
|
|
8857
|
+
function walk_project_files(project_path, extensions, exclude_dirs) {
|
|
8858
|
+
const nativeWalk = getNativeWalkProjectFiles();
|
|
8859
|
+
if (nativeWalk) {
|
|
8860
|
+
try {
|
|
8861
|
+
return nativeWalk(project_path, extensions, exclude_dirs ?? null);
|
|
8862
|
+
} catch {}
|
|
8645
8863
|
}
|
|
8646
|
-
return
|
|
8647
|
-
success: true,
|
|
8648
|
-
file_path,
|
|
8649
|
-
removed_file_id: file_id,
|
|
8650
|
-
removed_class_id: found.class_id
|
|
8651
|
-
};
|
|
8864
|
+
return walk_project_files_js(project_path, extensions, exclude_dirs);
|
|
8652
8865
|
}
|
|
8653
|
-
function
|
|
8654
|
-
const
|
|
8655
|
-
const
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
for (const compId of componentIds) {
|
|
8682
|
-
const block = doc.find_by_file_id(compId);
|
|
8683
|
-
if (block && block.class_id === 4) {
|
|
8684
|
-
transformId = compId;
|
|
8685
|
-
const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
|
|
8686
|
-
if (fatherMatch) {
|
|
8687
|
-
fatherId = fatherMatch[1];
|
|
8866
|
+
function walk_project_files_js(project_path, extensions, exclude_dirs) {
|
|
8867
|
+
const result = [];
|
|
8868
|
+
const skipSet = new Set([...SKIP_DIRS, ...exclude_dirs || []]);
|
|
8869
|
+
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
8870
|
+
function walk(dir) {
|
|
8871
|
+
let entries;
|
|
8872
|
+
try {
|
|
8873
|
+
entries = import_fs12.readdirSync(dir);
|
|
8874
|
+
} catch {
|
|
8875
|
+
return;
|
|
8876
|
+
}
|
|
8877
|
+
for (const entry of entries) {
|
|
8878
|
+
const full = path5.join(dir, entry);
|
|
8879
|
+
let stat;
|
|
8880
|
+
try {
|
|
8881
|
+
stat = import_fs12.statSync(full);
|
|
8882
|
+
} catch {
|
|
8883
|
+
continue;
|
|
8884
|
+
}
|
|
8885
|
+
if (stat.isDirectory()) {
|
|
8886
|
+
if (!skipSet.has(entry)) {
|
|
8887
|
+
walk(full);
|
|
8888
|
+
}
|
|
8889
|
+
} else if (stat.isFile()) {
|
|
8890
|
+
const ext = path5.extname(entry).toLowerCase();
|
|
8891
|
+
if (extSet.has(ext)) {
|
|
8892
|
+
result.push(full);
|
|
8893
|
+
}
|
|
8688
8894
|
}
|
|
8689
|
-
break;
|
|
8690
8895
|
}
|
|
8691
8896
|
}
|
|
8692
|
-
const
|
|
8693
|
-
|
|
8694
|
-
|
|
8897
|
+
const assetsDir = path5.join(project_path, "Assets");
|
|
8898
|
+
if (import_fs12.existsSync(assetsDir)) {
|
|
8899
|
+
walk(assetsDir);
|
|
8900
|
+
} else {
|
|
8901
|
+
walk(project_path);
|
|
8695
8902
|
}
|
|
8696
|
-
if (
|
|
8697
|
-
const
|
|
8698
|
-
|
|
8699
|
-
|
|
8903
|
+
if (extSet.has(".asset")) {
|
|
8904
|
+
const settingsDir = path5.join(project_path, "ProjectSettings");
|
|
8905
|
+
if (import_fs12.existsSync(settingsDir)) {
|
|
8906
|
+
walk(settingsDir);
|
|
8700
8907
|
}
|
|
8701
8908
|
}
|
|
8702
|
-
|
|
8703
|
-
doc.remove_child_from_parent(fatherId, transformId);
|
|
8704
|
-
}
|
|
8705
|
-
doc.remove_blocks(allIds);
|
|
8706
|
-
if (!doc.validate()) {
|
|
8707
|
-
return { success: false, file_path, error: "Validation failed after deleting GameObject" };
|
|
8708
|
-
}
|
|
8709
|
-
const writeResult = doc.save();
|
|
8710
|
-
if (!writeResult.success) {
|
|
8711
|
-
return { success: false, file_path, error: writeResult.error };
|
|
8712
|
-
}
|
|
8713
|
-
return {
|
|
8714
|
-
success: true,
|
|
8715
|
-
file_path,
|
|
8716
|
-
deleted_count: allIds.size
|
|
8717
|
-
};
|
|
8718
|
-
}
|
|
8719
|
-
function findPrefabInstanceBlock2(doc, identifier) {
|
|
8720
|
-
const asId = doc.find_by_file_id(identifier);
|
|
8721
|
-
if (asId && asId.class_id === 1001)
|
|
8722
|
-
return asId;
|
|
8723
|
-
const piBlocks = doc.find_by_class_id(1001);
|
|
8724
|
-
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8725
|
-
const namePattern = new RegExp(`propertyPath:\\s*m_Name\\s+value:\\s*${escaped}\\s`);
|
|
8726
|
-
for (const block of piBlocks) {
|
|
8727
|
-
if (namePattern.test(block.raw))
|
|
8728
|
-
return block;
|
|
8729
|
-
}
|
|
8730
|
-
return null;
|
|
8909
|
+
return result;
|
|
8731
8910
|
}
|
|
8732
|
-
function
|
|
8733
|
-
const {
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8911
|
+
function search_project(options) {
|
|
8912
|
+
const {
|
|
8913
|
+
project_path,
|
|
8914
|
+
name,
|
|
8915
|
+
exact = false,
|
|
8916
|
+
component,
|
|
8917
|
+
tag,
|
|
8918
|
+
layer,
|
|
8919
|
+
file_type = "all",
|
|
8920
|
+
max_matches
|
|
8921
|
+
} = options;
|
|
8922
|
+
if (max_matches !== undefined && max_matches < 1) {
|
|
8923
|
+
return {
|
|
8924
|
+
success: false,
|
|
8925
|
+
project_path,
|
|
8926
|
+
total_files_scanned: 0,
|
|
8927
|
+
total_matches: 0,
|
|
8928
|
+
cursor: 0,
|
|
8929
|
+
truncated: false,
|
|
8930
|
+
matches: [],
|
|
8931
|
+
error: "--max-matches must be a positive integer (>= 1)"
|
|
8932
|
+
};
|
|
8740
8933
|
}
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8934
|
+
if (name !== undefined && name.trim() === "") {
|
|
8935
|
+
return {
|
|
8936
|
+
success: false,
|
|
8937
|
+
project_path,
|
|
8938
|
+
total_files_scanned: 0,
|
|
8939
|
+
total_matches: 0,
|
|
8940
|
+
cursor: 0,
|
|
8941
|
+
truncated: false,
|
|
8942
|
+
matches: [],
|
|
8943
|
+
error: "Name pattern must not be empty"
|
|
8944
|
+
};
|
|
8746
8945
|
}
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8946
|
+
if (!import_fs12.existsSync(project_path)) {
|
|
8947
|
+
return {
|
|
8948
|
+
success: false,
|
|
8949
|
+
project_path,
|
|
8950
|
+
total_files_scanned: 0,
|
|
8951
|
+
total_matches: 0,
|
|
8952
|
+
cursor: 0,
|
|
8953
|
+
truncated: false,
|
|
8954
|
+
matches: [],
|
|
8955
|
+
error: `Project path not found: ${project_path}`
|
|
8956
|
+
};
|
|
8750
8957
|
}
|
|
8751
|
-
const
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8958
|
+
const ASSET_TYPE_EXTENSIONS = {
|
|
8959
|
+
mat: [".mat"],
|
|
8960
|
+
anim: [".anim"],
|
|
8961
|
+
controller: [".controller"],
|
|
8962
|
+
asset: [".asset"]
|
|
8963
|
+
};
|
|
8964
|
+
const isAssetType = file_type in ASSET_TYPE_EXTENSIONS;
|
|
8965
|
+
if (isAssetType) {
|
|
8966
|
+
const extensions2 = ASSET_TYPE_EXTENSIONS[file_type];
|
|
8967
|
+
const files2 = walk_project_files(project_path, extensions2);
|
|
8968
|
+
const matches2 = [];
|
|
8969
|
+
for (const file of files2) {
|
|
8970
|
+
const relPath = path5.relative(project_path, file);
|
|
8971
|
+
const fileName = path5.basename(file, path5.extname(file));
|
|
8972
|
+
if (name) {
|
|
8973
|
+
const nameLower = name.toLowerCase();
|
|
8974
|
+
const hasWildcard = name.includes("*") || name.includes("?");
|
|
8975
|
+
if (hasWildcard) {
|
|
8976
|
+
if (!glob_match(name, fileName))
|
|
8977
|
+
continue;
|
|
8978
|
+
} else if (exact) {
|
|
8979
|
+
if (fileName !== name)
|
|
8980
|
+
continue;
|
|
8981
|
+
} else {
|
|
8982
|
+
if (!fileName.toLowerCase().includes(nameLower))
|
|
8983
|
+
continue;
|
|
8984
|
+
}
|
|
8985
|
+
}
|
|
8986
|
+
let display_name = fileName;
|
|
8987
|
+
try {
|
|
8988
|
+
const content = import_fs12.readFileSync(file, "utf-8");
|
|
8989
|
+
const nameMatch = /^\s*m_Name:\s*(.+)$/m.exec(content.slice(0, 2000));
|
|
8990
|
+
if (nameMatch)
|
|
8991
|
+
display_name = nameMatch[1].trim();
|
|
8992
|
+
} catch {}
|
|
8993
|
+
matches2.push({
|
|
8994
|
+
file: relPath,
|
|
8995
|
+
game_object: display_name,
|
|
8996
|
+
file_id: "0"
|
|
8997
|
+
});
|
|
8998
|
+
if (max_matches !== undefined && matches2.length >= max_matches)
|
|
8999
|
+
break;
|
|
8757
9000
|
}
|
|
9001
|
+
return {
|
|
9002
|
+
success: true,
|
|
9003
|
+
project_path,
|
|
9004
|
+
total_files_scanned: files2.length,
|
|
9005
|
+
total_matches: matches2.length,
|
|
9006
|
+
cursor: 0,
|
|
9007
|
+
truncated: max_matches !== undefined && matches2.length >= max_matches,
|
|
9008
|
+
matches: matches2
|
|
9009
|
+
};
|
|
8758
9010
|
}
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
9011
|
+
if (!isNativeModuleAvailable()) {
|
|
9012
|
+
return {
|
|
9013
|
+
success: false,
|
|
9014
|
+
project_path,
|
|
9015
|
+
total_files_scanned: 0,
|
|
9016
|
+
total_matches: 0,
|
|
9017
|
+
cursor: 0,
|
|
9018
|
+
truncated: false,
|
|
9019
|
+
matches: [],
|
|
9020
|
+
error: "Native scanner module not available. Run bun install in the project root."
|
|
9021
|
+
};
|
|
9022
|
+
}
|
|
9023
|
+
const extensions = [];
|
|
9024
|
+
if (file_type === "scene" || file_type === "all")
|
|
9025
|
+
extensions.push(".unity");
|
|
9026
|
+
if (file_type === "prefab" || file_type === "all")
|
|
9027
|
+
extensions.push(".prefab");
|
|
9028
|
+
const files = walk_project_files(project_path, extensions);
|
|
9029
|
+
const scanner = new UnityScanner;
|
|
9030
|
+
const matches = [];
|
|
9031
|
+
let files_with_errors = 0;
|
|
9032
|
+
for (const file of files) {
|
|
9033
|
+
try {
|
|
9034
|
+
let gameObjects;
|
|
9035
|
+
const needComponents = !!component;
|
|
9036
|
+
const needMetadata = !!(tag || layer !== undefined);
|
|
9037
|
+
if (name && !needMetadata && !needComponents) {
|
|
9038
|
+
gameObjects = scanner.find_by_name(file, name, !exact);
|
|
9039
|
+
} else if (needComponents) {
|
|
9040
|
+
gameObjects = scanner.scan_scene_with_components(file);
|
|
9041
|
+
if (name && !is_match_all(name)) {
|
|
9042
|
+
const nameLower = name.toLowerCase();
|
|
9043
|
+
const hasWildcard = name.includes("*") || name.includes("?");
|
|
9044
|
+
gameObjects = gameObjects.filter((go) => {
|
|
9045
|
+
if (!go.name)
|
|
9046
|
+
return false;
|
|
9047
|
+
if (hasWildcard) {
|
|
9048
|
+
return glob_match(name, go.name);
|
|
9049
|
+
}
|
|
9050
|
+
if (exact) {
|
|
9051
|
+
return go.name === name;
|
|
9052
|
+
}
|
|
9053
|
+
return go.name.toLowerCase().includes(nameLower);
|
|
9054
|
+
});
|
|
9055
|
+
}
|
|
9056
|
+
} else if (needMetadata) {
|
|
9057
|
+
gameObjects = scanner.scan_scene_metadata(file);
|
|
9058
|
+
if (name && !is_match_all(name)) {
|
|
9059
|
+
const nameLower = name.toLowerCase();
|
|
9060
|
+
const hasWildcard = name.includes("*") || name.includes("?");
|
|
9061
|
+
gameObjects = gameObjects.filter((go) => {
|
|
9062
|
+
if (!go.name)
|
|
9063
|
+
return false;
|
|
9064
|
+
if (hasWildcard) {
|
|
9065
|
+
return glob_match(name, go.name);
|
|
9066
|
+
}
|
|
9067
|
+
if (exact) {
|
|
9068
|
+
return go.name === name;
|
|
9069
|
+
}
|
|
9070
|
+
return go.name.toLowerCase().includes(nameLower);
|
|
9071
|
+
});
|
|
9072
|
+
}
|
|
9073
|
+
} else {
|
|
9074
|
+
gameObjects = scanner.scan_scene_minimal(file);
|
|
9075
|
+
}
|
|
9076
|
+
for (const go of gameObjects) {
|
|
9077
|
+
const isFindResult = "resultType" in go;
|
|
9078
|
+
const isPrefab = isFindResult && go.resultType === "PrefabInstance";
|
|
9079
|
+
if (isPrefab && (component || tag || layer !== undefined)) {
|
|
9080
|
+
continue;
|
|
9081
|
+
}
|
|
9082
|
+
if (component) {
|
|
9083
|
+
if ("components" in go && go.components) {
|
|
9084
|
+
const hasComponent = go.components.some((c) => glob_match(component, c.type));
|
|
9085
|
+
if (!hasComponent)
|
|
9086
|
+
continue;
|
|
9087
|
+
} else {
|
|
9088
|
+
continue;
|
|
8776
9089
|
}
|
|
8777
9090
|
}
|
|
9091
|
+
if (tag) {
|
|
9092
|
+
if (!("tag" in go) || go.tag !== tag)
|
|
9093
|
+
continue;
|
|
9094
|
+
}
|
|
9095
|
+
if (layer !== undefined) {
|
|
9096
|
+
if (!("layer" in go) || go.layer !== layer)
|
|
9097
|
+
continue;
|
|
9098
|
+
}
|
|
9099
|
+
const relPath = path5.relative(project_path, file);
|
|
9100
|
+
const fileId = isFindResult ? go.fileId : go.file_id;
|
|
9101
|
+
const match = {
|
|
9102
|
+
file: relPath,
|
|
9103
|
+
game_object: go.name,
|
|
9104
|
+
file_id: fileId,
|
|
9105
|
+
tag: "tag" in go ? go.tag : undefined,
|
|
9106
|
+
layer: "layer" in go ? go.layer : undefined
|
|
9107
|
+
};
|
|
9108
|
+
if ("components" in go && go.components) {
|
|
9109
|
+
match.components = go.components.map((c) => c.type);
|
|
9110
|
+
}
|
|
9111
|
+
matches.push(match);
|
|
9112
|
+
if (max_matches !== undefined && matches.length >= max_matches)
|
|
9113
|
+
break;
|
|
8778
9114
|
}
|
|
9115
|
+
if (max_matches !== undefined && matches.length >= max_matches)
|
|
9116
|
+
break;
|
|
9117
|
+
} catch {
|
|
9118
|
+
files_with_errors++;
|
|
9119
|
+
continue;
|
|
8779
9120
|
}
|
|
8780
9121
|
}
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
|
|
8790
|
-
|
|
8791
|
-
|
|
8792
|
-
|
|
8793
|
-
|
|
8794
|
-
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
9122
|
+
return {
|
|
9123
|
+
success: true,
|
|
9124
|
+
project_path,
|
|
9125
|
+
total_files_scanned: files.length,
|
|
9126
|
+
total_matches: matches.length,
|
|
9127
|
+
files_with_errors: files_with_errors > 0 ? files_with_errors : undefined,
|
|
9128
|
+
cursor: 0,
|
|
9129
|
+
truncated: max_matches !== undefined && matches.length >= max_matches,
|
|
9130
|
+
matches
|
|
9131
|
+
};
|
|
9132
|
+
}
|
|
9133
|
+
function grep_project(options) {
|
|
9134
|
+
const nativeGrep = getNativeGrepProject();
|
|
9135
|
+
if (nativeGrep) {
|
|
9136
|
+
try {
|
|
9137
|
+
const nativeResult = nativeGrep({
|
|
9138
|
+
projectPath: options.project_path,
|
|
9139
|
+
pattern: options.pattern,
|
|
9140
|
+
fileType: options.file_type,
|
|
9141
|
+
maxResults: options.max_results,
|
|
9142
|
+
contextLines: options.context_lines
|
|
9143
|
+
});
|
|
9144
|
+
return {
|
|
9145
|
+
success: nativeResult.success,
|
|
9146
|
+
project_path: nativeResult.projectPath,
|
|
9147
|
+
pattern: nativeResult.pattern,
|
|
9148
|
+
total_files_scanned: nativeResult.totalFilesScanned,
|
|
9149
|
+
total_matches: nativeResult.totalMatches,
|
|
9150
|
+
truncated: nativeResult.truncated,
|
|
9151
|
+
error: nativeResult.error,
|
|
9152
|
+
matches: nativeResult.matches.map((m) => ({
|
|
9153
|
+
file: m.file,
|
|
9154
|
+
line_number: m.lineNumber,
|
|
9155
|
+
line: m.line,
|
|
9156
|
+
context_before: m.contextBefore,
|
|
9157
|
+
context_after: m.contextAfter
|
|
9158
|
+
}))
|
|
9159
|
+
};
|
|
9160
|
+
} catch {}
|
|
8799
9161
|
}
|
|
8800
|
-
|
|
8801
|
-
|
|
9162
|
+
return grep_project_js(options);
|
|
9163
|
+
}
|
|
9164
|
+
function grep_project_js(options) {
|
|
9165
|
+
const {
|
|
9166
|
+
project_path,
|
|
9167
|
+
pattern,
|
|
9168
|
+
file_type = "all",
|
|
9169
|
+
max_results = 100,
|
|
9170
|
+
context_lines = 0
|
|
9171
|
+
} = options;
|
|
9172
|
+
if (!import_fs12.existsSync(project_path)) {
|
|
9173
|
+
return {
|
|
9174
|
+
success: false,
|
|
9175
|
+
project_path,
|
|
9176
|
+
pattern,
|
|
9177
|
+
total_files_scanned: 0,
|
|
9178
|
+
total_matches: 0,
|
|
9179
|
+
truncated: false,
|
|
9180
|
+
matches: [],
|
|
9181
|
+
error: `Project path not found: ${project_path}`
|
|
9182
|
+
};
|
|
8802
9183
|
}
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
9184
|
+
let regex;
|
|
9185
|
+
try {
|
|
9186
|
+
regex = new RegExp(pattern, "i");
|
|
9187
|
+
} catch (err) {
|
|
9188
|
+
return {
|
|
9189
|
+
success: false,
|
|
9190
|
+
project_path,
|
|
9191
|
+
pattern,
|
|
9192
|
+
total_files_scanned: 0,
|
|
9193
|
+
total_matches: 0,
|
|
9194
|
+
truncated: false,
|
|
9195
|
+
matches: [],
|
|
9196
|
+
error: `Invalid regex pattern: ${err instanceof Error ? err.message : String(err)}`
|
|
9197
|
+
};
|
|
8806
9198
|
}
|
|
8807
|
-
const
|
|
8808
|
-
|
|
8809
|
-
|
|
9199
|
+
const EXTENSION_MAP = {
|
|
9200
|
+
cs: [".cs"],
|
|
9201
|
+
yaml: [
|
|
9202
|
+
".yaml",
|
|
9203
|
+
".yml",
|
|
9204
|
+
".unity",
|
|
9205
|
+
".prefab",
|
|
9206
|
+
".asset",
|
|
9207
|
+
".mat",
|
|
9208
|
+
".anim",
|
|
9209
|
+
".controller",
|
|
9210
|
+
".overrideController",
|
|
9211
|
+
".mask",
|
|
9212
|
+
".mixer",
|
|
9213
|
+
".lighting",
|
|
9214
|
+
".preset",
|
|
9215
|
+
".signal",
|
|
9216
|
+
".playable",
|
|
9217
|
+
".renderTexture",
|
|
9218
|
+
".flare",
|
|
9219
|
+
".guiskin",
|
|
9220
|
+
".terrainlayer",
|
|
9221
|
+
".cubemap"
|
|
9222
|
+
],
|
|
9223
|
+
unity: [".unity"],
|
|
9224
|
+
prefab: [".prefab"],
|
|
9225
|
+
asset: [".asset"],
|
|
9226
|
+
mat: [".mat"],
|
|
9227
|
+
anim: [".anim"],
|
|
9228
|
+
controller: [".controller"],
|
|
9229
|
+
all: [
|
|
9230
|
+
".cs",
|
|
9231
|
+
".unity",
|
|
9232
|
+
".prefab",
|
|
9233
|
+
".asset",
|
|
9234
|
+
".mat",
|
|
9235
|
+
".anim",
|
|
9236
|
+
".controller",
|
|
9237
|
+
".yaml",
|
|
9238
|
+
".yml",
|
|
9239
|
+
".txt",
|
|
9240
|
+
".json",
|
|
9241
|
+
".xml",
|
|
9242
|
+
".shader",
|
|
9243
|
+
".cginc",
|
|
9244
|
+
".hlsl",
|
|
9245
|
+
".compute",
|
|
9246
|
+
".asmdef",
|
|
9247
|
+
".asmref"
|
|
9248
|
+
]
|
|
9249
|
+
};
|
|
9250
|
+
const extensions = EXTENSION_MAP[file_type] || EXTENSION_MAP.all;
|
|
9251
|
+
const files = walk_project_files(project_path, extensions);
|
|
9252
|
+
const matches = [];
|
|
9253
|
+
let totalFilesScanned = 0;
|
|
9254
|
+
let truncated = false;
|
|
9255
|
+
for (const file of files) {
|
|
9256
|
+
const ext = path5.extname(file).toLowerCase();
|
|
9257
|
+
if (BINARY_EXTENSIONS.has(ext))
|
|
9258
|
+
continue;
|
|
9259
|
+
totalFilesScanned++;
|
|
9260
|
+
let content;
|
|
9261
|
+
try {
|
|
9262
|
+
content = import_fs12.readFileSync(file, "utf-8");
|
|
9263
|
+
} catch {
|
|
9264
|
+
continue;
|
|
9265
|
+
}
|
|
9266
|
+
const lines = content.split(`
|
|
9267
|
+
`);
|
|
9268
|
+
const relPath = path5.relative(project_path, file);
|
|
9269
|
+
for (let i = 0;i < lines.length; i++) {
|
|
9270
|
+
if (regex.test(lines[i])) {
|
|
9271
|
+
let line = lines[i];
|
|
9272
|
+
if (line.length > 200) {
|
|
9273
|
+
line = line.substring(0, 200) + "...";
|
|
9274
|
+
}
|
|
9275
|
+
const match = {
|
|
9276
|
+
file: relPath,
|
|
9277
|
+
line_number: i + 1,
|
|
9278
|
+
line
|
|
9279
|
+
};
|
|
9280
|
+
if (context_lines > 0) {
|
|
9281
|
+
match.context_before = [];
|
|
9282
|
+
match.context_after = [];
|
|
9283
|
+
for (let j = Math.max(0, i - context_lines);j < i; j++) {
|
|
9284
|
+
let ctxLine = lines[j];
|
|
9285
|
+
if (ctxLine.length > 200)
|
|
9286
|
+
ctxLine = ctxLine.substring(0, 200) + "...";
|
|
9287
|
+
match.context_before.push(ctxLine);
|
|
9288
|
+
}
|
|
9289
|
+
for (let j = i + 1;j <= Math.min(lines.length - 1, i + context_lines); j++) {
|
|
9290
|
+
let ctxLine = lines[j];
|
|
9291
|
+
if (ctxLine.length > 200)
|
|
9292
|
+
ctxLine = ctxLine.substring(0, 200) + "...";
|
|
9293
|
+
match.context_after.push(ctxLine);
|
|
9294
|
+
}
|
|
9295
|
+
}
|
|
9296
|
+
matches.push(match);
|
|
9297
|
+
if (matches.length >= max_results) {
|
|
9298
|
+
truncated = true;
|
|
9299
|
+
break;
|
|
9300
|
+
}
|
|
9301
|
+
}
|
|
9302
|
+
}
|
|
9303
|
+
if (truncated)
|
|
9304
|
+
break;
|
|
8810
9305
|
}
|
|
8811
9306
|
return {
|
|
8812
9307
|
success: true,
|
|
8813
|
-
|
|
8814
|
-
|
|
9308
|
+
project_path,
|
|
9309
|
+
pattern,
|
|
9310
|
+
total_files_scanned: totalFilesScanned,
|
|
9311
|
+
total_matches: matches.length,
|
|
9312
|
+
truncated,
|
|
9313
|
+
matches
|
|
8815
9314
|
};
|
|
8816
9315
|
}
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
9316
|
+
|
|
9317
|
+
// src/editor/delete.ts
|
|
9318
|
+
function find_component_by_type(doc, type_name, game_object, project_path) {
|
|
9319
|
+
let scope_blocks;
|
|
9320
|
+
if (game_object) {
|
|
9321
|
+
const goResult = doc.require_unique_game_object(game_object);
|
|
9322
|
+
if ("error" in goResult)
|
|
9323
|
+
return goResult;
|
|
9324
|
+
const comp_ids = [];
|
|
9325
|
+
const matches = goResult.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g);
|
|
9326
|
+
for (const m of matches)
|
|
9327
|
+
comp_ids.push(m[1]);
|
|
9328
|
+
scope_blocks = comp_ids.map((id) => doc.find_by_file_id(id)).filter((b) => b !== null);
|
|
9329
|
+
} else {
|
|
9330
|
+
scope_blocks = doc.blocks.filter((b) => b.class_id !== 1 && b.class_id !== 4 && b.class_id !== 224);
|
|
9331
|
+
}
|
|
9332
|
+
const candidates = [];
|
|
9333
|
+
const class_id = get_class_id(type_name);
|
|
9334
|
+
if (class_id !== null) {
|
|
9335
|
+
for (const block of scope_blocks) {
|
|
9336
|
+
if (block.class_id === class_id)
|
|
9337
|
+
candidates.push(block);
|
|
9338
|
+
}
|
|
9339
|
+
} else {
|
|
9340
|
+
let resolved = null;
|
|
9341
|
+
try {
|
|
9342
|
+
resolved = resolveScriptGuid(type_name, project_path);
|
|
9343
|
+
} catch {}
|
|
9344
|
+
if (resolved) {
|
|
9345
|
+
for (const block of scope_blocks) {
|
|
9346
|
+
if (block.class_id !== 114)
|
|
9347
|
+
continue;
|
|
9348
|
+
const scriptMatch = block.raw.match(/m_Script:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]+)/);
|
|
9349
|
+
if (scriptMatch && scriptMatch[1] === resolved.guid) {
|
|
9350
|
+
candidates.push(block);
|
|
9351
|
+
}
|
|
9352
|
+
}
|
|
9353
|
+
} else {
|
|
9354
|
+
return { error: `Component type "${type_name}" not found. For MonoBehaviour scripts, ensure "unity-agentic-tools setup" has been run.` };
|
|
8828
9355
|
}
|
|
8829
9356
|
}
|
|
8830
|
-
|
|
9357
|
+
if (candidates.length === 0) {
|
|
9358
|
+
return { error: `No "${type_name}" component found${game_object ? ` on "${game_object}"` : ""} in ${doc.file_path}` };
|
|
9359
|
+
}
|
|
9360
|
+
if (candidates.length > 1) {
|
|
9361
|
+
const ids = candidates.map((b) => b.file_id).join(", ");
|
|
9362
|
+
return { error: `Multiple "${type_name}" components found (fileIDs: ${ids}). Use a numeric fileID to specify which one${game_object ? "" : ", or use --on <gameobject> to scope the search"}.` };
|
|
9363
|
+
}
|
|
9364
|
+
return candidates[0];
|
|
8831
9365
|
}
|
|
8832
|
-
function
|
|
8833
|
-
const { file_path,
|
|
9366
|
+
function removeComponent(options) {
|
|
9367
|
+
const { file_path, file_id, game_object, project_path } = options;
|
|
9368
|
+
const pathError = validate_file_path(file_path, "write");
|
|
9369
|
+
if (pathError) {
|
|
9370
|
+
return { success: false, file_path, error: pathError };
|
|
9371
|
+
}
|
|
8834
9372
|
if (!import_fs13.existsSync(file_path)) {
|
|
8835
9373
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
8836
9374
|
}
|
|
@@ -8840,24 +9378,306 @@ function duplicateGameObject(options) {
|
|
|
8840
9378
|
} catch (err) {
|
|
8841
9379
|
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
8842
9380
|
}
|
|
8843
|
-
|
|
8844
|
-
if (
|
|
8845
|
-
|
|
8846
|
-
if (
|
|
8847
|
-
return { success: false, file_path, error: `
|
|
9381
|
+
let found;
|
|
9382
|
+
if (/^-?\d+$/.test(file_id)) {
|
|
9383
|
+
found = doc.find_by_file_id(file_id);
|
|
9384
|
+
if (!found) {
|
|
9385
|
+
return { success: false, file_path, error: `Component with file ID ${file_id} not found` };
|
|
8848
9386
|
}
|
|
8849
|
-
|
|
9387
|
+
} else {
|
|
9388
|
+
const result = find_component_by_type(doc, file_id, game_object, project_path);
|
|
9389
|
+
if ("error" in result) {
|
|
9390
|
+
return { success: false, file_path, error: result.error };
|
|
9391
|
+
}
|
|
9392
|
+
found = result;
|
|
8850
9393
|
}
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
const componentIds = [];
|
|
8854
|
-
const compMatches = goBlock.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
|
|
8855
|
-
for (const cm of compMatches) {
|
|
8856
|
-
componentIds.push(cm[1]);
|
|
9394
|
+
if (found.class_id === 1) {
|
|
9395
|
+
return { success: false, file_path, error: "Cannot remove a GameObject with remove-component. Use delete instead." };
|
|
8857
9396
|
}
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
9397
|
+
if (found.class_id === 4) {
|
|
9398
|
+
return { success: false, file_path, error: "Cannot remove a Transform with remove-component. Use delete to remove the entire GameObject." };
|
|
9399
|
+
}
|
|
9400
|
+
const resolved_file_id = found.file_id;
|
|
9401
|
+
const goMatch = found.raw.match(/m_GameObject:[ \t]*\{fileID:[ \t]*(-?\d+)\}/);
|
|
9402
|
+
if (goMatch) {
|
|
9403
|
+
const parentGoId = goMatch[1];
|
|
9404
|
+
const goBlock = doc.find_by_file_id(parentGoId);
|
|
9405
|
+
if (goBlock) {
|
|
9406
|
+
const escaped = resolved_file_id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9407
|
+
const compLinePattern = new RegExp(`^[ \\t]*- component: \\{fileID: ${escaped}\\}[ \\t]*\\n`, "m");
|
|
9408
|
+
const modifiedRaw = goBlock.raw.replace(compLinePattern, "");
|
|
9409
|
+
if (modifiedRaw === goBlock.raw) {}
|
|
9410
|
+
goBlock.replace_raw(modifiedRaw);
|
|
9411
|
+
}
|
|
9412
|
+
}
|
|
9413
|
+
const dangling = [];
|
|
9414
|
+
for (const block of doc.blocks) {
|
|
9415
|
+
if (block.file_id === resolved_file_id)
|
|
9416
|
+
continue;
|
|
9417
|
+
if (block.raw.includes(`{fileID: ${resolved_file_id}}`)) {
|
|
9418
|
+
dangling.push(block.file_id);
|
|
9419
|
+
}
|
|
9420
|
+
}
|
|
9421
|
+
doc.remove_block(resolved_file_id);
|
|
9422
|
+
if (!doc.validate()) {
|
|
9423
|
+
return { success: false, file_path, error: "Validation failed after removing component" };
|
|
9424
|
+
}
|
|
9425
|
+
const writeResult = doc.save();
|
|
9426
|
+
if (!writeResult.success) {
|
|
9427
|
+
return { success: false, file_path, error: writeResult.error };
|
|
9428
|
+
}
|
|
9429
|
+
return {
|
|
9430
|
+
success: true,
|
|
9431
|
+
file_path,
|
|
9432
|
+
removed_file_id: resolved_file_id,
|
|
9433
|
+
removed_class_id: found.class_id,
|
|
9434
|
+
warning: dangling.length > 0 ? `Dangling references to deleted component found in blocks: ${dangling.join(", ")}` : undefined
|
|
9435
|
+
};
|
|
9436
|
+
}
|
|
9437
|
+
function removeComponentBatch(options) {
|
|
9438
|
+
const { project_path, component_type, game_object } = options;
|
|
9439
|
+
const files = walk_project_files(project_path, [".unity", ".prefab"]);
|
|
9440
|
+
const removals = [];
|
|
9441
|
+
const errors = [];
|
|
9442
|
+
let skipped = 0;
|
|
9443
|
+
for (const file of files) {
|
|
9444
|
+
const result = removeComponent({
|
|
9445
|
+
file_path: file,
|
|
9446
|
+
file_id: component_type,
|
|
9447
|
+
game_object,
|
|
9448
|
+
project_path
|
|
9449
|
+
});
|
|
9450
|
+
if (result.success && result.removed_file_id) {
|
|
9451
|
+
removals.push({
|
|
9452
|
+
file,
|
|
9453
|
+
file_id: result.removed_file_id,
|
|
9454
|
+
class_id: result.removed_class_id ?? 0
|
|
9455
|
+
});
|
|
9456
|
+
} else if (result.error?.includes("not found") || result.error?.startsWith('No "')) {
|
|
9457
|
+
skipped++;
|
|
9458
|
+
} else if (result.error) {
|
|
9459
|
+
errors.push({ file, error: result.error });
|
|
9460
|
+
}
|
|
9461
|
+
}
|
|
9462
|
+
return {
|
|
9463
|
+
success: errors.length === 0,
|
|
9464
|
+
project_path,
|
|
9465
|
+
component: component_type,
|
|
9466
|
+
files_scanned: files.length,
|
|
9467
|
+
files_modified: removals.length,
|
|
9468
|
+
removals,
|
|
9469
|
+
skipped,
|
|
9470
|
+
errors
|
|
9471
|
+
};
|
|
9472
|
+
}
|
|
9473
|
+
function deleteGameObject(options) {
|
|
9474
|
+
const { file_path, object_name } = options;
|
|
9475
|
+
const pathError = validate_file_path(file_path, "write");
|
|
9476
|
+
if (pathError) {
|
|
9477
|
+
return { success: false, file_path, error: pathError };
|
|
9478
|
+
}
|
|
9479
|
+
if (!import_fs13.existsSync(file_path)) {
|
|
9480
|
+
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
9481
|
+
}
|
|
9482
|
+
let doc;
|
|
9483
|
+
try {
|
|
9484
|
+
doc = UnityDocument.from_file(file_path);
|
|
9485
|
+
} catch (err) {
|
|
9486
|
+
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
9487
|
+
}
|
|
9488
|
+
const goResult = doc.require_unique_game_object(object_name);
|
|
9489
|
+
if ("error" in goResult) {
|
|
9490
|
+
return { success: false, file_path, error: goResult.error };
|
|
9491
|
+
}
|
|
9492
|
+
const goBlock = goResult;
|
|
9493
|
+
const goId = goBlock.file_id;
|
|
9494
|
+
const componentIds = new Set;
|
|
9495
|
+
const compMatches = goBlock.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g);
|
|
9496
|
+
for (const cm of compMatches) {
|
|
9497
|
+
componentIds.add(cm[1]);
|
|
9498
|
+
}
|
|
9499
|
+
let transformId = null;
|
|
9500
|
+
let fatherId = "0";
|
|
9501
|
+
for (const compId of componentIds) {
|
|
9502
|
+
const block = doc.find_by_file_id(compId);
|
|
9503
|
+
if (block && block.class_id === 4) {
|
|
9504
|
+
transformId = compId;
|
|
9505
|
+
const fatherMatch = block.raw.match(/m_Father:[ \t]*\{fileID:[ \t]*(-?\d+)\}/);
|
|
9506
|
+
if (fatherMatch) {
|
|
9507
|
+
fatherId = fatherMatch[1];
|
|
9508
|
+
}
|
|
9509
|
+
break;
|
|
9510
|
+
}
|
|
9511
|
+
}
|
|
9512
|
+
const allIds = new Set([goId]);
|
|
9513
|
+
for (const id of componentIds) {
|
|
9514
|
+
allIds.add(id);
|
|
9515
|
+
}
|
|
9516
|
+
if (transformId !== null) {
|
|
9517
|
+
const descendants = doc.collect_hierarchy(transformId);
|
|
9518
|
+
for (const id of descendants) {
|
|
9519
|
+
allIds.add(id);
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9522
|
+
if (fatherId !== "0" && transformId !== null) {
|
|
9523
|
+
doc.remove_child_from_parent(fatherId, transformId);
|
|
9524
|
+
}
|
|
9525
|
+
doc.remove_blocks(allIds);
|
|
9526
|
+
if (!doc.validate()) {
|
|
9527
|
+
return { success: false, file_path, error: "Validation failed after deleting GameObject" };
|
|
9528
|
+
}
|
|
9529
|
+
const writeResult = doc.save();
|
|
9530
|
+
if (!writeResult.success) {
|
|
9531
|
+
return { success: false, file_path, error: writeResult.error };
|
|
9532
|
+
}
|
|
9533
|
+
return {
|
|
9534
|
+
success: true,
|
|
9535
|
+
file_path,
|
|
9536
|
+
deleted_count: allIds.size
|
|
9537
|
+
};
|
|
9538
|
+
}
|
|
9539
|
+
function findPrefabInstanceBlock2(doc, identifier) {
|
|
9540
|
+
const asId = doc.find_by_file_id(identifier);
|
|
9541
|
+
if (asId && asId.class_id === 1001)
|
|
9542
|
+
return asId;
|
|
9543
|
+
const piBlocks = doc.find_by_class_id(1001);
|
|
9544
|
+
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9545
|
+
const namePattern = new RegExp(`propertyPath:\\s*m_Name\\s+value:\\s*${escaped}\\s`);
|
|
9546
|
+
for (const block of piBlocks) {
|
|
9547
|
+
if (namePattern.test(block.raw))
|
|
9548
|
+
return block;
|
|
9549
|
+
}
|
|
9550
|
+
return null;
|
|
9551
|
+
}
|
|
9552
|
+
function deletePrefabInstance(options) {
|
|
9553
|
+
const { file_path, prefab_instance } = options;
|
|
9554
|
+
const pathError = validate_file_path(file_path, "write");
|
|
9555
|
+
if (pathError) {
|
|
9556
|
+
return { success: false, file_path, error: pathError };
|
|
9557
|
+
}
|
|
9558
|
+
if (!import_fs13.existsSync(file_path)) {
|
|
9559
|
+
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
9560
|
+
}
|
|
9561
|
+
let doc;
|
|
9562
|
+
try {
|
|
9563
|
+
doc = UnityDocument.from_file(file_path);
|
|
9564
|
+
} catch (err) {
|
|
9565
|
+
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
9566
|
+
}
|
|
9567
|
+
const piBlock = findPrefabInstanceBlock2(doc, prefab_instance);
|
|
9568
|
+
if (!piBlock) {
|
|
9569
|
+
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
9570
|
+
}
|
|
9571
|
+
const piId = piBlock.file_id;
|
|
9572
|
+
const allToRemove = new Set([piId]);
|
|
9573
|
+
const piRefPattern = new RegExp(`m_PrefabInstance:[ \\t]*\\{fileID:[ \\t]*${piId}\\}`);
|
|
9574
|
+
for (const block of doc.blocks) {
|
|
9575
|
+
if (block.is_stripped && piRefPattern.test(block.raw)) {
|
|
9576
|
+
allToRemove.add(block.file_id);
|
|
9577
|
+
}
|
|
9578
|
+
}
|
|
9579
|
+
const addedGOPattern = /m_AddedGameObjects:\s*\n((?:\s*- \{fileID: \d+\}\n)*)/m;
|
|
9580
|
+
const addedGOMatch = piBlock.raw.match(addedGOPattern);
|
|
9581
|
+
if (addedGOMatch) {
|
|
9582
|
+
const addedGOSection = addedGOMatch[1];
|
|
9583
|
+
const goMatches = addedGOSection.matchAll(/fileID:[ \t]*(\d+)/g);
|
|
9584
|
+
for (const match of goMatches) {
|
|
9585
|
+
const goId = match[1];
|
|
9586
|
+
allToRemove.add(goId);
|
|
9587
|
+
const goBlock = doc.find_by_file_id(goId);
|
|
9588
|
+
if (goBlock) {
|
|
9589
|
+
const compMatch = goBlock.raw.match(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
9590
|
+
if (compMatch) {
|
|
9591
|
+
const transformId = compMatch[1];
|
|
9592
|
+
allToRemove.add(transformId);
|
|
9593
|
+
const descendants = doc.collect_hierarchy(transformId);
|
|
9594
|
+
for (const id of descendants) {
|
|
9595
|
+
allToRemove.add(id);
|
|
9596
|
+
}
|
|
9597
|
+
}
|
|
9598
|
+
}
|
|
9599
|
+
}
|
|
9600
|
+
}
|
|
9601
|
+
const addedCompPattern = /m_AddedComponents:\s*\n((?:\s*- \{fileID: \d+\}\n)*)/m;
|
|
9602
|
+
const addedCompMatch = piBlock.raw.match(addedCompPattern);
|
|
9603
|
+
if (addedCompMatch) {
|
|
9604
|
+
const addedCompSection = addedCompMatch[1];
|
|
9605
|
+
const compMatches = addedCompSection.matchAll(/fileID:[ \t]*(\d+)/g);
|
|
9606
|
+
for (const match of compMatches) {
|
|
9607
|
+
allToRemove.add(match[1]);
|
|
9608
|
+
}
|
|
9609
|
+
}
|
|
9610
|
+
const parentMatch = piBlock.raw.match(/m_TransformParent:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
9611
|
+
const parentTransformId = parentMatch ? parentMatch[1] : "0";
|
|
9612
|
+
let strippedRootTransformId = null;
|
|
9613
|
+
for (const id of allToRemove) {
|
|
9614
|
+
const block = doc.find_by_file_id(id);
|
|
9615
|
+
if (block && block.class_id === 4 && block.is_stripped) {
|
|
9616
|
+
strippedRootTransformId = id;
|
|
9617
|
+
break;
|
|
9618
|
+
}
|
|
9619
|
+
}
|
|
9620
|
+
if (parentTransformId !== "0" && strippedRootTransformId !== null) {
|
|
9621
|
+
doc.remove_child_from_parent(parentTransformId, strippedRootTransformId);
|
|
9622
|
+
}
|
|
9623
|
+
doc.remove_blocks(allToRemove);
|
|
9624
|
+
if (!doc.validate()) {
|
|
9625
|
+
return { success: false, file_path, error: "Validation failed after deleting PrefabInstance" };
|
|
9626
|
+
}
|
|
9627
|
+
const writeResult = doc.save();
|
|
9628
|
+
if (!writeResult.success) {
|
|
9629
|
+
return { success: false, file_path, error: writeResult.error };
|
|
9630
|
+
}
|
|
9631
|
+
return {
|
|
9632
|
+
success: true,
|
|
9633
|
+
file_path,
|
|
9634
|
+
deleted_count: allToRemove.size
|
|
9635
|
+
};
|
|
9636
|
+
}
|
|
9637
|
+
// src/editor/duplicate.ts
|
|
9638
|
+
var import_fs14 = require("fs");
|
|
9639
|
+
var path6 = __toESM(require("path"));
|
|
9640
|
+
init_scanner();
|
|
9641
|
+
function findPrefabInstanceByName(doc, name) {
|
|
9642
|
+
const piBlocks = doc.find_by_class_id(1001);
|
|
9643
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9644
|
+
const namePattern = new RegExp(`propertyPath:\\s*m_Name\\s+value:\\s*${escapedName}\\s`);
|
|
9645
|
+
for (const block of piBlocks) {
|
|
9646
|
+
if (namePattern.test(block.raw)) {
|
|
9647
|
+
return { id: parseInt(block.file_id, 10) };
|
|
9648
|
+
}
|
|
9649
|
+
}
|
|
9650
|
+
return null;
|
|
9651
|
+
}
|
|
9652
|
+
function duplicateGameObject(options) {
|
|
9653
|
+
const { file_path, object_name, new_name } = options;
|
|
9654
|
+
if (!import_fs14.existsSync(file_path)) {
|
|
9655
|
+
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
9656
|
+
}
|
|
9657
|
+
let doc;
|
|
9658
|
+
try {
|
|
9659
|
+
doc = UnityDocument.from_file(file_path);
|
|
9660
|
+
} catch (err) {
|
|
9661
|
+
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
9662
|
+
}
|
|
9663
|
+
const goResult = doc.require_unique_game_object(object_name);
|
|
9664
|
+
if ("error" in goResult) {
|
|
9665
|
+
const piMatch = findPrefabInstanceByName(doc, object_name);
|
|
9666
|
+
if (piMatch) {
|
|
9667
|
+
return { success: false, file_path, error: `"${object_name}" is a PrefabInstance (fileID: ${piMatch.id}). Cloning PrefabInstances is not yet supported. Consider unpacking it first with \`update prefab\`.` };
|
|
9668
|
+
}
|
|
9669
|
+
return { success: false, file_path, error: goResult.error };
|
|
9670
|
+
}
|
|
9671
|
+
const goBlock = goResult;
|
|
9672
|
+
const goFileId = goBlock.file_id;
|
|
9673
|
+
const componentIds = [];
|
|
9674
|
+
const compMatches = goBlock.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
|
|
9675
|
+
for (const cm of compMatches) {
|
|
9676
|
+
componentIds.push(cm[1]);
|
|
9677
|
+
}
|
|
9678
|
+
let transformId = null;
|
|
9679
|
+
let fatherId = "0";
|
|
9680
|
+
for (const compId of componentIds) {
|
|
8861
9681
|
const compBlock = doc.find_by_file_id(compId);
|
|
8862
9682
|
if (compBlock && compBlock.class_id === 4) {
|
|
8863
9683
|
transformId = compId;
|
|
@@ -8964,7 +9784,7 @@ function duplicateGameObject(options) {
|
|
|
8964
9784
|
}
|
|
8965
9785
|
function unpackPrefab(options) {
|
|
8966
9786
|
const { file_path, prefab_instance, project_path } = options;
|
|
8967
|
-
if (!
|
|
9787
|
+
if (!import_fs14.existsSync(file_path)) {
|
|
8968
9788
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
8969
9789
|
}
|
|
8970
9790
|
let sceneDoc;
|
|
@@ -9010,25 +9830,25 @@ function unpackPrefab(options) {
|
|
|
9010
9830
|
sourcePrefabPath = resolvedPath;
|
|
9011
9831
|
}
|
|
9012
9832
|
}
|
|
9013
|
-
if (!sourcePrefabPath || !
|
|
9014
|
-
const inferredProject = project_path || find_unity_project_root(
|
|
9833
|
+
if (!sourcePrefabPath || !import_fs14.existsSync(sourcePrefabPath)) {
|
|
9834
|
+
const inferredProject = project_path || find_unity_project_root(path6.dirname(file_path));
|
|
9015
9835
|
if (inferredProject) {
|
|
9016
9836
|
const nativeBuild = getNativeBuildGuidCache();
|
|
9017
9837
|
if (nativeBuild) {
|
|
9018
9838
|
try {
|
|
9019
9839
|
const freshCache = nativeBuild(inferredProject);
|
|
9020
9840
|
if (freshCache[sourcePrefabGuid]) {
|
|
9021
|
-
sourcePrefabPath =
|
|
9841
|
+
sourcePrefabPath = path6.join(inferredProject, freshCache[sourcePrefabGuid]);
|
|
9022
9842
|
}
|
|
9023
9843
|
} catch {}
|
|
9024
9844
|
}
|
|
9025
9845
|
}
|
|
9026
9846
|
}
|
|
9027
|
-
if (!sourcePrefabPath || !
|
|
9847
|
+
if (!sourcePrefabPath || !import_fs14.existsSync(sourcePrefabPath)) {
|
|
9028
9848
|
const searchedPaths = [];
|
|
9029
9849
|
if (project_path)
|
|
9030
|
-
searchedPaths.push(`GUID cache: ${
|
|
9031
|
-
const inferredProject = project_path || find_unity_project_root(
|
|
9850
|
+
searchedPaths.push(`GUID cache: ${path6.join(project_path, ".unity-agentic", "guid-cache.json")}`);
|
|
9851
|
+
const inferredProject = project_path || find_unity_project_root(path6.dirname(file_path));
|
|
9032
9852
|
if (inferredProject)
|
|
9033
9853
|
searchedPaths.push(`Native GUID rebuild from: ${inferredProject}`);
|
|
9034
9854
|
const searchInfo = searchedPaths.length > 0 ? ` Searched: ${searchedPaths.join("; ")}` : "";
|
|
@@ -9156,11 +9976,11 @@ function unpackPrefab(options) {
|
|
|
9156
9976
|
}
|
|
9157
9977
|
// src/build-editor.ts
|
|
9158
9978
|
var fs3 = __toESM(require("fs"));
|
|
9159
|
-
var
|
|
9979
|
+
var path8 = __toESM(require("path"));
|
|
9160
9980
|
|
|
9161
9981
|
// src/build-settings.ts
|
|
9162
9982
|
var fs2 = __toESM(require("fs"));
|
|
9163
|
-
var
|
|
9983
|
+
var path7 = __toESM(require("path"));
|
|
9164
9984
|
function parse_editor_build_settings(filePath) {
|
|
9165
9985
|
if (!fs2.existsSync(filePath)) {
|
|
9166
9986
|
throw new Error(`EditorBuildSettings.asset not found: ${filePath}`);
|
|
@@ -9191,7 +10011,7 @@ function parse_build_profile(filePath) {
|
|
|
9191
10011
|
throw new Error(`Build profile not found: ${filePath}`);
|
|
9192
10012
|
}
|
|
9193
10013
|
const content = fs2.readFileSync(filePath, "utf-8");
|
|
9194
|
-
const name =
|
|
10014
|
+
const name = path7.basename(filePath, ".asset");
|
|
9195
10015
|
const profile = {
|
|
9196
10016
|
name,
|
|
9197
10017
|
path: filePath
|
|
@@ -9244,7 +10064,7 @@ function get_platform_name(buildTarget) {
|
|
|
9244
10064
|
return platforms[buildTarget] || `Unknown(${buildTarget})`;
|
|
9245
10065
|
}
|
|
9246
10066
|
function list_build_profiles(projectPath) {
|
|
9247
|
-
const profilesPath =
|
|
10067
|
+
const profilesPath = path7.join(projectPath, "Assets", "Settings", "Build Profiles");
|
|
9248
10068
|
if (!fs2.existsSync(profilesPath)) {
|
|
9249
10069
|
return [];
|
|
9250
10070
|
}
|
|
@@ -9252,7 +10072,7 @@ function list_build_profiles(projectPath) {
|
|
|
9252
10072
|
const files = fs2.readdirSync(profilesPath);
|
|
9253
10073
|
for (const file of files) {
|
|
9254
10074
|
if (file.endsWith(".asset")) {
|
|
9255
|
-
const filePath =
|
|
10075
|
+
const filePath = path7.join(profilesPath, file);
|
|
9256
10076
|
try {
|
|
9257
10077
|
profiles.push(parse_build_profile(filePath));
|
|
9258
10078
|
} catch (e) {}
|
|
@@ -9262,7 +10082,7 @@ function list_build_profiles(projectPath) {
|
|
|
9262
10082
|
}
|
|
9263
10083
|
function get_build_settings(projectPath) {
|
|
9264
10084
|
const projectInfo = get_project_info(projectPath);
|
|
9265
|
-
const editorBuildSettingsPath =
|
|
10085
|
+
const editorBuildSettingsPath = path7.join(projectPath, "ProjectSettings", "EditorBuildSettings.asset");
|
|
9266
10086
|
const editorBuildSettings = parse_editor_build_settings(editorBuildSettingsPath);
|
|
9267
10087
|
const buildProfiles = list_build_profiles(projectPath);
|
|
9268
10088
|
return {
|
|
@@ -9274,11 +10094,11 @@ function get_build_settings(projectPath) {
|
|
|
9274
10094
|
|
|
9275
10095
|
// src/build-editor.ts
|
|
9276
10096
|
function get_build_settings_path(projectPath) {
|
|
9277
|
-
return
|
|
10097
|
+
return path8.join(projectPath, "ProjectSettings", "EditorBuildSettings.asset");
|
|
9278
10098
|
}
|
|
9279
10099
|
function bootstrap_build_settings(projectPath) {
|
|
9280
10100
|
const filePath = get_build_settings_path(projectPath);
|
|
9281
|
-
const dir =
|
|
10101
|
+
const dir = path8.dirname(filePath);
|
|
9282
10102
|
if (!fs3.existsSync(dir)) {
|
|
9283
10103
|
fs3.mkdirSync(dir, { recursive: true });
|
|
9284
10104
|
}
|
|
@@ -9318,7 +10138,7 @@ ${scenesYaml}`);
|
|
|
9318
10138
|
fs3.renameSync(tempPath, filePath);
|
|
9319
10139
|
}
|
|
9320
10140
|
function get_scene_guid(projectPath, scenePath) {
|
|
9321
|
-
const fullPath =
|
|
10141
|
+
const fullPath = path8.join(projectPath, scenePath);
|
|
9322
10142
|
const metaPath = fullPath + ".meta";
|
|
9323
10143
|
if (!fs3.existsSync(metaPath)) {
|
|
9324
10144
|
return null;
|
|
@@ -9330,7 +10150,7 @@ function get_scene_guid(projectPath, scenePath) {
|
|
|
9330
10150
|
function add_scene(projectPath, scenePath, options) {
|
|
9331
10151
|
const enabled = options?.enabled ?? true;
|
|
9332
10152
|
const position = options?.position;
|
|
9333
|
-
const fullScenePath =
|
|
10153
|
+
const fullScenePath = path8.join(projectPath, scenePath);
|
|
9334
10154
|
if (!fs3.existsSync(fullScenePath)) {
|
|
9335
10155
|
return { success: false, message: `Scene file not found: ${scenePath}` };
|
|
9336
10156
|
}
|
|
@@ -9457,15 +10277,15 @@ function move_scene(projectPath, scenePath, newPosition) {
|
|
|
9457
10277
|
}
|
|
9458
10278
|
|
|
9459
10279
|
// src/packages.ts
|
|
9460
|
-
var
|
|
10280
|
+
var import_fs15 = require("fs");
|
|
9461
10281
|
var import_path6 = require("path");
|
|
9462
10282
|
function load_manifest(project_path) {
|
|
9463
10283
|
const manifest_path = import_path6.join(project_path, "Packages", "manifest.json");
|
|
9464
|
-
if (!
|
|
10284
|
+
if (!import_fs15.existsSync(manifest_path)) {
|
|
9465
10285
|
return { error: `manifest.json not found at ${manifest_path}` };
|
|
9466
10286
|
}
|
|
9467
10287
|
try {
|
|
9468
|
-
const raw =
|
|
10288
|
+
const raw = import_fs15.readFileSync(manifest_path, "utf-8");
|
|
9469
10289
|
const parsed = JSON.parse(raw);
|
|
9470
10290
|
if (!parsed.dependencies || typeof parsed.dependencies !== "object") {
|
|
9471
10291
|
return { error: `Invalid manifest.json: missing "dependencies" object` };
|
|
@@ -9476,12 +10296,7 @@ function load_manifest(project_path) {
|
|
|
9476
10296
|
}
|
|
9477
10297
|
}
|
|
9478
10298
|
function save_manifest(manifest_path, manifest) {
|
|
9479
|
-
|
|
9480
|
-
for (const key of Object.keys(manifest.dependencies).sort()) {
|
|
9481
|
-
sorted_deps[key] = manifest.dependencies[key];
|
|
9482
|
-
}
|
|
9483
|
-
const output = { ...manifest, dependencies: sorted_deps };
|
|
9484
|
-
import_fs14.writeFileSync(manifest_path, JSON.stringify(output, null, 2) + `
|
|
10299
|
+
import_fs15.writeFileSync(manifest_path, JSON.stringify(manifest, null, 2) + `
|
|
9485
10300
|
`, "utf-8");
|
|
9486
10301
|
}
|
|
9487
10302
|
function list_packages(project_path, search) {
|
|
@@ -9535,7 +10350,7 @@ function remove_package(project_path, name) {
|
|
|
9535
10350
|
}
|
|
9536
10351
|
|
|
9537
10352
|
// src/input-actions.ts
|
|
9538
|
-
var
|
|
10353
|
+
var import_fs16 = require("fs");
|
|
9539
10354
|
var import_crypto = require("crypto");
|
|
9540
10355
|
function generate_action_id() {
|
|
9541
10356
|
const bytes = import_crypto.randomBytes(16);
|
|
@@ -9549,18 +10364,19 @@ function generate_action_id() {
|
|
|
9549
10364
|
].join("-");
|
|
9550
10365
|
}
|
|
9551
10366
|
function load_input_actions(file) {
|
|
9552
|
-
if (!
|
|
10367
|
+
if (!import_fs16.existsSync(file)) {
|
|
9553
10368
|
return { error: `File not found: ${file}` };
|
|
9554
10369
|
}
|
|
9555
10370
|
try {
|
|
9556
|
-
const raw =
|
|
10371
|
+
const raw = import_fs16.readFileSync(file, "utf-8");
|
|
9557
10372
|
return JSON.parse(raw);
|
|
9558
10373
|
} catch (err) {
|
|
9559
10374
|
return { error: `Failed to parse input actions: ${err instanceof Error ? err.message : String(err)}` };
|
|
9560
10375
|
}
|
|
9561
10376
|
}
|
|
9562
10377
|
function save_input_actions(file, data) {
|
|
9563
|
-
|
|
10378
|
+
ensure_parent_dir(file);
|
|
10379
|
+
import_fs16.writeFileSync(file, JSON.stringify(data, null, 4) + `
|
|
9564
10380
|
`, "utf-8");
|
|
9565
10381
|
}
|
|
9566
10382
|
function add_map(data, name) {
|
|
@@ -9816,7 +10632,7 @@ function build_create_command() {
|
|
|
9816
10632
|
console.log(JSON.stringify({ success: false, error: "--shader <guid> is required" }, null, 2));
|
|
9817
10633
|
process.exit(1);
|
|
9818
10634
|
}
|
|
9819
|
-
if (
|
|
10635
|
+
if (import_fs17.existsSync(output_path)) {
|
|
9820
10636
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
9821
10637
|
process.exit(1);
|
|
9822
10638
|
}
|
|
@@ -9888,7 +10704,8 @@ Material:
|
|
|
9888
10704
|
m_Colors: ${color_section}
|
|
9889
10705
|
m_BuildTextureStacks: []
|
|
9890
10706
|
`;
|
|
9891
|
-
|
|
10707
|
+
ensure_parent_dir(output_path);
|
|
10708
|
+
import_fs17.writeFileSync(output_path, mat_content, "utf-8");
|
|
9892
10709
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
9893
10710
|
const meta_content = `fileFormatVersion: 2
|
|
9894
10711
|
guid: ${guid}
|
|
@@ -9899,7 +10716,7 @@ NativeFormatImporter:
|
|
|
9899
10716
|
assetBundleName:
|
|
9900
10717
|
assetBundleVariant:
|
|
9901
10718
|
`;
|
|
9902
|
-
|
|
10719
|
+
import_fs17.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
9903
10720
|
console.log(JSON.stringify({
|
|
9904
10721
|
success: true,
|
|
9905
10722
|
file: output_path,
|
|
@@ -9929,7 +10746,7 @@ NativeFormatImporter:
|
|
|
9929
10746
|
process.exitCode = 1;
|
|
9930
10747
|
return;
|
|
9931
10748
|
}
|
|
9932
|
-
if (
|
|
10749
|
+
if (import_fs17.existsSync(output_path)) {
|
|
9933
10750
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
9934
10751
|
process.exitCode = 1;
|
|
9935
10752
|
return;
|
|
@@ -9956,7 +10773,7 @@ ScriptedImporter:
|
|
|
9956
10773
|
wrapperClassName:
|
|
9957
10774
|
wrapperCodeNamespace:
|
|
9958
10775
|
`;
|
|
9959
|
-
|
|
10776
|
+
import_fs17.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
9960
10777
|
console.log(JSON.stringify({
|
|
9961
10778
|
success: true,
|
|
9962
10779
|
file: output_path,
|
|
@@ -9972,7 +10789,7 @@ ScriptedImporter:
|
|
|
9972
10789
|
return;
|
|
9973
10790
|
}
|
|
9974
10791
|
const name = name_arg || import_path7.basename(output_path).replace(/\.anim$/i, "");
|
|
9975
|
-
if (
|
|
10792
|
+
if (import_fs17.existsSync(output_path)) {
|
|
9976
10793
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
9977
10794
|
process.exitCode = 1;
|
|
9978
10795
|
return;
|
|
@@ -10039,7 +10856,8 @@ AnimationClip:
|
|
|
10039
10856
|
m_HasMotionFloatCurves: 0
|
|
10040
10857
|
m_Events: []
|
|
10041
10858
|
`;
|
|
10042
|
-
|
|
10859
|
+
ensure_parent_dir(output_path);
|
|
10860
|
+
import_fs17.writeFileSync(output_path, anim_content, "utf-8");
|
|
10043
10861
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
10044
10862
|
const meta_content = `fileFormatVersion: 2
|
|
10045
10863
|
guid: ${guid}
|
|
@@ -10050,7 +10868,7 @@ NativeFormatImporter:
|
|
|
10050
10868
|
assetBundleName:
|
|
10051
10869
|
assetBundleVariant:
|
|
10052
10870
|
`;
|
|
10053
|
-
|
|
10871
|
+
import_fs17.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
10054
10872
|
console.log(JSON.stringify({
|
|
10055
10873
|
success: true,
|
|
10056
10874
|
file: output_path,
|
|
@@ -10068,7 +10886,7 @@ NativeFormatImporter:
|
|
|
10068
10886
|
process.exitCode = 1;
|
|
10069
10887
|
return;
|
|
10070
10888
|
}
|
|
10071
|
-
if (
|
|
10889
|
+
if (import_fs17.existsSync(output_path)) {
|
|
10072
10890
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
10073
10891
|
process.exitCode = 1;
|
|
10074
10892
|
return;
|
|
@@ -10118,7 +10936,8 @@ AnimatorStateMachine:
|
|
|
10118
10936
|
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
|
10119
10937
|
m_DefaultState: {fileID: 0}
|
|
10120
10938
|
`;
|
|
10121
|
-
|
|
10939
|
+
ensure_parent_dir(output_path);
|
|
10940
|
+
import_fs17.writeFileSync(output_path, ctrl_content, "utf-8");
|
|
10122
10941
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
10123
10942
|
const meta_content = `fileFormatVersion: 2
|
|
10124
10943
|
guid: ${guid}
|
|
@@ -10129,7 +10948,7 @@ NativeFormatImporter:
|
|
|
10129
10948
|
assetBundleName:
|
|
10130
10949
|
assetBundleVariant:
|
|
10131
10950
|
`;
|
|
10132
|
-
|
|
10951
|
+
import_fs17.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
10133
10952
|
console.log(JSON.stringify({
|
|
10134
10953
|
success: true,
|
|
10135
10954
|
file: output_path,
|
|
@@ -10146,7 +10965,7 @@ NativeFormatImporter:
|
|
|
10146
10965
|
process.exitCode = 1;
|
|
10147
10966
|
return;
|
|
10148
10967
|
}
|
|
10149
|
-
if (
|
|
10968
|
+
if (import_fs17.existsSync(output_path)) {
|
|
10150
10969
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
10151
10970
|
process.exitCode = 1;
|
|
10152
10971
|
return;
|
|
@@ -10185,7 +11004,8 @@ Transform:
|
|
|
10185
11004
|
m_Father: {fileID: 0}
|
|
10186
11005
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
10187
11006
|
`;
|
|
10188
|
-
|
|
11007
|
+
ensure_parent_dir(output_path);
|
|
11008
|
+
import_fs17.writeFileSync(output_path, prefab_content, "utf-8");
|
|
10189
11009
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
10190
11010
|
const meta_content = `fileFormatVersion: 2
|
|
10191
11011
|
guid: ${guid}
|
|
@@ -10195,7 +11015,7 @@ PrefabImporter:
|
|
|
10195
11015
|
assetBundleName:
|
|
10196
11016
|
assetBundleVariant:
|
|
10197
11017
|
`;
|
|
10198
|
-
|
|
11018
|
+
import_fs17.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
10199
11019
|
console.log(JSON.stringify({
|
|
10200
11020
|
success: true,
|
|
10201
11021
|
file: output_path,
|
|
@@ -10209,7 +11029,7 @@ PrefabImporter:
|
|
|
10209
11029
|
|
|
10210
11030
|
// src/cmd-read.ts
|
|
10211
11031
|
init_scanner();
|
|
10212
|
-
var
|
|
11032
|
+
var import_fs18 = require("fs");
|
|
10213
11033
|
var import_path8 = require("path");
|
|
10214
11034
|
var import_os = require("os");
|
|
10215
11035
|
function parse_material_yaml(content) {
|
|
@@ -10456,7 +11276,7 @@ function categorize_asset(filePath) {
|
|
|
10456
11276
|
function find_project_root_from_file(filePath) {
|
|
10457
11277
|
let dir = import_path8.dirname(import_path8.resolve(filePath));
|
|
10458
11278
|
for (let i = 0;i < 20; i++) {
|
|
10459
|
-
if (
|
|
11279
|
+
if (import_fs18.existsSync(import_path8.join(dir, "Assets")) && import_fs18.existsSync(import_path8.join(dir, "ProjectSettings"))) {
|
|
10460
11280
|
return dir;
|
|
10461
11281
|
}
|
|
10462
11282
|
const parent = import_path8.dirname(dir);
|
|
@@ -10491,10 +11311,12 @@ function parse_log_line_timestamp(line) {
|
|
|
10491
11311
|
}
|
|
10492
11312
|
function parse_log_entries(lines) {
|
|
10493
11313
|
const entries = [];
|
|
10494
|
-
const error_re =
|
|
10495
|
-
const
|
|
11314
|
+
const error_re = /\b(error|exception)\b/i;
|
|
11315
|
+
const runtime_error_re = /\b(NullReferenceException|IndexOutOfRangeException|ArgumentException|MissingReferenceException|StackOverflowException|DivideByZeroException|InvalidOperationException|KeyNotFoundException|FormatException|ObjectDisposedException|MissingComponentException|UnassignedReferenceException)\b/;
|
|
11316
|
+
const warning_re = /\bwarning\b/i;
|
|
10496
11317
|
const compile_re = /Assets\/.*\.cs\(\d+,\d+\):\s*error\s+CS/;
|
|
10497
11318
|
const import_error_re = /Failed to import|Error while importing|Could not create asset|Unable to import|Shader error in|Import of asset .* failed/i;
|
|
11319
|
+
const assertion_re = /^Assertion failed/;
|
|
10498
11320
|
const stack_re = /^\s+at\s+|^\s*\(Filename:/;
|
|
10499
11321
|
for (let i = 0;i < lines.length; i++) {
|
|
10500
11322
|
const line = lines[i];
|
|
@@ -10503,7 +11325,9 @@ function parse_log_entries(lines) {
|
|
|
10503
11325
|
let level = "info";
|
|
10504
11326
|
if (import_error_re.test(line))
|
|
10505
11327
|
level = "import_error";
|
|
10506
|
-
else if (
|
|
11328
|
+
else if (compile_re.test(line))
|
|
11329
|
+
level = "error";
|
|
11330
|
+
else if (error_re.test(line) || runtime_error_re.test(line) || assertion_re.test(line))
|
|
10507
11331
|
level = "error";
|
|
10508
11332
|
else if (warning_re.test(line))
|
|
10509
11333
|
level = "warning";
|
|
@@ -10802,7 +11626,7 @@ function walk_files(dir, extensions) {
|
|
|
10802
11626
|
const current = stack.pop();
|
|
10803
11627
|
let entries;
|
|
10804
11628
|
try {
|
|
10805
|
-
entries =
|
|
11629
|
+
entries = import_fs18.readdirSync(current);
|
|
10806
11630
|
} catch {
|
|
10807
11631
|
continue;
|
|
10808
11632
|
}
|
|
@@ -10811,7 +11635,7 @@ function walk_files(dir, extensions) {
|
|
|
10811
11635
|
continue;
|
|
10812
11636
|
const full = import_path8.join(current, entry);
|
|
10813
11637
|
try {
|
|
10814
|
-
const stat =
|
|
11638
|
+
const stat = import_fs18.statSync(full);
|
|
10815
11639
|
if (stat.isDirectory()) {
|
|
10816
11640
|
stack.push(full);
|
|
10817
11641
|
} else if (extensions.has(import_path8.extname(full).toLowerCase())) {
|
|
@@ -10825,7 +11649,7 @@ function walk_files(dir, extensions) {
|
|
|
10825
11649
|
return results;
|
|
10826
11650
|
}
|
|
10827
11651
|
function validate_unity_yaml(file) {
|
|
10828
|
-
if (!
|
|
11652
|
+
if (!import_fs18.existsSync(file)) {
|
|
10829
11653
|
return `File not found: ${file}`;
|
|
10830
11654
|
}
|
|
10831
11655
|
try {
|
|
@@ -10956,7 +11780,7 @@ function build_read_command(getScanner) {
|
|
|
10956
11780
|
}
|
|
10957
11781
|
if (result.total === 0) {
|
|
10958
11782
|
try {
|
|
10959
|
-
const fileSize =
|
|
11783
|
+
const fileSize = import_fs18.statSync(file).size;
|
|
10960
11784
|
if (fileSize > 100) {
|
|
10961
11785
|
const corruptWarning = "File has valid Unity YAML header but contains no parseable GameObjects -- file may be corrupt or malformed";
|
|
10962
11786
|
result.warning = result.warning ? `${result.warning}; ${corruptWarning}` : corruptWarning;
|
|
@@ -11069,7 +11893,7 @@ function build_read_command(getScanner) {
|
|
|
11069
11893
|
console.log(JSON.stringify({ error: matValidationError }, null, 2));
|
|
11070
11894
|
process.exit(1);
|
|
11071
11895
|
}
|
|
11072
|
-
const content =
|
|
11896
|
+
const content = import_fs18.readFileSync(file, "utf-8");
|
|
11073
11897
|
if (!content.includes("Material:")) {
|
|
11074
11898
|
console.log(JSON.stringify({ error: `File "${file}" does not contain a Material block. Use 'read asset' for generic Unity YAML files.` }, null, 2));
|
|
11075
11899
|
process.exit(1);
|
|
@@ -11111,13 +11935,13 @@ function build_read_command(getScanner) {
|
|
|
11111
11935
|
}, null, 2));
|
|
11112
11936
|
});
|
|
11113
11937
|
cmd.command("dependencies <file>").description("List asset dependencies (GUIDs referenced by this file)").option("--project <path>", "Unity project root (for GUID resolution)").option("--unresolved", "Show only GUIDs that could not be resolved").option("--recursive [depth]", "Follow dependency chain N levels deep (default: 3)").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
11114
|
-
if (!
|
|
11938
|
+
if (!import_fs18.existsSync(file)) {
|
|
11115
11939
|
console.log(JSON.stringify({ error: `File not found: ${file}` }, null, 2));
|
|
11116
11940
|
process.exit(1);
|
|
11117
11941
|
}
|
|
11118
11942
|
let content;
|
|
11119
11943
|
try {
|
|
11120
|
-
content =
|
|
11944
|
+
content = import_fs18.readFileSync(file, "utf-8");
|
|
11121
11945
|
} catch {
|
|
11122
11946
|
console.log(JSON.stringify({ error: `Cannot read file: ${file}` }, null, 2));
|
|
11123
11947
|
process.exit(1);
|
|
@@ -11158,7 +11982,7 @@ function build_read_command(getScanner) {
|
|
|
11158
11982
|
const result = [];
|
|
11159
11983
|
let fileContent;
|
|
11160
11984
|
try {
|
|
11161
|
-
fileContent =
|
|
11985
|
+
fileContent = import_fs18.readFileSync(filePath, "utf-8");
|
|
11162
11986
|
} catch {
|
|
11163
11987
|
return [];
|
|
11164
11988
|
}
|
|
@@ -11175,7 +11999,7 @@ function build_read_command(getScanner) {
|
|
|
11175
11999
|
const rAbsPath = cache.resolve_absolute(g);
|
|
11176
12000
|
const rType = rPath ? categorize_asset(rPath) : "unknown";
|
|
11177
12001
|
const dep = { guid: g, path: rPath, type: rType, depth };
|
|
11178
|
-
if (rAbsPath && depth < max_depth &&
|
|
12002
|
+
if (rAbsPath && depth < max_depth && import_fs18.existsSync(rAbsPath)) {
|
|
11179
12003
|
const subs = traverse_file(rAbsPath, depth + 1);
|
|
11180
12004
|
if (subs.length > 0)
|
|
11181
12005
|
dep.sub_dependencies = subs;
|
|
@@ -11204,7 +12028,7 @@ function build_read_command(getScanner) {
|
|
|
11204
12028
|
const rDep = { guid: dep.guid, path: dep.path, type: dep.type, depth: 0 };
|
|
11205
12029
|
if (dep.path) {
|
|
11206
12030
|
const absPath = cache.resolve_absolute(dep.guid);
|
|
11207
|
-
if (absPath &&
|
|
12031
|
+
if (absPath && import_fs18.existsSync(absPath)) {
|
|
11208
12032
|
const subs = traverse_file(absPath, 1);
|
|
11209
12033
|
if (subs.length > 0)
|
|
11210
12034
|
rDep.sub_dependencies = subs;
|
|
@@ -11389,7 +12213,7 @@ function build_read_command(getScanner) {
|
|
|
11389
12213
|
});
|
|
11390
12214
|
cmd.command("target <file> <gameobject_name> [component_type]").description("Build a --target reference string for prefab override commands").option("-p, --project <path>", "Unity project path").option("-j, --json", "Output as JSON").action((file, gameobject_name, component_type, options) => {
|
|
11391
12215
|
try {
|
|
11392
|
-
if (!
|
|
12216
|
+
if (!import_fs18.existsSync(file)) {
|
|
11393
12217
|
console.log(JSON.stringify({ error: `File not found: ${file}` }, null, 2));
|
|
11394
12218
|
process.exit(1);
|
|
11395
12219
|
}
|
|
@@ -11509,7 +12333,7 @@ function build_read_command(getScanner) {
|
|
|
11509
12333
|
}
|
|
11510
12334
|
});
|
|
11511
12335
|
cmd.command("script <file>").description("Extract C# type declarations from a .cs file or .NET DLL").option("-j, --json", "Output as JSON").action((file, _options) => {
|
|
11512
|
-
if (!
|
|
12336
|
+
if (!import_fs18.existsSync(file)) {
|
|
11513
12337
|
console.log(JSON.stringify({ error: `File not found: ${file}` }, null, 2));
|
|
11514
12338
|
process.exit(1);
|
|
11515
12339
|
}
|
|
@@ -11598,11 +12422,11 @@ function build_read_command(getScanner) {
|
|
|
11598
12422
|
if (projectPath && !options.project)
|
|
11599
12423
|
options.project = projectPath;
|
|
11600
12424
|
const logPath = options.path || get_editor_log_path();
|
|
11601
|
-
if (!logPath || !
|
|
12425
|
+
if (!logPath || !import_fs18.existsSync(logPath)) {
|
|
11602
12426
|
console.log(JSON.stringify({ error: `Editor.log not found${logPath ? `: ${logPath}` : ". Could not detect platform log path."}` }, null, 2));
|
|
11603
12427
|
process.exit(1);
|
|
11604
12428
|
}
|
|
11605
|
-
const content =
|
|
12429
|
+
const content = import_fs18.readFileSync(logPath, "utf-8");
|
|
11606
12430
|
let lines = content.split(/\r?\n/);
|
|
11607
12431
|
if (options.project) {
|
|
11608
12432
|
const projectPath2 = import_path8.resolve(options.project);
|
|
@@ -11675,10 +12499,6 @@ function build_read_command(getScanner) {
|
|
|
11675
12499
|
}
|
|
11676
12500
|
}
|
|
11677
12501
|
}
|
|
11678
|
-
if (options.search) {
|
|
11679
|
-
const re = new RegExp(options.search, "i");
|
|
11680
|
-
lines = lines.filter((l) => re.test(l));
|
|
11681
|
-
}
|
|
11682
12502
|
if (options.errors || options.warnings || options.compileErrors || options.importErrors) {
|
|
11683
12503
|
const entries = parse_log_entries(lines);
|
|
11684
12504
|
let filtered = entries;
|
|
@@ -11692,6 +12512,10 @@ function build_read_command(getScanner) {
|
|
|
11692
12512
|
} else if (options.warnings) {
|
|
11693
12513
|
filtered = entries.filter((e) => e.level === "warning");
|
|
11694
12514
|
}
|
|
12515
|
+
if (options.search) {
|
|
12516
|
+
const re = new RegExp(options.search, "i");
|
|
12517
|
+
filtered = filtered.filter((e) => re.test(e.message) || e.stack_trace && e.stack_trace.some((s) => re.test(s)));
|
|
12518
|
+
}
|
|
11695
12519
|
const tail_filtered = parseInt(options.tail, 10);
|
|
11696
12520
|
if (isNaN(tail_filtered) || tail_filtered < 1) {
|
|
11697
12521
|
console.log(JSON.stringify({ error: `Invalid --tail value "${options.tail}". Must be a positive integer.` }, null, 2));
|
|
@@ -11707,6 +12531,10 @@ function build_read_command(getScanner) {
|
|
|
11707
12531
|
}, null, 2));
|
|
11708
12532
|
return;
|
|
11709
12533
|
}
|
|
12534
|
+
if (options.search) {
|
|
12535
|
+
const re = new RegExp(options.search, "i");
|
|
12536
|
+
lines = lines.filter((l) => re.test(l));
|
|
12537
|
+
}
|
|
11710
12538
|
const tail = parseInt(options.tail, 10);
|
|
11711
12539
|
if (isNaN(tail) || tail < 1) {
|
|
11712
12540
|
console.log(JSON.stringify({ error: `Invalid --tail value "${options.tail}". Must be a positive integer.` }, null, 2));
|
|
@@ -11723,11 +12551,11 @@ function build_read_command(getScanner) {
|
|
|
11723
12551
|
});
|
|
11724
12552
|
cmd.command("meta <file>").description("Read a Unity .meta file and show importer settings").option("--summary", "Show importer type and key settings only").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
11725
12553
|
const metaPath = file.endsWith(".meta") ? file : `${file}.meta`;
|
|
11726
|
-
if (!
|
|
12554
|
+
if (!import_fs18.existsSync(metaPath)) {
|
|
11727
12555
|
console.log(JSON.stringify({ error: `Meta file not found: ${metaPath}` }, null, 2));
|
|
11728
12556
|
process.exit(1);
|
|
11729
12557
|
}
|
|
11730
|
-
const content =
|
|
12558
|
+
const content = import_fs18.readFileSync(metaPath, "utf-8");
|
|
11731
12559
|
const lines = content.split(/\r?\n/);
|
|
11732
12560
|
let guid = "";
|
|
11733
12561
|
let importer_type = "Unknown";
|
|
@@ -11815,7 +12643,7 @@ function build_read_command(getScanner) {
|
|
|
11815
12643
|
console.log(JSON.stringify({ error: animValidationError }, null, 2));
|
|
11816
12644
|
process.exit(1);
|
|
11817
12645
|
}
|
|
11818
|
-
const content =
|
|
12646
|
+
const content = import_fs18.readFileSync(file, "utf-8");
|
|
11819
12647
|
const clip = parse_animation_yaml(content, options.curves === true);
|
|
11820
12648
|
if (!clip) {
|
|
11821
12649
|
console.log(JSON.stringify({ error: `No AnimationClip found in "${file}". Is this an .anim file?` }, null, 2));
|
|
@@ -11876,7 +12704,7 @@ function build_read_command(getScanner) {
|
|
|
11876
12704
|
console.log(JSON.stringify({ error: ctrlValidationError }, null, 2));
|
|
11877
12705
|
process.exit(1);
|
|
11878
12706
|
}
|
|
11879
|
-
const content =
|
|
12707
|
+
const content = import_fs18.readFileSync(file, "utf-8");
|
|
11880
12708
|
const blocks = split_yaml_blocks(content);
|
|
11881
12709
|
const controller_block = blocks.find((b) => b.class_id === 91);
|
|
11882
12710
|
if (!controller_block) {
|
|
@@ -12106,7 +12934,7 @@ function build_read_command(getScanner) {
|
|
|
12106
12934
|
process.exit(1);
|
|
12107
12935
|
}
|
|
12108
12936
|
const assetsDir = import_path8.join(import_path8.resolve(project_path), "Assets");
|
|
12109
|
-
if (!
|
|
12937
|
+
if (!import_fs18.existsSync(assetsDir)) {
|
|
12110
12938
|
console.log(JSON.stringify({ error: `Assets directory not found in "${project_path}"` }, null, 2));
|
|
12111
12939
|
process.exit(1);
|
|
12112
12940
|
}
|
|
@@ -12135,7 +12963,7 @@ function build_read_command(getScanner) {
|
|
|
12135
12963
|
const guid_pattern = `guid: ${guid}`;
|
|
12136
12964
|
for (const f of files) {
|
|
12137
12965
|
try {
|
|
12138
|
-
const fc =
|
|
12966
|
+
const fc = import_fs18.readFileSync(f, "utf-8");
|
|
12139
12967
|
if (fc.includes(guid_pattern)) {
|
|
12140
12968
|
const rel = import_path8.relative(import_path8.resolve(project_path), f);
|
|
12141
12969
|
const ftype = categorize_asset(f);
|
|
@@ -12165,7 +12993,7 @@ function build_read_command(getScanner) {
|
|
|
12165
12993
|
cmd.command("unused <project_path>").description("Find potentially unused assets (zero inbound GUID references)").option("--type <type>", "Filter to specific asset types").option("--ignore <glob>", "Exclude paths matching this pattern").option("--max <n>", "Maximum results to return (default 200)", "200").option("-j, --json", "Output as JSON").action((project_path, options) => {
|
|
12166
12994
|
const resolvedProject = import_path8.resolve(project_path);
|
|
12167
12995
|
const assetsDir = import_path8.join(resolvedProject, "Assets");
|
|
12168
|
-
if (!
|
|
12996
|
+
if (!import_fs18.existsSync(assetsDir)) {
|
|
12169
12997
|
console.log(JSON.stringify({ error: `Assets directory not found in "${project_path}"` }, null, 2));
|
|
12170
12998
|
process.exit(1);
|
|
12171
12999
|
}
|
|
@@ -12193,7 +13021,7 @@ function build_read_command(getScanner) {
|
|
|
12193
13021
|
const guid_re = /guid:\s*([a-f0-9]{32})/g;
|
|
12194
13022
|
for (const f of files) {
|
|
12195
13023
|
try {
|
|
12196
|
-
const fc =
|
|
13024
|
+
const fc = import_fs18.readFileSync(f, "utf-8");
|
|
12197
13025
|
let gm;
|
|
12198
13026
|
while ((gm = guid_re.exec(fc)) !== null) {
|
|
12199
13027
|
referenced_guids.add(gm[1]);
|
|
@@ -12204,8 +13032,8 @@ function build_read_command(getScanner) {
|
|
|
12204
13032
|
}
|
|
12205
13033
|
const buildSettingsPath = import_path8.join(resolvedProject, "ProjectSettings", "EditorBuildSettings.asset");
|
|
12206
13034
|
const build_scene_guids = new Set;
|
|
12207
|
-
if (
|
|
12208
|
-
const bsc =
|
|
13035
|
+
if (import_fs18.existsSync(buildSettingsPath)) {
|
|
13036
|
+
const bsc = import_fs18.readFileSync(buildSettingsPath, "utf-8");
|
|
12209
13037
|
let bm;
|
|
12210
13038
|
while ((bm = guid_re.exec(bsc)) !== null) {
|
|
12211
13039
|
build_scene_guids.add(bm[1]);
|
|
@@ -12327,7 +13155,7 @@ function build_read_command(getScanner) {
|
|
|
12327
13155
|
}
|
|
12328
13156
|
|
|
12329
13157
|
// src/cmd-update.ts
|
|
12330
|
-
var
|
|
13158
|
+
var import_fs19 = require("fs");
|
|
12331
13159
|
var import_path9 = require("path");
|
|
12332
13160
|
|
|
12333
13161
|
// src/animator-utils.ts
|
|
@@ -12494,7 +13322,7 @@ function build_update_command(getScanner) {
|
|
|
12494
13322
|
if (!result.success)
|
|
12495
13323
|
process.exitCode = 1;
|
|
12496
13324
|
});
|
|
12497
|
-
cmd.command("component <file> <file_id> <property> <value>").description("Edit any component property by file ID. Supports dotted paths (m_LocalPosition.x) and array paths (m_Materials.Array.data[0]). Quote paths with brackets or use dot notation (data.0) to avoid shell glob expansion").option("-j, --json", "Output as JSON").action((file, file_id, property, value,
|
|
13325
|
+
cmd.command("component <file> <file_id> <property> <value>").description("Edit any component property by file ID. Supports dotted paths (m_LocalPosition.x) and array paths (m_Materials.Array.data[0]). Quote paths with brackets or use dot notation (data.0) to avoid shell glob expansion").option("-j, --json", "Output as JSON").option("-p, --project <path>", "Unity project path (for asset reference resolution)").action((file, file_id, property, value, options) => {
|
|
12498
13326
|
if (property === "m_RootOrder") {
|
|
12499
13327
|
const num = Number(value);
|
|
12500
13328
|
if (!Number.isInteger(num) || num < 0) {
|
|
@@ -12507,7 +13335,8 @@ function build_update_command(getScanner) {
|
|
|
12507
13335
|
file_path: file,
|
|
12508
13336
|
file_id,
|
|
12509
13337
|
property,
|
|
12510
|
-
new_value: value
|
|
13338
|
+
new_value: value,
|
|
13339
|
+
project_path: options.project
|
|
12511
13340
|
});
|
|
12512
13341
|
console.log(JSON.stringify(result, null, 2));
|
|
12513
13342
|
if (!result.success)
|
|
@@ -12942,11 +13771,11 @@ function build_update_command(getScanner) {
|
|
|
12942
13771
|
}
|
|
12943
13772
|
}
|
|
12944
13773
|
}).action((file, options) => {
|
|
12945
|
-
if (!
|
|
13774
|
+
if (!import_fs19.existsSync(file)) {
|
|
12946
13775
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
12947
13776
|
process.exit(1);
|
|
12948
13777
|
}
|
|
12949
|
-
let content =
|
|
13778
|
+
let content = import_fs19.readFileSync(file, "utf-8");
|
|
12950
13779
|
const changes = [];
|
|
12951
13780
|
if (options.shader) {
|
|
12952
13781
|
const guid = options.shader;
|
|
@@ -13095,7 +13924,7 @@ ${lm[1]} - ${kw}
|
|
|
13095
13924
|
process.exitCode = 1;
|
|
13096
13925
|
return;
|
|
13097
13926
|
}
|
|
13098
|
-
|
|
13927
|
+
import_fs19.writeFileSync(file, content, "utf-8");
|
|
13099
13928
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
13100
13929
|
});
|
|
13101
13930
|
cmd.command("meta [file]").description("Edit Unity .meta file importer settings").option("--set <key=value>", "Set an importer setting (e.g., isReadable=1)", (v, p) => [...p, v], []).option("--max-size <n>", "Set TextureImporter maxTextureSize").option("--compression <type>", "Set textureCompression (0=None, 1=LowQuality, 2=Normal, 3=HighQuality)").option("--filter-mode <mode>", "Set filterMode (0=Point, 1=Bilinear, 2=Trilinear)").option("--read-write", "Enable isReadable").option("--no-read-write", "Disable isReadable").option("--batch <glob>", "Apply to all matching files").option("--dry-run", "Preview changes without writing").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
@@ -13156,9 +13985,9 @@ ${lm[1]} - ${kw}
|
|
|
13156
13985
|
const suffix = import_path9.basename(pattern).replace(/^\*+/, "");
|
|
13157
13986
|
const meta_files = [];
|
|
13158
13987
|
const scan = (d) => {
|
|
13159
|
-
for (const entry of
|
|
13988
|
+
for (const entry of import_fs19.readdirSync(d)) {
|
|
13160
13989
|
const full = import_path9.join(d, entry);
|
|
13161
|
-
if (
|
|
13990
|
+
if (import_fs19.statSync(full).isDirectory()) {
|
|
13162
13991
|
if (pattern.includes("**"))
|
|
13163
13992
|
scan(full);
|
|
13164
13993
|
} else if (entry.endsWith(suffix)) {
|
|
@@ -13166,7 +13995,7 @@ ${lm[1]} - ${kw}
|
|
|
13166
13995
|
}
|
|
13167
13996
|
}
|
|
13168
13997
|
};
|
|
13169
|
-
if (
|
|
13998
|
+
if (import_fs19.existsSync(dir))
|
|
13170
13999
|
scan(dir);
|
|
13171
14000
|
if (meta_files.length === 0) {
|
|
13172
14001
|
console.log(JSON.stringify({ success: false, error: `No files matched pattern: ${glob_pattern}` }, null, 2));
|
|
@@ -13174,7 +14003,7 @@ ${lm[1]} - ${kw}
|
|
|
13174
14003
|
}
|
|
13175
14004
|
const results = [];
|
|
13176
14005
|
for (const mf of meta_files) {
|
|
13177
|
-
let mc =
|
|
14006
|
+
let mc = import_fs19.readFileSync(mf, "utf-8");
|
|
13178
14007
|
const file_changes = [];
|
|
13179
14008
|
for (const edit of edits) {
|
|
13180
14009
|
const re = new RegExp(`^(\\s*${edit.key}:)[ \\t]*.*$`, "m");
|
|
@@ -13185,7 +14014,7 @@ ${lm[1]} - ${kw}
|
|
|
13185
14014
|
}
|
|
13186
14015
|
if (file_changes.length > 0) {
|
|
13187
14016
|
if (!options.dryRun)
|
|
13188
|
-
|
|
14017
|
+
import_fs19.writeFileSync(mf, mc, "utf-8");
|
|
13189
14018
|
results.push({ file: mf, changes: file_changes });
|
|
13190
14019
|
}
|
|
13191
14020
|
}
|
|
@@ -13198,11 +14027,11 @@ ${lm[1]} - ${kw}
|
|
|
13198
14027
|
}, null, 2));
|
|
13199
14028
|
return;
|
|
13200
14029
|
}
|
|
13201
|
-
if (!
|
|
14030
|
+
if (!import_fs19.existsSync(metaPath)) {
|
|
13202
14031
|
console.log(JSON.stringify({ success: false, error: `Meta file not found: ${metaPath}` }, null, 2));
|
|
13203
14032
|
process.exit(1);
|
|
13204
14033
|
}
|
|
13205
|
-
let content =
|
|
14034
|
+
let content = import_fs19.readFileSync(metaPath, "utf-8");
|
|
13206
14035
|
const changes = [];
|
|
13207
14036
|
for (const edit of edits) {
|
|
13208
14037
|
const re = new RegExp(`^(\\s*${edit.key}:)[ \\t]*.*$`, "m");
|
|
@@ -13217,11 +14046,11 @@ ${lm[1]} - ${kw}
|
|
|
13217
14046
|
console.log(JSON.stringify({ success: true, dry_run: true, file: metaPath, changes }, null, 2));
|
|
13218
14047
|
return;
|
|
13219
14048
|
}
|
|
13220
|
-
|
|
14049
|
+
import_fs19.writeFileSync(metaPath, content, "utf-8");
|
|
13221
14050
|
console.log(JSON.stringify({ success: true, file: metaPath, changes }, null, 2));
|
|
13222
14051
|
});
|
|
13223
14052
|
cmd.command("animation <file>").description("Edit AnimationClip settings and events").option("--set <property=value>", "Set a clip property (e.g., wrap-mode=2 for Loop)", (v, p) => [...p, v], []).option("--add-event <time,function[,data]>", "Add an animation event (e.g., 0.5,OnFootstep,left)", (v, p) => [...p, v], []).option("--remove-event <index>", "Remove an animation event by index (0-based)").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
13224
|
-
if (!
|
|
14053
|
+
if (!import_fs19.existsSync(file)) {
|
|
13225
14054
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
13226
14055
|
process.exit(1);
|
|
13227
14056
|
}
|
|
@@ -13229,7 +14058,7 @@ ${lm[1]} - ${kw}
|
|
|
13229
14058
|
console.log(JSON.stringify({ success: false, error: `File is not an AnimationClip (.anim): ${file}` }, null, 2));
|
|
13230
14059
|
process.exit(1);
|
|
13231
14060
|
}
|
|
13232
|
-
let content =
|
|
14061
|
+
let content = import_fs19.readFileSync(file, "utf-8");
|
|
13233
14062
|
const changes = [];
|
|
13234
14063
|
const property_map = {
|
|
13235
14064
|
"wrap-mode": "m_WrapMode",
|
|
@@ -13390,16 +14219,16 @@ ${event_yaml}
|
|
|
13390
14219
|
process.exitCode = 1;
|
|
13391
14220
|
return;
|
|
13392
14221
|
}
|
|
13393
|
-
|
|
14222
|
+
import_fs19.writeFileSync(file, content, "utf-8");
|
|
13394
14223
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
13395
14224
|
});
|
|
13396
14225
|
const PARAM_TYPE_MAP = { float: 1, int: 3, bool: 4, trigger: 9 };
|
|
13397
14226
|
cmd.command("animator <file>").description("Edit AnimatorController parameters").option("--add-parameter <name>", "Add a new parameter").option("--type <float|int|bool|trigger>", "Parameter type (required with --add-parameter)").option("--remove-parameter <name>", "Remove a parameter by name").option("--set-default <param=value>", "Set parameter default value (e.g., Speed=1.5)", (v, p) => [...p, v], []).option("-j, --json", "Output as JSON").action((file, options) => {
|
|
13398
|
-
if (!
|
|
14227
|
+
if (!import_fs19.existsSync(file)) {
|
|
13399
14228
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
13400
14229
|
process.exit(1);
|
|
13401
14230
|
}
|
|
13402
|
-
let content =
|
|
14231
|
+
let content = import_fs19.readFileSync(file, "utf-8");
|
|
13403
14232
|
const had_crlf = content.includes(`\r
|
|
13404
14233
|
`);
|
|
13405
14234
|
if (had_crlf)
|
|
@@ -13501,7 +14330,7 @@ $1`);
|
|
|
13501
14330
|
if (had_crlf)
|
|
13502
14331
|
content = content.replace(/\n/g, `\r
|
|
13503
14332
|
`);
|
|
13504
|
-
|
|
14333
|
+
import_fs19.writeFileSync(file, content, "utf-8");
|
|
13505
14334
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
13506
14335
|
});
|
|
13507
14336
|
cmd.command("sibling-index <file> <object_name> <index>").description("Set the sibling index of a GameObject, renumbering all siblings").option("-j, --json", "Output as JSON").action((file, object_name, index_str, _options) => {
|
|
@@ -13511,7 +14340,7 @@ $1`);
|
|
|
13511
14340
|
process.exitCode = 1;
|
|
13512
14341
|
return;
|
|
13513
14342
|
}
|
|
13514
|
-
if (!
|
|
14343
|
+
if (!import_fs19.existsSync(file)) {
|
|
13515
14344
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
13516
14345
|
process.exitCode = 1;
|
|
13517
14346
|
return;
|
|
@@ -13706,7 +14535,7 @@ $1`);
|
|
|
13706
14535
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
13707
14536
|
});
|
|
13708
14537
|
cmd.command("animation-curves <file>").description("Add, remove, or modify animation curves in an .anim file").option("--add-curve <json>", 'Add a curve (JSON: {"type":"float","path":"Body","attribute":"m_Alpha","classID":23,"keyframes":[{"time":0,"value":1}]})').option("--remove-curve <spec>", "Remove a curve by path:attribute (e.g., Body/Mesh:m_Alpha)").option("--set-keyframes <json>", 'Replace keyframes (JSON: {"curve":"path:attribute","keyframes":[{"time":0,"value":10}]})').option("-j, --json", "Output as JSON").action((file, options) => {
|
|
13709
|
-
if (!
|
|
14538
|
+
if (!import_fs19.existsSync(file)) {
|
|
13710
14539
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
13711
14540
|
process.exitCode = 1;
|
|
13712
14541
|
return;
|
|
@@ -13716,7 +14545,7 @@ $1`);
|
|
|
13716
14545
|
process.exitCode = 1;
|
|
13717
14546
|
return;
|
|
13718
14547
|
}
|
|
13719
|
-
let content =
|
|
14548
|
+
let content = import_fs19.readFileSync(file, "utf-8");
|
|
13720
14549
|
const had_crlf = content.includes(`\r
|
|
13721
14550
|
`);
|
|
13722
14551
|
if (had_crlf)
|
|
@@ -14014,16 +14843,16 @@ ${curve_yaml}`);
|
|
|
14014
14843
|
if (had_crlf)
|
|
14015
14844
|
content = content.replace(/\n/g, `\r
|
|
14016
14845
|
`);
|
|
14017
|
-
|
|
14846
|
+
import_fs19.writeFileSync(file, content, "utf-8");
|
|
14018
14847
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
14019
14848
|
});
|
|
14020
14849
|
cmd.command("animator-state <file>").description("Add/remove states and transitions in an AnimatorController").option("--add-state <name>", "Add a new AnimatorState").option("--motion <guid-or-path>", "Motion clip GUID or file path (companion to --add-state)").option("--layer <name>", "Target layer name (default: first layer)").option("--speed <n>", "State speed (companion to --add-state, default: 1)").option("--remove-state <name>", "Remove a state and all its transitions").option("--add-transition <src:dst>", 'Add a transition (use "any" for AnyState source)').option("--condition <param,mode,threshold>", "Transition condition (repeatable)", (v, p) => [...p, v], []).option("--has-exit-time", "Enable exit time on transition").option("--exit-time <n>", "Exit time value (default: 0.75)").option("--duration <n>", "Transition duration (default: 0.25)").option("--remove-transition <src:dst>", "Remove a transition by source:destination state names").option("--set-default-state <name>", "Set the default state in the state machine").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
14021
|
-
if (!
|
|
14850
|
+
if (!import_fs19.existsSync(file)) {
|
|
14022
14851
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
14023
14852
|
process.exitCode = 1;
|
|
14024
14853
|
return;
|
|
14025
14854
|
}
|
|
14026
|
-
let content =
|
|
14855
|
+
let content = import_fs19.readFileSync(file, "utf-8");
|
|
14027
14856
|
const had_crlf = content.includes(`\r
|
|
14028
14857
|
`);
|
|
14029
14858
|
if (had_crlf)
|
|
@@ -14362,7 +15191,7 @@ $1`);
|
|
|
14362
15191
|
if (had_crlf)
|
|
14363
15192
|
content = content.replace(/\n/g, `\r
|
|
14364
15193
|
`);
|
|
14365
|
-
|
|
15194
|
+
import_fs19.writeFileSync(file, content, "utf-8");
|
|
14366
15195
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
14367
15196
|
});
|
|
14368
15197
|
cmd.addCommand(prefab_cmd);
|
|
@@ -14405,14 +15234,27 @@ function build_delete_command() {
|
|
|
14405
15234
|
if (!result.success)
|
|
14406
15235
|
process.exitCode = 1;
|
|
14407
15236
|
});
|
|
14408
|
-
cmd.command("component <
|
|
14409
|
-
|
|
14410
|
-
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
15237
|
+
cmd.command("component <file_or_project> <component>").description('Remove a component by file ID or type name (e.g., "Rigidbody", "StandaloneInputModule")').option("--on <game_object>", "Scope to a specific GameObject (name or fileID)").option("-p, --project <path>", "Unity project path (for script GUID lookup)").option("--all", "Remove from all scenes and prefabs in the project (first arg becomes project path)").option("-j, --json", "Output as JSON").action((file_or_project, component, options) => {
|
|
15238
|
+
if (options.all) {
|
|
15239
|
+
const result = removeComponentBatch({
|
|
15240
|
+
project_path: file_or_project,
|
|
15241
|
+
component_type: component,
|
|
15242
|
+
game_object: options.on
|
|
15243
|
+
});
|
|
15244
|
+
console.log(JSON.stringify(result, null, 2));
|
|
15245
|
+
if (!result.success)
|
|
15246
|
+
process.exitCode = 1;
|
|
15247
|
+
} else {
|
|
15248
|
+
const result = removeComponent({
|
|
15249
|
+
file_path: file_or_project,
|
|
15250
|
+
file_id: component,
|
|
15251
|
+
game_object: options.on,
|
|
15252
|
+
project_path: options.project
|
|
15253
|
+
});
|
|
15254
|
+
console.log(JSON.stringify(result, null, 2));
|
|
15255
|
+
if (!result.success)
|
|
15256
|
+
process.exitCode = 1;
|
|
15257
|
+
}
|
|
14416
15258
|
});
|
|
14417
15259
|
cmd.command("build <project_path> <scene_path>").description("Remove a scene from build settings").option("-j, --json", "Output as JSON").action((project_path, scene_path, _options) => {
|
|
14418
15260
|
try {
|
|
@@ -14455,16 +15297,16 @@ function build_delete_command() {
|
|
|
14455
15297
|
var import_path11 = require("path");
|
|
14456
15298
|
|
|
14457
15299
|
// src/editor-client.ts
|
|
14458
|
-
var
|
|
15300
|
+
var import_fs20 = require("fs");
|
|
14459
15301
|
var import_path10 = require("path");
|
|
14460
15302
|
function read_editor_config(project_path) {
|
|
14461
15303
|
const config_path = import_path10.join(project_path, ".unity-agentic", "editor.json");
|
|
14462
|
-
if (!
|
|
15304
|
+
if (!import_fs20.existsSync(config_path)) {
|
|
14463
15305
|
return { error: `Editor bridge not found at ${config_path}. Is the Unity Editor running with the bridge package installed?` };
|
|
14464
15306
|
}
|
|
14465
15307
|
let config;
|
|
14466
15308
|
try {
|
|
14467
|
-
const raw =
|
|
15309
|
+
const raw = import_fs20.readFileSync(config_path, "utf-8");
|
|
14468
15310
|
config = JSON.parse(raw);
|
|
14469
15311
|
} catch (err) {
|
|
14470
15312
|
return { error: `Failed to parse editor.json: ${err instanceof Error ? err.message : String(err)}` };
|
|
@@ -14677,6 +15519,30 @@ async function stream_editor(options) {
|
|
|
14677
15519
|
connect(`ws://127.0.0.1:${config.port}/unity-agentic`);
|
|
14678
15520
|
});
|
|
14679
15521
|
}
|
|
15522
|
+
async function ping_editor(port, timeout_ms = 2000) {
|
|
15523
|
+
return new Promise((resolve7) => {
|
|
15524
|
+
const timer = setTimeout(() => {
|
|
15525
|
+
resolve7({ reachable: false, error: `Timeout after ${timeout_ms}ms` });
|
|
15526
|
+
}, timeout_ms);
|
|
15527
|
+
try {
|
|
15528
|
+
const ws = new WebSocket(`ws://127.0.0.1:${port}/unity-agentic`);
|
|
15529
|
+
ws.onopen = () => {
|
|
15530
|
+
clearTimeout(timer);
|
|
15531
|
+
try {
|
|
15532
|
+
ws.close();
|
|
15533
|
+
} catch {}
|
|
15534
|
+
resolve7({ reachable: true });
|
|
15535
|
+
};
|
|
15536
|
+
ws.onerror = (err) => {
|
|
15537
|
+
clearTimeout(timer);
|
|
15538
|
+
resolve7({ reachable: false, error: String(err) });
|
|
15539
|
+
};
|
|
15540
|
+
} catch (err) {
|
|
15541
|
+
clearTimeout(timer);
|
|
15542
|
+
resolve7({ reachable: false, error: String(err) });
|
|
15543
|
+
}
|
|
15544
|
+
});
|
|
15545
|
+
}
|
|
14680
15546
|
function resolve_config(options) {
|
|
14681
15547
|
if (options.port) {
|
|
14682
15548
|
return { port: options.port, pid: 0, version: "unknown" };
|
|
@@ -14749,11 +15615,14 @@ function build_editor_command() {
|
|
|
14749
15615
|
process.exitCode = 1;
|
|
14750
15616
|
return;
|
|
14751
15617
|
}
|
|
15618
|
+
const ping = await ping_editor(config.port, 2000);
|
|
14752
15619
|
console.log(JSON.stringify({
|
|
14753
15620
|
port: config.port,
|
|
14754
15621
|
pid: config.pid,
|
|
14755
15622
|
version: config.version,
|
|
14756
|
-
project_path
|
|
15623
|
+
project_path,
|
|
15624
|
+
bridge_reachable: ping.reachable,
|
|
15625
|
+
...ping.reachable ? {} : { bridge_error: ping.error }
|
|
14757
15626
|
}, null, 2));
|
|
14758
15627
|
});
|
|
14759
15628
|
cmd.command("play").description("Enter play mode").action(async function() {
|
|
@@ -15098,512 +15967,6 @@ function build_editor_command() {
|
|
|
15098
15967
|
return cmd;
|
|
15099
15968
|
}
|
|
15100
15969
|
|
|
15101
|
-
// src/project-search.ts
|
|
15102
|
-
init_scanner();
|
|
15103
|
-
var import_fs20 = require("fs");
|
|
15104
|
-
var path8 = __toESM(require("path"));
|
|
15105
|
-
var BINARY_EXTENSIONS = new Set([
|
|
15106
|
-
".png",
|
|
15107
|
-
".jpg",
|
|
15108
|
-
".jpeg",
|
|
15109
|
-
".gif",
|
|
15110
|
-
".bmp",
|
|
15111
|
-
".tga",
|
|
15112
|
-
".psd",
|
|
15113
|
-
".tif",
|
|
15114
|
-
".tiff",
|
|
15115
|
-
".fbx",
|
|
15116
|
-
".obj",
|
|
15117
|
-
".dae",
|
|
15118
|
-
".blend",
|
|
15119
|
-
".3ds",
|
|
15120
|
-
".max",
|
|
15121
|
-
".dll",
|
|
15122
|
-
".so",
|
|
15123
|
-
".dylib",
|
|
15124
|
-
".exe",
|
|
15125
|
-
".a",
|
|
15126
|
-
".lib",
|
|
15127
|
-
".mp3",
|
|
15128
|
-
".wav",
|
|
15129
|
-
".ogg",
|
|
15130
|
-
".aif",
|
|
15131
|
-
".aiff",
|
|
15132
|
-
".mp4",
|
|
15133
|
-
".mov",
|
|
15134
|
-
".avi",
|
|
15135
|
-
".wmv",
|
|
15136
|
-
".zip",
|
|
15137
|
-
".gz",
|
|
15138
|
-
".tar",
|
|
15139
|
-
".rar",
|
|
15140
|
-
".7z",
|
|
15141
|
-
".ttf",
|
|
15142
|
-
".otf",
|
|
15143
|
-
".woff",
|
|
15144
|
-
".woff2",
|
|
15145
|
-
".bank",
|
|
15146
|
-
".bytes",
|
|
15147
|
-
".db"
|
|
15148
|
-
]);
|
|
15149
|
-
var SKIP_DIRS = new Set(["Library", "Temp", "obj", "Logs", ".git", ".unity-agentic", "node_modules"]);
|
|
15150
|
-
function walk_project_files(project_path, extensions, exclude_dirs) {
|
|
15151
|
-
const nativeWalk = getNativeWalkProjectFiles();
|
|
15152
|
-
if (nativeWalk) {
|
|
15153
|
-
try {
|
|
15154
|
-
return nativeWalk(project_path, extensions, exclude_dirs ?? null);
|
|
15155
|
-
} catch {}
|
|
15156
|
-
}
|
|
15157
|
-
return walk_project_files_js(project_path, extensions, exclude_dirs);
|
|
15158
|
-
}
|
|
15159
|
-
function walk_project_files_js(project_path, extensions, exclude_dirs) {
|
|
15160
|
-
const result = [];
|
|
15161
|
-
const skipSet = new Set([...SKIP_DIRS, ...exclude_dirs || []]);
|
|
15162
|
-
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
15163
|
-
function walk(dir) {
|
|
15164
|
-
let entries;
|
|
15165
|
-
try {
|
|
15166
|
-
entries = import_fs20.readdirSync(dir);
|
|
15167
|
-
} catch {
|
|
15168
|
-
return;
|
|
15169
|
-
}
|
|
15170
|
-
for (const entry of entries) {
|
|
15171
|
-
const full = path8.join(dir, entry);
|
|
15172
|
-
let stat;
|
|
15173
|
-
try {
|
|
15174
|
-
stat = import_fs20.statSync(full);
|
|
15175
|
-
} catch {
|
|
15176
|
-
continue;
|
|
15177
|
-
}
|
|
15178
|
-
if (stat.isDirectory()) {
|
|
15179
|
-
if (!skipSet.has(entry)) {
|
|
15180
|
-
walk(full);
|
|
15181
|
-
}
|
|
15182
|
-
} else if (stat.isFile()) {
|
|
15183
|
-
const ext = path8.extname(entry).toLowerCase();
|
|
15184
|
-
if (extSet.has(ext)) {
|
|
15185
|
-
result.push(full);
|
|
15186
|
-
}
|
|
15187
|
-
}
|
|
15188
|
-
}
|
|
15189
|
-
}
|
|
15190
|
-
const assetsDir = path8.join(project_path, "Assets");
|
|
15191
|
-
if (import_fs20.existsSync(assetsDir)) {
|
|
15192
|
-
walk(assetsDir);
|
|
15193
|
-
} else {
|
|
15194
|
-
walk(project_path);
|
|
15195
|
-
}
|
|
15196
|
-
if (extSet.has(".asset")) {
|
|
15197
|
-
const settingsDir = path8.join(project_path, "ProjectSettings");
|
|
15198
|
-
if (import_fs20.existsSync(settingsDir)) {
|
|
15199
|
-
walk(settingsDir);
|
|
15200
|
-
}
|
|
15201
|
-
}
|
|
15202
|
-
return result;
|
|
15203
|
-
}
|
|
15204
|
-
function search_project(options) {
|
|
15205
|
-
const {
|
|
15206
|
-
project_path,
|
|
15207
|
-
name,
|
|
15208
|
-
exact = false,
|
|
15209
|
-
component,
|
|
15210
|
-
tag,
|
|
15211
|
-
layer,
|
|
15212
|
-
file_type = "all",
|
|
15213
|
-
max_matches
|
|
15214
|
-
} = options;
|
|
15215
|
-
if (max_matches !== undefined && max_matches < 1) {
|
|
15216
|
-
return {
|
|
15217
|
-
success: false,
|
|
15218
|
-
project_path,
|
|
15219
|
-
total_files_scanned: 0,
|
|
15220
|
-
total_matches: 0,
|
|
15221
|
-
cursor: 0,
|
|
15222
|
-
truncated: false,
|
|
15223
|
-
matches: [],
|
|
15224
|
-
error: "--max-matches must be a positive integer (>= 1)"
|
|
15225
|
-
};
|
|
15226
|
-
}
|
|
15227
|
-
if (name !== undefined && name.trim() === "") {
|
|
15228
|
-
return {
|
|
15229
|
-
success: false,
|
|
15230
|
-
project_path,
|
|
15231
|
-
total_files_scanned: 0,
|
|
15232
|
-
total_matches: 0,
|
|
15233
|
-
cursor: 0,
|
|
15234
|
-
truncated: false,
|
|
15235
|
-
matches: [],
|
|
15236
|
-
error: "Name pattern must not be empty"
|
|
15237
|
-
};
|
|
15238
|
-
}
|
|
15239
|
-
if (!import_fs20.existsSync(project_path)) {
|
|
15240
|
-
return {
|
|
15241
|
-
success: false,
|
|
15242
|
-
project_path,
|
|
15243
|
-
total_files_scanned: 0,
|
|
15244
|
-
total_matches: 0,
|
|
15245
|
-
cursor: 0,
|
|
15246
|
-
truncated: false,
|
|
15247
|
-
matches: [],
|
|
15248
|
-
error: `Project path not found: ${project_path}`
|
|
15249
|
-
};
|
|
15250
|
-
}
|
|
15251
|
-
const ASSET_TYPE_EXTENSIONS = {
|
|
15252
|
-
mat: [".mat"],
|
|
15253
|
-
anim: [".anim"],
|
|
15254
|
-
controller: [".controller"],
|
|
15255
|
-
asset: [".asset"]
|
|
15256
|
-
};
|
|
15257
|
-
const isAssetType = file_type in ASSET_TYPE_EXTENSIONS;
|
|
15258
|
-
if (isAssetType) {
|
|
15259
|
-
const extensions2 = ASSET_TYPE_EXTENSIONS[file_type];
|
|
15260
|
-
const files2 = walk_project_files(project_path, extensions2);
|
|
15261
|
-
const matches2 = [];
|
|
15262
|
-
for (const file of files2) {
|
|
15263
|
-
const relPath = path8.relative(project_path, file);
|
|
15264
|
-
const fileName = path8.basename(file, path8.extname(file));
|
|
15265
|
-
if (name) {
|
|
15266
|
-
const nameLower = name.toLowerCase();
|
|
15267
|
-
const hasWildcard = name.includes("*") || name.includes("?");
|
|
15268
|
-
if (hasWildcard) {
|
|
15269
|
-
if (!glob_match(name, fileName))
|
|
15270
|
-
continue;
|
|
15271
|
-
} else if (exact) {
|
|
15272
|
-
if (fileName !== name)
|
|
15273
|
-
continue;
|
|
15274
|
-
} else {
|
|
15275
|
-
if (!fileName.toLowerCase().includes(nameLower))
|
|
15276
|
-
continue;
|
|
15277
|
-
}
|
|
15278
|
-
}
|
|
15279
|
-
let display_name = fileName;
|
|
15280
|
-
try {
|
|
15281
|
-
const content = import_fs20.readFileSync(file, "utf-8");
|
|
15282
|
-
const nameMatch = /^\s*m_Name:\s*(.+)$/m.exec(content.slice(0, 2000));
|
|
15283
|
-
if (nameMatch)
|
|
15284
|
-
display_name = nameMatch[1].trim();
|
|
15285
|
-
} catch {}
|
|
15286
|
-
matches2.push({
|
|
15287
|
-
file: relPath,
|
|
15288
|
-
game_object: display_name,
|
|
15289
|
-
file_id: "0"
|
|
15290
|
-
});
|
|
15291
|
-
if (max_matches !== undefined && matches2.length >= max_matches)
|
|
15292
|
-
break;
|
|
15293
|
-
}
|
|
15294
|
-
return {
|
|
15295
|
-
success: true,
|
|
15296
|
-
project_path,
|
|
15297
|
-
total_files_scanned: files2.length,
|
|
15298
|
-
total_matches: matches2.length,
|
|
15299
|
-
cursor: 0,
|
|
15300
|
-
truncated: max_matches !== undefined && matches2.length >= max_matches,
|
|
15301
|
-
matches: matches2
|
|
15302
|
-
};
|
|
15303
|
-
}
|
|
15304
|
-
if (!isNativeModuleAvailable()) {
|
|
15305
|
-
return {
|
|
15306
|
-
success: false,
|
|
15307
|
-
project_path,
|
|
15308
|
-
total_files_scanned: 0,
|
|
15309
|
-
total_matches: 0,
|
|
15310
|
-
cursor: 0,
|
|
15311
|
-
truncated: false,
|
|
15312
|
-
matches: [],
|
|
15313
|
-
error: "Native scanner module not available. Run bun install in the project root."
|
|
15314
|
-
};
|
|
15315
|
-
}
|
|
15316
|
-
const extensions = [];
|
|
15317
|
-
if (file_type === "scene" || file_type === "all")
|
|
15318
|
-
extensions.push(".unity");
|
|
15319
|
-
if (file_type === "prefab" || file_type === "all")
|
|
15320
|
-
extensions.push(".prefab");
|
|
15321
|
-
const files = walk_project_files(project_path, extensions);
|
|
15322
|
-
const scanner = new UnityScanner;
|
|
15323
|
-
const matches = [];
|
|
15324
|
-
for (const file of files) {
|
|
15325
|
-
try {
|
|
15326
|
-
let gameObjects;
|
|
15327
|
-
const needComponents = !!component;
|
|
15328
|
-
const needMetadata = !!(tag || layer !== undefined);
|
|
15329
|
-
if (name && !needMetadata && !needComponents) {
|
|
15330
|
-
gameObjects = scanner.find_by_name(file, name, !exact);
|
|
15331
|
-
} else if (needComponents) {
|
|
15332
|
-
gameObjects = scanner.scan_scene_with_components(file);
|
|
15333
|
-
if (name && !is_match_all(name)) {
|
|
15334
|
-
const nameLower = name.toLowerCase();
|
|
15335
|
-
const hasWildcard = name.includes("*") || name.includes("?");
|
|
15336
|
-
gameObjects = gameObjects.filter((go) => {
|
|
15337
|
-
if (!go.name)
|
|
15338
|
-
return false;
|
|
15339
|
-
if (hasWildcard) {
|
|
15340
|
-
return glob_match(name, go.name);
|
|
15341
|
-
}
|
|
15342
|
-
if (exact) {
|
|
15343
|
-
return go.name === name;
|
|
15344
|
-
}
|
|
15345
|
-
return go.name.toLowerCase().includes(nameLower);
|
|
15346
|
-
});
|
|
15347
|
-
}
|
|
15348
|
-
} else if (needMetadata) {
|
|
15349
|
-
gameObjects = scanner.scan_scene_metadata(file);
|
|
15350
|
-
if (name && !is_match_all(name)) {
|
|
15351
|
-
const nameLower = name.toLowerCase();
|
|
15352
|
-
const hasWildcard = name.includes("*") || name.includes("?");
|
|
15353
|
-
gameObjects = gameObjects.filter((go) => {
|
|
15354
|
-
if (!go.name)
|
|
15355
|
-
return false;
|
|
15356
|
-
if (hasWildcard) {
|
|
15357
|
-
return glob_match(name, go.name);
|
|
15358
|
-
}
|
|
15359
|
-
if (exact) {
|
|
15360
|
-
return go.name === name;
|
|
15361
|
-
}
|
|
15362
|
-
return go.name.toLowerCase().includes(nameLower);
|
|
15363
|
-
});
|
|
15364
|
-
}
|
|
15365
|
-
} else {
|
|
15366
|
-
gameObjects = scanner.scan_scene_minimal(file);
|
|
15367
|
-
}
|
|
15368
|
-
for (const go of gameObjects) {
|
|
15369
|
-
const isFindResult = "resultType" in go;
|
|
15370
|
-
const isPrefab = isFindResult && go.resultType === "PrefabInstance";
|
|
15371
|
-
if (isPrefab && (component || tag || layer !== undefined)) {
|
|
15372
|
-
continue;
|
|
15373
|
-
}
|
|
15374
|
-
if (component) {
|
|
15375
|
-
if ("components" in go && go.components) {
|
|
15376
|
-
const hasComponent = go.components.some((c) => glob_match(component, c.type));
|
|
15377
|
-
if (!hasComponent)
|
|
15378
|
-
continue;
|
|
15379
|
-
} else {
|
|
15380
|
-
continue;
|
|
15381
|
-
}
|
|
15382
|
-
}
|
|
15383
|
-
if (tag) {
|
|
15384
|
-
if (!("tag" in go) || go.tag !== tag)
|
|
15385
|
-
continue;
|
|
15386
|
-
}
|
|
15387
|
-
if (layer !== undefined) {
|
|
15388
|
-
if (!("layer" in go) || go.layer !== layer)
|
|
15389
|
-
continue;
|
|
15390
|
-
}
|
|
15391
|
-
const relPath = path8.relative(project_path, file);
|
|
15392
|
-
const fileId = isFindResult ? go.fileId : go.file_id;
|
|
15393
|
-
const match = {
|
|
15394
|
-
file: relPath,
|
|
15395
|
-
game_object: go.name,
|
|
15396
|
-
file_id: fileId,
|
|
15397
|
-
tag: "tag" in go ? go.tag : undefined,
|
|
15398
|
-
layer: "layer" in go ? go.layer : undefined
|
|
15399
|
-
};
|
|
15400
|
-
if ("components" in go && go.components) {
|
|
15401
|
-
match.components = go.components.map((c) => c.type);
|
|
15402
|
-
}
|
|
15403
|
-
matches.push(match);
|
|
15404
|
-
if (max_matches !== undefined && matches.length >= max_matches)
|
|
15405
|
-
break;
|
|
15406
|
-
}
|
|
15407
|
-
if (max_matches !== undefined && matches.length >= max_matches)
|
|
15408
|
-
break;
|
|
15409
|
-
} catch {
|
|
15410
|
-
continue;
|
|
15411
|
-
}
|
|
15412
|
-
}
|
|
15413
|
-
return {
|
|
15414
|
-
success: true,
|
|
15415
|
-
project_path,
|
|
15416
|
-
total_files_scanned: files.length,
|
|
15417
|
-
total_matches: matches.length,
|
|
15418
|
-
cursor: 0,
|
|
15419
|
-
truncated: max_matches !== undefined && matches.length >= max_matches,
|
|
15420
|
-
matches
|
|
15421
|
-
};
|
|
15422
|
-
}
|
|
15423
|
-
function grep_project(options) {
|
|
15424
|
-
const nativeGrep = getNativeGrepProject();
|
|
15425
|
-
if (nativeGrep) {
|
|
15426
|
-
try {
|
|
15427
|
-
const nativeResult = nativeGrep({
|
|
15428
|
-
projectPath: options.project_path,
|
|
15429
|
-
pattern: options.pattern,
|
|
15430
|
-
fileType: options.file_type,
|
|
15431
|
-
maxResults: options.max_results,
|
|
15432
|
-
contextLines: options.context_lines
|
|
15433
|
-
});
|
|
15434
|
-
return {
|
|
15435
|
-
success: nativeResult.success,
|
|
15436
|
-
project_path: nativeResult.projectPath,
|
|
15437
|
-
pattern: nativeResult.pattern,
|
|
15438
|
-
total_files_scanned: nativeResult.totalFilesScanned,
|
|
15439
|
-
total_matches: nativeResult.totalMatches,
|
|
15440
|
-
truncated: nativeResult.truncated,
|
|
15441
|
-
error: nativeResult.error,
|
|
15442
|
-
matches: nativeResult.matches.map((m) => ({
|
|
15443
|
-
file: m.file,
|
|
15444
|
-
line_number: m.lineNumber,
|
|
15445
|
-
line: m.line,
|
|
15446
|
-
context_before: m.contextBefore,
|
|
15447
|
-
context_after: m.contextAfter
|
|
15448
|
-
}))
|
|
15449
|
-
};
|
|
15450
|
-
} catch {}
|
|
15451
|
-
}
|
|
15452
|
-
return grep_project_js(options);
|
|
15453
|
-
}
|
|
15454
|
-
function grep_project_js(options) {
|
|
15455
|
-
const {
|
|
15456
|
-
project_path,
|
|
15457
|
-
pattern,
|
|
15458
|
-
file_type = "all",
|
|
15459
|
-
max_results = 100,
|
|
15460
|
-
context_lines = 0
|
|
15461
|
-
} = options;
|
|
15462
|
-
if (!import_fs20.existsSync(project_path)) {
|
|
15463
|
-
return {
|
|
15464
|
-
success: false,
|
|
15465
|
-
project_path,
|
|
15466
|
-
pattern,
|
|
15467
|
-
total_files_scanned: 0,
|
|
15468
|
-
total_matches: 0,
|
|
15469
|
-
truncated: false,
|
|
15470
|
-
matches: [],
|
|
15471
|
-
error: `Project path not found: ${project_path}`
|
|
15472
|
-
};
|
|
15473
|
-
}
|
|
15474
|
-
let regex;
|
|
15475
|
-
try {
|
|
15476
|
-
regex = new RegExp(pattern, "i");
|
|
15477
|
-
} catch (err) {
|
|
15478
|
-
return {
|
|
15479
|
-
success: false,
|
|
15480
|
-
project_path,
|
|
15481
|
-
pattern,
|
|
15482
|
-
total_files_scanned: 0,
|
|
15483
|
-
total_matches: 0,
|
|
15484
|
-
truncated: false,
|
|
15485
|
-
matches: [],
|
|
15486
|
-
error: `Invalid regex pattern: ${err instanceof Error ? err.message : String(err)}`
|
|
15487
|
-
};
|
|
15488
|
-
}
|
|
15489
|
-
const EXTENSION_MAP = {
|
|
15490
|
-
cs: [".cs"],
|
|
15491
|
-
yaml: [
|
|
15492
|
-
".yaml",
|
|
15493
|
-
".yml",
|
|
15494
|
-
".unity",
|
|
15495
|
-
".prefab",
|
|
15496
|
-
".asset",
|
|
15497
|
-
".mat",
|
|
15498
|
-
".anim",
|
|
15499
|
-
".controller",
|
|
15500
|
-
".overrideController",
|
|
15501
|
-
".mask",
|
|
15502
|
-
".mixer",
|
|
15503
|
-
".lighting",
|
|
15504
|
-
".preset",
|
|
15505
|
-
".signal",
|
|
15506
|
-
".playable",
|
|
15507
|
-
".renderTexture",
|
|
15508
|
-
".flare",
|
|
15509
|
-
".guiskin",
|
|
15510
|
-
".terrainlayer",
|
|
15511
|
-
".cubemap"
|
|
15512
|
-
],
|
|
15513
|
-
unity: [".unity"],
|
|
15514
|
-
prefab: [".prefab"],
|
|
15515
|
-
asset: [".asset"],
|
|
15516
|
-
mat: [".mat"],
|
|
15517
|
-
anim: [".anim"],
|
|
15518
|
-
controller: [".controller"],
|
|
15519
|
-
all: [
|
|
15520
|
-
".cs",
|
|
15521
|
-
".unity",
|
|
15522
|
-
".prefab",
|
|
15523
|
-
".asset",
|
|
15524
|
-
".mat",
|
|
15525
|
-
".anim",
|
|
15526
|
-
".controller",
|
|
15527
|
-
".yaml",
|
|
15528
|
-
".yml",
|
|
15529
|
-
".txt",
|
|
15530
|
-
".json",
|
|
15531
|
-
".xml",
|
|
15532
|
-
".shader",
|
|
15533
|
-
".cginc",
|
|
15534
|
-
".hlsl",
|
|
15535
|
-
".compute",
|
|
15536
|
-
".asmdef",
|
|
15537
|
-
".asmref"
|
|
15538
|
-
]
|
|
15539
|
-
};
|
|
15540
|
-
const extensions = EXTENSION_MAP[file_type] || EXTENSION_MAP.all;
|
|
15541
|
-
const files = walk_project_files(project_path, extensions);
|
|
15542
|
-
const matches = [];
|
|
15543
|
-
let totalFilesScanned = 0;
|
|
15544
|
-
let truncated = false;
|
|
15545
|
-
for (const file of files) {
|
|
15546
|
-
const ext = path8.extname(file).toLowerCase();
|
|
15547
|
-
if (BINARY_EXTENSIONS.has(ext))
|
|
15548
|
-
continue;
|
|
15549
|
-
totalFilesScanned++;
|
|
15550
|
-
let content;
|
|
15551
|
-
try {
|
|
15552
|
-
content = import_fs20.readFileSync(file, "utf-8");
|
|
15553
|
-
} catch {
|
|
15554
|
-
continue;
|
|
15555
|
-
}
|
|
15556
|
-
const lines = content.split(`
|
|
15557
|
-
`);
|
|
15558
|
-
const relPath = path8.relative(project_path, file);
|
|
15559
|
-
for (let i = 0;i < lines.length; i++) {
|
|
15560
|
-
if (regex.test(lines[i])) {
|
|
15561
|
-
let line = lines[i];
|
|
15562
|
-
if (line.length > 200) {
|
|
15563
|
-
line = line.substring(0, 200) + "...";
|
|
15564
|
-
}
|
|
15565
|
-
const match = {
|
|
15566
|
-
file: relPath,
|
|
15567
|
-
line_number: i + 1,
|
|
15568
|
-
line
|
|
15569
|
-
};
|
|
15570
|
-
if (context_lines > 0) {
|
|
15571
|
-
match.context_before = [];
|
|
15572
|
-
match.context_after = [];
|
|
15573
|
-
for (let j = Math.max(0, i - context_lines);j < i; j++) {
|
|
15574
|
-
let ctxLine = lines[j];
|
|
15575
|
-
if (ctxLine.length > 200)
|
|
15576
|
-
ctxLine = ctxLine.substring(0, 200) + "...";
|
|
15577
|
-
match.context_before.push(ctxLine);
|
|
15578
|
-
}
|
|
15579
|
-
for (let j = i + 1;j <= Math.min(lines.length - 1, i + context_lines); j++) {
|
|
15580
|
-
let ctxLine = lines[j];
|
|
15581
|
-
if (ctxLine.length > 200)
|
|
15582
|
-
ctxLine = ctxLine.substring(0, 200) + "...";
|
|
15583
|
-
match.context_after.push(ctxLine);
|
|
15584
|
-
}
|
|
15585
|
-
}
|
|
15586
|
-
matches.push(match);
|
|
15587
|
-
if (matches.length >= max_results) {
|
|
15588
|
-
truncated = true;
|
|
15589
|
-
break;
|
|
15590
|
-
}
|
|
15591
|
-
}
|
|
15592
|
-
}
|
|
15593
|
-
if (truncated)
|
|
15594
|
-
break;
|
|
15595
|
-
}
|
|
15596
|
-
return {
|
|
15597
|
-
success: true,
|
|
15598
|
-
project_path,
|
|
15599
|
-
pattern,
|
|
15600
|
-
total_files_scanned: totalFilesScanned,
|
|
15601
|
-
total_matches: matches.length,
|
|
15602
|
-
truncated,
|
|
15603
|
-
matches
|
|
15604
|
-
};
|
|
15605
|
-
}
|
|
15606
|
-
|
|
15607
15970
|
// src/cli.ts
|
|
15608
15971
|
var path9 = __toESM(require("path"));
|
|
15609
15972
|
var { exec } = require("child_process");
|