@adhisang/minecraft-modding-mcp 4.1.0 → 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 (70) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/README.md +9 -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.d.ts +6 -1
  24. package/dist/entry-tools/validate-project/cases/project-summary.js +83 -9
  25. package/dist/entry-tools/validate-project/internal.d.ts +29 -18
  26. package/dist/entry-tools/validate-project/internal.js +37 -19
  27. package/dist/entry-tools/validate-project-service.d.ts +15 -1
  28. package/dist/entry-tools/validate-project-service.js +3 -2
  29. package/dist/entry-tools/verify-mixin-target-service.d.ts +2 -0
  30. package/dist/entry-tools/verify-mixin-target-service.js +1 -0
  31. package/dist/gradle-paths.d.ts +8 -3
  32. package/dist/gradle-paths.js +34 -5
  33. package/dist/index.js +29 -9
  34. package/dist/mapping/loaders/tiny-loom.d.ts +1 -1
  35. package/dist/mapping/loaders/tiny-loom.js +5 -2
  36. package/dist/mapping/types.d.ts +5 -0
  37. package/dist/mapping-service.d.ts +6 -1
  38. package/dist/mapping-service.js +26 -18
  39. package/dist/mixin-validator.d.ts +1 -1
  40. package/dist/mixin-validator.js +1 -1
  41. package/dist/source/access-validate.js +12 -8
  42. package/dist/source/artifact-resolver.d.ts +7 -1
  43. package/dist/source/artifact-resolver.js +120 -7
  44. package/dist/source/class-source/members-builder.d.ts +1 -0
  45. package/dist/source/class-source/members-builder.js +1 -1
  46. package/dist/source/class-source.d.ts +1 -0
  47. package/dist/source/class-source.js +9 -1
  48. package/dist/source/indexer.js +17 -0
  49. package/dist/source/lifecycle/diff.js +6 -6
  50. package/dist/source/lifecycle/mapping-helpers.d.ts +3 -3
  51. package/dist/source/lifecycle/mapping-helpers.js +17 -9
  52. package/dist/source/lifecycle/trace.js +2 -2
  53. package/dist/source/search.js +1 -0
  54. package/dist/source/state.d.ts +5 -0
  55. package/dist/source/state.js +5 -0
  56. package/dist/source/symbol-resolver.js +4 -1
  57. package/dist/source/validate-mixin/pipeline/mapping-health.js +2 -1
  58. package/dist/source/validate-mixin/pipeline/resolve.js +1 -0
  59. package/dist/source/validate-mixin/pipeline/target-lookup.js +12 -7
  60. package/dist/source-resolver.d.ts +1 -0
  61. package/dist/source-resolver.js +1 -1
  62. package/dist/source-service.d.ts +35 -1
  63. package/dist/source-service.js +5 -2
  64. package/dist/tool-contract-manifest.d.ts +1 -1
  65. package/dist/tool-contract-manifest.js +2 -2
  66. package/dist/tool-schemas.d.ts +91 -0
  67. package/dist/tool-schemas.js +20 -0
  68. package/docs/README-ja.md +4 -2
  69. package/docs/tool-reference.md +13 -7
  70. package/package.json +15 -3
@@ -1,3 +1,4 @@
1
+ import type { StageEmitter } from "../../stage-emitter.js";
1
2
  import type { SourceMapping } from "../../types.js";
2
3
  type TaskStatus = "ok" | "skipped" | "missing" | "error";
3
4
  type TaskEntryBase = {
@@ -44,8 +45,27 @@ type TaskStatusReport = {
44
45
  };
45
46
  };
46
47
  };
