@adhisang/minecraft-modding-mcp 3.1.0 → 3.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.
- package/CHANGELOG.md +62 -34
- package/README.md +79 -100
- package/dist/access-transformer-parser.d.ts +17 -0
- package/dist/access-transformer-parser.js +97 -0
- package/dist/concurrency.d.ts +1 -0
- package/dist/concurrency.js +24 -0
- package/dist/config.js +19 -11
- package/dist/decompiler/vineflower.js +22 -21
- package/dist/entry-tools/analyze-mod-service.d.ts +4 -4
- package/dist/entry-tools/analyze-symbol-service.d.ts +22 -20
- package/dist/entry-tools/analyze-symbol-service.js +6 -3
- package/dist/entry-tools/inspect-minecraft-service.d.ts +166 -149
- package/dist/entry-tools/inspect-minecraft-service.js +318 -55
- package/dist/entry-tools/validate-project-service.d.ts +153 -16
- package/dist/entry-tools/validate-project-service.js +360 -23
- package/dist/gradle-paths.d.ts +4 -0
- package/dist/gradle-paths.js +57 -0
- package/dist/index.js +274 -13
- package/dist/mapping-pipeline-service.d.ts +3 -1
- package/dist/mapping-pipeline-service.js +16 -1
- package/dist/mapping-service.d.ts +5 -0
- package/dist/mapping-service.js +200 -84
- package/dist/minecraft-explorer-service.d.ts +13 -0
- package/dist/minecraft-explorer-service.js +8 -4
- package/dist/mixin-validator.d.ts +33 -2
- package/dist/mixin-validator.js +197 -11
- package/dist/mod-analyzer.d.ts +1 -0
- package/dist/mod-analyzer.js +17 -1
- package/dist/mod-decompile-service.js +4 -4
- package/dist/mod-remap-service.js +1 -54
- package/dist/mod-search-service.d.ts +1 -0
- package/dist/mod-search-service.js +84 -51
- package/dist/response-utils.d.ts +35 -0
- package/dist/response-utils.js +113 -0
- package/dist/source-jar-reader.d.ts +16 -0
- package/dist/source-jar-reader.js +103 -1
- package/dist/source-resolver.js +9 -10
- package/dist/source-service.d.ts +24 -2
- package/dist/source-service.js +1052 -139
- package/dist/tool-contract-manifest.js +74 -74
- package/dist/types.d.ts +17 -0
- package/dist/workspace-mapping-service.d.ts +13 -0
- package/dist/workspace-mapping-service.js +146 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { ZodError, z } from "zod";
|
|
|
4
4
|
import { CompatStdioServerTransport } from "./compat-stdio-transport.js";
|
|
5
5
|
import { objectResult } from "./mcp-helpers.js";
|
|
6
6
|
import { prepareToolInput } from "./tool-input.js";
|
|
7
|
+
import { isCompactEnabled, COMPACT_MAPPING_TOOL_NAMES, compactResponse, compactArtifactResponse, compactMappingResponse } from "./response-utils.js";
|
|
7
8
|
import { loadConfig } from "./config.js";
|
|
8
9
|
import { createError, ERROR_CODES, isAppError } from "./errors.js";
|
|
9
10
|
import { log } from "./logger.js";
|
|
@@ -18,7 +19,7 @@ import { InspectMinecraftService, inspectMinecraftSchema, inspectMinecraftShape
|
|
|
18
19
|
import { AnalyzeSymbolService, analyzeSymbolSchema, analyzeSymbolShape } from "./entry-tools/analyze-symbol-service.js";
|
|
19
20
|
import { CompareMinecraftService, compareMinecraftSchema, compareMinecraftShape } from "./entry-tools/compare-minecraft-service.js";
|
|
20
21
|
import { AnalyzeModService, analyzeModSchema, analyzeModShape } from "./entry-tools/analyze-mod-service.js";
|
|
21
|
-
import { ValidateProjectService, validateProjectSchema, validateProjectShape, discoverWorkspaceAccessWideners, discoverWorkspaceMixins } from "./entry-tools/validate-project-service.js";
|
|
22
|
+
import { ValidateProjectService, validateProjectSchema, validateProjectShape, discoverWorkspaceAccessTransformers, discoverWorkspaceAccessWideners, discoverWorkspaceMixins } from "./entry-tools/validate-project-service.js";
|
|
22
23
|
import { ManageCacheService, manageCacheSchema, manageCacheShape } from "./entry-tools/manage-cache-service.js";
|
|
23
24
|
import { createCacheRegistry } from "./cache-registry.js";
|
|
24
25
|
import { buildEntryToolMeta } from "./entry-tools/response-contract.js";
|
|
@@ -89,7 +90,7 @@ const sourceLookupTargetSchema = z.discriminatedUnion("type", [
|
|
|
89
90
|
]);
|
|
90
91
|
const RESOLVE_ARTIFACT_TARGET_DESCRIPTION = "Object with kind and value. Example: {\"kind\":\"version\",\"value\":\"1.21.10\"}. Must be an object, not a string.";
|
|
91
92
|
const SOURCE_LOOKUP_TARGET_DESCRIPTION = "Object: {\"type\":\"resolve\",\"kind\":\"version\",\"value\":\"1.21.10\"} or {\"type\":\"artifact\",\"artifactId\":\"...\"}. Must be an object, not a string.";
|
|
92
|
-
const SOURCE_SCOPE_DESCRIPTION =
|
|
93
|
+
const SOURCE_SCOPE_DESCRIPTION = "vanilla = Mojang client jar only; merged = source-oriented merged runtime discovery; loader = loader/runtime artifact discovery when the workspace exposes transformed runtime jars.";
|
|
93
94
|
const SUGGESTED_CALL_DEFAULTS = {
|
|
94
95
|
allowDecompile: true,
|
|
95
96
|
preferProjectVersion: false,
|
|
@@ -109,6 +110,10 @@ const SUGGESTED_CALL_DEFAULTS = {
|
|
|
109
110
|
function isSuggestedCallDefault(field, value) {
|
|
110
111
|
return value === SUGGESTED_CALL_DEFAULTS[field];
|
|
111
112
|
}
|
|
113
|
+
const ANALYZE_MOD_INCLUDE_GROUPS = ["warnings", "files", "source", "samples", "timings"];
|
|
114
|
+
const ANALYZE_MOD_LEGACY_METADATA_INCLUDES = ["metadata", "entrypoints", "mixins", "dependencies"];
|
|
115
|
+
const VALIDATE_PROJECT_INCLUDE_GROUPS = ["warnings", "issues", "workspace", "recovery"];
|
|
116
|
+
const VALIDATE_PROJECT_LEGACY_WORKSPACE_INCLUDES = ["detectedConfig", "mixins", "accessWideners"];
|
|
112
117
|
const listVersionsShape = {
|
|
113
118
|
includeSnapshots: z.boolean().default(false),
|
|
114
119
|
limit: optionalPositiveInt.default(20).describe("max 200")
|
|
@@ -125,7 +130,9 @@ const resolveArtifactShape = {
|
|
|
125
130
|
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
126
131
|
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
127
132
|
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override target.value"),
|
|
128
|
-
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false.")
|
|
133
|
+
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
134
|
+
compact: z.boolean().default(false).describe("When true, return minimal fields (artifactId, origin, isDecompiled, version, requestedMapping, mappingApplied, qualityFlags). "
|
|
135
|
+
+ "Omit provenance, artifactContents, sampleEntries, adjacentSourceCandidates, binaryJarPath, coordinate, repoUrl, resolvedSourceJarPath.")
|
|
129
136
|
};
|
|
130
137
|
const resolveArtifactSchema = z.object(resolveArtifactShape);
|
|
131
138
|
const getClassSourceShape = {
|
|
@@ -246,7 +253,9 @@ const findMappingShape = {
|
|
|
246
253
|
})
|
|
247
254
|
.partial()
|
|
248
255
|
.optional(),
|
|
249
|
-
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates (max 200)")
|
|
256
|
+
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates (max 200)"),
|
|
257
|
+
compact: z.boolean().default(false).describe("When true, omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
258
|
+
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions.")
|
|
250
259
|
};
|
|
251
260
|
const findMappingSchema = z.object(findMappingShape).superRefine((value, ctx) => {
|
|
252
261
|
if (value.kind === "class") {
|
|
@@ -264,7 +273,7 @@ const findMappingSchema = z.object(findMappingShape).superRefine((value, ctx) =>
|
|
|
264
273
|
path: ["descriptor"]
|
|
265
274
|
});
|
|
266
275
|
}
|
|
267
|
-
if (!value.name.includes(".")) {
|
|
276
|
+
if (value.sourceMapping !== "obfuscated" && !value.name.includes(".")) {
|
|
268
277
|
ctx.addIssue({
|
|
269
278
|
code: z.ZodIssueCode.custom,
|
|
270
279
|
message: "name must be fully-qualified class name when kind=class.",
|
|
@@ -313,7 +322,9 @@ const resolveMethodMappingExactShape = {
|
|
|
313
322
|
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
314
323
|
targetMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
315
324
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
316
|
-
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates (max 200)")
|
|
325
|
+
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates (max 200)"),
|
|
326
|
+
compact: z.boolean().default(false).describe("When true, omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
327
|
+
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions.")
|
|
317
328
|
};
|
|
318
329
|
const resolveMethodMappingExactSchema = z
|
|
319
330
|
.object(resolveMethodMappingExactShape)
|
|
@@ -364,7 +375,9 @@ const resolveWorkspaceSymbolShape = {
|
|
|
364
375
|
descriptor: optionalNonEmptyString,
|
|
365
376
|
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
366
377
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
367
|
-
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates for field/method lookups (max 200)")
|
|
378
|
+
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates for field/method lookups (max 200)"),
|
|
379
|
+
compact: z.boolean().default(false).describe("When true, omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
380
|
+
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions.")
|
|
368
381
|
};
|
|
369
382
|
const resolveWorkspaceSymbolSchema = z
|
|
370
383
|
.object(resolveWorkspaceSymbolShape)
|
|
@@ -436,7 +449,9 @@ const checkSymbolExistsShape = {
|
|
|
436
449
|
nameMode: classNameModeSchema.default("fqcn").describe("fqcn | auto"),
|
|
437
450
|
signatureMode: z.enum(["exact", "name-only"]).default("exact")
|
|
438
451
|
.describe("exact: require descriptor for methods; name-only: match by owner+name only"),
|
|
439
|
-
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates (max 200)")
|
|
452
|
+
maxCandidates: optionalPositiveInt.default(200).describe("Limit returned candidates (max 200)"),
|
|
453
|
+
compact: z.boolean().default(false).describe("When true, omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
454
|
+
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions.")
|
|
440
455
|
};
|
|
441
456
|
const checkSymbolExistsSchema = z.object(checkSymbolExistsShape).superRefine((value, ctx) => {
|
|
442
457
|
if (value.kind === "class") {
|
|
@@ -577,9 +592,24 @@ const validateAccessWidenerShape = {
|
|
|
577
592
|
content: nonEmptyString.describe("Access Widener file content"),
|
|
578
593
|
version: nonEmptyString.describe("Minecraft version"),
|
|
579
594
|
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
580
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first")
|
|
595
|
+
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
596
|
+
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted runtime validation"),
|
|
597
|
+
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
598
|
+
preferProjectVersion: z.boolean().default(false)
|
|
599
|
+
.describe("When true, detect MC version from gradle.properties and override version")
|
|
581
600
|
};
|
|
582
601
|
const validateAccessWidenerSchema = z.object(validateAccessWidenerShape);
|
|
602
|
+
const validateAccessTransformerShape = {
|
|
603
|
+
content: nonEmptyString.describe("Access Transformer file content"),
|
|
604
|
+
version: nonEmptyString.describe("Minecraft version"),
|
|
605
|
+
atNamespace: z.enum(["srg", "mojang", "obfuscated"]).optional().describe("srg | mojang | obfuscated"),
|
|
606
|
+
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
607
|
+
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Forge/NeoForge runtime validation"),
|
|
608
|
+
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
609
|
+
preferProjectVersion: z.boolean().default(false)
|
|
610
|
+
.describe("When true, detect MC version from gradle.properties and override version")
|
|
611
|
+
};
|
|
612
|
+
const validateAccessTransformerSchema = z.object(validateAccessTransformerShape);
|
|
583
613
|
const analyzeModJarShape = {
|
|
584
614
|
jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
|
|
585
615
|
includeClasses: z.boolean().default(false).describe("Include full class listing")
|
|
@@ -680,6 +710,7 @@ const inspectMinecraftService = new InspectMinecraftService({
|
|
|
680
710
|
listVersions: (input) => sourceService.listVersions(input),
|
|
681
711
|
resolveArtifact: (input) => sourceService.resolveArtifact(input),
|
|
682
712
|
findClass: (input) => Promise.resolve(sourceService.findClass(input)),
|
|
713
|
+
checkSymbolExists: (input) => sourceService.checkSymbolExists(input),
|
|
683
714
|
getClassSource: (input) => sourceService.getClassSource(input),
|
|
684
715
|
getClassMembers: (input) => sourceService.getClassMembers(input),
|
|
685
716
|
searchClassSource: (input) => sourceService.searchClassSource(input),
|
|
@@ -710,8 +741,11 @@ const analyzeModService = new AnalyzeModService({
|
|
|
710
741
|
const validateProjectService = new ValidateProjectService({
|
|
711
742
|
validateMixin: (input) => sourceService.validateMixin(input),
|
|
712
743
|
validateAccessWidener: (input) => sourceService.validateAccessWidener(input),
|
|
744
|
+
validateAccessTransformer: (input) => sourceService.validateAccessTransformer(input),
|
|
713
745
|
discoverMixins: discoverWorkspaceMixins,
|
|
714
|
-
discoverAccessWideners: discoverWorkspaceAccessWideners
|
|
746
|
+
discoverAccessWideners: discoverWorkspaceAccessWideners,
|
|
747
|
+
discoverAccessTransformers: discoverWorkspaceAccessTransformers,
|
|
748
|
+
detectProjectMinecraftVersion: (projectPath) => workspaceMappingService.detectProjectMinecraftVersion(projectPath)
|
|
715
749
|
});
|
|
716
750
|
const manageCacheService = new ManageCacheService({
|
|
717
751
|
registry: createCacheRegistry({
|
|
@@ -1154,6 +1188,184 @@ function buildSourceLookupSuggestedParams(tool, normalizedInput) {
|
|
|
1154
1188
|
}
|
|
1155
1189
|
return result;
|
|
1156
1190
|
}
|
|
1191
|
+
function filterAllowedIncludeValues(values, allowed) {
|
|
1192
|
+
if (!values?.length) {
|
|
1193
|
+
return [];
|
|
1194
|
+
}
|
|
1195
|
+
const allowedSet = new Set(allowed);
|
|
1196
|
+
const filtered = values.filter((value) => allowedSet.has(value));
|
|
1197
|
+
return [...new Set(filtered)];
|
|
1198
|
+
}
|
|
1199
|
+
function buildAnalyzeModSuggestedParams(normalizedInput) {
|
|
1200
|
+
const record = asObjectRecord(normalizedInput);
|
|
1201
|
+
if (!record) {
|
|
1202
|
+
return {
|
|
1203
|
+
task: "summary",
|
|
1204
|
+
detail: "standard",
|
|
1205
|
+
subject: {
|
|
1206
|
+
kind: "jar",
|
|
1207
|
+
jarPath: "<mod-jar-path>"
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
const task = asNonEmptyString(record.task) ?? "summary";
|
|
1212
|
+
const result = { task };
|
|
1213
|
+
const subjectRecord = asObjectRecord(record.subject);
|
|
1214
|
+
const include = asStringArray(record.include);
|
|
1215
|
+
const canonicalInclude = filterAllowedIncludeValues(include, ANALYZE_MOD_INCLUDE_GROUPS);
|
|
1216
|
+
const wantsLegacyMetadata = include?.some((value) => ANALYZE_MOD_LEGACY_METADATA_INCLUDES.includes(value)) ?? false;
|
|
1217
|
+
const detail = asNonEmptyString(record.detail);
|
|
1218
|
+
if (task === "summary" && wantsLegacyMetadata) {
|
|
1219
|
+
result.detail = detail && detail !== "summary" ? detail : "standard";
|
|
1220
|
+
}
|
|
1221
|
+
else if (detail && detail !== "summary") {
|
|
1222
|
+
result.detail = detail;
|
|
1223
|
+
}
|
|
1224
|
+
if (canonicalInclude.length > 0) {
|
|
1225
|
+
result.include = canonicalInclude;
|
|
1226
|
+
}
|
|
1227
|
+
if (task === "class-source") {
|
|
1228
|
+
result.subject = {
|
|
1229
|
+
kind: "class",
|
|
1230
|
+
jarPath: asNonEmptyString(subjectRecord?.jarPath) ?? asNonEmptyString(record.subject) ?? "<mod-jar-path>",
|
|
1231
|
+
className: asNonEmptyString(subjectRecord?.className) ?? asNonEmptyString(record.className) ?? "<fully-qualified-class-name>"
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
else {
|
|
1235
|
+
result.subject = {
|
|
1236
|
+
kind: "jar",
|
|
1237
|
+
jarPath: asNonEmptyString(subjectRecord?.jarPath) ?? asNonEmptyString(record.subject) ?? asNonEmptyString(record.jarPath) ?? "<mod-jar-path>"
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
const stringFields = ["query", "searchType", "targetMapping", "outputJar", "executionMode"];
|
|
1241
|
+
for (const field of stringFields) {
|
|
1242
|
+
const value = record[field];
|
|
1243
|
+
if (typeof value === "string" && value.trim()) {
|
|
1244
|
+
result[field] = value;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
const booleanFields = ["includeFiles"];
|
|
1248
|
+
for (const field of booleanFields) {
|
|
1249
|
+
const value = record[field];
|
|
1250
|
+
if (typeof value === "boolean") {
|
|
1251
|
+
result[field] = value;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
const numericFields = ["limit", "maxFiles", "maxLines", "maxChars"];
|
|
1255
|
+
for (const field of numericFields) {
|
|
1256
|
+
const value = record[field];
|
|
1257
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1258
|
+
result[field] = value;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
return result;
|
|
1262
|
+
}
|
|
1263
|
+
function buildValidateProjectSuggestedParams(normalizedInput) {
|
|
1264
|
+
const record = asObjectRecord(normalizedInput);
|
|
1265
|
+
if (!record) {
|
|
1266
|
+
return {
|
|
1267
|
+
task: "project-summary",
|
|
1268
|
+
subject: {
|
|
1269
|
+
kind: "workspace",
|
|
1270
|
+
projectPath: "<workspace-path>"
|
|
1271
|
+
},
|
|
1272
|
+
preferProjectVersion: true
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
const task = asNonEmptyString(record.task) ?? "project-summary";
|
|
1276
|
+
const result = { task };
|
|
1277
|
+
const subjectRecord = asObjectRecord(record.subject);
|
|
1278
|
+
const include = asStringArray(record.include);
|
|
1279
|
+
const canonicalInclude = filterAllowedIncludeValues(include, VALIDATE_PROJECT_INCLUDE_GROUPS);
|
|
1280
|
+
const wantsWorkspaceInclude = include?.some((value) => VALIDATE_PROJECT_LEGACY_WORKSPACE_INCLUDES.includes(value)) ?? false;
|
|
1281
|
+
const detail = asNonEmptyString(record.detail);
|
|
1282
|
+
if (detail && detail !== "summary") {
|
|
1283
|
+
result.detail = detail;
|
|
1284
|
+
}
|
|
1285
|
+
const includeSuggestion = wantsWorkspaceInclude
|
|
1286
|
+
? [...new Set([...canonicalInclude, "workspace"])]
|
|
1287
|
+
: canonicalInclude;
|
|
1288
|
+
if (includeSuggestion.length > 0) {
|
|
1289
|
+
result.include = includeSuggestion;
|
|
1290
|
+
}
|
|
1291
|
+
const stringFields = [
|
|
1292
|
+
"version",
|
|
1293
|
+
"mapping",
|
|
1294
|
+
"sourcePriority",
|
|
1295
|
+
"scope",
|
|
1296
|
+
"minSeverity",
|
|
1297
|
+
"warningMode"
|
|
1298
|
+
];
|
|
1299
|
+
for (const field of stringFields) {
|
|
1300
|
+
const value = record[field];
|
|
1301
|
+
if (typeof value === "string" && value.trim()) {
|
|
1302
|
+
result[field] = value;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
const booleanFields = [
|
|
1306
|
+
"preferProjectVersion",
|
|
1307
|
+
"preferProjectMapping",
|
|
1308
|
+
"hideUncertain",
|
|
1309
|
+
"explain",
|
|
1310
|
+
"treatInfoAsWarning",
|
|
1311
|
+
"includeIssues"
|
|
1312
|
+
];
|
|
1313
|
+
for (const field of booleanFields) {
|
|
1314
|
+
const value = record[field];
|
|
1315
|
+
if (typeof value === "boolean" &&
|
|
1316
|
+
(!Object.prototype.hasOwnProperty.call(SUGGESTED_CALL_DEFAULTS, field) ||
|
|
1317
|
+
!isSuggestedCallDefault(field, value))) {
|
|
1318
|
+
result[field] = value;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
const sourceRoots = asStringArray(record.sourceRoots);
|
|
1322
|
+
if (sourceRoots?.length) {
|
|
1323
|
+
result.sourceRoots = sourceRoots;
|
|
1324
|
+
}
|
|
1325
|
+
const configPaths = asStringArray(record.configPaths);
|
|
1326
|
+
if (configPaths?.length) {
|
|
1327
|
+
result.configPaths = configPaths;
|
|
1328
|
+
}
|
|
1329
|
+
const warningCategoryFilter = asStringArray(record.warningCategoryFilter);
|
|
1330
|
+
if (warningCategoryFilter?.length) {
|
|
1331
|
+
result.warningCategoryFilter = warningCategoryFilter;
|
|
1332
|
+
}
|
|
1333
|
+
if (task === "project-summary") {
|
|
1334
|
+
const subject = {
|
|
1335
|
+
kind: "workspace",
|
|
1336
|
+
projectPath: asNonEmptyString(subjectRecord?.projectPath) ??
|
|
1337
|
+
asNonEmptyString(record.subject) ??
|
|
1338
|
+
asNonEmptyString(record.projectPath) ??
|
|
1339
|
+
"<workspace-path>"
|
|
1340
|
+
};
|
|
1341
|
+
const discover = asStringArray(subjectRecord?.discover);
|
|
1342
|
+
if (discover?.length) {
|
|
1343
|
+
subject.discover = discover;
|
|
1344
|
+
}
|
|
1345
|
+
result.subject = subject;
|
|
1346
|
+
return result;
|
|
1347
|
+
}
|
|
1348
|
+
if (task === "mixin") {
|
|
1349
|
+
const inputRecord = asObjectRecord(subjectRecord?.input) ?? asObjectRecord(record.input);
|
|
1350
|
+
result.subject = {
|
|
1351
|
+
kind: "mixin",
|
|
1352
|
+
input: inputRecord ?? {
|
|
1353
|
+
mode: "inline",
|
|
1354
|
+
source: "<Mixin Java source>"
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
return result;
|
|
1358
|
+
}
|
|
1359
|
+
const inputRecord = asObjectRecord(subjectRecord?.input) ?? asObjectRecord(record.input);
|
|
1360
|
+
result.subject = {
|
|
1361
|
+
kind: "access-widener",
|
|
1362
|
+
input: inputRecord ?? {
|
|
1363
|
+
mode: "inline",
|
|
1364
|
+
content: "<access widener contents>"
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
return result;
|
|
1368
|
+
}
|
|
1157
1369
|
function buildInvalidInputGuidance(tool, normalizedInput) {
|
|
1158
1370
|
if (tool === "validate-mixin") {
|
|
1159
1371
|
const hints = [
|
|
@@ -1193,6 +1405,32 @@ function buildInvalidInputGuidance(tool, normalizedInput) {
|
|
|
1193
1405
|
}
|
|
1194
1406
|
};
|
|
1195
1407
|
}
|
|
1408
|
+
if (tool === "validate-project") {
|
|
1409
|
+
return {
|
|
1410
|
+
hints: [
|
|
1411
|
+
"validate-project.subject must be an object with subject.kind=workspace|mixin|access-widener|access-transformer.",
|
|
1412
|
+
"task=\"project-summary\" uses {\"subject\":{\"kind\":\"workspace\",\"projectPath\":\"/workspace\"}}.",
|
|
1413
|
+
"Legacy include names like projectSummary/detectedConfig/validationSummary are not accepted; use include:[\"workspace\"] only when you need discovery details."
|
|
1414
|
+
],
|
|
1415
|
+
suggestedCall: {
|
|
1416
|
+
tool,
|
|
1417
|
+
params: buildValidateProjectSuggestedParams(normalizedInput)
|
|
1418
|
+
}
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
if (tool === "analyze-mod") {
|
|
1422
|
+
return {
|
|
1423
|
+
hints: [
|
|
1424
|
+
"analyze-mod.subject must be an object with subject.kind=jar|class.",
|
|
1425
|
+
"task=\"summary\" uses {\"subject\":{\"kind\":\"jar\",\"jarPath\":\"/path/to/mod.jar\"}}.",
|
|
1426
|
+
"Legacy include names like metadata/entrypoints/mixins/dependencies are not accepted; use detail=\"standard\" to surface the metadata block, and canonical include groups only for warnings/files/source/samples/timings."
|
|
1427
|
+
],
|
|
1428
|
+
suggestedCall: {
|
|
1429
|
+
tool,
|
|
1430
|
+
params: buildAnalyzeModSuggestedParams(normalizedInput)
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1196
1434
|
return undefined;
|
|
1197
1435
|
}
|
|
1198
1436
|
function mapErrorToProblem(caughtError, requestId, context) {
|
|
@@ -1293,6 +1531,17 @@ async function runTool(tool, rawInput, schema, action) {
|
|
|
1293
1531
|
? heavyToolExecutionGate.run(tool, () => action(parsedInput))
|
|
1294
1532
|
: action(parsedInput));
|
|
1295
1533
|
const { result, warnings, meta: resultMeta } = splitWarnings(payload);
|
|
1534
|
+
const isCompact = isCompactEnabled(tool, parsedInput);
|
|
1535
|
+
let projectedResult = result;
|
|
1536
|
+
if (isCompact) {
|
|
1537
|
+
if (tool === "resolve-artifact") {
|
|
1538
|
+
projectedResult = compactArtifactResponse(projectedResult);
|
|
1539
|
+
}
|
|
1540
|
+
if (COMPACT_MAPPING_TOOL_NAMES.has(tool)) {
|
|
1541
|
+
projectedResult = compactMappingResponse(projectedResult);
|
|
1542
|
+
}
|
|
1543
|
+
projectedResult = compactResponse(projectedResult);
|
|
1544
|
+
}
|
|
1296
1545
|
const entryMeta = ENTRY_TOOL_NAMES.has(tool)
|
|
1297
1546
|
? buildEntryToolMeta({
|
|
1298
1547
|
detail: normalizedInput &&
|
|
@@ -1310,7 +1559,7 @@ async function runTool(tool, rawInput, schema, action) {
|
|
|
1310
1559
|
})
|
|
1311
1560
|
: undefined;
|
|
1312
1561
|
return objectResult({
|
|
1313
|
-
result,
|
|
1562
|
+
result: projectedResult,
|
|
1314
1563
|
meta: {
|
|
1315
1564
|
...(entryMeta ?? {}),
|
|
1316
1565
|
...resultMeta,
|
|
@@ -1375,7 +1624,7 @@ server.tool("inspect-minecraft", "High-level v3 entry tool for version discovery
|
|
|
1375
1624
|
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)));
|
|
1376
1625
|
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)));
|
|
1377
1626
|
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)));
|
|
1378
|
-
server.tool("validate-project", "High-level v3 entry tool for project summary, direct mixin validation, and access widener validation.", validateProjectShape, { readOnlyHint: true }, async (args) => runTool("validate-project", args, validateProjectSchema, async (input) => validateProjectService.execute(input)));
|
|
1627
|
+
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)));
|
|
1379
1628
|
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)));
|
|
1380
1629
|
server.tool("resolve-artifact", "Resolve source artifact from a target object ({ kind, value }) and return artifact metadata. For target.kind=jar, only <basename>-sources.jar is auto-adopted; other adjacent *-sources.jar files are informational.", resolveArtifactShape, { readOnlyHint: true }, async (args) => runTool("resolve-artifact", args, resolveArtifactSchema, async (input) => sourceService.resolveArtifact({
|
|
1381
1630
|
target: input.target,
|
|
@@ -1576,7 +1825,19 @@ server.tool("validate-access-widener", "Validate Access Widener file entries aga
|
|
|
1576
1825
|
content: input.content,
|
|
1577
1826
|
version: input.version,
|
|
1578
1827
|
mapping: input.mapping,
|
|
1579
|
-
sourcePriority: input.sourcePriority
|
|
1828
|
+
sourcePriority: input.sourcePriority,
|
|
1829
|
+
projectPath: input.projectPath,
|
|
1830
|
+
scope: input.scope,
|
|
1831
|
+
preferProjectVersion: input.preferProjectVersion
|
|
1832
|
+
})));
|
|
1833
|
+
server.tool("validate-access-transformer", "Validate Access Transformer file entries against Minecraft bytecode signatures for a given version.", validateAccessTransformerShape, { readOnlyHint: true }, async (args) => runTool("validate-access-transformer", args, validateAccessTransformerSchema, async (input) => sourceService.validateAccessTransformer({
|
|
1834
|
+
content: input.content,
|
|
1835
|
+
version: input.version,
|
|
1836
|
+
atNamespace: input.atNamespace,
|
|
1837
|
+
sourcePriority: input.sourcePriority,
|
|
1838
|
+
projectPath: input.projectPath,
|
|
1839
|
+
scope: input.scope,
|
|
1840
|
+
preferProjectVersion: input.preferProjectVersion
|
|
1580
1841
|
})));
|
|
1581
1842
|
server.tool("analyze-mod-jar", "Analyze a Minecraft mod JAR to extract loader type, metadata, entrypoints, mixins, and dependencies.", analyzeModJarShape, { readOnlyHint: true }, async (args) => runTool("analyze-mod-jar", args, analyzeModJarSchema, async (input) => {
|
|
1582
1843
|
const result = await analyzeModJar(input.jarPath, {
|
|
@@ -3,6 +3,7 @@ export interface MappingPipelineInput {
|
|
|
3
3
|
requestedMapping: SourceMapping;
|
|
4
4
|
target: SourceTargetInput;
|
|
5
5
|
resolved: ResolvedSourceArtifact;
|
|
6
|
+
runtimeNamesUnobfuscated?: boolean;
|
|
6
7
|
}
|
|
7
8
|
export interface MappingPipelineResult {
|
|
8
9
|
mappingApplied: SourceMapping;
|
|
@@ -13,6 +14,7 @@ export interface MappingPipelineResult {
|
|
|
13
14
|
* Mapping pipeline for v0.3.
|
|
14
15
|
* Current implementation enforces explicit guarantees:
|
|
15
16
|
* - obfuscated: always pass-through
|
|
16
|
-
* - mojang: requires source-backed
|
|
17
|
+
* - mojang: requires source-backed artifacts on legacy obfuscated versions,
|
|
18
|
+
* but unobfuscated runtime jars can pass through directly
|
|
17
19
|
*/
|
|
18
20
|
export declare function applyMappingPipeline(input: MappingPipelineInput): MappingPipelineResult;
|
|
@@ -3,7 +3,8 @@ import { createError, ERROR_CODES } from "./errors.js";
|
|
|
3
3
|
* Mapping pipeline for v0.3.
|
|
4
4
|
* Current implementation enforces explicit guarantees:
|
|
5
5
|
* - obfuscated: always pass-through
|
|
6
|
-
* - mojang: requires source-backed
|
|
6
|
+
* - mojang: requires source-backed artifacts on legacy obfuscated versions,
|
|
7
|
+
* but unobfuscated runtime jars can pass through directly
|
|
7
8
|
*/
|
|
8
9
|
export function applyMappingPipeline(input) {
|
|
9
10
|
const transformChain = [];
|
|
@@ -22,6 +23,20 @@ export function applyMappingPipeline(input) {
|
|
|
22
23
|
transformChain
|
|
23
24
|
};
|
|
24
25
|
}
|
|
26
|
+
if (input.requestedMapping === "mojang" && input.runtimeNamesUnobfuscated) {
|
|
27
|
+
transformChain.push("mapping:mojang-runtime-unobfuscated");
|
|
28
|
+
if (input.resolved.isDecompiled) {
|
|
29
|
+
qualityFlags.push("decompiled");
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
qualityFlags.push("source-backed");
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
mappingApplied: "mojang",
|
|
36
|
+
qualityFlags,
|
|
37
|
+
transformChain
|
|
38
|
+
};
|
|
39
|
+
}
|
|
25
40
|
if (input.requestedMapping !== "mojang" &&
|
|
26
41
|
input.requestedMapping !== "intermediary" &&
|
|
27
42
|
input.requestedMapping !== "yarn") {
|
|
@@ -62,6 +62,7 @@ export type FindMappingInput = {
|
|
|
62
62
|
sourceMapping: SourceMapping;
|
|
63
63
|
targetMapping: SourceMapping;
|
|
64
64
|
sourcePriority?: MappingSourcePriority;
|
|
65
|
+
projectPath?: string;
|
|
65
66
|
disambiguation?: {
|
|
66
67
|
ownerHint?: string;
|
|
67
68
|
descriptorHint?: string;
|
|
@@ -74,6 +75,7 @@ export type EnsureMappingAvailableInput = {
|
|
|
74
75
|
sourceMapping: SourceMapping;
|
|
75
76
|
targetMapping: SourceMapping;
|
|
76
77
|
sourcePriority?: MappingSourcePriority;
|
|
78
|
+
projectPath?: string;
|
|
77
79
|
};
|
|
78
80
|
export type EnsureMappingAvailableOutput = {
|
|
79
81
|
transformChain: string[];
|
|
@@ -88,6 +90,7 @@ export type ResolveMethodMappingExactInput = {
|
|
|
88
90
|
sourceMapping: SourceMapping;
|
|
89
91
|
targetMapping: SourceMapping;
|
|
90
92
|
sourcePriority?: MappingSourcePriority;
|
|
93
|
+
projectPath?: string;
|
|
91
94
|
maxCandidates?: number;
|
|
92
95
|
};
|
|
93
96
|
export type ResolveMethodMappingExactOutput = SymbolResolutionOutput;
|
|
@@ -153,6 +156,7 @@ export declare class MappingService {
|
|
|
153
156
|
checkSymbolExists(input: SymbolExistenceInput): Promise<SymbolExistenceOutput>;
|
|
154
157
|
private mapRecordBetweenMappings;
|
|
155
158
|
private mapCandidatesAlongPath;
|
|
159
|
+
private projectMethodDescriptorToTarget;
|
|
156
160
|
private provenanceForPath;
|
|
157
161
|
/**
|
|
158
162
|
* Probe the mapping graph health for a given version.
|
|
@@ -177,6 +181,7 @@ export declare class MappingService {
|
|
|
177
181
|
private parseTinyFromJar;
|
|
178
182
|
private fetchYarnCoordinates;
|
|
179
183
|
private trimGraphCache;
|
|
184
|
+
releaseGraphCacheEntry(version: string, sourcePriority?: MappingSourcePriority): void;
|
|
180
185
|
}
|
|
181
186
|
/**
|
|
182
187
|
* Resolve and cache a Tiny v2 mapping file for the given Minecraft version.
|