@adhisang/minecraft-modding-mcp 7.0.0-rc.3 → 7.1.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 (60) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +3 -2
  3. package/dist/cache-registry.d.ts +16 -0
  4. package/dist/cache-registry.js +78 -10
  5. package/dist/entry-tools/analyze-mod-service.d.ts +2 -2
  6. package/dist/entry-tools/analyze-symbol-service.d.ts +2 -2
  7. package/dist/entry-tools/batch-class-members-service.d.ts +3 -2
  8. package/dist/entry-tools/batch-class-members-service.js +20 -6
  9. package/dist/entry-tools/batch-class-source-service.d.ts +3 -2
  10. package/dist/entry-tools/batch-class-source-service.js +10 -0
  11. package/dist/entry-tools/compare-minecraft-service.d.ts +27 -4
  12. package/dist/entry-tools/compare-minecraft-service.js +65 -4
  13. package/dist/entry-tools/entry-tool-schema.d.ts +2 -2
  14. package/dist/entry-tools/inspect-minecraft-service.d.ts +2 -2
  15. package/dist/entry-tools/manage-cache-service.d.ts +2 -2
  16. package/dist/entry-tools/validate-project/cases/project-summary.js +71 -12
  17. package/dist/entry-tools/validate-project-service.d.ts +2 -2
  18. package/dist/index.js +37 -15
  19. package/dist/json-rpc-framing.d.ts +20 -0
  20. package/dist/json-rpc-framing.js +80 -7
  21. package/dist/mapping/loaders/tiny-maven.d.ts +9 -0
  22. package/dist/mapping/loaders/tiny-maven.js +10 -2
  23. package/dist/repo-downloader.js +13 -2
  24. package/dist/source/artifact-resolver.d.ts +14 -0
  25. package/dist/source/artifact-resolver.js +106 -12
  26. package/dist/source/class-source/members-builder.d.ts +7 -0
  27. package/dist/source/class-source/members-builder.js +4 -1
  28. package/dist/source/class-source.d.ts +9 -2
  29. package/dist/source/class-source.js +229 -26
  30. package/dist/source/indexer.js +69 -1
  31. package/dist/source/lifecycle/mapping-helpers.d.ts +20 -1
  32. package/dist/source/lifecycle/mapping-helpers.js +29 -3
  33. package/dist/source/lifecycle/runtime-check.d.ts +25 -0
  34. package/dist/source/lifecycle/runtime-check.js +68 -39
  35. package/dist/source/symbol-resolver.js +88 -0
  36. package/dist/source-jar-reader.d.ts +33 -0
  37. package/dist/source-jar-reader.js +58 -0
  38. package/dist/source-resolver.d.ts +7 -0
  39. package/dist/source-resolver.js +20 -5
  40. package/dist/source-service.d.ts +5 -0
  41. package/dist/source-service.js +7 -0
  42. package/dist/stdio-supervisor.js +193 -34
  43. package/dist/storage/db.d.ts +62 -2
  44. package/dist/storage/db.js +186 -21
  45. package/dist/storage/sqlite.d.ts +31 -1
  46. package/dist/storage/sqlite.js +125 -16
  47. package/dist/tool-guidance.js +4 -1
  48. package/dist/tool-schemas.d.ts +64 -52
  49. package/dist/tool-schemas.js +9 -7
  50. package/dist/types.d.ts +9 -0
  51. package/dist/v1-parity-schemas.js +36 -2
  52. package/dist/version-diff-service.d.ts +23 -0
  53. package/dist/version-diff-service.js +101 -0
  54. package/dist/version-service.d.ts +14 -0
  55. package/dist/version-service.js +45 -3
  56. package/dist/workspace-mapping-service.d.ts +8 -0
  57. package/dist/workspace-mapping-service.js +35 -7
  58. package/docs/README-ja.md +2 -0
  59. package/docs/tool-reference.md +55 -11
  60. package/package.json +1 -1