48
+ type MinecraftArtifactProbeInput = {
49
+ target: {
50
+ kind: "version";
51
+ value: string;
52
+ };
53
+ mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
54
+ sourcePriority?: "loom-first" | "maven-first";
55
+ projectPath?: string;
56
+ gradleUserHome?: string;
57
+ scope?: "vanilla" | "merged" | "loader";
58
+ preferProjectVersion?: boolean;
59
+ };
60
+ type MinecraftArtifactProbeOutput = {
61
+ artifactId: string;
62
+ mappingApplied: SourceMapping;
63
+ warnings?: string[];
64
+ };
47
65
  export type ValidateProjectDeps = {
48
- validateMixin: (input: Record<string, unknown>) => Promise<Record<string, unknown> & {
66
+ validateMixin: (input: Record<string, unknown>, options?: {
67
+ stageEmitter?: StageEmitter;
68
+ }) => Promise<Record<string, unknown> & {
49
69
  warnings?: string[];
50
70
  }>;
51
71
  validateAccessWidener: (input: {
@@ -54,6 +74,7 @@ export type ValidateProjectDeps = {
54
74
  mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
55
75
  sourcePriority?: "loom-first" | "maven-first";
56
76
  projectPath?: string;
77
+ gradleUserHome?: string;
57
78
  scope?: "vanilla" | "merged" | "loader";
58
79
  preferProjectVersion?: boolean;
59
80
  }) => Promise<Record<string, unknown> & {
@@ -65,6 +86,7 @@ export type ValidateProjectDeps = {
65
86
  atNamespace?: "srg" | "mojang" | "obfuscated";
66
87
  sourcePriority?: "loom-first" | "maven-first";
67
88
  projectPath?: string;
89
+ gradleUserHome?: string;
68
90
  scope?: "vanilla" | "merged" | "loader";
69
91
  preferProjectVersion?: boolean;
70
92
  }) => Promise<Record<string, unknown> & {
@@ -74,23 +96,10 @@ export type ValidateProjectDeps = {
74
96
  discoverAccessWideners: (projectPath: string) => Promise<string[]>;
75
97
  discoverAccessTransformers?: (projectPath: string) => Promise<string[]>;
76
98
  detectProjectMinecraftVersion?: (projectPath: string) => Promise<string | undefined>;
77
- resolveArtifact?: (input: {
78
- target: {
79
- kind: "version";
80
- value: string;
81
- };
82
- mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
83
- sourcePriority?: "loom-first" | "maven-first";
84
- projectPath?: string;
85
- scope?: "vanilla" | "merged" | "loader";
86
- preferProjectVersion?: boolean;
87
- }) => Promise<{
88
- artifactId: string;
89
- mappingApplied: SourceMapping;
90
- warnings?: string[];
91
- }>;
99
+ probeMinecraftArtifact?: (input: MinecraftArtifactProbeInput) => Promise<MinecraftArtifactProbeOutput>;
100
+ resolveArtifact?: (input: MinecraftArtifactProbeInput) => Promise<MinecraftArtifactProbeOutput>;
92
101
  };
93
- export declare function runUpstreamProbes(projectPath: string): Promise<{
102
+ export declare function runUpstreamProbes(projectPath: string, gradleUserHome?: string): Promise<{
94
103
  workspace: TaskStatusReport["workspace.detected"];
95
104
  gradle: TaskStatusReport["gradle.readable"];
96
105
  loom: TaskStatusReport["loom.cache.found"];
@@ -99,7 +108,7 @@ export declare function buildEarlyTasksForBlocked(projectPath: string, detail: "
99
108
  mixinDiscoveryCount: number;
100
109
  awDiscoveryCount: number;
101
110
  atDiscoveryCount: number;
102
- }): Promise<TaskStatusReport | undefined>;
111
+ }, gradleUserHome?: string): Promise<TaskStatusReport | undefined>;
103
112
  export declare function buildFullTaskStatusReport(deps: ValidateProjectDeps, args: {
104
113
  projectPath: string;
105
114
  detail: "summary" | "standard" | "full";
@@ -107,6 +116,7 @@ export declare function buildFullTaskStatusReport(deps: ValidateProjectDeps, arg
107
116
  resolvedVersion: string;
108
117
  mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
109
118
  sourcePriority?: "loom-first" | "maven-first";
119
+ gradleUserHome?: string;
110
120
  scope?: "vanilla" | "merged" | "loader";
111
121
  preferProjectVersion?: boolean;
112
122
  mixinDiscoveryCount: number;
@@ -131,5 +141,6 @@ export declare function buildFullTaskStatusReport(deps: ValidateProjectDeps, arg
131
141
  invalid: number;
132
142
  };
133
143
  atDurationMs: number;
144
+ stageEmitter?: StageEmitter;
134
145
  }): Promise<TaskStatusReport | undefined>;
135
146
  export {};
@@ -100,10 +100,10 @@ async function probeGradleReadable(projectPath) {
100
100
  };
101
101
  }
102
102
  }
103
- async function probeLoomCacheFound(projectPath) {
103
+ async function probeLoomCacheFound(projectPath, gradleUserHome) {
104
104
  const startedAt = Date.now();
105
105
  try {
106
- const roots = buildVersionSourceSearchRoots(projectPath);
106
+ const roots = buildVersionSourceSearchRoots({ projectPath, gradleUserHome });
107
107
  for (const root of roots) {
108
108
  if (await pathExists(root)) {
109
109
  return {
@@ -126,14 +126,28 @@ async function probeLoomCacheFound(projectPath) {
126
126
  };
127
127
  }
128
128
  }
129
- async function probeMinecraftArtifactResolved(resolveArtifact, args) {
129
+ async function probeMinecraftArtifactResolved(artifactProbe, args, stageEmitter) {
130
130
  const startedAt = Date.now();
131
+ // Stage notification kept outside the probe's try block: a telemetry
132
+ // failure must not be classified as ERR_ARTIFACT_PROBE_FAILED.
131
133
  try {
132
- const output = await resolveArtifact({
134
+ await stageEmitter?.("validate-project:artifact-probe", {
135
+ version: args.version,
136
+ mapping: args.mapping ?? "obfuscated",
137
+ projectPath: args.projectPath,
138
+ scope: args.scope ?? null
139
+ });
140
+ }
141
+ catch {
142
+ // swallow telemetry failure
143
+ }
144
+ try {
145
+ const output = await artifactProbe({
133
146
  target: { kind: "version", value: args.version },
134
147
  mapping: args.mapping,
135
148
  sourcePriority: args.sourcePriority,
136
149
  projectPath: args.projectPath,
150
+ gradleUserHome: args.gradleUserHome,
137
151
  scope: args.scope,
138
152
  preferProjectVersion: args.preferProjectVersion
139
153
  });
@@ -168,16 +182,18 @@ function downstreamSkipReason(report, upstream) {
168
182
  return undefined;
169
183
  }
170
184
  function buildValidationEntryWithCounts(upstream, discoveredCount, errorCount, counts, durationMs) {
185
+ // Real validator outcomes win over upstream skip when validators ran.
186
+ // The artifact probe is informational; its failure must not erase real counts.
187
+ if (discoveredCount > 0 || errorCount > 0) {
188
+ if (errorCount > 0) {
189
+ return { status: "error", durationMs, counts };
190
+ }
191
+ return { status: "ok", durationMs, counts };
192
+ }
171
193
  if (upstream) {
172
194
  return upstream;
173
195
  }
174
- if (discoveredCount === 0) {
175
- return { status: "missing", durationMs };
176
- }
177
- if (errorCount > 0) {
178
- return { status: "error", durationMs, counts };
179
- }
180
- return { status: "ok", durationMs, counts };
196
+ return { status: "missing", durationMs };
181
197
  }
182
198
  function projectTaskEntry(entry, detail, include) {
183
199
  const fullDetail = detail !== "summary" && include.includes("workspace");
@@ -200,9 +216,9 @@ function projectTaskStatusReport(report, detail, include) {
200
216
  }
201
217
  return projected;
202
218
  }
203
- export async function runUpstreamProbes(projectPath) {
219
+ export async function runUpstreamProbes(projectPath, gradleUserHome) {
204
220
  const workspace = await probeWorkspaceDetected(projectPath);
205
- const loom = await probeLoomCacheFound(projectPath);
221
+ const loom = await probeLoomCacheFound(projectPath, gradleUserHome);
206
222
  let gradle;
207
223
  if (workspace.status !== "ok") {
208
224
  gradle = { status: "skipped" };
@@ -212,11 +228,11 @@ export async function runUpstreamProbes(projectPath) {
212
228
  }
213
229
  return { workspace, gradle, loom };
214
230
  }
215
- export async function buildEarlyTasksForBlocked(projectPath, detail, include, discovery) {
231
+ export async function buildEarlyTasksForBlocked(projectPath, detail, include, discovery, gradleUserHome) {
216
232
  if (VALIDATE_PROJECT_TASKS_OFF) {
217
233
  return undefined;
218
234
  }
219
- const { workspace, gradle, loom } = await runUpstreamProbes(projectPath);
235
+ const { workspace, gradle, loom } = await runUpstreamProbes(projectPath, gradleUserHome);
220
236
  const minecraftArtifactResolved = {
221
237
  status: "skipped"
222
238
  };
@@ -247,20 +263,22 @@ export async function buildFullTaskStatusReport(deps, args) {
247
263
  if (VALIDATE_PROJECT_TASKS_OFF) {
248
264
  return undefined;
249
265
  }
250
- const { workspace, gradle, loom } = await runUpstreamProbes(args.projectPath);
266
+ const { workspace, gradle, loom } = await runUpstreamProbes(args.projectPath, args.gradleUserHome);
251
267
  let minecraftArtifactResolved;
252
268
  if (workspace.status !== "ok" || gradle.status !== "ok") {
253
269
  minecraftArtifactResolved = { status: "skipped" };
254
270
  }
255
- else if (deps.resolveArtifact) {
256
- minecraftArtifactResolved = await probeMinecraftArtifactResolved(deps.resolveArtifact, {
271
+ else if (deps.probeMinecraftArtifact ?? deps.resolveArtifact) {
272
+ const artifactProbe = deps.probeMinecraftArtifact ?? deps.resolveArtifact;
273
+ minecraftArtifactResolved = await probeMinecraftArtifactResolved(artifactProbe, {
257
274
  version: args.resolvedVersion,
258
275
  mapping: args.mapping,
259
276
  sourcePriority: args.sourcePriority,
260
277
  projectPath: args.projectPath,
278
+ gradleUserHome: args.gradleUserHome,
261
279
  scope: args.scope,
262
280
  preferProjectVersion: args.preferProjectVersion
263
- });
281
+ }, args.stageEmitter);
264
282
  }
265
283
  else {
266
284
  minecraftArtifactResolved = { status: "skipped" };
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import type { StageEmitter } from "../stage-emitter.js";
2
3
  import type { SourceMapping } from "../types.js";
3
4
  import { type ValidateProjectDeps } from "./validate-project/internal.js";
4
5
  export type TaskStatus = "ok" | "skipped" | "missing" | "error";
@@ -51,14 +52,17 @@ export declare const validateProjectShape: {
51
52
  subject: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
52
53
  kind: z.ZodLiteral<"workspace">;
53
54
  projectPath: z.ZodString;
55
+ gradleUserHome: z.ZodOptional<z.ZodString>;
54
56
  discover: z.ZodOptional<z.ZodArray<z.ZodEnum<["mixins", "access-wideners", "access-transformers"]>, "many">>;
55
57
  }, "strip", z.ZodTypeAny, {
56
58
  kind: "workspace";
57
59
  projectPath: string;
60
+ gradleUserHome?: string | undefined;
58
61
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
59
62
  }, {
60
63
  kind: "workspace";
61
64
  projectPath: string;
65
+ gradleUserHome?: string | undefined;
62
66
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
63
67
  }>, z.ZodObject<{
64
68
  kind: z.ZodLiteral<"mixin">;
@@ -247,14 +251,17 @@ export declare const validateProjectSchema: z.ZodEffects<z.ZodObject<{
247
251
  subject: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
248
252
  kind: z.ZodLiteral<"workspace">;
249
253
  projectPath: z.ZodString;
254
+ gradleUserHome: z.ZodOptional<z.ZodString>;
250
255
  discover: z.ZodOptional<z.ZodArray<z.ZodEnum<["mixins", "access-wideners", "access-transformers"]>, "many">>;
251
256
  }, "strip", z.ZodTypeAny, {
252
257
  kind: "workspace";
253
258
  projectPath: string;
259
+ gradleUserHome?: string | undefined;
254
260
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
255
261
  }, {
256
262
  kind: "workspace";
257
263
  projectPath: string;
264
+ gradleUserHome?: string | undefined;
258
265
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
259
266
  }>, z.ZodObject<{
260
267
  kind: z.ZodLiteral<"mixin">;
@@ -448,6 +455,7 @@ export declare const validateProjectSchema: z.ZodEffects<z.ZodObject<{
448
455
  subject: {
449
456
  kind: "workspace";
450
457
  projectPath: string;
458
+ gradleUserHome?: string | undefined;
451
459
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
452
460
  } | {
453
461
  kind: "mixin";
@@ -503,6 +511,7 @@ export declare const validateProjectSchema: z.ZodEffects<z.ZodObject<{
503
511
  subject: {
504
512
  kind: "workspace";
505
513
  projectPath: string;
514
+ gradleUserHome?: string | undefined;
506
515
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
507
516
  } | {
508
517
  kind: "mixin";
@@ -570,6 +579,7 @@ export declare const validateProjectSchema: z.ZodEffects<z.ZodObject<{
570
579
  subject: {
571
580
  kind: "workspace";
572
581
  projectPath: string;
582
+ gradleUserHome?: string | undefined;
573
583
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
574
584
  } | {
575
585
  kind: "mixin";
@@ -625,6 +635,7 @@ export declare const validateProjectSchema: z.ZodEffects<z.ZodObject<{
625
635
  subject: {
626
636
  kind: "workspace";
627
637
  projectPath: string;
638
+ gradleUserHome?: string | undefined;
628
639
  discover?: ("mixins" | "access-wideners" | "access-transformers")[] | undefined;
629
640
  } | {
630
641
  kind: "mixin";
@@ -683,13 +694,16 @@ export declare const validateProjectSchema: z.ZodEffects<z.ZodObject<{
683
694
  include?: string[] | undefined;
684
695
  }>;
685
696
  export type ValidateProjectInput = z.infer<typeof validateProjectSchema>;
697
+ export type ValidateProjectExecuteOptions = {
698
+ stageEmitter?: StageEmitter;
699
+ };
686
700
  export declare function discoverWorkspaceMixins(projectPath: string, configPaths?: string[]): Promise<string[]>;
687
701
  export declare function discoverWorkspaceAccessWideners(projectPath: string): Promise<string[]>;
688
702
  export declare function discoverWorkspaceAccessTransformers(projectPath: string): Promise<string[]>;
689
703
  export declare class ValidateProjectService {
690
704
  private readonly deps;
691
705
  constructor(deps: ValidateProjectDeps);
692
- execute(input: ValidateProjectInput): Promise<Record<string, unknown> & {
706
+ execute(input: ValidateProjectInput, options?: ValidateProjectExecuteOptions): Promise<Record<string, unknown> & {
693
707
  warnings?: string[];
694
708
  }>;
695
709
  }
@@ -31,6 +31,7 @@ const subjectSchema = z.discriminatedUnion("kind", [
31
31
  z.object({
32
32
  kind: z.literal("workspace"),
33
33
  projectPath: nonEmptyString,
34
+ gradleUserHome: nonEmptyString.optional(),
34
35
  discover: z.array(z.enum(["mixins", "access-wideners", "access-transformers"])).optional()
35
36
  }),
36
37
  z.object({
@@ -263,7 +264,7 @@ export class ValidateProjectService {
263
264
  constructor(deps) {
264
265
  this.deps = deps;
265
266
  }
266
- async execute(input) {
267
+ async execute(input, options = {}) {
267
268
  const detail = resolveDetail(input.detail);
268
269
  const include = resolveInclude(input.include);
269
270
  switch (input.task) {
@@ -274,7 +275,7 @@ export class ValidateProjectService {
274
275
  case "access-transformer":
275
276
  return handleAccessTransformer(this.deps, input, detail, include);
276
277
  case "project-summary":
277
- return handleProjectSummary(this.deps, input, detail, include);
278
+ return handleProjectSummary(this.deps, input, detail, include, options);
278
279
  }
279
280
  }
280
281
  }
@@ -16,6 +16,7 @@ export type VerifyMixinTargetInput = {
16
16
  mapping?: SourceMapping;
17
17
  sourcePriority?: MappingSourcePriority;
18
18
  projectPath?: string;
19
+ gradleUserHome?: string;
19
20
  target?: ResolveArtifactTargetInput;
20
21
  scope?: ArtifactScope;
21
22
  preferProjectVersion?: boolean;
@@ -82,6 +83,7 @@ export type VerifyMixinTargetDeps = {
82
83
  mapping?: SourceMapping;
83
84
  sourcePriority?: MappingSourcePriority;
84
85
  projectPath?: string;
86
+ gradleUserHome?: string;
85
87
  scope?: ArtifactScope;
86
88
  preferProjectVersion?: boolean;
87
89
  strictVersion?: boolean;
@@ -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
@@ -129,7 +129,7 @@ const analyzeModService = new AnalyzeModService({
129
129
  remapModJar: (input) => remapModJar(input, config)
130
130
  });
131
131
  const validateProjectService = new ValidateProjectService({
132
- validateMixin: (input) => sourceService.validateMixin(input),
132
+ validateMixin: (input, options) => sourceService.validateMixin(input, options),
133
133
  validateAccessWidener: (input) => sourceService.validateAccessWidener(input),
134
134
  validateAccessTransformer: (input) => sourceService.validateAccessTransformer(input),
135
135
  discoverMixins: discoverWorkspaceMixins,
@@ -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
  });
@@ -150,7 +151,8 @@ const validateProjectService = new ValidateProjectService({
150
151
  mappingApplied: output.mappingApplied,
151
152
  warnings: output.warnings
152
153
  };
153
- }
154
+ },
155
+ probeMinecraftArtifact: (input) => sourceService.probeMinecraftArtifact(input)
154
156
  });
155
157
  const manageCacheService = new ManageCacheService({
156
158
  registry: createCacheRegistry({
@@ -165,6 +167,7 @@ const verifyMixinTargetService = new VerifyMixinTargetService({
165
167
  mapping: input.mapping,
166
168
  sourcePriority: input.sourcePriority,
167
169
  projectPath: input.projectPath,
170
+ gradleUserHome: input.gradleUserHome,
168
171
  scope: input.scope,
169
172
  preferProjectVersion: input.preferProjectVersion,
170
173
  strictVersion: input.strictVersion
@@ -405,17 +408,19 @@ server.tool("list-versions", "List available Minecraft versions from Mojang mani
405
408
  limit: input.limit
406
409
  })));
407
410
  registerToolSchema("list-versions", listVersionsSchema);
408
- 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)));
409
412
  registerToolSchema("inspect-minecraft", inspectMinecraftSchema);
410
- 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)));
411
414
  registerToolSchema("analyze-symbol", analyzeSymbolSchema);
412
- 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)));
413
416
  registerToolSchema("compare-minecraft", compareMinecraftSchema);
414
- 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)));
415
418
  registerToolSchema("analyze-mod", analyzeModSchema);
416
- 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) => 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, {
420
+ stageEmitter: makeStageEmitter(extra)
421
+ })));
417
422
  registerToolSchema("validate-project", validateProjectSchema);
418
- 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)));
419
424
  registerToolSchema("manage-cache", manageCacheSchema);
420
425
  if (!VERIFY_MIXIN_TARGET_OFF) {
421
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({
@@ -425,6 +430,7 @@ if (!VERIFY_MIXIN_TARGET_OFF) {
425
430
  mapping: input.mapping,
426
431
  sourcePriority: input.sourcePriority,
427
432
  projectPath: input.projectPath,
433
+ gradleUserHome: input.gradleUserHome,
428
434
  target: input.target,
429
435
  scope: input.scope,
430
436
  preferProjectVersion: input.preferProjectVersion,
@@ -448,6 +454,7 @@ server.tool("resolve-artifact", "Resolve source artifact from a target object ({
448
454
  sourcePriority: input.sourcePriority,
449
455
  allowDecompile: input.allowDecompile,
450
456
  projectPath: input.projectPath,
457
+ gradleUserHome: input.gradleUserHome,
451
458
  scope: input.scope,
452
459
  preferProjectVersion: input.preferProjectVersion,
453
460
  strictVersion: input.strictVersion,
@@ -477,6 +484,7 @@ server.tool("get-class-source", "Get Java source for a class by target ({ type:
477
484
  sourcePriority: input.sourcePriority,
478
485
  allowDecompile: input.allowDecompile,
479
486
  projectPath: input.projectPath,
487
+ gradleUserHome: input.gradleUserHome,
480
488
  scope: input.scope,
481
489
  preferProjectVersion: input.preferProjectVersion,
482
490
  strictVersion: input.strictVersion,
@@ -503,6 +511,7 @@ server.tool("get-class-members", "Get fields/methods/constructors for one class
503
511
  memberPattern: input.memberPattern,
504
512
  maxMembers: input.maxMembers,
505
513
  projectPath: input.projectPath,
514
+ gradleUserHome: input.gradleUserHome,
506
515
  scope: input.scope,
507
516
  preferProjectVersion: input.preferProjectVersion,
508
517
  strictVersion: input.strictVersion
@@ -527,7 +536,8 @@ server.tool("search-class-source", "Search indexed class source files for one ar
527
536
  limit: input.limit,
528
537
  cursor: input.cursor,
529
538
  queryNamespace: input.queryNamespace,
530
- sourcePriority: input.sourcePriority
539
+ sourcePriority: input.sourcePriority,
540
+ gradleUserHome: input.gradleUserHome
531
541
  });
532
542
  }));
533
543
  registerToolSchema("search-class-source", searchClassSourceSchema);
@@ -551,6 +561,7 @@ server.tool("trace-symbol-lifecycle", "Trace which Minecraft versions contain a
551
561
  toVersion: input.toVersion,
552
562
  mapping: input.mapping,
553
563
  sourcePriority: input.sourcePriority,
564
+ gradleUserHome: input.gradleUserHome,
554
565
  includeSnapshots: input.includeSnapshots,
555
566
  maxVersions: input.maxVersions,
556
567
  includeTimeline: input.includeTimeline
@@ -562,6 +573,7 @@ server.tool("diff-class-signatures", "Compare one class signature between two Mi
562
573
  toVersion: input.toVersion,
563
574
  mapping: input.mapping,
564
575
  sourcePriority: input.sourcePriority,
576
+ gradleUserHome: input.gradleUserHome,
565
577
  includeFullDiff: input.includeFullDiff
566
578
  })));
567
579
  registerToolSchema("diff-class-signatures", diffClassSignaturesSchema);
@@ -574,6 +586,7 @@ server.tool("find-mapping", "Find symbol mapping candidates between namespaces u
574
586
  sourceMapping: input.sourceMapping,
575
587
  targetMapping: input.targetMapping,
576
588
  sourcePriority: input.sourcePriority,
589
+ gradleUserHome: input.gradleUserHome,
577
590
  signatureMode: input.signatureMode,
578
591
  disambiguation: input.disambiguation,
579
592
  maxCandidates: input.maxCandidates
@@ -587,6 +600,7 @@ server.tool("resolve-method-mapping-exact", "Resolve one method mapping exactly
587
600
  sourceMapping: input.sourceMapping,
588
601
  targetMapping: input.targetMapping,
589
602
  sourcePriority: input.sourcePriority,
603
+ gradleUserHome: input.gradleUserHome,
590
604
  maxCandidates: input.maxCandidates
591
605
  })));
592
606
  registerToolSchema("resolve-method-mapping-exact", resolveMethodMappingExactSchema);
@@ -596,6 +610,7 @@ server.tool("get-class-api-matrix", "List class/member API rows across obfuscate
596
610
  classNameMapping: input.classNameMapping,
597
611
  includeKinds: parseClassApiKinds(input.includeKinds),
598
612
  sourcePriority: input.sourcePriority,
613
+ gradleUserHome: input.gradleUserHome,
599
614
  maxRows: input.maxRows
600
615
  })));
601
616
  registerToolSchema("get-class-api-matrix", getClassApiMatrixSchema);
@@ -608,6 +623,7 @@ server.tool("resolve-workspace-symbol", "Resolve class/field/method names as see
608
623
  descriptor: input.descriptor,
609
624
  sourceMapping: input.sourceMapping,
610
625
  sourcePriority: input.sourcePriority,
626
+ gradleUserHome: input.gradleUserHome,
611
627
  maxCandidates: input.maxCandidates
612
628
  })));
613
629
  registerToolSchema("resolve-workspace-symbol", resolveWorkspaceSymbolSchema);
@@ -619,6 +635,7 @@ server.tool("check-symbol-exists", "Check whether a class/field/method symbol ex
619
635
  descriptor: input.descriptor,
620
636
  sourceMapping: input.sourceMapping,
621
637
  sourcePriority: input.sourcePriority,
638
+ gradleUserHome: input.gradleUserHome,
622
639
  nameMode: input.nameMode,
623
640
  signatureMode: input.signatureMode,
624
641
  maxCandidates: input.maxCandidates
@@ -654,6 +671,7 @@ server.tool("validate-mixin", "Validate Mixin source against Minecraft bytecode
654
671
  sourcePriority: input.sourcePriority,
655
672
  scope: input.scope,
656
673
  projectPath: input.projectPath,
674
+ gradleUserHome: input.gradleUserHome,
657
675
  preferProjectVersion: input.preferProjectVersion,
658
676
  minSeverity: input.minSeverity,
659
677
  hideUncertain: input.hideUncertain,
@@ -674,6 +692,7 @@ server.tool("validate-access-widener", "Validate Access Widener file entries aga
674
692
  mapping: input.mapping,
675
693
  sourcePriority: input.sourcePriority,
676
694
  projectPath: input.projectPath,
695
+ gradleUserHome: input.gradleUserHome,
677
696
  scope: input.scope,
678
697
  preferProjectVersion: input.preferProjectVersion
679
698
  })));
@@ -684,6 +703,7 @@ server.tool("validate-access-transformer", "Validate Access Transformer file ent
684
703
  atNamespace: input.atNamespace,
685
704
  sourcePriority: input.sourcePriority,
686
705
  projectPath: input.projectPath,
706
+ gradleUserHome: input.gradleUserHome,
687
707
  scope: input.scope,
688
708
  preferProjectVersion: input.preferProjectVersion
689
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) {