@adhisang/minecraft-modding-mcp 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +7 -2
  2. package/README.md +5 -2
  3. package/dist/entry-tools/analyze-symbol-service.d.ts +12 -0
  4. package/dist/entry-tools/analyze-symbol-service.js +7 -0
  5. package/dist/entry-tools/batch-class-members-service.d.ts +1 -0
  6. package/dist/entry-tools/batch-class-members-service.js +2 -0
  7. package/dist/entry-tools/batch-class-source-service.d.ts +1 -0
  8. package/dist/entry-tools/batch-class-source-service.js +2 -0
  9. package/dist/entry-tools/batch-mappings-service.d.ts +1 -0
  10. package/dist/entry-tools/batch-mappings-service.js +1 -0
  11. package/dist/entry-tools/batch-symbol-exists-service.d.ts +1 -0
  12. package/dist/entry-tools/batch-symbol-exists-service.js +2 -0
  13. package/dist/entry-tools/compare-minecraft-service.d.ts +9 -0
  14. package/dist/entry-tools/compare-minecraft-service.js +3 -1
  15. package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +1 -0
  16. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +3 -1
  17. package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +1 -0
  18. package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +1 -0
  19. package/dist/entry-tools/inspect-minecraft/handlers/search.js +2 -1
  20. package/dist/entry-tools/inspect-minecraft/internal.d.ts +17 -0
  21. package/dist/entry-tools/inspect-minecraft/internal.js +10 -0
  22. package/dist/entry-tools/inspect-minecraft-service.d.ts +40 -0
  23. package/dist/entry-tools/validate-project/cases/project-summary.js +8 -3
  24. package/dist/entry-tools/validate-project/internal.d.ts +6 -2
  25. package/dist/entry-tools/validate-project/internal.js +9 -7
  26. package/dist/entry-tools/validate-project-service.d.ts +10 -0
  27. package/dist/entry-tools/validate-project-service.js +1 -0
  28. package/dist/entry-tools/verify-mixin-target-service.d.ts +2 -0
  29. package/dist/entry-tools/verify-mixin-target-service.js +1 -0
  30. package/dist/gradle-paths.d.ts +8 -3
  31. package/dist/gradle-paths.js +34 -5
  32. package/dist/index.js +24 -7
  33. package/dist/mapping/loaders/tiny-loom.d.ts +1 -1
  34. package/dist/mapping/loaders/tiny-loom.js +5 -2
  35. package/dist/mapping/types.d.ts +5 -0
  36. package/dist/mapping-service.d.ts +1 -0
  37. package/dist/mapping-service.js +16 -13
  38. package/dist/mixin-validator.d.ts +1 -1
  39. package/dist/mixin-validator.js +1 -1
  40. package/dist/source/access-validate.js +12 -8
  41. package/dist/source/artifact-resolver.d.ts +5 -0
  42. package/dist/source/artifact-resolver.js +23 -7
  43. package/dist/source/class-source/members-builder.d.ts +1 -0
  44. package/dist/source/class-source/members-builder.js +1 -1
  45. package/dist/source/class-source.d.ts +1 -0
  46. package/dist/source/class-source.js +9 -1
  47. package/dist/source/lifecycle/diff.js +6 -6
  48. package/dist/source/lifecycle/mapping-helpers.d.ts +3 -3
  49. package/dist/source/lifecycle/mapping-helpers.js +17 -9
  50. package/dist/source/lifecycle/trace.js +2 -2
  51. package/dist/source/search.js +1 -0
  52. package/dist/source/symbol-resolver.js +4 -1
  53. package/dist/source/validate-mixin/pipeline/mapping-health.js +2 -1
  54. package/dist/source/validate-mixin/pipeline/resolve.js +1 -0
  55. package/dist/source/validate-mixin/pipeline/target-lookup.js +12 -7
  56. package/dist/source-service.d.ts +18 -1
  57. package/dist/source-service.js +2 -2
  58. package/dist/tool-contract-manifest.d.ts +1 -1
  59. package/dist/tool-contract-manifest.js +2 -2
  60. package/dist/tool-schemas.d.ts +91 -0
  61. package/dist/tool-schemas.js +20 -0
  62. package/docs/README-ja.md +2 -2
  63. package/docs/tool-reference.md +4 -1
  64. package/package.json +1 -1