@@ -219,6 +219,40 @@ const RUNTIME_JAR_VERSION_REGEX = /(?:^|[^0-9.])(1\.\d+(?:\.\d+)?)(?![0-9.])/;
219
219
  export function inferRuntimeJarMinecraftVersion(path) {
220
220
  return RUNTIME_JAR_VERSION_REGEX.exec(normalizePathStyle(path))?.[1];
221
221
  }
222
+ /**
223
+ * The Minecraft version a `kind: "jar"` target PROVES it is the unobfuscated
224
+ * runtime of, or undefined. The file path is never evidence: Loom and other
225
+ * tools lay jars out in ways that path heuristics have misread before.
226
+ *
227
+ * All three must hold: the walk met no `.java` entry, the jar ships
228
+ * `net/minecraft/SharedConstants.class`, and its root `version.json` parses with a
229
+ * string `id` that `isUnobfuscatedVersion` accepts. The id is put to that test
230
+ * only once the other two hold, so it is the id a Minecraft `version.json`
231
+ * declares, never a library's own release number. A Loom-mapped 1.x jar carries
232
+ * both signals too; its `1.x` id is what keeps it out. The path is never read.
233
+ */
234
+ export function provenUnobfuscatedRuntimeJarVersion(scan) {
235
+ const signals = scan?.minecraftRuntimeSignals;
236
+ if (!scan || scan.hasJavaSources || !signals?.hasSharedConstantsClass || signals.versionJsonText === undefined) {
237
+ return undefined;
238
+ }
239
+ let parsed;
240
+ try {
241
+ parsed = JSON.parse(signals.versionJsonText);
242
+ }
243
+ catch {
244
+ return undefined;
245
+ }
246
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
247
+ return undefined;
248
+ }
249
+ const id = parsed.id;
250
+ if (typeof id !== "string") {
251
+ return undefined;
252
+ }
253
+ const version = id.trim();
254
+ return isUnobfuscatedVersion(version) ? version : undefined;
255
+ }
222
256
  /**
223
257
  * Segment that opens a directory tree a BUILD TOOL wrote: a dot-directory
224
258
  * (`.gradle`, `.gradle-user-home`, `.m2`), Gradle's `caches` root, or a project
@@ -378,7 +412,8 @@ function buildProvenance(input) {
378
412
  version: input.resolved.version,
379
413
  repoUrl: input.resolved.repoUrl
380
414
  },
381
- transformChain: [...input.transformChain]
415
+ transformChain: [...input.transformChain],
416
+ ...(input.unobfuscatedRuntime ? { unobfuscatedRuntime: true } : {})
382
417
  };
383
418
  if (!provenance.resolvedAt || !provenance.target.kind || !provenance.target.value) {
384
419
  throw createError({
@@ -1238,7 +1273,14 @@ export async function buildMappingFallbackSuggestedCall(svc, args) {
1238
1273
  return buildLegacyMappingFallback({ kind, value, scope, isVanillaMojang, projectPath: undefined });
1239
1274
  }
1240
1275
  if (kind !== "version") {
1241
- return buildLegacyMappingFallback({ kind, value, scope, isVanillaMojang, projectPath });
1276
+ return buildLegacyMappingFallback({
1277
+ kind,
1278
+ value,
1279
+ scope,
1280
+ isVanillaMojang,
1281
+ projectPath,
1282
+ projectRuntimeUnobfuscated: isVanillaMojang && (await projectNamesUnobfuscatedMinecraft(svc, projectPath))
1283
+ });
1242
1284
  }
1243
1285
  const cached = svc.workspaceContextCache.read(projectPath);
1244
1286
  if (cached &&
@@ -1299,9 +1341,28 @@ export async function buildMappingFallbackSuggestedCall(svc, args) {
1299
1341
  }
1300
1342
  return buildLegacyMappingFallback({ kind, value, scope, isVanillaMojang, projectPath });
1301
1343
  }
1344
+ /**
1345
+ * Whether the project's gradle.properties names a Minecraft 26.1+ release. The
1346
+ * property is a Minecraft version by name (`minecraft_version` and its aliases), so
1347
+ * it may be put to `isUnobfuscatedVersion`. Unreadable or absent answers false.
1348
+ */
1349
+ async function projectNamesUnobfuscatedMinecraft(svc, projectPath) {
1350
+ try {
1351
+ const version = await svc.workspaceMappingService.detectProjectMinecraftVersion(projectPath);
1352
+ return version !== undefined && isUnobfuscatedVersion(version);
1353
+ }
1354
+ catch {
1355
+ return false;
1356
+ }
1357
+ }
1302
1358
  function buildLegacyMappingFallback(args) {
1303
1359
  const { kind, value, scope, isVanillaMojang, projectPath } = args;
1304
- if (isVanillaMojang && projectPath) {
1360
+ // scope=merged reaches Loom source discovery only for a version target. For a
1361
+ // jar or coordinate in a 26.1+ project, re-suggesting mojang+merged on the same
1362
+ // target repeats the request that was just refused, so that case takes the
1363
+ // generic retry below instead.
1364
+ const mergedRetryWouldRepeat = kind !== "version" && args.projectRuntimeUnobfuscated === true;
1365
+ if (isVanillaMojang && projectPath && !mergedRetryWouldRepeat) {
1305
1366
  return {
1306
1367
  ...buildSuggestedCall({
1307
1368
  tool: "resolve-artifact",
@@ -1311,7 +1372,7 @@ function buildLegacyMappingFallback(args) {
1311
1372
  "Retry with scope=merged to allow source-jar resolution from the project cache."
1312
1373
  };
1313
1374
  }
1314
- if (isVanillaMojang) {
1375
+ if (isVanillaMojang && !projectPath) {
1315
1376
  return {
1316
1377
  ...buildSuggestedCall({
1317
1378
  tool: "resolve-artifact",
@@ -1326,7 +1387,14 @@ function buildLegacyMappingFallback(args) {
1326
1387
  tool: "resolve-artifact",
1327
1388
  params: buildResolveArtifactParams({ kind, value }, { mapping: "obfuscated", ...(scope ? { scope } : {}) })
1328
1389
  }),
1329
- nextAction: "Retry with mapping=obfuscated to use the runtime obfuscated namespace."
1390
+ // A jar reaches here only when it was NOT proven to be a Minecraft runtime jar,
1391
+ // so its version is unknown and "obfuscated" must not be described as
1392
+ // obfuscated names: on 26.1+ the as-shipped names are Mojang names. Version and
1393
+ // coordinate refusals keep their established wording.
1394
+ nextAction: kind === "jar"
1395
+ ? "Retry with mapping=obfuscated to read this jar's names as shipped (already Mojang names on Minecraft 26.1+). " +
1396
+ "For a vanilla Minecraft release, use target kind \"version\" instead."
1397
+ : "Retry with mapping=obfuscated to use the runtime obfuscated namespace."
1330
1398
  };
1331
1399
  }
1332
1400
  export async function resolveArtifact(svc, input) {
@@ -1431,13 +1499,19 @@ export async function resolveArtifact(svc, input) {
1431
1499
  // below), so its mapping is never actually enforced either way.
1432
1500
  const versionNamesMinecraft = kind === "version" ||
1433
1501
  (kind === "coordinate" && !dependencyOrigin && coordinateIsMinecraftRuntime);
1434
- const minecraftVersion = versionNamesMinecraft ? resolvedVersion : undefined;
1435
- const runtimeNamesUnobfuscated = minecraftVersion !== undefined && isUnobfuscatedVersion(minecraftVersion);
1502
+ // A kind="jar" target names no version at all. It joins this gate only AFTER its
1503
+ // archive has been walked and proved to be a Minecraft 26.1+ runtime jar (see
1504
+ // `provenUnobfuscatedRuntimeJarVersion` below); until then it stays out.
1505
+ let minecraftVersion = versionNamesMinecraft ? resolvedVersion : undefined;
1506
+ let runtimeNamesUnobfuscated = minecraftVersion !== undefined && isUnobfuscatedVersion(minecraftVersion);
1436
1507
  let effectiveMapping = mapping;
1437
- if ((mapping === "intermediary" || mapping === "yarn") && runtimeNamesUnobfuscated) {
1438
- warnings.push(`Version ${minecraftVersion} is unobfuscated; ${mapping} mappings are not applicable. Using the obfuscated namespace label for the deobfuscated runtime names.`);
1439
- effectiveMapping = "obfuscated";
1440
- }
1508
+ const dropInapplicableUnobfuscatedMapping = () => {
1509
+ if ((effectiveMapping === "intermediary" || effectiveMapping === "yarn") && runtimeNamesUnobfuscated) {
1510
+ warnings.push(`Version ${minecraftVersion} is unobfuscated; ${effectiveMapping} mappings are not applicable. Using the obfuscated namespace label for the deobfuscated runtime names.`);
1511
+ effectiveMapping = "obfuscated";
1512
+ }
1513
+ };
1514
+ dropInapplicableUnobfuscatedMapping();
1441
1515
  if (kind === "version" &&
1442
1516
  resolvedVersion &&
1443
1517
  effectiveMapping === "mojang" &&
@@ -1471,9 +1545,21 @@ export async function resolveArtifact(svc, input) {
1471
1545
  if (binaryRemapGate.warnings.length > 0) {
1472
1546
  warnings.push(...binaryRemapGate.warnings);
1473
1547
  }
1548
+ // Only a jar the caller named directly can be proved from its contents. A
1549
+ // dependency-origin jar is excluded for the reason given above, and a version
1550
+ // target is rewritten into a jar but already carries its version.
1551
+ const proveRuntimeJar = kind === "jar" && !dependencyOrigin;
1552
+ let subjectJarScan = undefined;
1474
1553
  const resolved = await resolveSourceTargetInternal(resolvedTarget, {
1475
1554
  allowDecompile: effectiveMapping === "mojang" ? true : input.allowDecompile ?? true,
1476
1555
  mappingVariant: binaryRemapGate.mappingVariant,
1556
+ ...(proveRuntimeJar
1557
+ ? {
1558
+ onSubjectJarScanned: (scan) => {
1559
+ subjectJarScan = scan;
1560
+ }
1561
+ }
1562
+ : {}),
1477
1563
  onRepoFailover: (event) => {
1478
1564
  svc.metrics.recordRepoFailover();
1479
1565
  log("warn", "repo.failover", {
@@ -1486,6 +1572,13 @@ export async function resolveArtifact(svc, input) {
1486
1572
  });
1487
1573
  }
1488
1574
  }, svc.config);
1575
+ const provenJarVersion = proveRuntimeJar ? provenUnobfuscatedRuntimeJarVersion(subjectJarScan) : undefined;
1576
+ if (provenJarVersion) {
1577
+ resolvedVersion = provenJarVersion;
1578
+ minecraftVersion = provenJarVersion;
1579
+ runtimeNamesUnobfuscated = true;
1580
+ dropInapplicableUnobfuscatedMapping();
1581
+ }
1489
1582
  resolved.version = resolvedVersion;
1490
1583
  let mappingDecision;
1491
1584
  try {
@@ -1569,7 +1662,8 @@ export async function resolveArtifact(svc, input) {
1569
1662
  const provenance = buildProvenance({
1570
1663
  requestedTarget: { kind, value },
1571
1664
  resolved,
1572
- transformChain: [...mappingDecision.transformChain, ...additionalTransformChain]
1665
+ transformChain: [...mappingDecision.transformChain, ...additionalTransformChain],
1666
+ unobfuscatedRuntime: runtimeNamesUnobfuscated
1573
1667
  });
1574
1668
  if (workspaceProvenance) {
1575
1669
  provenance.workspaceResolution = workspaceProvenance;
@@ -17,6 +17,13 @@ export type RemapMembersInput = {
17
17
  signatureFields: SignatureMember[];
18
18
  signatureMethods: SignatureMember[];
19
19
  version: string | undefined;
20
+ /**
21
+ * `version` when it is a Minecraft version, else undefined: a dependency
22
+ * artifact's `version` is its own release number, which must not reach the
23
+ * 26.1+ obfuscated<->mojang identity shortcut, which may only be asked about a
24
+ * string proven to be a Minecraft version.
25
+ */
26
+ minecraftVersion: string | undefined;
20
27
  mappingApplied: SourceMapping;
21
28
  requestedMapping: SourceMapping;
22
29
  sourcePriority: MappingSourcePriority | undefined;
@@ -1,10 +1,13 @@
1
+ import { remapSignatureMembers } from "../lifecycle/mapping-helpers.js";
1
2
  import { matchesMemberPattern } from "../member-pattern.js";
2
3
  export async function remapAndCountMembers(svc, input) {
3
4
  const remap = async (members, kind) => {
4
5
  if (input.version == null) {
5
6
  return members;
6
7
  }
7
- const result = await svc.remapSignatureMembers(members, kind, input.version, input.mappingApplied, input.requestedMapping, input.sourcePriority, input.warnings, undefined, input.gradleUserHome);
8
+ // Called directly rather than through svc.remapSignatureMembers, whose fixed
9
+ // parameter list cannot carry minecraftVersion.
10
+ const result = await remapSignatureMembers(svc, members, kind, input.version, input.mappingApplied, input.requestedMapping, input.sourcePriority, input.warnings, undefined, input.gradleUserHome, { minecraftVersion: input.minecraftVersion });
8
11
  return result.members;
9
12
  };
10
13
  let constructors = await remap(input.signatureConstructors, "method");
@@ -21,7 +21,7 @@ import type { ArtifactProvenance, ArtifactScope, MappingSourcePriority, Resolved
21
21
  */
22
22
  export declare function reconcileUnobfuscatedNamespace(version: string | undefined, requestedMapping: SourceMapping, mappingApplied: SourceMapping): SourceMapping;
23
23
  export declare function resolveClassFilePath(svc: SourceService, artifactId: string, className: string): string | undefined;
24
- export declare function resolveClassNameForLookup(svc: SourceService, input: {
24
+ type ClassNameLookupInput = {
25
25
  className: string;
26
26
  version?: string;
27
27
  sourceMapping: SourceMapping;
@@ -30,7 +30,13 @@ export declare function resolveClassNameForLookup(svc: SourceService, input: {
30
30
  gradleUserHome?: string;
31
31
  warnings: string[];
32
32
  context: string;
33
- }): Promise<string>;
33
+ };
34
+ /**
35
+ * The class-name translation behind `svc.resolveClassNameForLookup`, whose callers
36
+ * (the lifecycle tools) pass a Minecraft version, so `version` also keys the 26.1+
37
+ * identity shortcut.
38
+ */
39
+ export declare function resolveClassNameForLookup(svc: SourceService, input: ClassNameLookupInput): Promise<string>;
34
40
  export declare function buildFallbackProvenance(svc: SourceService, input: {
35
41
  artifactId: string;
36
42
  origin: ResolvedSourceArtifact["origin"];
@@ -98,3 +104,4 @@ export declare function findClass(svc: SourceService, input: FindClassInput): Fi
98
104
  export declare function findClassIncludingNested(svc: SourceService, input: FindClassInput): Promise<FindClassOutput>;
99
105
  export declare function getClassSource(svc: SourceService, input: GetClassSourceInput): Promise<GetClassSourceOutput>;
100
106
  export declare function getClassMembers(svc: SourceService, input: GetClassMembersInput): Promise<GetClassMembersOutput>;
107
+ export {};