@adhisang/minecraft-modding-mcp 4.2.0 → 5.0.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 +40 -0
- package/README.md +6 -4
- package/dist/access-transformer-parser.d.ts +2 -1
- package/dist/access-transformer-parser.js +10 -1
- package/dist/build-suggested-call.js +31 -10
- package/dist/cache-registry.d.ts +8 -0
- package/dist/cache-registry.js +99 -6
- package/dist/config.d.ts +1 -0
- package/dist/config.js +4 -0
- package/dist/entry-tools/analyze-mod-service.d.ts +24 -24
- package/dist/entry-tools/analyze-symbol-service.d.ts +57 -22
- package/dist/entry-tools/analyze-symbol-service.js +124 -28
- package/dist/entry-tools/batch-class-members-service.d.ts +3 -1
- package/dist/entry-tools/batch-class-members-service.js +6 -6
- package/dist/entry-tools/batch-class-source-service.d.ts +3 -1
- package/dist/entry-tools/batch-class-source-service.js +5 -6
- package/dist/entry-tools/batch-mappings-service.d.ts +3 -1
- package/dist/entry-tools/batch-mappings-service.js +4 -5
- package/dist/entry-tools/batch-symbol-exists-service.d.ts +3 -1
- package/dist/entry-tools/batch-symbol-exists-service.js +4 -5
- package/dist/entry-tools/compare-minecraft-service.d.ts +10 -10
- package/dist/entry-tools/entry-tool-schema.d.ts +1 -1
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +1 -3
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +2 -2
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +0 -5
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/file.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +8 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.js +13 -2
- package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +1 -1
- package/dist/entry-tools/inspect-minecraft/handlers/versions.js +1 -1
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +90 -89
- package/dist/entry-tools/inspect-minecraft/internal.js +30 -14
- package/dist/entry-tools/inspect-minecraft-service.d.ts +218 -218
- package/dist/entry-tools/inspect-minecraft-service.js +1 -1
- package/dist/entry-tools/manage-cache-service.d.ts +4 -4
- package/dist/entry-tools/response-contract.d.ts +1 -1
- package/dist/entry-tools/response-contract.js +1 -0
- package/dist/entry-tools/validate-project/cases/mixin.js +2 -1
- package/dist/entry-tools/validate-project/cases/project-summary.js +5 -3
- package/dist/entry-tools/validate-project-service.d.ts +42 -36
- package/dist/entry-tools/validate-project-service.js +3 -1
- package/dist/entry-tools/verify-mixin-target-service.d.ts +30 -0
- package/dist/entry-tools/verify-mixin-target-service.js +113 -22
- package/dist/error-mapping.d.ts +51 -0
- package/dist/error-mapping.js +157 -2
- package/dist/errors.js +4 -1
- package/dist/index.js +138 -71
- package/dist/java-process.d.ts +9 -0
- package/dist/java-process.js +11 -5
- package/dist/mapping/internal-types.d.ts +7 -0
- package/dist/mapping/lookup.d.ts +1 -1
- package/dist/mapping/lookup.js +7 -1
- package/dist/mapping/types.d.ts +6 -0
- package/dist/mapping-service.d.ts +26 -2
- package/dist/mapping-service.js +178 -36
- package/dist/mcp-helpers.d.ts +1 -0
- package/dist/mcp-helpers.js +25 -3
- package/dist/minecraft-explorer-service.js +24 -11
- package/dist/mixin/access-validators.js +33 -1
- package/dist/mixin/annotation-validators.js +53 -7
- package/dist/mixin/parsed-validator.js +2 -2
- package/dist/mixin-parser.js +48 -4
- package/dist/mod-decompile-service.js +2 -1
- package/dist/mod-remap-service.d.ts +20 -1
- package/dist/mod-remap-service.js +95 -40
- package/dist/nbt/java-nbt-codec.js +87 -2
- package/dist/observability.d.ts +6 -0
- package/dist/observability.js +10 -0
- package/dist/page-cursor.d.ts +17 -0
- package/dist/page-cursor.js +0 -0
- package/dist/registry-service.js +25 -1
- package/dist/resources.js +45 -9
- package/dist/response-utils.d.ts +29 -4
- package/dist/response-utils.js +95 -5
- package/dist/source/access-validate.js +12 -2
- package/dist/source/artifact-resolver.js +1 -1
- package/dist/source/cache-metrics.js +2 -2
- package/dist/source/class-source/members-builder.d.ts +44 -1
- package/dist/source/class-source/members-builder.js +51 -4
- package/dist/source/class-source/snippet-builder.d.ts +13 -0
- package/dist/source/class-source/snippet-builder.js +48 -4
- package/dist/source/class-source-helpers.js +67 -11
- package/dist/source/class-source.js +97 -20
- package/dist/source/indexer.d.ts +31 -6
- package/dist/source/indexer.js +95 -25
- package/dist/source/search.d.ts +1 -1
- package/dist/source/search.js +94 -22
- package/dist/source/validate-mixin.d.ts +2 -1
- package/dist/source/validate-mixin.js +45 -4
- package/dist/source/workspace-target.js +15 -9
- package/dist/source-jar-reader.d.ts +54 -1
- package/dist/source-jar-reader.js +121 -10
- package/dist/source-service.d.ts +28 -7
- package/dist/storage/files-repo.d.ts +12 -0
- package/dist/storage/files-repo.js +24 -0
- package/dist/storage/symbols-repo.d.ts +6 -0
- package/dist/storage/symbols-repo.js +6 -0
- package/dist/symbols/symbol-extractor.js +35 -6
- package/dist/text-truncate.d.ts +7 -0
- package/dist/text-truncate.js +21 -0
- package/dist/tiny-remapper-resolver.js +10 -0
- package/dist/tiny-remapper-service.js +3 -3
- package/dist/tool-contract-manifest.js +2 -2
- package/dist/tool-execution-gate.js +12 -1
- package/dist/tool-guidance.d.ts +4 -1
- package/dist/tool-guidance.js +37 -12
- package/dist/tool-schemas.d.ts +559 -494
- package/dist/tool-schemas.js +99 -63
- package/dist/types.d.ts +1 -0
- package/dist/version-diff-service.js +5 -0
- package/dist/version-service.d.ts +3 -0
- package/dist/version-service.js +18 -2
- package/dist/warning-details.d.ts +18 -0
- package/dist/warning-details.js +63 -0
- package/docs/README-ja.md +2 -2
- package/docs/examples.md +26 -2
- package/docs/tool-reference.md +23 -17
- package/package.json +1 -1
package/dist/tool-schemas.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { isAbsolute as pathIsAbsolute, resolve as pathResolve } from "node:path";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { DETAIL_LEVELS, CANONICAL_INCLUDE_GROUPS } from "./entry-tools/response-contract.js";
|
|
4
|
+
// Shared response-shape controls for the expert + batch tools (replacing the old
|
|
5
|
+
// per-tool `compact` boolean). detail: summary|standard|full + include[] mirrors the
|
|
6
|
+
// entry-tool contract. Defaults are per-tool (see DEFAULT_DETAIL_BY_TOOL in response-utils):
|
|
7
|
+
// resolution/mapping tools + batch default "summary"; source/file tools default "standard".
|
|
8
|
+
const DETAIL_DESCRIPTION = "Response detail: 'summary' (terse: drops diagnostics/empties, slims candidates), 'standard' (default for source/file tools: keeps fields but drops heavy diagnostics), 'full' (everything). Replaces the old `compact` flag.";
|
|
9
|
+
const RESPONSE_INCLUDE_DESCRIPTION = "Opt specific field groups back in regardless of detail, e.g. [\"provenance\"], [\"candidates\"], [\"samples\"], [\"artifact\"], [\"descriptors\"].";
|
|
10
|
+
function detailParam(defaultLevel) {
|
|
11
|
+
return z.enum(DETAIL_LEVELS).default(defaultLevel).describe(DETAIL_DESCRIPTION);
|
|
12
|
+
}
|
|
13
|
+
const responseIncludeParam = z
|
|
14
|
+
.array(z.enum(CANONICAL_INCLUDE_GROUPS))
|
|
15
|
+
.optional()
|
|
16
|
+
.describe(RESPONSE_INCLUDE_DESCRIPTION);
|
|
3
17
|
export const SOURCE_MAPPINGS = ["obfuscated", "mojang", "intermediary", "yarn"];
|
|
4
18
|
export const SOURCE_PRIORITIES = ["loom-first", "maven-first"];
|
|
5
19
|
export const TARGET_KINDS = ["version", "jar", "coordinate"];
|
|
@@ -62,32 +76,26 @@ export const resolveArtifactTargetSchema = z.discriminatedUnion("kind", [
|
|
|
62
76
|
workspaceTargetSchema,
|
|
63
77
|
dependencyTargetSchema
|
|
64
78
|
]);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
z.object({
|
|
72
|
-
z.object({
|
|
73
|
-
z.object({
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
strict: z.boolean().optional()
|
|
78
|
-
}),
|
|
79
|
-
z.object({
|
|
80
|
-
type: z.literal("resolve"),
|
|
81
|
-
kind: z.literal("dependency"),
|
|
82
|
-
group: nonEmptyString,
|
|
83
|
-
name: nonEmptyString,
|
|
84
|
-
version: z.string().trim().min(1).optional(),
|
|
85
|
-
versionFromProject: z.boolean().optional()
|
|
86
|
-
})
|
|
79
|
+
// Extended target schema for the source-lookup tools (get-class-source / get-class-members):
|
|
80
|
+
// the same kind-based shape as resolveArtifactTargetSchema, PLUS a `kind:"artifact"` variant
|
|
81
|
+
// that short-circuits resolution by reusing an already-resolved artifactId. The shared
|
|
82
|
+
// resolveArtifactTargetSchema is intentionally NOT widened — the artifact kind has no
|
|
83
|
+
// resolution meaning for resolve-artifact / verify-mixin-target / the batch tools.
|
|
84
|
+
export const sourceLookupTargetSchema = z.discriminatedUnion("kind", [
|
|
85
|
+
z.object({ kind: z.literal("version"), value: nonEmptyString }),
|
|
86
|
+
z.object({ kind: z.literal("jar"), value: nonEmptyString }),
|
|
87
|
+
z.object({ kind: z.literal("coordinate"), value: nonEmptyString }),
|
|
88
|
+
workspaceTargetSchema,
|
|
89
|
+
dependencyTargetSchema,
|
|
90
|
+
z.object({ kind: z.literal("artifact"), artifactId: nonEmptyString })
|
|
87
91
|
]);
|
|
88
92
|
export const RESOLVE_ARTIFACT_TARGET_DESCRIPTION = 'Object with kind. Examples: {"kind":"version","value":"1.21.10"}, {"kind":"workspace"} (uses projectPath), or {"kind":"dependency","group":"dev.architectury","name":"architectury"}. Must be an object, not a string.';
|
|
89
|
-
export const SOURCE_LOOKUP_TARGET_DESCRIPTION = 'Object: {"
|
|
93
|
+
export const SOURCE_LOOKUP_TARGET_DESCRIPTION = 'Object with kind (same shape as resolve-artifact). Examples: {"kind":"version","value":"1.21.10"}, {"kind":"workspace"} (uses projectPath), {"kind":"dependency","group":"...","name":"..."}, or {"kind":"artifact","artifactId":"..."} to reuse an already-resolved artifact. Must be an object, not a string.';
|
|
90
94
|
export 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.";
|
|
95
|
+
// Shared describe() text reused by every symbol-lookup tool so the contract reads
|
|
96
|
+
// identically on find-mapping and check-symbol-exists (and any future sibling).
|
|
97
|
+
export const SIGNATURE_MODE_DESCRIPTION = "exact: descriptor required for kind=method; name-only (default): match by owner+name only.";
|
|
98
|
+
export const NAME_MODE_DESCRIPTION = "auto (default): accept a fully-qualified name, or a dotless name where the tool allows it; fqcn: require a fully-qualified name.";
|
|
91
99
|
export const listVersionsShape = {
|
|
92
100
|
includeSnapshots: z.boolean().default(false),
|
|
93
101
|
limit: optionalPositiveInt.default(20).describe("max 200")
|
|
@@ -103,9 +111,8 @@ export const resolveArtifactShape = {
|
|
|
103
111
|
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
104
112
|
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override target.value"),
|
|
105
113
|
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
+ "Enabled by default; set to false for full output.")
|
|
114
|
+
detail: detailParam("summary"),
|
|
115
|
+
include: responseIncludeParam
|
|
109
116
|
};
|
|
110
117
|
export const resolveArtifactSchema = z.object(resolveArtifactShape);
|
|
111
118
|
export const getClassSourceShape = {
|
|
@@ -125,7 +132,9 @@ export const getClassSourceShape = {
|
|
|
125
132
|
maxLines: optionalPositiveInt,
|
|
126
133
|
maxChars: optionalPositiveInt.describe("Hard character limit on sourceText; truncates if exceeded"),
|
|
127
134
|
outputFile: optionalNonEmptyString.describe("Write source to this file path and return metadata-only response"),
|
|
128
|
-
|
|
135
|
+
detail: detailParam("standard"),
|
|
136
|
+
include: responseIncludeParam,
|
|
137
|
+
includeProvenance: z.boolean().default(false).describe("Alias for include:[\"provenance\"]. When true, include diagnostic metadata (provenance, qualityFlags, artifactContents). Default false — omitted to keep the common path lean.")
|
|
129
138
|
};
|
|
130
139
|
export const getClassSourceSchema = z
|
|
131
140
|
.object(getClassSourceShape)
|
|
@@ -150,25 +159,29 @@ export const getClassMembersShape = {
|
|
|
150
159
|
includeSynthetic: z.boolean().default(false),
|
|
151
160
|
includeInherited: z.boolean().default(false),
|
|
152
161
|
memberPattern: optionalNonEmptyString,
|
|
153
|
-
maxMembers: optionalPositiveInt.describe("default
|
|
162
|
+
maxMembers: optionalPositiveInt.describe("default 150, max 5000. Page beyond the first 150 with cursor."),
|
|
163
|
+
cursor: optionalNonEmptyString.describe("Continuation cursor from a previous response's nextCursor; resumes the member list after the last returned page."),
|
|
154
164
|
projectPath: optionalNonEmptyString,
|
|
155
165
|
gradleUserHome: gradleUserHomeSchema,
|
|
156
166
|
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
157
167
|
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override version"),
|
|
158
168
|
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
159
|
-
|
|
169
|
+
detail: detailParam("standard"),
|
|
170
|
+
include: responseIncludeParam,
|
|
171
|
+
includeProvenance: z.boolean().default(false).describe("Alias for include:[\"provenance\"]. When true, include diagnostic metadata (provenance, qualityFlags, artifactContents). Default false — omitted to keep the common path lean."),
|
|
172
|
+
includeDescriptors: z.boolean().default(false).describe("Alias for include:[\"descriptors\"]. When true, also emit jvmDescriptor on FIELD members. Default false: field descriptors are omitted (the type is already in javaSignature). Method/constructor descriptors are always present for overload disambiguation.")
|
|
160
173
|
};
|
|
161
174
|
export const getClassMembersSchema = z.object(getClassMembersShape);
|
|
162
175
|
export const verifyMixinTargetMemberSchema = z.discriminatedUnion("kind", [
|
|
163
176
|
z.object({
|
|
164
177
|
kind: z.literal("method"),
|
|
165
178
|
name: nonEmptyString,
|
|
166
|
-
descriptor:
|
|
179
|
+
descriptor: optionalDescriptorString.describe('Optional JVM method descriptor, e.g. "()V". Empty/whitespace strings are treated as omitted.')
|
|
167
180
|
}),
|
|
168
181
|
z.object({
|
|
169
182
|
kind: z.literal("field"),
|
|
170
183
|
name: nonEmptyString,
|
|
171
|
-
descriptor:
|
|
184
|
+
descriptor: optionalDescriptorString.describe('Optional JVM field descriptor, e.g. "I". Empty/whitespace strings are treated as omitted.')
|
|
172
185
|
})
|
|
173
186
|
]);
|
|
174
187
|
export const verifyMixinTargetShape = {
|
|
@@ -176,6 +189,7 @@ export const verifyMixinTargetShape = {
|
|
|
176
189
|
member: verifyMixinTargetMemberSchema.describe('Member to verify. Object with kind. Examples: {"kind":"method","name":"tick","descriptor":"()V"} or {"kind":"field","name":"airSupply"}.'),
|
|
177
190
|
mixinMemberName: optionalNonEmptyString.describe("Optional caller-authored mixin field/method name. Drives @Accessor (getXxx/setXxx) and @Invoker (invokeXxx/callXxx) advice when the target is private."),
|
|
178
191
|
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
192
|
+
autoRemap: z.boolean().optional().describe("When true and mapping differs from the artifact namespace, translate owner+member via find-mapping instead of failing ERR_NAMESPACE_MISMATCH. Requires a version-based target."),
|
|
179
193
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
180
194
|
projectPath: optionalNonEmptyString.describe("Workspace root path for target.kind=workspace and Loom cache assistance."),
|
|
181
195
|
gradleUserHome: gradleUserHomeSchema,
|
|
@@ -207,7 +221,8 @@ export const batchClassSourceShape = {
|
|
|
207
221
|
strictVersion: z.boolean().optional(),
|
|
208
222
|
concurrency: z.number().int().min(1).max(8).optional().describe("1..8, default 4"),
|
|
209
223
|
failFast: z.boolean().optional().describe("default false"),
|
|
210
|
-
|
|
224
|
+
detail: detailParam("summary"),
|
|
225
|
+
include: responseIncludeParam,
|
|
211
226
|
entries: z
|
|
212
227
|
.array(batchClassSourceEntrySchema)
|
|
213
228
|
.min(1)
|
|
@@ -262,7 +277,8 @@ export const batchClassMembersShape = {
|
|
|
262
277
|
strictVersion: z.boolean().optional(),
|
|
263
278
|
concurrency: z.number().int().min(1).max(8).optional(),
|
|
264
279
|
failFast: z.boolean().optional(),
|
|
265
|
-
|
|
280
|
+
detail: detailParam("summary"),
|
|
281
|
+
include: responseIncludeParam,
|
|
266
282
|
entries: z.array(batchClassMembersEntrySchema).min(1).max(50)
|
|
267
283
|
};
|
|
268
284
|
export const batchClassMembersSchema = z.object(batchClassMembersShape);
|
|
@@ -291,7 +307,8 @@ export const batchSymbolExistsShape = {
|
|
|
291
307
|
strictVersion: z.boolean().optional(),
|
|
292
308
|
concurrency: z.number().int().min(1).max(8).optional(),
|
|
293
309
|
failFast: z.boolean().optional(),
|
|
294
|
-
|
|
310
|
+
detail: detailParam("summary"),
|
|
311
|
+
include: responseIncludeParam,
|
|
295
312
|
entries: z.array(batchSymbolExistsEntrySchema).min(1).max(50)
|
|
296
313
|
};
|
|
297
314
|
export const batchSymbolExistsSchema = z.object(batchSymbolExistsShape);
|
|
@@ -321,7 +338,8 @@ export const batchMappingsShape = {
|
|
|
321
338
|
gradleUserHome: gradleUserHomeSchema,
|
|
322
339
|
concurrency: z.number().int().min(1).max(8).optional(),
|
|
323
340
|
failFast: z.boolean().optional(),
|
|
324
|
-
|
|
341
|
+
detail: detailParam("summary"),
|
|
342
|
+
include: responseIncludeParam,
|
|
325
343
|
entries: z.array(batchMappingsEntrySchema).min(1).max(50)
|
|
326
344
|
};
|
|
327
345
|
export const batchMappingsSchema = z.object(batchMappingsShape);
|
|
@@ -339,7 +357,8 @@ export const searchClassSourceShape = {
|
|
|
339
357
|
queryNamespace: sourceMappingSchema.optional().describe("Namespace of the query. When set and intent='symbol' with a fully-qualified class name, the query is translated through find-mapping before searching the artifact namespace. Ignored for text/path intents (warning surfaced)."),
|
|
340
358
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first. Used only when queryNamespace triggers translation."),
|
|
341
359
|
gradleUserHome: gradleUserHomeSchema,
|
|
342
|
-
|
|
360
|
+
detail: detailParam("standard"),
|
|
361
|
+
include: responseIncludeParam
|
|
343
362
|
};
|
|
344
363
|
export const searchClassSourceSchema = z.object(searchClassSourceShape).superRefine((value, ctx) => {
|
|
345
364
|
if (value.symbolKind && value.intent && value.intent !== "symbol") {
|
|
@@ -361,7 +380,8 @@ export const listArtifactFilesShape = {
|
|
|
361
380
|
prefix: optionalNonEmptyString,
|
|
362
381
|
limit: optionalPositiveInt,
|
|
363
382
|
cursor: optionalNonEmptyString,
|
|
364
|
-
|
|
383
|
+
detail: detailParam("standard"),
|
|
384
|
+
include: responseIncludeParam
|
|
365
385
|
};
|
|
366
386
|
export const listArtifactFilesSchema = z.object(listArtifactFilesShape);
|
|
367
387
|
export const traceSymbolLifecycleShape = {
|
|
@@ -397,8 +417,8 @@ export const findMappingShape = {
|
|
|
397
417
|
targetMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
398
418
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
399
419
|
gradleUserHome: gradleUserHomeSchema,
|
|
400
|
-
|
|
401
|
-
|
|
420
|
+
nameMode: classNameModeSchema.default("auto").describe(NAME_MODE_DESCRIPTION),
|
|
421
|
+
signatureMode: z.enum(["exact", "name-only"]).default("name-only").describe(SIGNATURE_MODE_DESCRIPTION),
|
|
402
422
|
disambiguation: z
|
|
403
423
|
.object({
|
|
404
424
|
ownerHint: optionalNonEmptyString,
|
|
@@ -407,9 +427,8 @@ export const findMappingShape = {
|
|
|
407
427
|
.partial()
|
|
408
428
|
.optional(),
|
|
409
429
|
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates (default 5, max 200). Raise when you need the full candidate list."),
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
+ "Enabled by default; set to false for full output.")
|
|
430
|
+
detail: detailParam("summary"),
|
|
431
|
+
include: responseIncludeParam
|
|
413
432
|
};
|
|
414
433
|
export const findMappingSchema = z.object(findMappingShape).superRefine((value, ctx) => {
|
|
415
434
|
if (value.kind === "class") {
|
|
@@ -427,7 +446,7 @@ export const findMappingSchema = z.object(findMappingShape).superRefine((value,
|
|
|
427
446
|
path: ["descriptor"]
|
|
428
447
|
});
|
|
429
448
|
}
|
|
430
|
-
if (value.
|
|
449
|
+
if (value.nameMode !== "auto" && !value.name.includes(".")) {
|
|
431
450
|
ctx.addIssue({
|
|
432
451
|
code: z.ZodIssueCode.custom,
|
|
433
452
|
message: "name must be fully-qualified class name when kind=class.",
|
|
@@ -468,6 +487,10 @@ export const findMappingSchema = z.object(findMappingShape).superRefine((value,
|
|
|
468
487
|
});
|
|
469
488
|
}
|
|
470
489
|
});
|
|
490
|
+
// Strict shortcut for find-mapping(kind=method, signatureMode=exact): identical inputs,
|
|
491
|
+
// but requires a COMPLETE descriptor projection and returns mapping_unavailable when the
|
|
492
|
+
// descriptor's class references cannot all be projected (find-mapping's exact mode is more
|
|
493
|
+
// lenient there). Prefer find-mapping unless you need that strict-completeness guarantee.
|
|
471
494
|
export const resolveMethodMappingExactShape = {
|
|
472
495
|
version: nonEmptyString,
|
|
473
496
|
name: nonEmptyString,
|
|
@@ -478,9 +501,8 @@ export const resolveMethodMappingExactShape = {
|
|
|
478
501
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
479
502
|
gradleUserHome: gradleUserHomeSchema,
|
|
480
503
|
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates (default 5, max 200). Raise when you need the full candidate list."),
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
+ "Enabled by default; set to false for full output.")
|
|
504
|
+
detail: detailParam("summary"),
|
|
505
|
+
include: responseIncludeParam
|
|
484
506
|
};
|
|
485
507
|
export const resolveMethodMappingExactSchema = z
|
|
486
508
|
.object(resolveMethodMappingExactShape)
|
|
@@ -520,7 +542,8 @@ export const getClassApiMatrixShape = {
|
|
|
520
542
|
includeKinds: classApiKindsSchema.optional().describe("comma-separated: class,field,method"),
|
|
521
543
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
522
544
|
gradleUserHome: gradleUserHomeSchema,
|
|
523
|
-
maxRows: optionalPositiveInt.describe("Limit returned rows (max 5000)")
|
|
545
|
+
maxRows: optionalPositiveInt.describe("Limit returned rows (max 5000)"),
|
|
546
|
+
cursor: optionalNonEmptyString.describe("Continuation cursor from a previous response's nextCursor; resumes after the last returned row.")
|
|
524
547
|
};
|
|
525
548
|
export const getClassApiMatrixSchema = z.object(getClassApiMatrixShape);
|
|
526
549
|
export const resolveWorkspaceSymbolShape = {
|
|
@@ -534,9 +557,8 @@ export const resolveWorkspaceSymbolShape = {
|
|
|
534
557
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
535
558
|
gradleUserHome: gradleUserHomeSchema,
|
|
536
559
|
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates for field/method lookups (default 5, max 200). Raise when you need the full candidate list."),
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
+ "Enabled by default; set to false for full output.")
|
|
560
|
+
detail: detailParam("summary"),
|
|
561
|
+
include: responseIncludeParam
|
|
540
562
|
};
|
|
541
563
|
export const resolveWorkspaceSymbolSchema = z
|
|
542
564
|
.object(resolveWorkspaceSymbolShape)
|
|
@@ -602,17 +624,15 @@ export const checkSymbolExistsShape = {
|
|
|
602
624
|
kind: workspaceSymbolKindSchema.describe("class | field | method"),
|
|
603
625
|
owner: optionalNonEmptyString,
|
|
604
626
|
name: nonEmptyString,
|
|
605
|
-
descriptor: optionalDescriptorString.describe("
|
|
627
|
+
descriptor: optionalDescriptorString.describe("JVM descriptor. Optional when signatureMode='name-only' (default). Empty strings are treated as omitted."),
|
|
606
628
|
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
607
629
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
608
630
|
gradleUserHome: gradleUserHomeSchema,
|
|
609
|
-
nameMode: classNameModeSchema.default("
|
|
610
|
-
signatureMode: z.enum(["exact", "name-only"]).default("
|
|
611
|
-
.describe("exact: require descriptor for methods; name-only: match by owner+name only"),
|
|
631
|
+
nameMode: classNameModeSchema.default("auto").describe(NAME_MODE_DESCRIPTION),
|
|
632
|
+
signatureMode: z.enum(["exact", "name-only"]).default("name-only").describe(SIGNATURE_MODE_DESCRIPTION),
|
|
612
633
|
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates (default 5, max 200). Raise when you need the full candidate list."),
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
+ "Enabled by default; set to false for full output.")
|
|
634
|
+
detail: detailParam("summary"),
|
|
635
|
+
include: responseIncludeParam
|
|
616
636
|
};
|
|
617
637
|
export const checkSymbolExistsSchema = z.object(checkSymbolExistsShape).superRefine((value, ctx) => {
|
|
618
638
|
if (value.kind === "class") {
|
|
@@ -723,7 +743,7 @@ export const validateMixinShape = {
|
|
|
723
743
|
]).describe("One of { mode: 'inline', source }, { mode: 'path', path }, { mode: 'paths', paths[] }, { mode: 'config', configPaths[] }, or { mode: 'project', path }."),
|
|
724
744
|
sourceRoots: z.array(z.string().min(1)).optional()
|
|
725
745
|
.describe("Array of source roots for multi-module projects (e.g. ['common/src/main/java', 'neoforge/src/main/java'])"),
|
|
726
|
-
version:
|
|
746
|
+
version: optionalNonEmptyString.describe("Minecraft version. Optional when input.mode='project' (detected from the workspace) or preferProjectVersion=true with projectPath set; required otherwise."),
|
|
727
747
|
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
728
748
|
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
729
749
|
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
@@ -740,8 +760,8 @@ export const validateMixinShape = {
|
|
|
740
760
|
.describe("'full'=all warnings; 'aggregated'=group warnings by category with counts and samples. Single validation uses the provided value as-is; batch validation defaults to 'aggregated'"),
|
|
741
761
|
preferProjectMapping: z.boolean().default(false)
|
|
742
762
|
.describe("When true, auto-detect mapping from project config even if mapping is explicitly provided"),
|
|
743
|
-
reportMode: z.enum(["compact", "full", "summary-first"]).default("
|
|
744
|
-
.describe("'compact' omits heavy per-result detail
|
|
763
|
+
reportMode: z.enum(["compact", "full", "summary-first"]).default("summary-first")
|
|
764
|
+
.describe("Default 'summary-first': hoists shared provenance/warnings/incomplete reasons and drops per-result resolvedMembers/toolHealth/structuredWarnings. 'compact' omits heavy per-result detail; 'full'=everything. resolvedMembers/per-result toolHealth/resolutionTrace require reportMode='full' or explain=true."),
|
|
745
765
|
warningCategoryFilter: z.array(z.enum(["mapping", "configuration", "validation", "resolution", "parse"])).optional()
|
|
746
766
|
.describe("Only include warnings/issues matching these categories (default: all)"),
|
|
747
767
|
treatInfoAsWarning: z.boolean().default(true)
|
|
@@ -749,7 +769,19 @@ export const validateMixinShape = {
|
|
|
749
769
|
includeIssues: z.boolean().default(true)
|
|
750
770
|
.describe("When false, keep summary fields but omit per-result issues[] payloads")
|
|
751
771
|
};
|
|
752
|
-
export const validateMixinSchema = z.object(validateMixinShape)
|
|
772
|
+
export const validateMixinSchema = z.object(validateMixinShape).superRefine((value, ctx) => {
|
|
773
|
+
if (value.version) {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
const canDetectVersion = value.input?.mode === "project" || (value.preferProjectVersion === true && Boolean(value.projectPath));
|
|
777
|
+
if (!canDetectVersion) {
|
|
778
|
+
ctx.addIssue({
|
|
779
|
+
code: z.ZodIssueCode.custom,
|
|
780
|
+
path: ["version"],
|
|
781
|
+
message: "version is required unless input.mode='project' or preferProjectVersion=true with projectPath set (so the Minecraft version can be detected from gradle.properties)."
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
});
|
|
753
785
|
export const validateAccessWidenerShape = {
|
|
754
786
|
content: nonEmptyString.describe("Access Widener file content"),
|
|
755
787
|
version: nonEmptyString.describe("Minecraft version"),
|
|
@@ -782,7 +814,7 @@ export const analyzeModJarSchema = z.object(analyzeModJarShape);
|
|
|
782
814
|
export const getRegistryDataShape = {
|
|
783
815
|
version: nonEmptyString.describe("Minecraft version (e.g. 1.21)"),
|
|
784
816
|
registry: optionalNonEmptyString.describe('Optional registry name (e.g. "block", "item", "minecraft:biome"). Omit to list all registries.'),
|
|
785
|
-
includeData: z.boolean().default(true).describe("When false, return registry names/counts without
|
|
817
|
+
includeData: z.boolean().default(true).describe("When false, return registry names/counts only. To discover which registries exist without pulling every entry body, pass includeData:false (omitting registry with the default includeData:true returns the full data for every registry)."),
|
|
786
818
|
maxEntriesPerRegistry: optionalPositiveInt.describe("Limit returned entries per registry body")
|
|
787
819
|
};
|
|
788
820
|
export const getRegistryDataSchema = z.object(getRegistryDataShape);
|
|
@@ -826,7 +858,11 @@ export const remapModJarShape = {
|
|
|
826
858
|
inputJar: nonEmptyString.describe("Path to the mod JAR file"),
|
|
827
859
|
outputJar: optionalNonEmptyString.describe("Output path for remapped JAR (auto-generated if omitted)"),
|
|
828
860
|
mcVersion: optionalNonEmptyString.describe("Minecraft version (auto-detected from mod metadata if omitted)"),
|
|
829
|
-
targetMapping: remapTargetSchema.describe("yarn | mojang")
|
|
861
|
+
targetMapping: remapTargetSchema.describe("yarn | mojang"),
|
|
862
|
+
forceRemap: z
|
|
863
|
+
.boolean()
|
|
864
|
+
.optional()
|
|
865
|
+
.describe("Skip the cache and re-resolve the newest yarn build (busts a stale remap)")
|
|
830
866
|
};
|
|
831
867
|
export const remapModJarSchema = z.object(remapModJarShape);
|
|
832
868
|
export const emptySchema = z.object({}).passthrough();
|
package/dist/types.d.ts
CHANGED
|
@@ -145,6 +145,11 @@ export class VersionDiffService {
|
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
147
|
const warnings = [];
|
|
148
|
+
if (input.maxClassResults != null &&
|
|
149
|
+
Number.isFinite(input.maxClassResults) &&
|
|
150
|
+
input.maxClassResults > MAX_CLASS_RESULTS_LIMIT) {
|
|
151
|
+
warnings.push(`maxClassResults was clamped to ${MAX_CLASS_RESULTS_LIMIT} from ${input.maxClassResults}.`);
|
|
152
|
+
}
|
|
148
153
|
const startedAt = Date.now();
|
|
149
154
|
log("info", "version-diff.start", { fromVersion, toVersion, category });
|
|
150
155
|
const includeClasses = category === "classes" || category === "all";
|
|
@@ -16,6 +16,7 @@ export type ListVersionsOutput = {
|
|
|
16
16
|
snapshots?: VersionEntry[];
|
|
17
17
|
cached: string[];
|
|
18
18
|
totalAvailable: number;
|
|
19
|
+
warnings?: string[];
|
|
19
20
|
};
|
|
20
21
|
export type ResolvedVersionJar = {
|
|
21
22
|
version: string;
|
|
@@ -47,6 +48,7 @@ export declare class VersionService {
|
|
|
47
48
|
private manifestCache;
|
|
48
49
|
private readonly versionDetailCache;
|
|
49
50
|
private readonly resolveLocks;
|
|
51
|
+
private indexWriteChain;
|
|
50
52
|
constructor(config: Config, fetchFn?: typeof fetch);
|
|
51
53
|
listVersions(input?: ListVersionsInput): Promise<ListVersionsOutput>;
|
|
52
54
|
listVersionIds(input?: ListVersionIdsInput): Promise<string[]>;
|
|
@@ -60,6 +62,7 @@ export declare class VersionService {
|
|
|
60
62
|
private cacheIndexPath;
|
|
61
63
|
private loadCacheIndex;
|
|
62
64
|
private recordCacheEntry;
|
|
65
|
+
private recordCacheEntryInternal;
|
|
63
66
|
private trimVersionDetailCache;
|
|
64
67
|
}
|
|
65
68
|
/**
|
package/dist/version-service.js
CHANGED
|
@@ -38,6 +38,9 @@ export class VersionService {
|
|
|
38
38
|
manifestCache;
|
|
39
39
|
versionDetailCache = new Map();
|
|
40
40
|
resolveLocks = new Map();
|
|
41
|
+
// Serializes index.json read-modify-write so parallel resolutions of different
|
|
42
|
+
// versions can't clobber each other (resolveLocks only guards the same version).
|
|
43
|
+
indexWriteChain = Promise.resolve();
|
|
41
44
|
constructor(config, fetchFn = globalThis.fetch) {
|
|
42
45
|
this.config = config;
|
|
43
46
|
this.fetchFn = fetchFn;
|
|
@@ -47,6 +50,10 @@ export class VersionService {
|
|
|
47
50
|
const manifest = await this.fetchManifest();
|
|
48
51
|
const includeSnapshots = input.includeSnapshots ?? false;
|
|
49
52
|
const limit = clampLimit(input.limit, 20, 200);
|
|
53
|
+
const warnings = [];
|
|
54
|
+
if (input.limit != null && Number.isFinite(input.limit) && input.limit > 200) {
|
|
55
|
+
warnings.push(`limit was clamped to 200 from ${input.limit}.`);
|
|
56
|
+
}
|
|
50
57
|
const versions = manifest.versions ?? [];
|
|
51
58
|
const releases = versions
|
|
52
59
|
.filter((entry) => entry.type === "release")
|
|
@@ -65,7 +72,8 @@ export class VersionService {
|
|
|
65
72
|
releases,
|
|
66
73
|
snapshots: includeSnapshots ? snapshots : undefined,
|
|
67
74
|
cached: Array.from(new Set(cached)).sort((a, b) => a.localeCompare(b)),
|
|
68
|
-
totalAvailable: versions.length
|
|
75
|
+
totalAvailable: versions.length,
|
|
76
|
+
...(warnings.length ? { warnings } : {})
|
|
69
77
|
};
|
|
70
78
|
}
|
|
71
79
|
async listVersionIds(input = {}) {
|
|
@@ -389,7 +397,15 @@ export class VersionService {
|
|
|
389
397
|
return { entries: [] };
|
|
390
398
|
}
|
|
391
399
|
}
|
|
392
|
-
|
|
400
|
+
recordCacheEntry(entry) {
|
|
401
|
+
// Chain onto the previous write so reads and writes never interleave. The
|
|
402
|
+
// caller still awaits its own write's result, but the shared chain swallows
|
|
403
|
+
// failures so one rejected write cannot poison subsequent writes.
|
|
404
|
+
const next = this.indexWriteChain.then(() => this.recordCacheEntryInternal(entry));
|
|
405
|
+
this.indexWriteChain = next.catch(() => undefined);
|
|
406
|
+
return next;
|
|
407
|
+
}
|
|
408
|
+
async recordCacheEntryInternal(entry) {
|
|
393
409
|
const indexPath = this.cacheIndexPath();
|
|
394
410
|
const existing = await this.loadCacheIndex();
|
|
395
411
|
const deduped = existing.entries.filter((candidate) => candidate.version !== entry.version);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type WarningCategory = "pagination" | "mapping" | "coverage" | "validation" | "general";
|
|
2
|
+
export type WarningSeverity = "warning" | "info";
|
|
3
|
+
export type WarningDetail = {
|
|
4
|
+
/** Stable machine code for the warning family. */
|
|
5
|
+
code: string;
|
|
6
|
+
category: WarningCategory;
|
|
7
|
+
severity: WarningSeverity;
|
|
8
|
+
/** Index into `meta.warnings[]` that holds the original human-readable text. */
|
|
9
|
+
index: number;
|
|
10
|
+
/** Input fields a caller can adjust to address the warning, when applicable. */
|
|
11
|
+
affectedFields?: string[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Build the structured `warningDetails[]` companion for a list of warning strings.
|
|
15
|
+
* The mapping is 1:1 and order-preserving, so each entry's `index` equals its
|
|
16
|
+
* position and dereferences the text via `warnings[index]`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function classifyWarnings(warnings: string[]): WarningDetail[];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Structured companion to the string `meta.warnings`. Each warning string is
|
|
2
|
+
// classified into a high-value family so agents can branch on category/severity
|
|
3
|
+
// without parsing prose. The original text is NOT duplicated here; each entry
|
|
4
|
+
// references its warning by position via `index` (read `meta.warnings[index]`).
|
|
5
|
+
// First matching rule wins; more specific patterns precede broader ones.
|
|
6
|
+
const WARNING_RULES = [
|
|
7
|
+
{
|
|
8
|
+
test: /Member list was truncated|truncated to \d+ (entries|rows)|Raise maxCandidates|Raise maxRows/i,
|
|
9
|
+
code: "result_truncated",
|
|
10
|
+
category: "pagination",
|
|
11
|
+
severity: "info",
|
|
12
|
+
affectedFields: ["maxMembers", "maxRows", "maxCandidates", "cursor"]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
test: /\bwas clamped to\b/i,
|
|
16
|
+
code: "input_clamped",
|
|
17
|
+
category: "validation",
|
|
18
|
+
severity: "info"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
test: /are not indexed|non-Java resources are not indexed/i,
|
|
22
|
+
code: "resource_not_indexed",
|
|
23
|
+
category: "coverage",
|
|
24
|
+
severity: "info"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
test: /namespace translation requires a version|could not be applied because the artifact has no version|Could not (re)?map .* (from .* to|to .* namespace)|Remap failed for|Mapping lookup failed|No exact class symbol matched|Unsupported .* namespace/i,
|
|
28
|
+
code: "namespace_fallback",
|
|
29
|
+
category: "mapping",
|
|
30
|
+
severity: "warning",
|
|
31
|
+
affectedFields: ["mapping", "version"]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
test: /falling back to vanilla|resolution failed; falling back|sources jar\.?\s*Falling back|does not include net\.minecraft/i,
|
|
35
|
+
code: "partial_coverage",
|
|
36
|
+
category: "coverage",
|
|
37
|
+
severity: "warning",
|
|
38
|
+
affectedFields: ["scope"]
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
function classifyWarning(message, index) {
|
|
42
|
+
for (const rule of WARNING_RULES) {
|
|
43
|
+
if (rule.test.test(message)) {
|
|
44
|
+
return {
|
|
45
|
+
code: rule.code,
|
|
46
|
+
category: rule.category,
|
|
47
|
+
severity: rule.severity,
|
|
48
|
+
index,
|
|
49
|
+
...(rule.affectedFields ? { affectedFields: rule.affectedFields } : {})
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { code: "general", category: "general", severity: "info", index };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the structured `warningDetails[]` companion for a list of warning strings.
|
|
57
|
+
* The mapping is 1:1 and order-preserving, so each entry's `index` equals its
|
|
58
|
+
* position and dereferences the text via `warnings[index]`.
|
|
59
|
+
*/
|
|
60
|
+
export function classifyWarnings(warnings) {
|
|
61
|
+
return warnings.map((message, index) => classifyWarning(message, index));
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=warning-details.js.map
|
package/docs/README-ja.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
stdio で動作し、Claude Desktop、Claude Code、VS Code、Codex CLI、Gemini CLI などの MCP 対応クライアントから利用できます。
|
|
17
17
|
|
|
18
|
-
**
|
|
18
|
+
**41 ツール**(6 エントリー + 35 エキスパート) | **9 リソース** | **4 マッピング名前空間** | **SQLite ベースのキャッシュ**
|
|
19
19
|
|
|
20
20
|
## 特長
|
|
21
21
|
|
|
@@ -301,7 +301,7 @@ Minecraft バージョン間でのクラス / レジストリ変更比較と、
|
|
|
301
301
|
| ツール | 役割 |
|
|
302
302
|
| --- | --- |
|
|
303
303
|
| `find-mapping` | クラス、フィールド、メソッドのシンボルに対するマッピング候補を調べる |
|
|
304
|
-
| `resolve-method-mapping-exact` | owner
|
|
304
|
+
| `resolve-method-mapping-exact` | `find-mapping`(kind=method, signatureMode=exact)の厳密版ショートカット。owner+name+descriptor の三つ組が必須 |
|
|
305
305
|
| `get-class-api-matrix` | 1 つのクラス API を `obfuscated`、`mojang`、`intermediary`、`yarn` で見比べる |
|
|
306
306
|
| `resolve-workspace-symbol` | Gradle ワークスペースからコンパイル時に見えるシンボル名を解決する |
|
|
307
307
|
| `check-symbol-exists` | 名前空間内でクラス、フィールド、メソッドが存在するかを確認する |
|
package/docs/examples.md
CHANGED
|
@@ -105,7 +105,7 @@ Start with these top-level workflow tools when possible. They cover the common w
|
|
|
105
105
|
"tool": "get-class-source",
|
|
106
106
|
"arguments": {
|
|
107
107
|
"target": {
|
|
108
|
-
"
|
|
108
|
+
"kind": "artifact",
|
|
109
109
|
"artifactId": "<artifact-id>"
|
|
110
110
|
},
|
|
111
111
|
"className": "net.minecraft.server.Main",
|
|
@@ -137,7 +137,7 @@ Start with these top-level workflow tools when possible. They cover the common w
|
|
|
137
137
|
"tool": "get-class-members",
|
|
138
138
|
"arguments": {
|
|
139
139
|
"target": {
|
|
140
|
-
"
|
|
140
|
+
"kind": "artifact",
|
|
141
141
|
"artifactId": "<artifact-id>"
|
|
142
142
|
},
|
|
143
143
|
"className": "net.minecraft.server.Main",
|
|
@@ -395,6 +395,30 @@ Start with these top-level workflow tools when possible. They cover the common w
|
|
|
395
395
|
|
|
396
396
|
If the input JAR was already built with Mojang mappings, use `targetMapping: "mojang"` to get a copied output JAR and a `fromMapping: "mojang"` result.
|
|
397
397
|
|
|
398
|
+
### Bridge a mod hit to a Minecraft-side check
|
|
399
|
+
|
|
400
|
+
When `search-mod-source` or `get-mod-class-source` surfaces a class or member that
|
|
401
|
+
looks like a Minecraft target (for example a Mixin `@Shadow`/`@Inject` target, or a
|
|
402
|
+
symbol from a crash stack), verify it against the target Minecraft version before
|
|
403
|
+
trusting it. Feed the owner/member into `verify-mixin-target`. When your owner/member
|
|
404
|
+
are in a readable namespace (e.g. `mojang`/`yarn`) but the resolved artifact is
|
|
405
|
+
obfuscated, set `autoRemap: true` to translate them automatically in one call:
|
|
406
|
+
|
|
407
|
+
```json
|
|
408
|
+
{
|
|
409
|
+
"tool": "verify-mixin-target",
|
|
410
|
+
"arguments": {
|
|
411
|
+
"target": { "kind": "version", "value": "1.21.10" },
|
|
412
|
+
"owner": "net.minecraft.world.entity.LivingEntity",
|
|
413
|
+
"member": { "kind": "method", "name": "tickServer", "descriptor": "()V" },
|
|
414
|
+
"mapping": "mojang",
|
|
415
|
+
"autoRemap": true
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
For a plain "does this symbol exist in this version?" question, use `analyze-symbol task="exists"` instead.
|
|
421
|
+
|
|
398
422
|
## Validation
|
|
399
423
|
|
|
400
424
|
### Validate Mixin source
|