@@ -185,6 +185,7 @@ export class VerifyMixinTargetService {
185
185
  mapping: input.mapping,
186
186
  sourcePriority: input.sourcePriority,
187
187
  projectPath: input.projectPath,
188
+ gradleUserHome: input.gradleUserHome,
188
189
  scope: input.scope,
189
190
  preferProjectVersion: input.preferProjectVersion,
190
191
  strictVersion: input.strictVersion
@@ -1,4 +1,9 @@
1
1
  export declare function normalizeOptionalProjectPath(projectPath: string | undefined): string | undefined;
2
- export declare function resolveGradleUserHomePath(): string;
3
- export declare function buildVersionSourceSearchRoots(projectPath: string | undefined): string[];
4
- export declare function buildLoaderRuntimeSearchRoots(projectPath: string | undefined): string[];
2
+ export declare function normalizeOptionalGradleUserHomePath(gradleUserHome: string | undefined): string | undefined;
3
+ export declare function resolveGradleUserHomePath(gradleUserHome?: string): string;
4
+ export type GradleCacheSearchInput = string | {
5
+ projectPath?: string;
6
+ gradleUserHome?: string;
7
+ } | undefined;
8
+ export declare function buildVersionSourceSearchRoots(input: GradleCacheSearchInput): string[];
9
+ export declare function buildLoaderRuntimeSearchRoots(input: GradleCacheSearchInput): string[];
@@ -12,7 +12,22 @@ export function normalizeOptionalProjectPath(projectPath) {
12
12
  const normalized = normalizePathForHost(trimmed, undefined, "projectPath");
13
13
  return isAbsolute(normalized) ? normalized : resolvePath(process.cwd(), normalized);
14
14
  }
15
- export function resolveGradleUserHomePath() {
15
+ export function normalizeOptionalGradleUserHomePath(gradleUserHome) {
16
+ if (!gradleUserHome) {
17
+ return undefined;
18
+ }
19
+ const trimmed = gradleUserHome.trim();
20
+ if (!trimmed) {
21
+ return undefined;
22
+ }
23
+ const normalized = normalizePathForHost(trimmed, undefined, "gradleUserHome");
24
+ return isAbsolute(normalized) ? normalized : resolvePath(process.cwd(), normalized);
25
+ }
26
+ export function resolveGradleUserHomePath(gradleUserHome) {
27
+ const explicit = normalizeOptionalGradleUserHomePath(gradleUserHome);
28
+ if (explicit) {
29
+ return explicit;
30
+ }
16
31
  const configured = process.env.GRADLE_USER_HOME?.trim();
17
32
  if (!configured) {
18
33
  return resolvePath(homedir(), ".gradle");
@@ -20,7 +35,20 @@ export function resolveGradleUserHomePath() {
20
35
  const normalized = normalizePathForHost(configured, undefined, "GRADLE_USER_HOME");
21
36
  return isAbsolute(normalized) ? normalized : resolvePath(process.cwd(), normalized);
22
37
  }
23
- export function buildVersionSourceSearchRoots(projectPath) {
38
+ function normalizeGradleCacheSearchInput(input) {
39
+ if (typeof input === "string" || input === undefined) {
40
+ return {
41
+ projectPath: normalizeOptionalProjectPath(input)
42
+ };
43
+ }
44
+ const gradleUserHome = normalizeOptionalGradleUserHomePath(input.gradleUserHome);
45
+ return {
46
+ projectPath: normalizeOptionalProjectPath(input.projectPath),
47
+ gradleUserHome
48
+ };
49
+ }
50
+ export function buildVersionSourceSearchRoots(input) {
51
+ const { projectPath, gradleUserHome } = normalizeGradleCacheSearchInput(input);
24
52
  const roots = new Set();
25
53
  if (projectPath) {
26
54
  roots.add(resolvePath(projectPath, ".gradle", "loom-cache"));
@@ -30,12 +58,13 @@ export function buildVersionSourceSearchRoots(projectPath) {
30
58
  roots.add(resolvePath(projectParent, ".gradle-user-home", "loom-cache"));
31
59
  roots.add(resolvePath(projectParent, ".gradle-user-home", "caches", "fabric-loom"));
32
60
  }
33
- const homeGradle = resolveGradleUserHomePath();
61
+ const homeGradle = resolveGradleUserHomePath(gradleUserHome);
34
62
  roots.add(resolvePath(homeGradle, "loom-cache"));
35
63
  roots.add(resolvePath(homeGradle, "caches", "fabric-loom"));
36
64
  return [...roots];
37
65
  }
38
- export function buildLoaderRuntimeSearchRoots(projectPath) {
66
+ export function buildLoaderRuntimeSearchRoots(input) {
67
+ const { projectPath, gradleUserHome } = normalizeGradleCacheSearchInput(input);
39
68
  const roots = new Set();
40
69
  if (projectPath) {
41
70
  roots.add(resolvePath(projectPath, "build"));
@@ -47,7 +76,7 @@ export function buildLoaderRuntimeSearchRoots(projectPath) {
47
76
  roots.add(resolvePath(projectPath, ".gradle", "caches", "neoformruntime"));
48
77
  roots.add(resolvePath(projectPath, ".gradle", "caches", "moddev"));
49
78
  }
50
- const homeGradle = resolveGradleUserHomePath();
79
+ const homeGradle = resolveGradleUserHomePath(gradleUserHome);
51
80
  roots.add(resolvePath(homeGradle, "caches", "forge_gradle"));
52
81
  roots.add(resolvePath(homeGradle, "caches", "neogradle"));
53
82
  roots.add(resolvePath(homeGradle, "caches", "neoformruntime"));
package/dist/index.js CHANGED
@@ -142,6 +142,7 @@ const validateProjectService = new ValidateProjectService({
142
142
  mapping: input.mapping,
143
143
  sourcePriority: input.sourcePriority,
144
144
  projectPath: input.projectPath,
145
+ gradleUserHome: input.gradleUserHome,
145
146
  scope: input.scope,
146
147
  preferProjectVersion: input.preferProjectVersion
147
148
  });
@@ -166,6 +167,7 @@ const verifyMixinTargetService = new VerifyMixinTargetService({
166
167
  mapping: input.mapping,
167
168
  sourcePriority: input.sourcePriority,
168
169
  projectPath: input.projectPath,
170
+ gradleUserHome: input.gradleUserHome,
169
171
  scope: input.scope,
170
172
  preferProjectVersion: input.preferProjectVersion,
171
173
  strictVersion: input.strictVersion
@@ -406,19 +408,19 @@ server.tool("list-versions", "List available Minecraft versions from Mojang mani
406
408
  limit: input.limit
407
409
  })));
408
410
  registerToolSchema("list-versions", listVersionsSchema);
409
- server.tool("inspect-minecraft", "High-level v3 entry tool for version discovery, artifact resolution, class inspection, source search, file reads, and file listings.", inspectMinecraftShape, { readOnlyHint: true }, async (args) => runTool("inspect-minecraft", args, inspectMinecraftSchema, async (input) => inspectMinecraftService.execute(input)));
411
+ server.tool("inspect-minecraft", "Top-level workflow tool for version discovery, artifact resolution, class inspection, source search, file reads, and file listings.", inspectMinecraftShape, { readOnlyHint: true }, async (args) => runTool("inspect-minecraft", args, inspectMinecraftSchema, async (input) => inspectMinecraftService.execute(input)));
410
412
  registerToolSchema("inspect-minecraft", inspectMinecraftSchema);
411
- server.tool("analyze-symbol", "High-level v3 entry tool for symbol existence, mapping, lifecycle, workspace analysis, and API overview.", analyzeSymbolShape, { readOnlyHint: true }, async (args) => runTool("analyze-symbol", args, analyzeSymbolSchema, async (input) => analyzeSymbolService.execute(input)));
413
+ server.tool("analyze-symbol", "Top-level workflow tool for symbol existence, mapping, lifecycle, workspace analysis, and API overview.", analyzeSymbolShape, { readOnlyHint: true }, async (args) => runTool("analyze-symbol", args, analyzeSymbolSchema, async (input) => analyzeSymbolService.execute(input)));
412
414
  registerToolSchema("analyze-symbol", analyzeSymbolSchema);
413
- server.tool("compare-minecraft", "High-level v3 entry tool for version comparisons, class diffs, registry diffs, and migration overviews.", compareMinecraftShape, { readOnlyHint: true }, async (args) => runTool("compare-minecraft", args, compareMinecraftSchema, async (input) => compareMinecraftService.execute(input)));
415
+ server.tool("compare-minecraft", "Top-level workflow tool for version comparisons, class diffs, registry diffs, and migration overviews.", compareMinecraftShape, { readOnlyHint: true }, async (args) => runTool("compare-minecraft", args, compareMinecraftSchema, async (input) => compareMinecraftService.execute(input)));
414
416
  registerToolSchema("compare-minecraft", compareMinecraftSchema);
415
- server.tool("analyze-mod", "High-level v3 entry tool for mod metadata inspection, decompile/search flows, class source, and safe remap previews/applies.", analyzeModShape, { readOnlyHint: false }, async (args) => runTool("analyze-mod", args, analyzeModSchema, async (input) => analyzeModService.execute(input)));
417
+ server.tool("analyze-mod", "Top-level workflow tool for mod metadata inspection, decompile/search flows, class source, and safe remap previews/applies.", analyzeModShape, { readOnlyHint: false }, async (args) => runTool("analyze-mod", args, analyzeModSchema, async (input) => analyzeModService.execute(input)));
416
418
  registerToolSchema("analyze-mod", analyzeModSchema);
417
- server.tool("validate-project", "High-level v3 entry tool for project summary, direct mixin validation, and access widener/access transformer validation.", validateProjectShape, { readOnlyHint: true }, async (args, extra) => runTool("validate-project", args, validateProjectSchema, async (input) => validateProjectService.execute(input, {
419
+ server.tool("validate-project", "Top-level workflow tool for project summary, direct mixin validation, and access widener/access transformer validation.", validateProjectShape, { readOnlyHint: true }, async (args, extra) => runTool("validate-project", args, validateProjectSchema, async (input) => validateProjectService.execute(input, {
418
420
  stageEmitter: makeStageEmitter(extra)
419
421
  })));
420
422
  registerToolSchema("validate-project", validateProjectSchema);
421
- server.tool("manage-cache", "High-level v3 entry tool for cache summaries, listing, verification, previewed mutation, and explicit apply operations.", manageCacheShape, { readOnlyHint: false }, async (args) => runTool("manage-cache", args, manageCacheSchema, async (input) => manageCacheService.execute(input)));
423
+ server.tool("manage-cache", "Top-level workflow tool for cache summaries, listing, verification, previewed mutation, and explicit apply operations.", manageCacheShape, { readOnlyHint: false }, async (args) => runTool("manage-cache", args, manageCacheSchema, async (input) => manageCacheService.execute(input)));
422
424
  registerToolSchema("manage-cache", manageCacheSchema);
423
425
  if (!VERIFY_MIXIN_TARGET_OFF) {
424
426
  server.tool("verify-mixin-target", "Single-call probe: does this target owner / member exist and which @Shadow / @Accessor / @Invoker should the mixin use? Reuses target.kind workspace/version/coordinate/dependency/jar.", verifyMixinTargetShape, { readOnlyHint: true }, async (args) => runTool("verify-mixin-target", args, verifyMixinTargetSchema, async (input) => verifyMixinTargetService.execute({
@@ -428,6 +430,7 @@ if (!VERIFY_MIXIN_TARGET_OFF) {
428
430
  mapping: input.mapping,
429
431
  sourcePriority: input.sourcePriority,
430
432
  projectPath: input.projectPath,
433
+ gradleUserHome: input.gradleUserHome,
431
434
  target: input.target,
432
435
  scope: input.scope,
433
436
  preferProjectVersion: input.preferProjectVersion,
@@ -451,6 +454,7 @@ server.tool("resolve-artifact", "Resolve source artifact from a target object ({
451
454
  sourcePriority: input.sourcePriority,
452
455
  allowDecompile: input.allowDecompile,
453
456
  projectPath: input.projectPath,
457
+ gradleUserHome: input.gradleUserHome,
454
458
  scope: input.scope,
455
459
  preferProjectVersion: input.preferProjectVersion,
456
460
  strictVersion: input.strictVersion,
@@ -480,6 +484,7 @@ server.tool("get-class-source", "Get Java source for a class by target ({ type:
480
484
  sourcePriority: input.sourcePriority,
481
485
  allowDecompile: input.allowDecompile,
482
486
  projectPath: input.projectPath,
487
+ gradleUserHome: input.gradleUserHome,
483
488
  scope: input.scope,
484
489
  preferProjectVersion: input.preferProjectVersion,
485
490
  strictVersion: input.strictVersion,
@@ -506,6 +511,7 @@ server.tool("get-class-members", "Get fields/methods/constructors for one class
506
511
  memberPattern: input.memberPattern,
507
512
  maxMembers: input.maxMembers,
508
513
  projectPath: input.projectPath,
514
+ gradleUserHome: input.gradleUserHome,
509
515
  scope: input.scope,
510
516
  preferProjectVersion: input.preferProjectVersion,
511
517
  strictVersion: input.strictVersion
@@ -530,7 +536,8 @@ server.tool("search-class-source", "Search indexed class source files for one ar
530
536
  limit: input.limit,
531
537
  cursor: input.cursor,
532
538
  queryNamespace: input.queryNamespace,
533
- sourcePriority: input.sourcePriority
539
+ sourcePriority: input.sourcePriority,
540
+ gradleUserHome: input.gradleUserHome
534
541
  });
535
542
  }));
536
543
  registerToolSchema("search-class-source", searchClassSourceSchema);
@@ -554,6 +561,7 @@ server.tool("trace-symbol-lifecycle", "Trace which Minecraft versions contain a
554
561
  toVersion: input.toVersion,
555
562
  mapping: input.mapping,
556
563
  sourcePriority: input.sourcePriority,
564
+ gradleUserHome: input.gradleUserHome,
557
565
  includeSnapshots: input.includeSnapshots,
558
566
  maxVersions: input.maxVersions,
559
567
  includeTimeline: input.includeTimeline
@@ -565,6 +573,7 @@ server.tool("diff-class-signatures", "Compare one class signature between two Mi
565
573
  toVersion: input.toVersion,
566
574
  mapping: input.mapping,
567
575
  sourcePriority: input.sourcePriority,
576
+ gradleUserHome: input.gradleUserHome,
568
577
  includeFullDiff: input.includeFullDiff
569
578
  })));
570
579
  registerToolSchema("diff-class-signatures", diffClassSignaturesSchema);
@@ -577,6 +586,7 @@ server.tool("find-mapping", "Find symbol mapping candidates between namespaces u
577
586
  sourceMapping: input.sourceMapping,
578
587
  targetMapping: input.targetMapping,
579
588
  sourcePriority: input.sourcePriority,
589
+ gradleUserHome: input.gradleUserHome,
580
590
  signatureMode: input.signatureMode,
581
591
  disambiguation: input.disambiguation,
582
592
  maxCandidates: input.maxCandidates
@@ -590,6 +600,7 @@ server.tool("resolve-method-mapping-exact", "Resolve one method mapping exactly
590
600
  sourceMapping: input.sourceMapping,
591
601
  targetMapping: input.targetMapping,
592
602
  sourcePriority: input.sourcePriority,
603
+ gradleUserHome: input.gradleUserHome,
593
604
  maxCandidates: input.maxCandidates
594
605
  })));
595
606
  registerToolSchema("resolve-method-mapping-exact", resolveMethodMappingExactSchema);
@@ -599,6 +610,7 @@ server.tool("get-class-api-matrix", "List class/member API rows across obfuscate
599
610
  classNameMapping: input.classNameMapping,
600
611
  includeKinds: parseClassApiKinds(input.includeKinds),
601
612
  sourcePriority: input.sourcePriority,
613
+ gradleUserHome: input.gradleUserHome,
602
614
  maxRows: input.maxRows
603
615
  })));
604
616
  registerToolSchema("get-class-api-matrix", getClassApiMatrixSchema);
@@ -611,6 +623,7 @@ server.tool("resolve-workspace-symbol", "Resolve class/field/method names as see
611
623
  descriptor: input.descriptor,
612
624
  sourceMapping: input.sourceMapping,
613
625
  sourcePriority: input.sourcePriority,
626
+ gradleUserHome: input.gradleUserHome,
614
627
  maxCandidates: input.maxCandidates
615
628
  })));
616
629
  registerToolSchema("resolve-workspace-symbol", resolveWorkspaceSymbolSchema);
@@ -622,6 +635,7 @@ server.tool("check-symbol-exists", "Check whether a class/field/method symbol ex
622
635
  descriptor: input.descriptor,
623
636
  sourceMapping: input.sourceMapping,
624
637
  sourcePriority: input.sourcePriority,
638
+ gradleUserHome: input.gradleUserHome,
625
639
  nameMode: input.nameMode,
626
640
  signatureMode: input.signatureMode,
627
641
  maxCandidates: input.maxCandidates
@@ -657,6 +671,7 @@ server.tool("validate-mixin", "Validate Mixin source against Minecraft bytecode
657
671
  sourcePriority: input.sourcePriority,
658
672
  scope: input.scope,
659
673
  projectPath: input.projectPath,
674
+ gradleUserHome: input.gradleUserHome,
660
675
  preferProjectVersion: input.preferProjectVersion,
661
676
  minSeverity: input.minSeverity,
662
677
  hideUncertain: input.hideUncertain,
@@ -677,6 +692,7 @@ server.tool("validate-access-widener", "Validate Access Widener file entries aga
677
692
  mapping: input.mapping,
678
693
  sourcePriority: input.sourcePriority,
679
694
  projectPath: input.projectPath,
695
+ gradleUserHome: input.gradleUserHome,
680
696
  scope: input.scope,
681
697
  preferProjectVersion: input.preferProjectVersion
682
698
  })));
@@ -687,6 +703,7 @@ server.tool("validate-access-transformer", "Validate Access Transformer file ent
687
703
  atNamespace: input.atNamespace,
688
704
  sourcePriority: input.sourcePriority,
689
705
  projectPath: input.projectPath,
706
+ gradleUserHome: input.gradleUserHome,
690
707
  scope: input.scope,
691
708
  preferProjectVersion: input.preferProjectVersion
692
709
  })));
@@ -1,2 +1,2 @@
1
1
  import type { MappingLoaderResult } from "./types.js";
2
- export declare function loadTinyPairsFromLoom(version: string, projectPath?: string): Promise<MappingLoaderResult>;
2
+ export declare function loadTinyPairsFromLoom(version: string, projectPath?: string, gradleUserHome?: string): Promise<MappingLoaderResult>;
@@ -7,8 +7,11 @@ import { effectiveLoomSearchProjectPath } from "../lookup.js";
7
7
  import { mergeDirectionIndexes } from "../parsers/symbol-records.js";
8
8
  import { parseTinyMappings } from "../parsers/tiny.js";
9
9
  const GLOB_SPECIAL_CHARS = /[\\!*+?()[\]{}@|]/g;
10
- export async function loadTinyPairsFromLoom(version, projectPath) {
11
- const searchRoots = buildVersionSourceSearchRoots(effectiveLoomSearchProjectPath(projectPath));
10
+ export async function loadTinyPairsFromLoom(version, projectPath, gradleUserHome) {
11
+ const searchRoots = buildVersionSourceSearchRoots({
12
+ projectPath: effectiveLoomSearchProjectPath(projectPath),
13
+ gradleUserHome
14
+ });
12
15
  const merged = new Map();
13
16
  const discoveredPaths = new Set();
14
17
  for (const root of searchRoots) {
@@ -60,6 +60,7 @@ export type FindMappingInput = {
60
60
  targetMapping: SourceMapping;
61
61
  sourcePriority?: MappingSourcePriority;
62
62
  projectPath?: string;
63
+ gradleUserHome?: string;
63
64
  disambiguation?: {
64
65
  ownerHint?: string;
65
66
  descriptorHint?: string;
@@ -73,6 +74,7 @@ export type EnsureMappingAvailableInput = {
73
74
  targetMapping: SourceMapping;
74
75
  sourcePriority?: MappingSourcePriority;
75
76
  projectPath?: string;
77
+ gradleUserHome?: string;
76
78
  };
77
79
  export type EnsureMappingAvailableOutput = {
78
80
  transformChain: string[];
@@ -88,6 +90,7 @@ export type ResolveMethodMappingExactInput = {
88
90
  targetMapping: SourceMapping;
89
91
  sourcePriority?: MappingSourcePriority;
90
92
  projectPath?: string;
93
+ gradleUserHome?: string;
91
94
  maxCandidates?: number;
92
95
  };
93
96
  export type ResolveMethodMappingExactOutput = SymbolResolutionOutput;
@@ -97,6 +100,7 @@ export type ClassApiMatrixInput = {
97
100
  className: string;
98
101
  classNameMapping: SourceMapping;
99
102
  sourcePriority?: MappingSourcePriority;
103
+ gradleUserHome?: string;
100
104
  includeKinds?: ClassApiMatrixKind[];
101
105
  maxRows?: number;
102
106
  };
@@ -134,6 +138,7 @@ export type SymbolExistenceInput = {
134
138
  descriptor?: string;
135
139
  sourceMapping: SourceMapping;
136
140
  sourcePriority?: MappingSourcePriority;
141
+ gradleUserHome?: string;
137
142
  nameMode?: "fqcn" | "auto";
138
143
  signatureMode?: "exact" | "name-only";
139
144
  maxCandidates?: number;
@@ -41,6 +41,7 @@ export declare class MappingService {
41
41
  version: string;
42
42
  requestedMapping: SourceMapping;
43
43
  sourcePriority?: MappingSourcePriority;
44
+ gradleUserHome?: string;
44
45
  }): Promise<{
45
46
  mojangMappingsAvailable: boolean;
46
47
  tinyMappingsAvailable: boolean;
@@ -3,6 +3,7 @@ import { mkdir, writeFile } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  import { buildSuggestedCall } from "./build-suggested-call.js";
5
5
  import { createError, ERROR_CODES } from "./errors.js";
6
+ import { resolveGradleUserHomePath } from "./gradle-paths.js";
6
7
  import { defaultDownloadPath, downloadToCache } from "./repo-downloader.js";
7
8
  import { collectMatchedJarEntriesAsUtf8 } from "./source-jar-reader.js";
8
9
  import { VersionService, isUnobfuscatedVersion } from "./version-service.js";
@@ -112,7 +113,7 @@ export class MappingService {
112
113
  warnings: []
113
114
  };
114
115
  }
115
- const graph = await this.loadGraph(version, priority, requiresOnlyObfuscatedMojangGraph(sourceMapping, targetMapping) ? "obfuscated-mojang-only" : "full", input.projectPath);
116
+ const graph = await this.loadGraph(version, priority, requiresOnlyObfuscatedMojangGraph(sourceMapping, targetMapping) ? "obfuscated-mojang-only" : "full", input.projectPath, input.gradleUserHome);
116
117
  const path = namespacePath(graph, sourceMapping, targetMapping);
117
118
  if (!path) {
118
119
  return {
@@ -254,7 +255,7 @@ export class MappingService {
254
255
  warnings: []
255
256
  };
256
257
  }
257
- const graph = await this.loadGraph(version, priority, requiresOnlyObfuscatedMojangGraph(sourceMapping, targetMapping) ? "obfuscated-mojang-only" : "full", input.projectPath);
258
+ const graph = await this.loadGraph(version, priority, requiresOnlyObfuscatedMojangGraph(sourceMapping, targetMapping) ? "obfuscated-mojang-only" : "full", input.projectPath, input.gradleUserHome);
258
259
  const path = namespacePath(graph, sourceMapping, targetMapping);
259
260
  if (!path) {
260
261
  throw createError({
@@ -338,7 +339,7 @@ export class MappingService {
338
339
  warnings: []
339
340
  };
340
341
  }
341
- const graph = await this.loadGraph(version, priority, requiresOnlyObfuscatedMojangGraph(sourceMapping, targetMapping) ? "obfuscated-mojang-only" : "full", input.projectPath);
342
+ const graph = await this.loadGraph(version, priority, requiresOnlyObfuscatedMojangGraph(sourceMapping, targetMapping) ? "obfuscated-mojang-only" : "full", input.projectPath, input.gradleUserHome);
342
343
  const path = namespacePath(graph, sourceMapping, targetMapping);
343
344
  if (!path) {
344
345
  return {
@@ -448,7 +449,7 @@ export class MappingService {
448
449
  });
449
450
  }
450
451
  const priority = mappingPriorityFromInput(this.config.mappingSourcePriority, input.sourcePriority);
451
- const graph = await this.loadGraph(version, priority, "full");
452
+ const graph = await this.loadGraph(version, priority, "full", undefined, input.gradleUserHome);
452
453
  const warnings = [...graph.warnings];
453
454
  const includeKinds = normalizeIncludedKinds(input.includeKinds);
454
455
  const pathCache = new Map();
@@ -669,7 +670,7 @@ export class MappingService {
669
670
  querySymbol
670
671
  };
671
672
  })();
672
- const graph = await this.loadGraph(version, priority, sourceMapping === "mojang" ? "obfuscated-mojang-only" : "full");
673
+ const graph = await this.loadGraph(version, priority, sourceMapping === "mojang" ? "obfuscated-mojang-only" : "full", undefined, input.gradleUserHome);
673
674
  const warnings = [...graph.warnings];
674
675
  const records = collectTargetRecords(graph, sourceMapping);
675
676
  if (records.length === 0) {
@@ -950,7 +951,7 @@ export class MappingService {
950
951
  }
951
952
  let graph;
952
953
  try {
953
- graph = await this.loadGraph(input.version, priority, needsTinyMappings ? "full" : "obfuscated-mojang-only");
954
+ graph = await this.loadGraph(input.version, priority, needsTinyMappings ? "full" : "obfuscated-mojang-only", undefined, input.gradleUserHome);
954
955
  }
955
956
  catch {
956
957
  return {
@@ -994,9 +995,10 @@ export class MappingService {
994
995
  degradations
995
996
  };
996
997
  }
997
- async loadGraph(version, priority, mode, projectPath) {
998
+ async loadGraph(version, priority, mode, projectPath, gradleUserHome) {
998
999
  const effectiveProjectPath = effectiveLoomSearchProjectPath(projectPath);
999
- const cacheKey = `${version}|${priority}|${mode}|${effectiveProjectPath ?? ""}`;
1000
+ const effectiveGradleUserHome = resolveGradleUserHomePath(gradleUserHome);
1001
+ const cacheKey = `${version}|${priority}|${mode}|${effectiveProjectPath ?? ""}|${effectiveGradleUserHome}`;
1000
1002
  const cached = this.graphCache.get(cacheKey);
1001
1003
  if (cached) {
1002
1004
  this.graphCache.delete(cacheKey);
@@ -1007,7 +1009,7 @@ export class MappingService {
1007
1009
  if (existingLock) {
1008
1010
  return existingLock;
1009
1011
  }
1010
- const buildPromise = this.buildGraph(version, priority, mode, effectiveProjectPath);
1012
+ const buildPromise = this.buildGraph(version, priority, mode, effectiveProjectPath, effectiveGradleUserHome);
1011
1013
  this.buildLocks.set(cacheKey, buildPromise);
1012
1014
  try {
1013
1015
  const built = await buildPromise;
@@ -1019,7 +1021,7 @@ export class MappingService {
1019
1021
  this.buildLocks.delete(cacheKey);
1020
1022
  }
1021
1023
  }
1022
- async buildGraph(version, priority, mode, projectPath) {
1024
+ async buildGraph(version, priority, mode, projectPath, gradleUserHome) {
1023
1025
  if (isUnobfuscatedVersion(version)) {
1024
1026
  return {
1025
1027
  version,
@@ -1052,7 +1054,7 @@ export class MappingService {
1052
1054
  const deferredTinyWarnings = [];
1053
1055
  for (const source of mappingSourceOrder(priority)) {
1054
1056
  const tinyLoad = source === "loom-cache"
1055
- ? await this.loadTinyPairsFromLoom(version, projectPath)
1057
+ ? await this.loadTinyPairsFromLoom(version, projectPath, gradleUserHome)
1056
1058
  : await this.loadTinyPairsFromMaven(version);
1057
1059
  if (tinyLoad.pairs.size === 0) {
1058
1060
  deferredTinyWarnings.push(...tinyLoad.warnings);
@@ -1095,8 +1097,8 @@ export class MappingService {
1095
1097
  async loadMojangPairs(version) {
1096
1098
  return loadMojangPairs(this.loaderDeps(), version);
1097
1099
  }
1098
- async loadTinyPairsFromLoom(version, projectPath) {
1099
- return loadTinyPairsFromLoom(version, projectPath);
1100
+ async loadTinyPairsFromLoom(version, projectPath, gradleUserHome) {
1101
+ return loadTinyPairsFromLoom(version, projectPath, gradleUserHome);
1100
1102
  }
1101
1103
  async loadTinyPairsFromMaven(version) {
1102
1104
  return loadTinyPairsFromMaven(this.loaderDeps(), version);
@@ -1152,6 +1154,7 @@ export class MappingService {
1152
1154
  input.targetMapping,
1153
1155
  input.sourcePriority ?? "",
1154
1156
  effectiveLoomSearchProjectPath(input.projectPath) ?? "",
1157
+ resolveGradleUserHomePath(input.gradleUserHome),
1155
1158
  effectiveSignatureMode,
1156
1159
  String(input.maxCandidates ?? ""),
1157
1160
  JSON.stringify(input.disambiguation ?? "")
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Public barrel for the mixin validation engine. The implementation lives
3
3
  * under `src/mixin/`; this file preserves the historical entry point used
4
- * by source-service, entry tools, and tests.
4
+ * by source-service, top-level workflow tools, and tests.
5
5
  */
6
6
  export type { AccessTransformerValidationResult, AccessWidenerValidationResult, AggregatedWarningGroup, ConfidenceBreakdown, ConfidencePenalty, IssueCategory, IssueConfidence, MappingHealthReport, MixinStageBudgets, MixinValidationProvenance, MixinValidationResult, ResolutionPath, ResolvedMember, ResolvedTargetMembers, StructuredWarning, TargetOutcome, ValidationIssue, ValidationStatus, ValidationSummary } from "./mixin/types.js";
7
7
  export { loadMixinStageBudgets } from "./mixin/types.js";
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Public barrel for the mixin validation engine. The implementation lives
3
3
  * under `src/mixin/`; this file preserves the historical entry point used
4
- * by source-service, entry tools, and tests.
4
+ * by source-service, top-level workflow tools, and tests.
5
5
  */
6
6
  export { loadMixinStageBudgets } from "./mixin/types.js";
7
7
  export { accessLevelFromFlags, buildQuickSummary, computeConfidenceBreakdown, computeFalsePositiveRisk, computeValidationStatus, extractMethodDescriptor, extractMethodName, levenshteinDistance, refreshMixinValidationOutcome, suggestSimilar, summarizeResolvedMembers } from "./mixin/helpers.js";
@@ -56,6 +56,7 @@ export async function validateAccessWidener(svc, input) {
56
56
  version,
57
57
  awNamespace,
58
58
  projectPath: input.projectPath,
59
+ gradleUserHome: input.gradleUserHome,
59
60
  scope: input.scope,
60
61
  preferProjectVersion: input.preferProjectVersion
61
62
  });
@@ -85,7 +86,8 @@ export async function validateAccessWidener(svc, input) {
85
86
  sourceMapping: awNamespace,
86
87
  targetMapping: lookupMapping,
87
88
  sourcePriority: input.sourcePriority,
88
- projectPath: input.projectPath
89
+ projectPath: input.projectPath,
90
+ gradleUserHome: input.gradleUserHome
89
91
  });
90
92
  if (mapped.resolved && mapped.resolvedSymbol) {
91
93
  lookupFqn = mapped.resolvedSymbol.name;
@@ -110,9 +112,9 @@ export async function validateAccessWidener(svc, input) {
110
112
  let fields = sig.fields;
111
113
  if (needsLookupMapping) {
112
114
  const [ctorResult, methodResult, fieldResult] = await Promise.all([
113
- svc.remapSignatureMembers(sig.constructors, "method", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath),
114
- svc.remapSignatureMembers(sig.methods, "method", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath),
115
- svc.remapSignatureMembers(sig.fields, "field", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath)
115
+ svc.remapSignatureMembers(sig.constructors, "method", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath, input.gradleUserHome),
116
+ svc.remapSignatureMembers(sig.methods, "method", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath, input.gradleUserHome),
117
+ svc.remapSignatureMembers(sig.fields, "field", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath, input.gradleUserHome)
116
118
  ]);
117
119
  constructors = ctorResult.members;
118
120
  methods = methodResult.members;
@@ -163,6 +165,7 @@ export async function validateAccessTransformer(svc, input) {
163
165
  version,
164
166
  atNamespace,
165
167
  projectPath: input.projectPath,
168
+ gradleUserHome: input.gradleUserHome,
166
169
  scope: input.scope,
167
170
  preferProjectVersion: input.preferProjectVersion
168
171
  });
@@ -197,7 +200,8 @@ export async function validateAccessTransformer(svc, input) {
197
200
  sourceMapping: atNamespace,
198
201
  targetMapping: lookupMapping,
199
202
  sourcePriority: input.sourcePriority,
200
- projectPath: input.projectPath
203
+ projectPath: input.projectPath,
204
+ gradleUserHome: input.gradleUserHome
201
205
  });
202
206
  if (mapped.resolved && mapped.resolvedSymbol) {
203
207
  lookupFqn = mapped.resolvedSymbol.name;
@@ -223,9 +227,9 @@ export async function validateAccessTransformer(svc, input) {
223
227
  let fields = sig.fields;
224
228
  if (needsLookupMapping && isSourceMappingNamespace(atNamespace) && isSourceMappingNamespace(lookupMapping)) {
225
229
  const [ctorResult, methodResult, fieldResult] = await Promise.all([
226
- svc.remapSignatureMembers(sig.constructors, "method", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath),
227
- svc.remapSignatureMembers(sig.methods, "method", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath),
228
- svc.remapSignatureMembers(sig.fields, "field", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath)
230
+ svc.remapSignatureMembers(sig.constructors, "method", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath, input.gradleUserHome),
231
+ svc.remapSignatureMembers(sig.methods, "method", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath, input.gradleUserHome),
232
+ svc.remapSignatureMembers(sig.fields, "field", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath, input.gradleUserHome)
229
233
  ]);
230
234
  constructors = ctorResult.members;
231
235
  methods = methodResult.members;
@@ -32,11 +32,13 @@ export declare function hasExactVersionToken(path: string, version: string): boo
32
32
  export declare function discoverVersionSourceJar(_svc: SourceService, input: {
33
33
  version: string;
34
34
  projectPath?: string;
35
+ gradleUserHome?: string;
35
36
  }): Promise<VersionSourceDiscovery>;
36
37
  export declare function probeMinecraftArtifact(svc: SourceService, input: ProbeMinecraftArtifactInput): Promise<ProbeMinecraftArtifactOutput>;
37
38
  export declare function discoverAccessWidenerRuntimeCandidates(_svc: SourceService, input: {
38
39
  version: string;
39
40
  projectPath?: string;
41
+ gradleUserHome?: string;
40
42
  requestedScope: ArtifactScope;
41
43
  }): Promise<{
42
44
  searchedPaths: string[];
@@ -46,6 +48,7 @@ export declare function discoverAccessWidenerRuntimeCandidates(_svc: SourceServi
46
48
  export declare function discoverAccessTransformerRuntimeCandidates(_svc: SourceService, input: {
47
49
  version: string;
48
50
  projectPath?: string;
51
+ gradleUserHome?: string;
49
52
  requestedScope: ArtifactScope;
50
53
  atNamespace: AccessTransformerNamespace;
51
54
  loader: WorkspaceProjectLoader | "unknown";
@@ -58,6 +61,7 @@ export declare function resolveAccessWidenerRuntimeArtifact(svc: SourceService,
58
61
  version: string;
59
62
  awNamespace: SourceMapping;
60
63
  projectPath?: string;
64
+ gradleUserHome?: string;
61
65
  scope?: ArtifactScope;
62
66
  preferProjectVersion?: boolean;
63
67
  }): Promise<RuntimeValidationProvenance<SourceMapping>>;
@@ -69,6 +73,7 @@ export declare function resolveAccessTransformerRuntimeArtifact(svc: SourceServi
69
73
  version: string;
70
74
  atNamespace: AccessTransformerNamespace;
71
75
  projectPath?: string;
76
+ gradleUserHome?: string;
72
77
  scope?: ArtifactScope;
73
78
  preferProjectVersion?: boolean;
74
79
  }): Promise<RuntimeValidationProvenance<AccessTransformerNamespace>>;