unity-agentic-tools 0.3.0 → 0.3.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 CHANGED
@@ -2294,7 +2294,7 @@ var require_package = __commonJS((exports2, module2) => {
2294
2294
  module2.exports = {
2295
2295
  name: "unity-agentic-tools",
2296
2296
  packageManager: "bun@latest",
2297
- version: "0.3.0",
2297
+ version: "0.3.1",
2298
2298
  description: "Fast, token-efficient Unity YAML parser for AI agents",
2299
2299
  exports: {
2300
2300
  ".": {
@@ -3663,7 +3663,7 @@ ${element_indent2}- ${value}`);
3663
3663
  }
3664
3664
  extract_file_id_refs() {
3665
3665
  const refs = [];
3666
- const pattern = /\{fileID:\s*(\d+)/g;
3666
+ const pattern = /\{fileID:\s*(-?\d+)/g;
3667
3667
  const first_newline = this._raw.indexOf(`
3668
3668
  `);
3669
3669
  const body = first_newline === -1 ? "" : this._raw.slice(first_newline);
@@ -3969,7 +3969,7 @@ class UnityDocument {
3969
3969
  const game_objects = this.find_game_objects_by_name(name);
3970
3970
  const transform_ids = [];
3971
3971
  for (const go of game_objects) {
3972
- const comp_matches = go.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/g);
3972
+ const comp_matches = go.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g);
3973
3973
  for (const cm of comp_matches) {
3974
3974
  const comp_block = this.find_by_file_id(cm[1]);
3975
3975
  if (comp_block && (comp_block.class_id === 4 || comp_block.class_id === 224)) {
@@ -3981,7 +3981,7 @@ class UnityDocument {
3981
3981
  return transform_ids;
3982
3982
  }
3983
3983
  require_unique_game_object(name_or_id) {
3984
- if (/^\d+$/.test(name_or_id)) {
3984
+ if (/^-?\d+$/.test(name_or_id)) {
3985
3985
  const block = this.find_by_file_id(name_or_id);
3986
3986
  if (!block) {
3987
3987
  return { error: `GameObject with fileID ${name_or_id} not found` };
@@ -4002,7 +4002,7 @@ class UnityDocument {
4002
4002
  return matches[0];
4003
4003
  }
4004
4004
  require_unique_transform(name_or_id) {
4005
- if (/^\d+$/.test(name_or_id)) {
4005
+ if (/^-?\d+$/.test(name_or_id)) {
4006
4006
  const block = this.find_by_file_id(name_or_id);
4007
4007
  if (!block) {
4008
4008
  return { error: `Block with fileID ${name_or_id} not found` };
@@ -4014,7 +4014,7 @@ class UnityDocument {
4014
4014
  return block;
4015
4015
  }
4016
4016
  if (block.class_id === 1) {
4017
- const comp_matches = block.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/g);
4017
+ const comp_matches = block.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g);
4018
4018
  for (const cm of comp_matches) {
4019
4019
  const comp_block = this.find_by_file_id(cm[1]);
4020
4020
  if (comp_block && (comp_block.class_id === 4 || comp_block.class_id === 224)) {
@@ -4042,7 +4042,7 @@ class UnityDocument {
4042
4042
  find_prefab_root() {
4043
4043
  for (const block of this._blocks) {
4044
4044
  if (block.class_id === 4 && !block.is_stripped && /m_Father:\s*\{fileID:\s*0\}/.test(block.raw)) {
4045
- const go_match = block.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
4045
+ const go_match = block.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
4046
4046
  if (go_match) {
4047
4047
  const go_block = this.find_by_file_id(go_match[1]);
4048
4048
  if (go_block) {
@@ -4239,7 +4239,7 @@ class UnityDocument {
4239
4239
  return true;
4240
4240
  }
4241
4241
  if (raw.includes("m_Children:") && !raw.includes(`fileID: ${child_id}`)) {
4242
- raw = raw.replace(/(m_Children:\s*\n(?:\s*-\s*\{fileID:\s*\d+\}\s*\n)*)/, `$1 - {fileID: ${child_id}}
4242
+ raw = raw.replace(/(m_Children:\s*\n(?:\s*-\s*\{fileID:\s*-?\d+\}\s*\n)*)/, `$1 - {fileID: ${child_id}}
4243
4243
  `);
4244
4244
  parent.replace_raw(raw);
4245
4245
  return true;
@@ -4275,7 +4275,7 @@ class UnityDocument {
4275
4275
  if (!children_section)
4276
4276
  return;
4277
4277
  const child_ids = [];
4278
- const child_matches = children_section[0].matchAll(/\{fileID:\s*(\d+)\}/g);
4278
+ const child_matches = children_section[0].matchAll(/\{fileID:\s*(-?\d+)\}/g);
4279
4279
  for (const m of child_matches) {
4280
4280
  if (m[1] !== "0")
4281
4281
  child_ids.push(m[1]);
@@ -4284,13 +4284,13 @@ class UnityDocument {
4284
4284
  result.add(child_transform_id);
4285
4285
  const child_transform = this.find_by_file_id(child_transform_id);
4286
4286
  if (child_transform) {
4287
- const go_match = child_transform.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
4287
+ const go_match = child_transform.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
4288
4288
  if (go_match) {
4289
4289
  const go_id = go_match[1];
4290
4290
  result.add(go_id);
4291
4291
  const go_block = this.find_by_file_id(go_id);
4292
4292
  if (go_block) {
4293
- const comp_matches = go_block.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
4293
+ const comp_matches = go_block.raw.matchAll(/component:\s*\{fileID:\s*(-?\d+)\}/g);
4294
4294
  for (const cm of comp_matches) {
4295
4295
  result.add(cm[1]);
4296
4296
  }
@@ -4315,7 +4315,7 @@ class UnityDocument {
4315
4315
  return 0;
4316
4316
  const children_match = parent.raw.match(/m_Children:[\s\S]*?(?=\s*m_Father:)/);
4317
4317
  if (children_match) {
4318
- const entries = children_match[0].match(/\{fileID:\s*\d+\}/g);
4318
+ const entries = children_match[0].match(/\{fileID:\s*-?\d+\}/g);
4319
4319
  return entries ? entries.length : 0;
4320
4320
  }
4321
4321
  return 0;
@@ -4350,7 +4350,7 @@ ${new_children}`);
4350
4350
  const transform = this.find_by_file_id(transform_id);
4351
4351
  if (!transform)
4352
4352
  continue;
4353
- const go_match = transform.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
4353
+ const go_match = transform.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
4354
4354
  if (!go_match)
4355
4355
  continue;
4356
4356
  const go_id = go_match[1];
@@ -4358,7 +4358,7 @@ ${new_children}`);
4358
4358
  if (!go)
4359
4359
  continue;
4360
4360
  const comp_ids = [];
4361
- const comp_matches = go.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
4361
+ const comp_matches = go.raw.matchAll(/component:\s*\{fileID:\s*(-?\d+)\}/g);
4362
4362
  for (const m of comp_matches) {
4363
4363
  comp_ids.push(m[1]);
4364
4364
  }
@@ -6382,7 +6382,7 @@ function isAncestor(doc, childTransformId, candidateAncestorTransformId) {
6382
6382
  const block = doc.find_by_file_id(currentId);
6383
6383
  if (!block || block.class_id !== 4)
6384
6384
  break;
6385
- const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(\d+)\}/);
6385
+ const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
6386
6386
  currentId = fatherMatch ? fatherMatch[1] : "0";
6387
6387
  }
6388
6388
  return false;
@@ -6392,7 +6392,7 @@ function resolveTransformByGameObjectId(doc, gameObjectFileId) {
6392
6392
  if (!found || found.class_id !== 1) {
6393
6393
  return { error: `GameObject with fileID ${gameObjectFileId} not found` };
6394
6394
  }
6395
- const componentMatch = found.raw.match(/m_Component:\s*\n\s*-\s*component:\s*\{fileID:\s*(\d+)\}/);
6395
+ const componentMatch = found.raw.match(/m_Component:\s*\n\s*-\s*component:\s*\{fileID:\s*(-?\d+)\}/);
6396
6396
  if (!componentMatch) {
6397
6397
  return { error: `GameObject fileID ${gameObjectFileId} has no Transform component` };
6398
6398
  }
@@ -6477,7 +6477,7 @@ function safeUnityYAMLEdit(filePath, objectName, propertyName, newValue, project
6477
6477
  newValue = "0";
6478
6478
  }
6479
6479
  let targetBlock = null;
6480
- if (/^\d+$/.test(objectName)) {
6480
+ if (/^-?\d+$/.test(objectName)) {
6481
6481
  targetBlock = doc.find_by_file_id(objectName);
6482
6482
  if (!targetBlock) {
6483
6483
  return {
@@ -6593,7 +6593,7 @@ function editComponentByFileId(options) {
6593
6593
  };
6594
6594
  }
6595
6595
  const classId = targetBlock.class_id;
6596
- const sameFileRefMatch = new_value.match(/^\{fileID:\s*(\d+)\}$/);
6596
+ const sameFileRefMatch = new_value.match(/^\{fileID:\s*(-?\d+)\}$/);
6597
6597
  if (sameFileRefMatch) {
6598
6598
  const refId = sameFileRefMatch[1];
6599
6599
  if (refId !== "0" && !doc.find_by_file_id(refId)) {
@@ -6888,7 +6888,7 @@ function reparentGameObject(options) {
6888
6888
  return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
6889
6889
  }
6890
6890
  let childTransformId;
6891
- if (by_id || /^\d+$/.test(object_name)) {
6891
+ if (by_id || /^-?\d+$/.test(object_name)) {
6892
6892
  if (isNaN(parseInt(object_name, 10))) {
6893
6893
  return { success: false, file_path, error: `Invalid fileID: "${object_name}" \u2014 expected a numeric value` };
6894
6894
  }
@@ -6908,11 +6908,11 @@ function reparentGameObject(options) {
6908
6908
  if (!childBlock) {
6909
6909
  return { success: false, file_path, error: `Transform ${childTransformId} not found` };
6910
6910
  }
6911
- const fatherMatch = childBlock.raw.match(/m_Father:\s*\{fileID:\s*(\d+)\}/);
6911
+ const fatherMatch = childBlock.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
6912
6912
  const oldParentTransformId = fatherMatch ? fatherMatch[1] : "0";
6913
6913
  let newParentTransformId = "0";
6914
6914
  if (new_parent.toLowerCase() !== "root") {
6915
- if (by_id || /^\d+$/.test(new_parent)) {
6915
+ if (by_id || /^-?\d+$/.test(new_parent)) {
6916
6916
  if (isNaN(parseInt(new_parent, 10))) {
6917
6917
  return { success: false, file_path, error: `Invalid parent fileID: "${new_parent}" \u2014 expected a numeric value, or "root"` };
6918
6918
  }
@@ -7371,7 +7371,7 @@ function removeComponent(options) {
7371
7371
  if (found.class_id === 4) {
7372
7372
  return { success: false, file_path, error: "Cannot remove a Transform with remove-component. Use delete to remove the entire GameObject." };
7373
7373
  }
7374
- const goMatch = found.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
7374
+ const goMatch = found.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
7375
7375
  if (goMatch) {
7376
7376
  const parentGoId = goMatch[1];
7377
7377
  const goBlock = doc.find_by_file_id(parentGoId);
@@ -7418,7 +7418,7 @@ function deleteGameObject(options) {
7418
7418
  const goBlock = goResult;
7419
7419
  const goId = goBlock.file_id;
7420
7420
  const componentIds = new Set;
7421
- const compMatches = goBlock.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
7421
+ const compMatches = goBlock.raw.matchAll(/component:\s*\{fileID:\s*(-?\d+)\}/g);
7422
7422
  for (const cm of compMatches) {
7423
7423
  componentIds.add(cm[1]);
7424
7424
  }
@@ -7428,7 +7428,7 @@ function deleteGameObject(options) {
7428
7428
  const block = doc.find_by_file_id(compId);
7429
7429
  if (block && block.class_id === 4) {
7430
7430
  transformId = compId;
7431
- const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(\d+)\}/);
7431
+ const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
7432
7432
  if (fatherMatch) {
7433
7433
  fatherId = fatherMatch[1];
7434
7434
  }
@@ -8929,7 +8929,7 @@ function parse_material_yaml(content) {
8929
8929
  floats: [],
8930
8930
  colors: []
8931
8931
  };
8932
- const inline_ref_re = /\{[^}]*fileID:\s*(\d+)[^}]*guid:\s*([a-f0-9]{32})[^}]*\}/;
8932
+ const inline_ref_re = /\{[^}]*fileID:\s*(-?\d+)[^}]*guid:\s*([a-f0-9]{32})[^}]*\}/;
8933
8933
  const color_re = /\{[^}]*r:\s*([\d.e+-]+)[^}]*g:\s*([\d.e+-]+)[^}]*b:\s*([\d.e+-]+)[^}]*a:\s*([\d.e+-]+)[^}]*\}/;
8934
8934
  const scale_offset_re = /\{[^}]*x:\s*([\d.e+-]+)[^}]*y:\s*([\d.e+-]+)[^}]*\}/;
8935
8935
  let i = 0;
@@ -9654,7 +9654,7 @@ function build_read_command(getScanner) {
9654
9654
  process.exit(1);
9655
9655
  }
9656
9656
  let resolved_id = object_id;
9657
- if (!/^\d+$/.test(object_id)) {
9657
+ if (!/^-?\d+$/.test(object_id)) {
9658
9658
  const matches = getScanner().find_by_name(file, object_id, false);
9659
9659
  if (matches.length > 1) {
9660
9660
  const ids = matches.map((m) => m.fileId).join(", ");
@@ -9672,7 +9672,7 @@ function build_read_command(getScanner) {
9672
9672
  verbose: options.verbose
9673
9673
  });
9674
9674
  if (!result) {
9675
- const label = /^\d+$/.test(object_id) ? "fileID" : "name";
9675
+ const label = /^-?\d+$/.test(object_id) ? "fileID" : "name";
9676
9676
  console.log(JSON.stringify({ error: `GameObject with ${label} "${object_id}" not found` }, null, 2));
9677
9677
  process.exit(1);
9678
9678
  }
@@ -9932,7 +9932,7 @@ function build_read_command(getScanner) {
9932
9932
  try {
9933
9933
  const doc = UnityDocument.from_file(file);
9934
9934
  let block = null;
9935
- if (/^\d+$/.test(prefab_instance)) {
9935
+ if (/^-?\d+$/.test(prefab_instance)) {
9936
9936
  block = doc.find_by_file_id(prefab_instance);
9937
9937
  if (block && block.class_id !== 1001) {
9938
9938
  console.log(JSON.stringify({ error: `fileID ${prefab_instance} is not a PrefabInstance (class ${block.class_id})` }, null, 2));
@@ -9957,10 +9957,10 @@ function build_read_command(getScanner) {
9957
9957
  let i = 0;
9958
9958
  while (i < lines.length) {
9959
9959
  if (lines[i].trim().startsWith("- target:")) {
9960
- const target_match = lines[i].match(/\{fileID:\s*(\d+)/);
9960
+ const target_match = lines[i].match(/\{fileID:\s*(-?\d+)/);
9961
9961
  const property_match = i + 1 < lines.length ? lines[i + 1].match(/propertyPath:\s*(.+)/) : null;
9962
9962
  const value_match = i + 2 < lines.length ? lines[i + 2].match(/value:\s*(.*)/) : null;
9963
- const obj_ref_match = i + 3 < lines.length ? lines[i + 3].match(/objectReference:\s*\{fileID:\s*(\d+)/) : null;
9963
+ const obj_ref_match = i + 3 < lines.length ? lines[i + 3].match(/objectReference:\s*\{fileID:\s*(-?\d+)/) : null;
9964
9964
  if (target_match && property_match) {
9965
9965
  modifications.push({
9966
9966
  target_file_id: target_match[1],
@@ -10992,7 +10992,7 @@ function parseVector(str) {
10992
10992
  }
10993
10993
  function resolve_transform_id(scanner, file, identifier) {
10994
10994
  let resolved_id = identifier;
10995
- if (!/^\d+$/.test(identifier)) {
10995
+ if (!/^-?\d+$/.test(identifier)) {
10996
10996
  const matches = scanner.find_by_name(file, identifier, false);
10997
10997
  if (matches.length > 1) {
10998
10998
  const ids = matches.map((m) => m.fileId).join(", ");
@@ -11008,7 +11008,7 @@ function resolve_transform_id(scanner, file, identifier) {
11008
11008
  if (transform)
11009
11009
  return { transform_id: parseInt(transform.file_id, 10) };
11010
11010
  }
11011
- if (/^\d+$/.test(identifier)) {
11011
+ if (/^-?\d+$/.test(identifier)) {
11012
11012
  return { transform_id: parseInt(identifier, 10) };
11013
11013
  }
11014
11014
  return { error: `Could not resolve "${identifier}" to a Transform component. Use a GameObject name or transform fileID.` };
package/dist/index.js CHANGED
@@ -200,7 +200,7 @@ var require_package = __commonJS((exports2, module2) => {
200
200
  module2.exports = {
201
201
  name: "unity-agentic-tools",
202
202
  packageManager: "bun@latest",
203
- version: "0.3.0",
203
+ version: "0.3.1",
204
204
  description: "Fast, token-efficient Unity YAML parser for AI agents",
205
205
  exports: {
206
206
  ".": {
@@ -2707,7 +2707,7 @@ ${element_indent2}- ${value}`);
2707
2707
  }
2708
2708
  extract_file_id_refs() {
2709
2709
  const refs = [];
2710
- const pattern = /\{fileID:\s*(\d+)/g;
2710
+ const pattern = /\{fileID:\s*(-?\d+)/g;
2711
2711
  const first_newline = this._raw.indexOf(`
2712
2712
  `);
2713
2713
  const body = first_newline === -1 ? "" : this._raw.slice(first_newline);
@@ -3013,7 +3013,7 @@ class UnityDocument {
3013
3013
  const game_objects = this.find_game_objects_by_name(name);
3014
3014
  const transform_ids = [];
3015
3015
  for (const go of game_objects) {
3016
- const comp_matches = go.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/g);
3016
+ const comp_matches = go.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g);
3017
3017
  for (const cm of comp_matches) {
3018
3018
  const comp_block = this.find_by_file_id(cm[1]);
3019
3019
  if (comp_block && (comp_block.class_id === 4 || comp_block.class_id === 224)) {
@@ -3025,7 +3025,7 @@ class UnityDocument {
3025
3025
  return transform_ids;
3026
3026
  }
3027
3027
  require_unique_game_object(name_or_id) {
3028
- if (/^\d+$/.test(name_or_id)) {
3028
+ if (/^-?\d+$/.test(name_or_id)) {
3029
3029
  const block = this.find_by_file_id(name_or_id);
3030
3030
  if (!block) {
3031
3031
  return { error: `GameObject with fileID ${name_or_id} not found` };
@@ -3046,7 +3046,7 @@ class UnityDocument {
3046
3046
  return matches[0];
3047
3047
  }
3048
3048
  require_unique_transform(name_or_id) {
3049
- if (/^\d+$/.test(name_or_id)) {
3049
+ if (/^-?\d+$/.test(name_or_id)) {
3050
3050
  const block = this.find_by_file_id(name_or_id);
3051
3051
  if (!block) {
3052
3052
  return { error: `Block with fileID ${name_or_id} not found` };
@@ -3058,7 +3058,7 @@ class UnityDocument {
3058
3058
  return block;
3059
3059
  }
3060
3060
  if (block.class_id === 1) {
3061
- const comp_matches = block.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/g);
3061
+ const comp_matches = block.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g);
3062
3062
  for (const cm of comp_matches) {
3063
3063
  const comp_block = this.find_by_file_id(cm[1]);
3064
3064
  if (comp_block && (comp_block.class_id === 4 || comp_block.class_id === 224)) {
@@ -3086,7 +3086,7 @@ class UnityDocument {
3086
3086
  find_prefab_root() {
3087
3087
  for (const block of this._blocks) {
3088
3088
  if (block.class_id === 4 && !block.is_stripped && /m_Father:\s*\{fileID:\s*0\}/.test(block.raw)) {
3089
- const go_match = block.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
3089
+ const go_match = block.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
3090
3090
  if (go_match) {
3091
3091
  const go_block = this.find_by_file_id(go_match[1]);
3092
3092
  if (go_block) {
@@ -3283,7 +3283,7 @@ class UnityDocument {
3283
3283
  return true;
3284
3284
  }
3285
3285
  if (raw.includes("m_Children:") && !raw.includes(`fileID: ${child_id}`)) {
3286
- raw = raw.replace(/(m_Children:\s*\n(?:\s*-\s*\{fileID:\s*\d+\}\s*\n)*)/, `$1 - {fileID: ${child_id}}
3286
+ raw = raw.replace(/(m_Children:\s*\n(?:\s*-\s*\{fileID:\s*-?\d+\}\s*\n)*)/, `$1 - {fileID: ${child_id}}
3287
3287
  `);
3288
3288
  parent.replace_raw(raw);
3289
3289
  return true;
@@ -3319,7 +3319,7 @@ class UnityDocument {
3319
3319
  if (!children_section)
3320
3320
  return;
3321
3321
  const child_ids = [];
3322
- const child_matches = children_section[0].matchAll(/\{fileID:\s*(\d+)\}/g);
3322
+ const child_matches = children_section[0].matchAll(/\{fileID:\s*(-?\d+)\}/g);
3323
3323
  for (const m of child_matches) {
3324
3324
  if (m[1] !== "0")
3325
3325
  child_ids.push(m[1]);
@@ -3328,13 +3328,13 @@ class UnityDocument {
3328
3328
  result.add(child_transform_id);
3329
3329
  const child_transform = this.find_by_file_id(child_transform_id);
3330
3330
  if (child_transform) {
3331
- const go_match = child_transform.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
3331
+ const go_match = child_transform.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
3332
3332
  if (go_match) {
3333
3333
  const go_id = go_match[1];
3334
3334
  result.add(go_id);
3335
3335
  const go_block = this.find_by_file_id(go_id);
3336
3336
  if (go_block) {
3337
- const comp_matches = go_block.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
3337
+ const comp_matches = go_block.raw.matchAll(/component:\s*\{fileID:\s*(-?\d+)\}/g);
3338
3338
  for (const cm of comp_matches) {
3339
3339
  result.add(cm[1]);
3340
3340
  }
@@ -3359,7 +3359,7 @@ class UnityDocument {
3359
3359
  return 0;
3360
3360
  const children_match = parent.raw.match(/m_Children:[\s\S]*?(?=\s*m_Father:)/);
3361
3361
  if (children_match) {
3362
- const entries = children_match[0].match(/\{fileID:\s*\d+\}/g);
3362
+ const entries = children_match[0].match(/\{fileID:\s*-?\d+\}/g);
3363
3363
  return entries ? entries.length : 0;
3364
3364
  }
3365
3365
  return 0;
@@ -3394,7 +3394,7 @@ ${new_children}`);
3394
3394
  const transform = this.find_by_file_id(transform_id);
3395
3395
  if (!transform)
3396
3396
  continue;
3397
- const go_match = transform.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
3397
+ const go_match = transform.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
3398
3398
  if (!go_match)
3399
3399
  continue;
3400
3400
  const go_id = go_match[1];
@@ -3402,7 +3402,7 @@ ${new_children}`);
3402
3402
  if (!go)
3403
3403
  continue;
3404
3404
  const comp_ids = [];
3405
- const comp_matches = go.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
3405
+ const comp_matches = go.raw.matchAll(/component:\s*\{fileID:\s*(-?\d+)\}/g);
3406
3406
  for (const m of comp_matches) {
3407
3407
  comp_ids.push(m[1]);
3408
3408
  }
@@ -4799,7 +4799,7 @@ function isAncestor(doc, childTransformId, candidateAncestorTransformId) {
4799
4799
  const block = doc.find_by_file_id(currentId);
4800
4800
  if (!block || block.class_id !== 4)
4801
4801
  break;
4802
- const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(\d+)\}/);
4802
+ const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
4803
4803
  currentId = fatherMatch ? fatherMatch[1] : "0";
4804
4804
  }
4805
4805
  return false;
@@ -4809,7 +4809,7 @@ function resolveTransformByGameObjectId(doc, gameObjectFileId) {
4809
4809
  if (!found || found.class_id !== 1) {
4810
4810
  return { error: `GameObject with fileID ${gameObjectFileId} not found` };
4811
4811
  }
4812
- const componentMatch = found.raw.match(/m_Component:\s*\n\s*-\s*component:\s*\{fileID:\s*(\d+)\}/);
4812
+ const componentMatch = found.raw.match(/m_Component:\s*\n\s*-\s*component:\s*\{fileID:\s*(-?\d+)\}/);
4813
4813
  if (!componentMatch) {
4814
4814
  return { error: `GameObject fileID ${gameObjectFileId} has no Transform component` };
4815
4815
  }
@@ -4894,7 +4894,7 @@ function safeUnityYAMLEdit(filePath, objectName, propertyName, newValue, project
4894
4894
  newValue = "0";
4895
4895
  }
4896
4896
  let targetBlock = null;
4897
- if (/^\d+$/.test(objectName)) {
4897
+ if (/^-?\d+$/.test(objectName)) {
4898
4898
  targetBlock = doc.find_by_file_id(objectName);
4899
4899
  if (!targetBlock) {
4900
4900
  return {
@@ -5010,7 +5010,7 @@ function editComponentByFileId(options) {
5010
5010
  };
5011
5011
  }
5012
5012
  const classId = targetBlock.class_id;
5013
- const sameFileRefMatch = new_value.match(/^\{fileID:\s*(\d+)\}$/);
5013
+ const sameFileRefMatch = new_value.match(/^\{fileID:\s*(-?\d+)\}$/);
5014
5014
  if (sameFileRefMatch) {
5015
5015
  const refId = sameFileRefMatch[1];
5016
5016
  if (refId !== "0" && !doc.find_by_file_id(refId)) {
@@ -5305,7 +5305,7 @@ function reparentGameObject(options) {
5305
5305
  return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
5306
5306
  }
5307
5307
  let childTransformId;
5308
- if (by_id || /^\d+$/.test(object_name)) {
5308
+ if (by_id || /^-?\d+$/.test(object_name)) {
5309
5309
  if (isNaN(parseInt(object_name, 10))) {
5310
5310
  return { success: false, file_path, error: `Invalid fileID: "${object_name}" \u2014 expected a numeric value` };
5311
5311
  }
@@ -5325,11 +5325,11 @@ function reparentGameObject(options) {
5325
5325
  if (!childBlock) {
5326
5326
  return { success: false, file_path, error: `Transform ${childTransformId} not found` };
5327
5327
  }
5328
- const fatherMatch = childBlock.raw.match(/m_Father:\s*\{fileID:\s*(\d+)\}/);
5328
+ const fatherMatch = childBlock.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
5329
5329
  const oldParentTransformId = fatherMatch ? fatherMatch[1] : "0";
5330
5330
  let newParentTransformId = "0";
5331
5331
  if (new_parent.toLowerCase() !== "root") {
5332
- if (by_id || /^\d+$/.test(new_parent)) {
5332
+ if (by_id || /^-?\d+$/.test(new_parent)) {
5333
5333
  if (isNaN(parseInt(new_parent, 10))) {
5334
5334
  return { success: false, file_path, error: `Invalid parent fileID: "${new_parent}" \u2014 expected a numeric value, or "root"` };
5335
5335
  }
@@ -5788,7 +5788,7 @@ function removeComponent(options) {
5788
5788
  if (found.class_id === 4) {
5789
5789
  return { success: false, file_path, error: "Cannot remove a Transform with remove-component. Use delete to remove the entire GameObject." };
5790
5790
  }
5791
- const goMatch = found.raw.match(/m_GameObject:\s*\{fileID:\s*(\d+)\}/);
5791
+ const goMatch = found.raw.match(/m_GameObject:\s*\{fileID:\s*(-?\d+)\}/);
5792
5792
  if (goMatch) {
5793
5793
  const parentGoId = goMatch[1];
5794
5794
  const goBlock = doc.find_by_file_id(parentGoId);
@@ -5835,7 +5835,7 @@ function deleteGameObject(options) {
5835
5835
  const goBlock = goResult;
5836
5836
  const goId = goBlock.file_id;
5837
5837
  const componentIds = new Set;
5838
- const compMatches = goBlock.raw.matchAll(/component:\s*\{fileID:\s*(\d+)\}/g);
5838
+ const compMatches = goBlock.raw.matchAll(/component:\s*\{fileID:\s*(-?\d+)\}/g);
5839
5839
  for (const cm of compMatches) {
5840
5840
  componentIds.add(cm[1]);
5841
5841
  }
@@ -5845,7 +5845,7 @@ function deleteGameObject(options) {
5845
5845
  const block = doc.find_by_file_id(compId);
5846
5846
  if (block && block.class_id === 4) {
5847
5847
  transformId = compId;
5848
- const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(\d+)\}/);
5848
+ const fatherMatch = block.raw.match(/m_Father:\s*\{fileID:\s*(-?\d+)\}/);
5849
5849
  if (fatherMatch) {
5850
5850
  fatherId = fatherMatch[1];
5851
5851
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unity-agentic-tools",
3
3
  "packageManager": "bun@latest",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "description": "Fast, token-efficient Unity YAML parser for AI agents",
6
6
  "exports": {
7
7
  ".": {