@adhisang/minecraft-modding-mcp 4.0.0 → 4.1.1
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 +61 -0
- package/README.md +40 -23
- package/dist/build-suggested-call.d.ts +29 -0
- package/dist/build-suggested-call.js +58 -0
- package/dist/cache-registry.d.ts +3 -1
- package/dist/cache-registry.js +50 -6
- package/dist/entry-tools/analyze-symbol-service.d.ts +16 -16
- package/dist/entry-tools/batch-class-members-service.d.ts +34 -0
- package/dist/entry-tools/batch-class-members-service.js +97 -0
- package/dist/entry-tools/batch-class-source-service.d.ts +37 -0
- package/dist/entry-tools/batch-class-source-service.js +100 -0
- package/dist/entry-tools/batch-mappings-service.d.ts +36 -0
- package/dist/entry-tools/batch-mappings-service.js +66 -0
- package/dist/entry-tools/batch-runner.d.ts +72 -0
- package/dist/entry-tools/batch-runner.js +90 -0
- package/dist/entry-tools/batch-symbol-exists-service.d.ts +46 -0
- package/dist/entry-tools/batch-symbol-exists-service.js +113 -0
- package/dist/entry-tools/compare-minecraft-service.d.ts +6 -6
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +83 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.d.ts +6 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +80 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +248 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +60 -0
- package/dist/entry-tools/inspect-minecraft/handlers/file.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/file.js +54 -0
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +100 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.js +155 -0
- package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +6 -0
- package/dist/entry-tools/inspect-minecraft/handlers/versions.js +49 -0
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +1042 -0
- package/dist/entry-tools/inspect-minecraft/internal.js +448 -0
- package/dist/entry-tools/inspect-minecraft-service.d.ts +193 -308
- package/dist/entry-tools/inspect-minecraft-service.js +20 -1244
- package/dist/entry-tools/manage-cache-service.d.ts +16 -16
- package/dist/entry-tools/validate-project/cases/access-transformer.d.ts +6 -0
- package/dist/entry-tools/validate-project/cases/access-transformer.js +106 -0
- package/dist/entry-tools/validate-project/cases/access-widener.d.ts +6 -0
- package/dist/entry-tools/validate-project/cases/access-widener.js +86 -0
- package/dist/entry-tools/validate-project/cases/mixin.d.ts +6 -0
- package/dist/entry-tools/validate-project/cases/mixin.js +90 -0
- package/dist/entry-tools/validate-project/cases/project-summary.d.ts +102 -0
- package/dist/entry-tools/validate-project/cases/project-summary.js +415 -0
- package/dist/entry-tools/validate-project/internal.d.ts +142 -0
- package/dist/entry-tools/validate-project/internal.js +303 -0
- package/dist/entry-tools/validate-project-service.d.ts +67 -47
- package/dist/entry-tools/validate-project-service.js +13 -563
- package/dist/entry-tools/verify-mixin-target-service.d.ts +133 -0
- package/dist/entry-tools/verify-mixin-target-service.js +323 -0
- package/dist/error-mapping.d.ts +40 -0
- package/dist/error-mapping.js +139 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +6 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +147 -1354
- package/dist/mapping/internal-types.d.ts +54 -0
- package/dist/mapping/internal-types.js +14 -0
- package/dist/mapping/loaders/mojang.d.ts +2 -0
- package/dist/mapping/loaders/mojang.js +64 -0
- package/dist/mapping/loaders/tiny-loom.d.ts +2 -0
- package/dist/mapping/loaders/tiny-loom.js +73 -0
- package/dist/mapping/loaders/tiny-maven.d.ts +2 -0
- package/dist/mapping/loaders/tiny-maven.js +104 -0
- package/dist/mapping/loaders/types.d.ts +14 -0
- package/dist/mapping/loaders/types.js +2 -0
- package/dist/mapping/lookup.d.ts +52 -0
- package/dist/mapping/lookup.js +496 -0
- package/dist/mapping/parsers/normalize.d.ts +10 -0
- package/dist/mapping/parsers/normalize.js +52 -0
- package/dist/mapping/parsers/proguard.d.ts +20 -0
- package/dist/mapping/parsers/proguard.js +138 -0
- package/dist/mapping/parsers/symbol-records.d.ts +27 -0
- package/dist/mapping/parsers/symbol-records.js +216 -0
- package/dist/mapping/parsers/tiny.d.ts +9 -0
- package/dist/mapping/parsers/tiny.js +96 -0
- package/dist/mapping/types.d.ts +147 -0
- package/dist/mapping/types.js +2 -0
- package/dist/mapping-pipeline-service.js +3 -2
- package/dist/mapping-service.d.ts +8 -145
- package/dist/mapping-service.js +30 -1207
- package/dist/mixin/access-validators.d.ts +9 -0
- package/dist/mixin/access-validators.js +257 -0
- package/dist/mixin/annotation-validators.d.ts +5 -0
- package/dist/mixin/annotation-validators.js +162 -0
- package/dist/mixin/helpers.d.ts +28 -0
- package/dist/mixin/helpers.js +315 -0
- package/dist/mixin/parsed-validator.d.ts +8 -0
- package/dist/mixin/parsed-validator.js +337 -0
- package/dist/mixin/types.d.ts +208 -0
- package/dist/mixin/types.js +28 -0
- package/dist/mixin-validator.d.ts +9 -201
- package/dist/mixin-validator.js +8 -1020
- package/dist/source/access-validate.d.ts +4 -0
- package/dist/source/access-validate.js +254 -0
- package/dist/source/artifact-resolver.d.ts +111 -0
- package/dist/source/artifact-resolver.js +1271 -0
- package/dist/source/cache-metrics.d.ts +26 -0
- package/dist/source/cache-metrics.js +172 -0
- package/dist/source/class-source/members-builder.d.ts +34 -0
- package/dist/source/class-source/members-builder.js +46 -0
- package/dist/source/class-source/snippet-builder.d.ts +19 -0
- package/dist/source/class-source/snippet-builder.js +46 -0
- package/dist/source/class-source-helpers.d.ts +34 -0
- package/dist/source/class-source-helpers.js +140 -0
- package/dist/source/class-source.d.ts +42 -0
- package/dist/source/class-source.js +883 -0
- package/dist/source/descriptor-utils.d.ts +6 -0
- package/dist/source/descriptor-utils.js +37 -0
- package/dist/source/file-access.d.ts +4 -0
- package/dist/source/file-access.js +102 -0
- package/dist/source/indexer.d.ts +82 -0
- package/dist/source/indexer.js +522 -0
- package/dist/source/lifecycle/diff-utils.d.ts +9 -0
- package/dist/source/lifecycle/diff-utils.js +107 -0
- package/dist/source/lifecycle/diff.d.ts +2 -0
- package/dist/source/lifecycle/diff.js +265 -0
- package/dist/source/lifecycle/mapping-helpers.d.ts +22 -0
- package/dist/source/lifecycle/mapping-helpers.js +327 -0
- package/dist/source/lifecycle/runtime-check.d.ts +2 -0
- package/dist/source/lifecycle/runtime-check.js +142 -0
- package/dist/source/lifecycle/trace.d.ts +2 -0
- package/dist/source/lifecycle/trace.js +231 -0
- package/dist/source/lifecycle.d.ts +4 -0
- package/dist/source/lifecycle.js +5 -0
- package/dist/source/search.d.ts +51 -0
- package/dist/source/search.js +676 -0
- package/dist/source/shared-utils.d.ts +6 -0
- package/dist/source/shared-utils.js +55 -0
- package/dist/source/state.d.ts +26 -0
- package/dist/source/state.js +24 -0
- package/dist/source/symbol-resolver.d.ts +3 -0
- package/dist/source/symbol-resolver.js +212 -0
- package/dist/source/validate-mixin/pipeline/mapping-health.d.ts +3 -0
- package/dist/source/validate-mixin/pipeline/mapping-health.js +41 -0
- package/dist/source/validate-mixin/pipeline/parse.d.ts +2 -0
- package/dist/source/validate-mixin/pipeline/parse.js +10 -0
- package/dist/source/validate-mixin/pipeline/resolve.d.ts +3 -0
- package/dist/source/validate-mixin/pipeline/resolve.js +78 -0
- package/dist/source/validate-mixin/pipeline/target-lookup.d.ts +6 -0
- package/dist/source/validate-mixin/pipeline/target-lookup.js +260 -0
- package/dist/source/validate-mixin/pipeline-context.d.ts +72 -0
- package/dist/source/validate-mixin/pipeline-context.js +93 -0
- package/dist/source/validate-mixin.d.ts +22 -0
- package/dist/source/validate-mixin.js +799 -0
- package/dist/source/workspace-target.d.ts +18 -0
- package/dist/source/workspace-target.js +305 -0
- package/dist/source-resolver.d.ts +1 -0
- package/dist/source-resolver.js +1 -1
- package/dist/source-service.d.ts +164 -170
- package/dist/source-service.js +70 -6116
- package/dist/stage-emitter.d.ts +13 -0
- package/dist/stage-emitter.js +30 -0
- package/dist/stdio-supervisor.d.ts +61 -0
- package/dist/stdio-supervisor.js +326 -9
- package/dist/tool-contract-manifest.d.ts +1 -1
- package/dist/tool-contract-manifest.js +23 -6
- package/dist/tool-guidance.d.ts +82 -0
- package/dist/tool-guidance.js +734 -0
- package/dist/tool-schema-registry.d.ts +16 -0
- package/dist/tool-schema-registry.js +37 -0
- package/dist/tool-schemas.d.ts +3518 -0
- package/dist/tool-schemas.js +813 -0
- package/dist/types.d.ts +36 -0
- package/dist/version-service.js +7 -6
- package/dist/workspace-context-cache.d.ts +32 -0
- package/dist/workspace-context-cache.js +66 -0
- package/dist/workspace-mapping-service.d.ts +16 -0
- package/dist/workspace-mapping-service.js +173 -1
- package/docs/README-ja.md +416 -0
- package/docs/examples.md +483 -0
- package/docs/tool-reference.md +462 -0
- package/package.json +17 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { makeStageEmitter } from "./stage-emitter.js";
|
|
3
4
|
import { ZodError, z } from "zod";
|
|
4
5
|
import { CompatStdioServerTransport } from "./compat-stdio-transport.js";
|
|
5
6
|
import { objectResult } from "./mcp-helpers.js";
|
|
@@ -21,24 +22,22 @@ import { CompareMinecraftService, compareMinecraftSchema, compareMinecraftShape
|
|
|
21
22
|
import { AnalyzeModService, analyzeModSchema, analyzeModShape } from "./entry-tools/analyze-mod-service.js";
|
|
22
23
|
import { ValidateProjectService, validateProjectSchema, validateProjectShape, discoverWorkspaceAccessTransformers, discoverWorkspaceAccessWideners, discoverWorkspaceMixins } from "./entry-tools/validate-project-service.js";
|
|
23
24
|
import { ManageCacheService, manageCacheSchema, manageCacheShape } from "./entry-tools/manage-cache-service.js";
|
|
25
|
+
import { VerifyMixinTargetService, VERIFY_MIXIN_TARGET_OFF } from "./entry-tools/verify-mixin-target-service.js";
|
|
26
|
+
import { BATCH_TOOLS_OFF } from "./entry-tools/batch-runner.js";
|
|
27
|
+
import { BatchClassSourceService } from "./entry-tools/batch-class-source-service.js";
|
|
28
|
+
import { BatchClassMembersService } from "./entry-tools/batch-class-members-service.js";
|
|
29
|
+
import { BatchSymbolExistsService } from "./entry-tools/batch-symbol-exists-service.js";
|
|
30
|
+
import { BatchMappingsService } from "./entry-tools/batch-mappings-service.js";
|
|
24
31
|
import { createCacheRegistry } from "./cache-registry.js";
|
|
25
32
|
import { buildEntryToolMeta } from "./entry-tools/response-contract.js";
|
|
33
|
+
import { registerToolSchema } from "./tool-schema-registry.js";
|
|
34
|
+
import { buildSuggestedCall } from "./build-suggested-call.js";
|
|
35
|
+
import { applyErrorMetaExtensions, mapErrorToProblem } from "./tool-guidance.js";
|
|
36
|
+
import { nonEmptyString, optionalPositiveInt, analyzeModJarSchema, analyzeModJarShape, batchClassMembersSchema, batchClassMembersShape, batchClassSourceSchema, batchClassSourceShape, batchMappingsSchema, batchMappingsShape, batchSymbolExistsSchema, batchSymbolExistsShape, checkSymbolExistsSchema, checkSymbolExistsShape, compareVersionsSchema, compareVersionsShape, decompileModJarSchema, decompileModJarShape, diffClassSignaturesSchema, diffClassSignaturesShape, emptySchema, findMappingSchema, findMappingShape, getArtifactFileSchema, getArtifactFileShape, getClassApiMatrixSchema, getClassApiMatrixShape, getClassMembersSchema, getClassMembersShape, getClassSourceSchema, getClassSourceShape, getModClassSourceSchema, getModClassSourceShape, getRegistryDataSchema, getRegistryDataShape, indexArtifactSchema, indexArtifactShape, jsonToNbtSchema, jsonToNbtShape, listArtifactFilesSchema, listArtifactFilesShape, listVersionsSchema, listVersionsShape, nbtApplyJsonPatchSchema, nbtApplyJsonPatchShape, nbtToJsonSchema, nbtToJsonShape, remapModJarSchema, remapModJarShape, resolveArtifactSchema, resolveArtifactShape, resolveMethodMappingExactSchema, resolveMethodMappingExactShape, resolveWorkspaceSymbolSchema, resolveWorkspaceSymbolShape, searchClassSourceSchema, searchClassSourceShape, searchModSourceSchema, searchModSourceShape, traceSymbolLifecycleSchema, traceSymbolLifecycleShape, validateAccessTransformerSchema, validateAccessTransformerShape, validateAccessWidenerSchema, validateAccessWidenerShape, validateMixinSchema, validateMixinShape, verifyMixinTargetSchema, verifyMixinTargetShape } from "./tool-schemas.js";
|
|
37
|
+
export { mapErrorToProblem, applyErrorMetaExtensions };
|
|
26
38
|
if (!process.env.NODE_ENV) {
|
|
27
39
|
process.env.NODE_ENV = "production";
|
|
28
40
|
}
|
|
29
|
-
const SOURCE_MAPPINGS = ["obfuscated", "mojang", "intermediary", "yarn"];
|
|
30
|
-
const SOURCE_PRIORITIES = ["loom-first", "maven-first"];
|
|
31
|
-
const TARGET_KINDS = ["version", "jar", "coordinate"];
|
|
32
|
-
const SEARCH_INTENTS = ["symbol", "text", "path"];
|
|
33
|
-
const SEARCH_MATCHES = ["exact", "prefix", "contains", "regex"];
|
|
34
|
-
const SEARCH_SYMBOL_KINDS = ["class", "interface", "enum", "record", "method", "field"];
|
|
35
|
-
const MEMBER_ACCESS = ["public", "all"];
|
|
36
|
-
const WORKSPACE_SYMBOL_KINDS = ["class", "field", "method"];
|
|
37
|
-
const CLASS_NAME_MODES = ["fqcn", "auto"];
|
|
38
|
-
const SOURCE_MODES = ["metadata", "snippet", "full"];
|
|
39
|
-
const ARTIFACT_SCOPES = ["vanilla", "merged", "loader"];
|
|
40
|
-
const DECODE_COMPRESSIONS = ["none", "gzip", "auto"];
|
|
41
|
-
const ENCODE_COMPRESSIONS = ["none", "gzip"];
|
|
42
41
|
const HEAVY_TOOL_NAMES = new Set([
|
|
43
42
|
"trace-symbol-lifecycle",
|
|
44
43
|
"diff-class-signatures",
|
|
@@ -57,641 +56,6 @@ const ENTRY_TOOL_NAMES = new Set([
|
|
|
57
56
|
"manage-cache"
|
|
58
57
|
]);
|
|
59
58
|
const heavyToolExecutionGate = new ToolExecutionGate({ maxConcurrent: 1, maxQueue: 2 });
|
|
60
|
-
const nonEmptyString = z.string().trim().min(1);
|
|
61
|
-
const optionalNonEmptyString = z.string().trim().min(1).optional();
|
|
62
|
-
const optionalPositiveInt = z.number().int().positive().optional();
|
|
63
|
-
// Optional descriptor: "" and whitespace-only strings are normalized to undefined so that
|
|
64
|
-
// tools with signatureMode="name-only" can accept "caller omitted descriptor" inputs whether
|
|
65
|
-
// the caller passed an empty string or omitted the field entirely. Malformed descriptors are
|
|
66
|
-
// still rejected downstream by normalizeMethodDescriptor in mapping-service.
|
|
67
|
-
const optionalDescriptorString = z
|
|
68
|
-
.string()
|
|
69
|
-
.optional()
|
|
70
|
-
.transform((value) => {
|
|
71
|
-
if (value === undefined)
|
|
72
|
-
return undefined;
|
|
73
|
-
const trimmed = value.trim();
|
|
74
|
-
return trimmed.length === 0 ? undefined : trimmed;
|
|
75
|
-
});
|
|
76
|
-
const sourceMappingSchema = z.enum(SOURCE_MAPPINGS);
|
|
77
|
-
const mappingSourcePrioritySchema = z.enum(SOURCE_PRIORITIES);
|
|
78
|
-
const targetKindSchema = z.enum(TARGET_KINDS);
|
|
79
|
-
const searchIntentSchema = z.enum(SEARCH_INTENTS);
|
|
80
|
-
const searchMatchSchema = z.enum(SEARCH_MATCHES);
|
|
81
|
-
const searchSymbolKindSchema = z.enum(SEARCH_SYMBOL_KINDS);
|
|
82
|
-
const memberAccessSchema = z.enum(MEMBER_ACCESS);
|
|
83
|
-
const workspaceSymbolKindSchema = z.enum(WORKSPACE_SYMBOL_KINDS);
|
|
84
|
-
const classNameModeSchema = z.enum(CLASS_NAME_MODES);
|
|
85
|
-
const sourceModeSchema = z.enum(SOURCE_MODES);
|
|
86
|
-
const artifactScopeSchema = z.enum(ARTIFACT_SCOPES);
|
|
87
|
-
const decodeCompressionSchema = z.enum(DECODE_COMPRESSIONS);
|
|
88
|
-
const encodeCompressionSchema = z.enum(ENCODE_COMPRESSIONS);
|
|
89
|
-
const resolveArtifactTargetSchema = z.object({
|
|
90
|
-
kind: targetKindSchema,
|
|
91
|
-
value: nonEmptyString
|
|
92
|
-
});
|
|
93
|
-
const sourceLookupTargetSchema = z.discriminatedUnion("type", [
|
|
94
|
-
z.object({
|
|
95
|
-
type: z.literal("artifact"),
|
|
96
|
-
artifactId: nonEmptyString
|
|
97
|
-
}),
|
|
98
|
-
z.object({
|
|
99
|
-
type: z.literal("resolve"),
|
|
100
|
-
kind: targetKindSchema,
|
|
101
|
-
value: nonEmptyString
|
|
102
|
-
})
|
|
103
|
-
]);
|
|
104
|
-
const RESOLVE_ARTIFACT_TARGET_DESCRIPTION = "Object with kind and value. Example: {\"kind\":\"version\",\"value\":\"1.21.10\"}. Must be an object, not a string.";
|
|
105
|
-
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.";
|
|
106
|
-
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.";
|
|
107
|
-
const SUGGESTED_CALL_DEFAULTS = {
|
|
108
|
-
allowDecompile: true,
|
|
109
|
-
preferProjectVersion: false,
|
|
110
|
-
strictVersion: false,
|
|
111
|
-
mode: "metadata",
|
|
112
|
-
access: "public",
|
|
113
|
-
includeSynthetic: false,
|
|
114
|
-
includeInherited: false,
|
|
115
|
-
hideUncertain: false,
|
|
116
|
-
explain: false,
|
|
117
|
-
preferProjectMapping: false,
|
|
118
|
-
minSeverity: "all",
|
|
119
|
-
reportMode: "full",
|
|
120
|
-
treatInfoAsWarning: true,
|
|
121
|
-
includeIssues: true
|
|
122
|
-
};
|
|
123
|
-
function isSuggestedCallDefault(field, value) {
|
|
124
|
-
return value === SUGGESTED_CALL_DEFAULTS[field];
|
|
125
|
-
}
|
|
126
|
-
const ANALYZE_MOD_INCLUDE_GROUPS = ["warnings", "files", "source", "samples", "timings"];
|
|
127
|
-
const ANALYZE_MOD_LEGACY_METADATA_INCLUDES = ["metadata", "entrypoints", "mixins", "dependencies"];
|
|
128
|
-
const VALIDATE_PROJECT_INCLUDE_GROUPS = ["warnings", "issues", "workspace", "recovery"];
|
|
129
|
-
const VALIDATE_PROJECT_LEGACY_WORKSPACE_INCLUDES = ["detectedConfig", "mixins", "accessWideners"];
|
|
130
|
-
const listVersionsShape = {
|
|
131
|
-
includeSnapshots: z.boolean().default(false),
|
|
132
|
-
limit: optionalPositiveInt.default(20).describe("max 200")
|
|
133
|
-
};
|
|
134
|
-
const listVersionsSchema = z.object(listVersionsShape);
|
|
135
|
-
const resolveArtifactShape = {
|
|
136
|
-
target: z.object({
|
|
137
|
-
kind: targetKindSchema,
|
|
138
|
-
value: nonEmptyString
|
|
139
|
-
}).describe(RESOLVE_ARTIFACT_TARGET_DESCRIPTION),
|
|
140
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
141
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
142
|
-
allowDecompile: z.boolean().default(true),
|
|
143
|
-
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
144
|
-
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
145
|
-
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override target.value"),
|
|
146
|
-
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
147
|
-
compact: z.boolean().default(true).describe("Return minimal fields (artifactId, origin, isDecompiled, version, requestedMapping, mappingApplied, qualityFlags). "
|
|
148
|
-
+ "Omit provenance, artifactContents, sampleEntries, adjacentSourceCandidates, binaryJarPath, coordinate, repoUrl, resolvedSourceJarPath. "
|
|
149
|
-
+ "Enabled by default; set to false for full output.")
|
|
150
|
-
};
|
|
151
|
-
const resolveArtifactSchema = z.object(resolveArtifactShape);
|
|
152
|
-
const getClassSourceShape = {
|
|
153
|
-
className: nonEmptyString,
|
|
154
|
-
mode: sourceModeSchema.default("metadata").describe("metadata = symbol outline only; snippet = source with default maxLines=200; full = entire source"),
|
|
155
|
-
target: sourceLookupTargetSchema.describe(SOURCE_LOOKUP_TARGET_DESCRIPTION),
|
|
156
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
157
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
158
|
-
allowDecompile: z.boolean().default(true),
|
|
159
|
-
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
160
|
-
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
161
|
-
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override target.value"),
|
|
162
|
-
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
163
|
-
startLine: optionalPositiveInt,
|
|
164
|
-
endLine: optionalPositiveInt,
|
|
165
|
-
maxLines: optionalPositiveInt,
|
|
166
|
-
maxChars: optionalPositiveInt.describe("Hard character limit on sourceText; truncates if exceeded"),
|
|
167
|
-
outputFile: optionalNonEmptyString.describe("Write source to this file path and return metadata-only response"),
|
|
168
|
-
compact: z.boolean().default(false).describe("When true, strip debug metadata (provenance, artifactContents, qualityFlags) and empty fields from the response. Default false.")
|
|
169
|
-
};
|
|
170
|
-
const getClassSourceSchema = z
|
|
171
|
-
.object(getClassSourceShape)
|
|
172
|
-
.superRefine((value, ctx) => {
|
|
173
|
-
if (value.startLine !== undefined &&
|
|
174
|
-
value.endLine !== undefined &&
|
|
175
|
-
value.startLine > value.endLine) {
|
|
176
|
-
ctx.addIssue({
|
|
177
|
-
code: z.ZodIssueCode.custom,
|
|
178
|
-
message: "startLine must be less than or equal to endLine.",
|
|
179
|
-
path: ["startLine"]
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
const getClassMembersShape = {
|
|
184
|
-
className: nonEmptyString,
|
|
185
|
-
target: sourceLookupTargetSchema.describe(SOURCE_LOOKUP_TARGET_DESCRIPTION),
|
|
186
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn (default obfuscated)"),
|
|
187
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
188
|
-
allowDecompile: z.boolean().default(true),
|
|
189
|
-
access: memberAccessSchema.default("public").describe("public | all"),
|
|
190
|
-
includeSynthetic: z.boolean().default(false),
|
|
191
|
-
includeInherited: z.boolean().default(false),
|
|
192
|
-
memberPattern: optionalNonEmptyString,
|
|
193
|
-
maxMembers: optionalPositiveInt.describe("default 500, max 5000"),
|
|
194
|
-
projectPath: optionalNonEmptyString,
|
|
195
|
-
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
196
|
-
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override version"),
|
|
197
|
-
strictVersion: z.boolean().optional().describe("When true, reject version-approximated results instead of returning them. Default false."),
|
|
198
|
-
compact: z.boolean().default(false).describe("When true, strip debug metadata (provenance, artifactContents, qualityFlags, context) and empty fields from the response. Default false.")
|
|
199
|
-
};
|
|
200
|
-
const getClassMembersSchema = z.object(getClassMembersShape);
|
|
201
|
-
const searchClassSourceShape = {
|
|
202
|
-
artifactId: nonEmptyString,
|
|
203
|
-
query: nonEmptyString,
|
|
204
|
-
intent: searchIntentSchema.optional().describe("symbol | text | path"),
|
|
205
|
-
match: searchMatchSchema.optional().describe("exact | prefix | contains | regex"),
|
|
206
|
-
packagePrefix: optionalNonEmptyString,
|
|
207
|
-
fileGlob: optionalNonEmptyString,
|
|
208
|
-
symbolKind: searchSymbolKindSchema.optional().describe("class | interface | enum | record | method | field"),
|
|
209
|
-
queryMode: z.enum(["auto", "token", "literal"]).default("auto").describe("auto: indexed search, including separator queries like foo.bar; token: indexed-only; literal: explicit substring scan only"),
|
|
210
|
-
limit: optionalPositiveInt.default(20),
|
|
211
|
-
cursor: optionalNonEmptyString,
|
|
212
|
-
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)."),
|
|
213
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first. Used only when queryNamespace triggers translation."),
|
|
214
|
-
compact: z.boolean().default(false).describe("When true, strip the artifactContents summary and empty fields from the response. Default false.")
|
|
215
|
-
};
|
|
216
|
-
const searchClassSourceSchema = z.object(searchClassSourceShape).superRefine((value, ctx) => {
|
|
217
|
-
if (value.symbolKind && value.intent && value.intent !== "symbol") {
|
|
218
|
-
ctx.addIssue({
|
|
219
|
-
code: z.ZodIssueCode.custom,
|
|
220
|
-
path: ["symbolKind"],
|
|
221
|
-
message: 'symbolKind filter is only supported when intent="symbol".'
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
const getArtifactFileShape = {
|
|
226
|
-
artifactId: nonEmptyString,
|
|
227
|
-
filePath: nonEmptyString,
|
|
228
|
-
maxBytes: optionalPositiveInt
|
|
229
|
-
};
|
|
230
|
-
const getArtifactFileSchema = z.object(getArtifactFileShape);
|
|
231
|
-
const listArtifactFilesShape = {
|
|
232
|
-
artifactId: nonEmptyString,
|
|
233
|
-
prefix: optionalNonEmptyString,
|
|
234
|
-
limit: optionalPositiveInt,
|
|
235
|
-
cursor: optionalNonEmptyString,
|
|
236
|
-
compact: z.boolean().default(false).describe("When true, strip the artifactContents summary and empty fields from the response. Default false.")
|
|
237
|
-
};
|
|
238
|
-
const listArtifactFilesSchema = z.object(listArtifactFilesShape);
|
|
239
|
-
const traceSymbolLifecycleShape = {
|
|
240
|
-
symbol: nonEmptyString.describe("fully.qualified.Class.method"),
|
|
241
|
-
descriptor: optionalDescriptorString.describe('optional JVM descriptor, e.g. "(I)V". Empty strings are treated as omitted.'),
|
|
242
|
-
fromVersion: optionalNonEmptyString,
|
|
243
|
-
toVersion: optionalNonEmptyString,
|
|
244
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn (default obfuscated)"),
|
|
245
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
246
|
-
includeSnapshots: z.boolean().default(false),
|
|
247
|
-
maxVersions: optionalPositiveInt.default(120).describe("max 400"),
|
|
248
|
-
includeTimeline: z.boolean().default(false)
|
|
249
|
-
};
|
|
250
|
-
const traceSymbolLifecycleSchema = z.object(traceSymbolLifecycleShape);
|
|
251
|
-
const diffClassSignaturesShape = {
|
|
252
|
-
className: nonEmptyString,
|
|
253
|
-
fromVersion: nonEmptyString,
|
|
254
|
-
toVersion: nonEmptyString,
|
|
255
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn (default obfuscated)"),
|
|
256
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
257
|
-
includeFullDiff: z.boolean().default(true).describe("When false, omit from/to snapshots from modified entries and keep only key+changed")
|
|
258
|
-
};
|
|
259
|
-
const diffClassSignaturesSchema = z.object(diffClassSignaturesShape);
|
|
260
|
-
const findMappingShape = {
|
|
261
|
-
version: nonEmptyString,
|
|
262
|
-
kind: workspaceSymbolKindSchema.describe("class | field | method"),
|
|
263
|
-
name: nonEmptyString,
|
|
264
|
-
owner: optionalNonEmptyString,
|
|
265
|
-
descriptor: optionalDescriptorString.describe("JVM descriptor. Optional when signatureMode='name-only' (default). Empty strings are treated as omitted."),
|
|
266
|
-
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
267
|
-
targetMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
268
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
269
|
-
signatureMode: z.enum(["exact", "name-only"]).default("name-only")
|
|
270
|
-
.describe("exact: descriptor required for kind=method; name-only (default): match by owner+name only"),
|
|
271
|
-
disambiguation: z
|
|
272
|
-
.object({
|
|
273
|
-
ownerHint: optionalNonEmptyString,
|
|
274
|
-
descriptorHint: optionalNonEmptyString
|
|
275
|
-
})
|
|
276
|
-
.partial()
|
|
277
|
-
.optional(),
|
|
278
|
-
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates (default 5, max 200). Raise when you need the full candidate list."),
|
|
279
|
-
compact: z.boolean().default(true).describe("Omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
280
|
-
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions. "
|
|
281
|
-
+ "Enabled by default; set to false for full output.")
|
|
282
|
-
};
|
|
283
|
-
const findMappingSchema = z.object(findMappingShape).superRefine((value, ctx) => {
|
|
284
|
-
if (value.kind === "class") {
|
|
285
|
-
if (value.owner) {
|
|
286
|
-
ctx.addIssue({
|
|
287
|
-
code: z.ZodIssueCode.custom,
|
|
288
|
-
message: "owner is not allowed when kind=class.",
|
|
289
|
-
path: ["owner"]
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
if (value.descriptor) {
|
|
293
|
-
ctx.addIssue({
|
|
294
|
-
code: z.ZodIssueCode.custom,
|
|
295
|
-
message: "descriptor is not allowed when kind=class.",
|
|
296
|
-
path: ["descriptor"]
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
if (value.sourceMapping !== "obfuscated" && !value.name.includes(".")) {
|
|
300
|
-
ctx.addIssue({
|
|
301
|
-
code: z.ZodIssueCode.custom,
|
|
302
|
-
message: "name must be fully-qualified class name when kind=class.",
|
|
303
|
-
path: ["name"]
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (!value.owner) {
|
|
309
|
-
ctx.addIssue({
|
|
310
|
-
code: z.ZodIssueCode.custom,
|
|
311
|
-
message: "owner is required when kind is field or method.",
|
|
312
|
-
path: ["owner"]
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
if (/[\s./()]/.test(value.name)) {
|
|
316
|
-
ctx.addIssue({
|
|
317
|
-
code: z.ZodIssueCode.custom,
|
|
318
|
-
message: "name must be a simple member name when kind is field or method.",
|
|
319
|
-
path: ["name"]
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
if (value.kind === "field") {
|
|
323
|
-
if (value.descriptor) {
|
|
324
|
-
ctx.addIssue({
|
|
325
|
-
code: z.ZodIssueCode.custom,
|
|
326
|
-
message: "descriptor is not allowed when kind=field.",
|
|
327
|
-
path: ["descriptor"]
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
if (!value.descriptor && value.signatureMode !== "name-only") {
|
|
333
|
-
ctx.addIssue({
|
|
334
|
-
code: z.ZodIssueCode.custom,
|
|
335
|
-
message: "descriptor is required when kind=method (use signatureMode='name-only' to match by name only).",
|
|
336
|
-
path: ["descriptor"]
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
const resolveMethodMappingExactShape = {
|
|
341
|
-
version: nonEmptyString,
|
|
342
|
-
name: nonEmptyString,
|
|
343
|
-
owner: nonEmptyString,
|
|
344
|
-
descriptor: nonEmptyString.describe("required JVM descriptor"),
|
|
345
|
-
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
346
|
-
targetMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
347
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
348
|
-
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates (default 5, max 200). Raise when you need the full candidate list."),
|
|
349
|
-
compact: z.boolean().default(true).describe("Omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
350
|
-
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions. "
|
|
351
|
-
+ "Enabled by default; set to false for full output.")
|
|
352
|
-
};
|
|
353
|
-
const resolveMethodMappingExactSchema = z
|
|
354
|
-
.object(resolveMethodMappingExactShape)
|
|
355
|
-
.superRefine((value, ctx) => {
|
|
356
|
-
if (/[\s./()]/.test(value.name)) {
|
|
357
|
-
ctx.addIssue({
|
|
358
|
-
code: z.ZodIssueCode.custom,
|
|
359
|
-
message: "name must be a simple method name.",
|
|
360
|
-
path: ["name"]
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
const classApiKindsSchema = z.string().superRefine((value, ctx) => {
|
|
365
|
-
const tokens = value
|
|
366
|
-
.split(",")
|
|
367
|
-
.map((entry) => entry.trim().toLowerCase())
|
|
368
|
-
.filter((entry) => entry.length > 0);
|
|
369
|
-
if (tokens.length === 0) {
|
|
370
|
-
ctx.addIssue({
|
|
371
|
-
code: z.ZodIssueCode.custom,
|
|
372
|
-
message: "includeKinds must include at least one of class, field, method."
|
|
373
|
-
});
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
const invalidTokens = tokens.filter((entry) => entry !== "class" && entry !== "field" && entry !== "method");
|
|
377
|
-
if (invalidTokens.length > 0) {
|
|
378
|
-
ctx.addIssue({
|
|
379
|
-
code: z.ZodIssueCode.custom,
|
|
380
|
-
message: `includeKinds contains invalid values: ${invalidTokens.join(", ")}. Allowed values are class, field, method.`
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
const getClassApiMatrixShape = {
|
|
385
|
-
version: nonEmptyString,
|
|
386
|
-
className: nonEmptyString,
|
|
387
|
-
classNameMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
388
|
-
includeKinds: classApiKindsSchema.optional().describe("comma-separated: class,field,method"),
|
|
389
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
390
|
-
maxRows: optionalPositiveInt.describe("Limit returned rows (max 5000)")
|
|
391
|
-
};
|
|
392
|
-
const getClassApiMatrixSchema = z.object(getClassApiMatrixShape);
|
|
393
|
-
const resolveWorkspaceSymbolShape = {
|
|
394
|
-
projectPath: nonEmptyString,
|
|
395
|
-
version: nonEmptyString,
|
|
396
|
-
kind: workspaceSymbolKindSchema.describe("class | field | method"),
|
|
397
|
-
name: nonEmptyString,
|
|
398
|
-
owner: optionalNonEmptyString,
|
|
399
|
-
descriptor: optionalDescriptorString.describe("JVM descriptor. Empty strings are treated as omitted."),
|
|
400
|
-
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
401
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
402
|
-
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates for field/method lookups (default 5, max 200). Raise when you need the full candidate list."),
|
|
403
|
-
compact: z.boolean().default(true).describe("Omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
404
|
-
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions. "
|
|
405
|
-
+ "Enabled by default; set to false for full output.")
|
|
406
|
-
};
|
|
407
|
-
const resolveWorkspaceSymbolSchema = z
|
|
408
|
-
.object(resolveWorkspaceSymbolShape)
|
|
409
|
-
.superRefine((value, ctx) => {
|
|
410
|
-
if (value.kind === "class") {
|
|
411
|
-
if (value.owner) {
|
|
412
|
-
ctx.addIssue({
|
|
413
|
-
code: z.ZodIssueCode.custom,
|
|
414
|
-
message: "owner is not allowed when kind=class.",
|
|
415
|
-
path: ["owner"]
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
if (value.descriptor) {
|
|
419
|
-
ctx.addIssue({
|
|
420
|
-
code: z.ZodIssueCode.custom,
|
|
421
|
-
message: "descriptor is not allowed when kind=class.",
|
|
422
|
-
path: ["descriptor"]
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
if (!value.name.includes(".")) {
|
|
426
|
-
ctx.addIssue({
|
|
427
|
-
code: z.ZodIssueCode.custom,
|
|
428
|
-
message: "name must be fully-qualified class name when kind=class.",
|
|
429
|
-
path: ["name"]
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
if (!value.owner) {
|
|
435
|
-
ctx.addIssue({
|
|
436
|
-
code: z.ZodIssueCode.custom,
|
|
437
|
-
message: "owner is required when kind is field or method.",
|
|
438
|
-
path: ["owner"]
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
if (/[\s./()]/.test(value.name)) {
|
|
442
|
-
ctx.addIssue({
|
|
443
|
-
code: z.ZodIssueCode.custom,
|
|
444
|
-
message: "name must be a simple member name when kind is field or method.",
|
|
445
|
-
path: ["name"]
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
if (value.kind === "field") {
|
|
449
|
-
if (value.descriptor) {
|
|
450
|
-
ctx.addIssue({
|
|
451
|
-
code: z.ZodIssueCode.custom,
|
|
452
|
-
message: "descriptor is not allowed when kind=field.",
|
|
453
|
-
path: ["descriptor"]
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
if (!value.descriptor) {
|
|
459
|
-
ctx.addIssue({
|
|
460
|
-
code: z.ZodIssueCode.custom,
|
|
461
|
-
message: "descriptor is required when kind=method.",
|
|
462
|
-
path: ["descriptor"]
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
|
-
const checkSymbolExistsShape = {
|
|
467
|
-
version: nonEmptyString,
|
|
468
|
-
kind: workspaceSymbolKindSchema.describe("class | field | method"),
|
|
469
|
-
owner: optionalNonEmptyString,
|
|
470
|
-
name: nonEmptyString,
|
|
471
|
-
descriptor: optionalDescriptorString.describe("required for kind=method unless signatureMode=name-only. Empty strings are treated as omitted."),
|
|
472
|
-
sourceMapping: sourceMappingSchema.describe("obfuscated | mojang | intermediary | yarn"),
|
|
473
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
474
|
-
nameMode: classNameModeSchema.default("fqcn").describe("fqcn | auto"),
|
|
475
|
-
signatureMode: z.enum(["exact", "name-only"]).default("exact")
|
|
476
|
-
.describe("exact: require descriptor for methods; name-only: match by owner+name only"),
|
|
477
|
-
maxCandidates: optionalPositiveInt.default(5).describe("Limit returned candidates (default 5, max 200). Raise when you need the full candidate list."),
|
|
478
|
-
compact: z.boolean().default(true).describe("Omit top-level empty arrays, null/undefined values, and empty objects from the response. "
|
|
479
|
-
+ "Also omit redundant candidates array for single full-confidence exact-match resolutions. "
|
|
480
|
-
+ "Enabled by default; set to false for full output.")
|
|
481
|
-
};
|
|
482
|
-
const checkSymbolExistsSchema = z.object(checkSymbolExistsShape).superRefine((value, ctx) => {
|
|
483
|
-
if (value.kind === "class") {
|
|
484
|
-
if (value.owner) {
|
|
485
|
-
ctx.addIssue({
|
|
486
|
-
code: z.ZodIssueCode.custom,
|
|
487
|
-
message: "owner is not allowed when kind=class.",
|
|
488
|
-
path: ["owner"]
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
if (value.descriptor) {
|
|
492
|
-
ctx.addIssue({
|
|
493
|
-
code: z.ZodIssueCode.custom,
|
|
494
|
-
message: "descriptor is not allowed when kind=class.",
|
|
495
|
-
path: ["descriptor"]
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
if (value.nameMode !== "auto" && !value.name.includes(".")) {
|
|
499
|
-
ctx.addIssue({
|
|
500
|
-
code: z.ZodIssueCode.custom,
|
|
501
|
-
message: "name must be fully-qualified class name when kind=class.",
|
|
502
|
-
path: ["name"]
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
if (!value.owner) {
|
|
508
|
-
ctx.addIssue({
|
|
509
|
-
code: z.ZodIssueCode.custom,
|
|
510
|
-
message: "owner is required when kind is field or method.",
|
|
511
|
-
path: ["owner"]
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
if (/[\s./()]/.test(value.name)) {
|
|
515
|
-
ctx.addIssue({
|
|
516
|
-
code: z.ZodIssueCode.custom,
|
|
517
|
-
message: "name must be a simple member name when kind is field or method.",
|
|
518
|
-
path: ["name"]
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
if (value.kind === "field") {
|
|
522
|
-
if (value.descriptor) {
|
|
523
|
-
ctx.addIssue({
|
|
524
|
-
code: z.ZodIssueCode.custom,
|
|
525
|
-
message: "descriptor is not allowed when kind=field.",
|
|
526
|
-
path: ["descriptor"]
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
if (!value.descriptor && value.signatureMode !== "name-only") {
|
|
532
|
-
ctx.addIssue({
|
|
533
|
-
code: z.ZodIssueCode.custom,
|
|
534
|
-
message: "descriptor is required when kind=method (use signatureMode='name-only' to match by name only).",
|
|
535
|
-
path: ["descriptor"]
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
const nbtToJsonShape = {
|
|
540
|
-
nbtBase64: nonEmptyString,
|
|
541
|
-
compression: decodeCompressionSchema.default("auto").describe("none | gzip | auto")
|
|
542
|
-
};
|
|
543
|
-
const nbtToJsonSchema = z.object(nbtToJsonShape);
|
|
544
|
-
const nbtPatchOperationSchema = z
|
|
545
|
-
.object({
|
|
546
|
-
op: z.enum(["add", "remove", "replace", "test"]),
|
|
547
|
-
path: nonEmptyString,
|
|
548
|
-
value: z.unknown().optional()
|
|
549
|
-
})
|
|
550
|
-
.passthrough();
|
|
551
|
-
const nbtApplyJsonPatchShape = {
|
|
552
|
-
typedJson: z.unknown(),
|
|
553
|
-
patch: z.array(nbtPatchOperationSchema).describe("RFC6902 operation array (add/remove/replace/test)")
|
|
554
|
-
};
|
|
555
|
-
const nbtApplyJsonPatchSchema = z.object(nbtApplyJsonPatchShape);
|
|
556
|
-
const jsonToNbtShape = {
|
|
557
|
-
typedJson: z.unknown(),
|
|
558
|
-
compression: encodeCompressionSchema.default("none").describe("none | gzip")
|
|
559
|
-
};
|
|
560
|
-
const jsonToNbtSchema = z.object(jsonToNbtShape);
|
|
561
|
-
const indexArtifactShape = {
|
|
562
|
-
artifactId: nonEmptyString,
|
|
563
|
-
force: z.boolean().default(false)
|
|
564
|
-
};
|
|
565
|
-
const indexArtifactSchema = z.object(indexArtifactShape);
|
|
566
|
-
const validateMixinShape = {
|
|
567
|
-
input: z.discriminatedUnion("mode", [
|
|
568
|
-
z.object({
|
|
569
|
-
mode: z.literal("inline"),
|
|
570
|
-
source: nonEmptyString.describe("Mixin Java source text")
|
|
571
|
-
}),
|
|
572
|
-
z.object({
|
|
573
|
-
mode: z.literal("path"),
|
|
574
|
-
path: nonEmptyString.describe("Path to a Mixin .java file")
|
|
575
|
-
}),
|
|
576
|
-
z.object({
|
|
577
|
-
mode: z.literal("paths"),
|
|
578
|
-
paths: z.array(nonEmptyString).min(1).describe("Array of Mixin .java file paths for batch validation")
|
|
579
|
-
}),
|
|
580
|
-
z.object({
|
|
581
|
-
mode: z.literal("config"),
|
|
582
|
-
configPaths: z.array(nonEmptyString).min(1).describe("Path array to mixin config JSON files (e.g. modid.mixins.json)")
|
|
583
|
-
}),
|
|
584
|
-
z.object({
|
|
585
|
-
mode: z.literal("project"),
|
|
586
|
-
path: nonEmptyString.describe("Workspace root path used to discover *.mixins.json files automatically")
|
|
587
|
-
})
|
|
588
|
-
]).describe("One of { mode: 'inline', source }, { mode: 'path', path }, { mode: 'paths', paths[] }, { mode: 'config', configPaths[] }, or { mode: 'project', path }."),
|
|
589
|
-
sourceRoots: z.array(z.string().min(1)).optional()
|
|
590
|
-
.describe("Array of source roots for multi-module projects (e.g. ['common/src/main/java', 'neoforge/src/main/java'])"),
|
|
591
|
-
version: nonEmptyString.describe("Minecraft version"),
|
|
592
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
593
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
594
|
-
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
595
|
-
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted source resolution"),
|
|
596
|
-
preferProjectVersion: z.boolean().optional().describe("When true, detect MC version from gradle.properties and override version"),
|
|
597
|
-
minSeverity: z.enum(["error", "warning", "all"]).default("all")
|
|
598
|
-
.describe("'error'=errors only, 'warning'=errors+warnings, 'all'=everything"),
|
|
599
|
-
hideUncertain: z.boolean().default(false)
|
|
600
|
-
.describe("Omit issues with confidence='uncertain'"),
|
|
601
|
-
explain: z.boolean().default(false)
|
|
602
|
-
.describe("When true, enrich each issue with explanation and suggestedCall for agent recovery"),
|
|
603
|
-
warningMode: z.enum(["full", "aggregated"]).optional()
|
|
604
|
-
.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'"),
|
|
605
|
-
preferProjectMapping: z.boolean().default(false)
|
|
606
|
-
.describe("When true, auto-detect mapping from project config even if mapping is explicitly provided"),
|
|
607
|
-
reportMode: z.enum(["compact", "full", "summary-first"]).default("full")
|
|
608
|
-
.describe("'compact' omits heavy per-result detail, 'summary-first' hoists shared provenance/warnings/incomplete reasons, 'full'=everything"),
|
|
609
|
-
warningCategoryFilter: z.array(z.enum(["mapping", "configuration", "validation", "resolution", "parse"])).optional()
|
|
610
|
-
.describe("Only include warnings/issues matching these categories (default: all)"),
|
|
611
|
-
treatInfoAsWarning: z.boolean().default(true)
|
|
612
|
-
.describe("When false, suppress info-severity structured warnings from output"),
|
|
613
|
-
includeIssues: z.boolean().default(true)
|
|
614
|
-
.describe("When false, keep summary fields but omit per-result issues[] payloads")
|
|
615
|
-
};
|
|
616
|
-
const validateMixinSchema = z.object(validateMixinShape);
|
|
617
|
-
const validateAccessWidenerShape = {
|
|
618
|
-
content: nonEmptyString.describe("Access Widener file content"),
|
|
619
|
-
version: nonEmptyString.describe("Minecraft version"),
|
|
620
|
-
mapping: sourceMappingSchema.optional().describe("obfuscated | mojang | intermediary | yarn"),
|
|
621
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
622
|
-
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Loom cache-assisted runtime validation"),
|
|
623
|
-
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
624
|
-
preferProjectVersion: z.boolean().default(false)
|
|
625
|
-
.describe("When true, detect MC version from gradle.properties and override version")
|
|
626
|
-
};
|
|
627
|
-
const validateAccessWidenerSchema = z.object(validateAccessWidenerShape);
|
|
628
|
-
const validateAccessTransformerShape = {
|
|
629
|
-
content: nonEmptyString.describe("Access Transformer file content"),
|
|
630
|
-
version: nonEmptyString.describe("Minecraft version"),
|
|
631
|
-
atNamespace: z.enum(["srg", "mojang", "obfuscated"]).optional().describe("srg | mojang | obfuscated"),
|
|
632
|
-
sourcePriority: mappingSourcePrioritySchema.optional().describe("loom-first | maven-first"),
|
|
633
|
-
projectPath: optionalNonEmptyString.describe("Optional workspace root path for Forge/NeoForge runtime validation"),
|
|
634
|
-
scope: artifactScopeSchema.optional().describe(SOURCE_SCOPE_DESCRIPTION),
|
|
635
|
-
preferProjectVersion: z.boolean().default(false)
|
|
636
|
-
.describe("When true, detect MC version from gradle.properties and override version")
|
|
637
|
-
};
|
|
638
|
-
const validateAccessTransformerSchema = z.object(validateAccessTransformerShape);
|
|
639
|
-
const analyzeModJarShape = {
|
|
640
|
-
jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
|
|
641
|
-
includeClasses: z.boolean().default(false).describe("Include full class listing")
|
|
642
|
-
};
|
|
643
|
-
const analyzeModJarSchema = z.object(analyzeModJarShape);
|
|
644
|
-
const getRegistryDataShape = {
|
|
645
|
-
version: nonEmptyString.describe("Minecraft version (e.g. 1.21)"),
|
|
646
|
-
registry: optionalNonEmptyString.describe('Optional registry name (e.g. "block", "item", "minecraft:biome"). Omit to list all registries.'),
|
|
647
|
-
includeData: z.boolean().default(true).describe("When false, return registry names/counts without full entry bodies"),
|
|
648
|
-
maxEntriesPerRegistry: optionalPositiveInt.describe("Limit returned entries per registry body")
|
|
649
|
-
};
|
|
650
|
-
const getRegistryDataSchema = z.object(getRegistryDataShape);
|
|
651
|
-
const COMPARE_VERSIONS_CATEGORIES = ["classes", "registry", "all"];
|
|
652
|
-
const compareVersionsCategorySchema = z.enum(COMPARE_VERSIONS_CATEGORIES);
|
|
653
|
-
const compareVersionsShape = {
|
|
654
|
-
fromVersion: nonEmptyString.describe("Older Minecraft version (e.g. 1.20.4)"),
|
|
655
|
-
toVersion: nonEmptyString.describe("Newer Minecraft version (e.g. 1.21)"),
|
|
656
|
-
category: compareVersionsCategorySchema.default("all").describe("classes | registry | all"),
|
|
657
|
-
packageFilter: optionalNonEmptyString.describe("Filter classes to a package prefix (e.g. net.minecraft.world.item)"),
|
|
658
|
-
maxClassResults: optionalPositiveInt.default(500).describe("Max class results per direction (max 5000)")
|
|
659
|
-
};
|
|
660
|
-
const compareVersionsSchema = z.object(compareVersionsShape);
|
|
661
|
-
const decompileModJarShape = {
|
|
662
|
-
jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
|
|
663
|
-
className: optionalNonEmptyString.describe("Optional fully-qualified class name to view source. Omit to list all classes."),
|
|
664
|
-
includeFiles: z.boolean().default(true).describe("When false, omit the full class list and return counts only"),
|
|
665
|
-
maxFiles: optionalPositiveInt.describe("Limit returned class names when files are included")
|
|
666
|
-
};
|
|
667
|
-
const decompileModJarSchema = z.object(decompileModJarShape);
|
|
668
|
-
const getModClassSourceShape = {
|
|
669
|
-
jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
|
|
670
|
-
className: nonEmptyString.describe("Fully-qualified class name (e.g. com.example.MyMixin)"),
|
|
671
|
-
maxLines: optionalPositiveInt.describe("Max lines to return"),
|
|
672
|
-
maxChars: optionalPositiveInt.describe("Hard character limit; truncates if exceeded"),
|
|
673
|
-
outputFile: optionalNonEmptyString.describe("Write full source to file, return placeholder in content")
|
|
674
|
-
};
|
|
675
|
-
const getModClassSourceSchema = z.object(getModClassSourceShape);
|
|
676
|
-
const MOD_SEARCH_TYPES = ["class", "method", "field", "content", "all"];
|
|
677
|
-
const modSearchTypeSchema = z.enum(MOD_SEARCH_TYPES);
|
|
678
|
-
const searchModSourceShape = {
|
|
679
|
-
jarPath: nonEmptyString.describe("Local path to the mod JAR file"),
|
|
680
|
-
query: nonEmptyString.describe("Search pattern (regex or literal string)"),
|
|
681
|
-
searchType: modSearchTypeSchema.default("all").describe("class | method | field | content | all"),
|
|
682
|
-
limit: optionalPositiveInt.default(50).describe("Max results (max 200)")
|
|
683
|
-
};
|
|
684
|
-
const searchModSourceSchema = z.object(searchModSourceShape);
|
|
685
|
-
const REMAP_TARGETS = ["yarn", "mojang"];
|
|
686
|
-
const remapTargetSchema = z.enum(REMAP_TARGETS);
|
|
687
|
-
const remapModJarShape = {
|
|
688
|
-
inputJar: nonEmptyString.describe("Path to the mod JAR file"),
|
|
689
|
-
outputJar: optionalNonEmptyString.describe("Output path for remapped JAR (auto-generated if omitted)"),
|
|
690
|
-
mcVersion: optionalNonEmptyString.describe("Minecraft version (auto-detected from mod metadata if omitted)"),
|
|
691
|
-
targetMapping: remapTargetSchema.describe("yarn | mojang")
|
|
692
|
-
};
|
|
693
|
-
const remapModJarSchema = z.object(remapModJarShape);
|
|
694
|
-
const emptySchema = z.object({}).passthrough();
|
|
695
59
|
function getServerVersionFromPackageJson() {
|
|
696
60
|
try {
|
|
697
61
|
const packageJsonUrl = new URL("../package.json", import.meta.url);
|
|
@@ -765,13 +129,29 @@ const analyzeModService = new AnalyzeModService({
|
|
|
765
129
|
remapModJar: (input) => remapModJar(input, config)
|
|
766
130
|
});
|
|
767
131
|
const validateProjectService = new ValidateProjectService({
|
|
768
|
-
validateMixin: (input) => sourceService.validateMixin(input),
|
|
132
|
+
validateMixin: (input, options) => sourceService.validateMixin(input, options),
|
|
769
133
|
validateAccessWidener: (input) => sourceService.validateAccessWidener(input),
|
|
770
134
|
validateAccessTransformer: (input) => sourceService.validateAccessTransformer(input),
|
|
771
135
|
discoverMixins: discoverWorkspaceMixins,
|
|
772
136
|
discoverAccessWideners: discoverWorkspaceAccessWideners,
|
|
773
137
|
discoverAccessTransformers: discoverWorkspaceAccessTransformers,
|
|
774
|
-
detectProjectMinecraftVersion: (projectPath) => workspaceMappingService.detectProjectMinecraftVersion(projectPath)
|
|
138
|
+
detectProjectMinecraftVersion: (projectPath) => workspaceMappingService.detectProjectMinecraftVersion(projectPath),
|
|
139
|
+
resolveArtifact: async (input) => {
|
|
140
|
+
const output = await sourceService.resolveArtifact({
|
|
141
|
+
target: input.target,
|
|
142
|
+
mapping: input.mapping,
|
|
143
|
+
sourcePriority: input.sourcePriority,
|
|
144
|
+
projectPath: input.projectPath,
|
|
145
|
+
scope: input.scope,
|
|
146
|
+
preferProjectVersion: input.preferProjectVersion
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
artifactId: output.artifactId,
|
|
150
|
+
mappingApplied: output.mappingApplied,
|
|
151
|
+
warnings: output.warnings
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
probeMinecraftArtifact: (input) => sourceService.probeMinecraftArtifact(input)
|
|
775
155
|
});
|
|
776
156
|
const manageCacheService = new ManageCacheService({
|
|
777
157
|
registry: createCacheRegistry({
|
|
@@ -779,6 +159,42 @@ const manageCacheService = new ManageCacheService({
|
|
|
779
159
|
sqlitePath: config.sqlitePath
|
|
780
160
|
})
|
|
781
161
|
});
|
|
162
|
+
const verifyMixinTargetService = new VerifyMixinTargetService({
|
|
163
|
+
resolveArtifact: async (input) => {
|
|
164
|
+
const output = await sourceService.resolveArtifact({
|
|
165
|
+
target: input.target,
|
|
166
|
+
mapping: input.mapping,
|
|
167
|
+
sourcePriority: input.sourcePriority,
|
|
168
|
+
projectPath: input.projectPath,
|
|
169
|
+
scope: input.scope,
|
|
170
|
+
preferProjectVersion: input.preferProjectVersion,
|
|
171
|
+
strictVersion: input.strictVersion
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
artifactId: output.artifactId,
|
|
175
|
+
mappingApplied: output.mappingApplied,
|
|
176
|
+
binaryJarPath: output.binaryJarPath,
|
|
177
|
+
provenance: output.provenance,
|
|
178
|
+
warnings: output.warnings
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
getSignature: (input) => sourceService.explorerService.getSignature(input)
|
|
182
|
+
});
|
|
183
|
+
const batchClassSourceService = new BatchClassSourceService({
|
|
184
|
+
resolveArtifact: (input) => sourceService.resolveArtifact(input),
|
|
185
|
+
getClassSource: (input) => sourceService.getClassSource(input)
|
|
186
|
+
});
|
|
187
|
+
const batchClassMembersService = new BatchClassMembersService({
|
|
188
|
+
resolveArtifact: (input) => sourceService.resolveArtifact(input),
|
|
189
|
+
getClassMembers: (input) => sourceService.getClassMembers(input)
|
|
190
|
+
});
|
|
191
|
+
const batchSymbolExistsService = new BatchSymbolExistsService({
|
|
192
|
+
resolveArtifact: (input) => sourceService.resolveArtifact(input),
|
|
193
|
+
checkSymbolExists: (input) => sourceService.checkSymbolExists(input)
|
|
194
|
+
});
|
|
195
|
+
const batchMappingsService = new BatchMappingsService({
|
|
196
|
+
findMapping: (input) => sourceService.findMapping(input)
|
|
197
|
+
});
|
|
782
198
|
registerResources(server, sourceService);
|
|
783
199
|
let processHandlersAttached = false;
|
|
784
200
|
let serverStarted = false;
|
|
@@ -811,12 +227,8 @@ function normalizeSourceLookupTarget(target) {
|
|
|
811
227
|
if (target.type === "artifact") {
|
|
812
228
|
return { artifactId: target.artifactId };
|
|
813
229
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
kind: target.kind,
|
|
817
|
-
value: target.value
|
|
818
|
-
}
|
|
819
|
-
};
|
|
230
|
+
const { type: _type, ...rest } = target;
|
|
231
|
+
return { target: rest };
|
|
820
232
|
}
|
|
821
233
|
function parseClassApiKinds(value) {
|
|
822
234
|
if (value == null) {
|
|
@@ -831,692 +243,6 @@ function parseClassApiKinds(value) {
|
|
|
831
243
|
}
|
|
832
244
|
return [...new Set(normalized)];
|
|
833
245
|
}
|
|
834
|
-
function toFieldErrorsFromZod(error) {
|
|
835
|
-
return error.issues.map((issue) => ({
|
|
836
|
-
path: issue.path.join(".") || "$",
|
|
837
|
-
message: issue.message,
|
|
838
|
-
code: issue.code
|
|
839
|
-
}));
|
|
840
|
-
}
|
|
841
|
-
function toHints(details) {
|
|
842
|
-
if (typeof details !== "object" || details == null) {
|
|
843
|
-
return undefined;
|
|
844
|
-
}
|
|
845
|
-
const hints = [];
|
|
846
|
-
const maybeNextAction = details.nextAction;
|
|
847
|
-
if (typeof maybeNextAction === "string" && maybeNextAction.trim()) {
|
|
848
|
-
hints.push(maybeNextAction.trim());
|
|
849
|
-
}
|
|
850
|
-
if (hints.length === 0) {
|
|
851
|
-
return undefined;
|
|
852
|
-
}
|
|
853
|
-
return hints;
|
|
854
|
-
}
|
|
855
|
-
function toSuggestedCall(details) {
|
|
856
|
-
if (typeof details !== "object" || details == null) {
|
|
857
|
-
return undefined;
|
|
858
|
-
}
|
|
859
|
-
const maybe = details.suggestedCall;
|
|
860
|
-
if (typeof maybe !== "object" || maybe == null) {
|
|
861
|
-
return undefined;
|
|
862
|
-
}
|
|
863
|
-
const call = maybe;
|
|
864
|
-
if (typeof call.tool !== "string" || typeof call.params !== "object" || call.params == null) {
|
|
865
|
-
return undefined;
|
|
866
|
-
}
|
|
867
|
-
return { tool: call.tool, params: call.params };
|
|
868
|
-
}
|
|
869
|
-
function statusForErrorCode(code) {
|
|
870
|
-
if (code === ERROR_CODES.INVALID_INPUT ||
|
|
871
|
-
code === ERROR_CODES.COORDINATE_PARSE_FAILED ||
|
|
872
|
-
code === ERROR_CODES.INVALID_LINE_RANGE ||
|
|
873
|
-
code === ERROR_CODES.NBT_PARSE_FAILED ||
|
|
874
|
-
code === ERROR_CODES.NBT_INVALID_TYPED_JSON ||
|
|
875
|
-
code === ERROR_CODES.JSON_PATCH_INVALID ||
|
|
876
|
-
code === ERROR_CODES.NBT_ENCODE_FAILED ||
|
|
877
|
-
code === ERROR_CODES.NBT_UNSUPPORTED_FEATURE) {
|
|
878
|
-
return 400;
|
|
879
|
-
}
|
|
880
|
-
if (code === ERROR_CODES.JSON_PATCH_CONFLICT || code === ERROR_CODES.CONTEXT_UNRESOLVED) {
|
|
881
|
-
return 409;
|
|
882
|
-
}
|
|
883
|
-
if (code === ERROR_CODES.SOURCE_NOT_FOUND ||
|
|
884
|
-
code === ERROR_CODES.FILE_NOT_FOUND ||
|
|
885
|
-
code === ERROR_CODES.JAR_NOT_FOUND ||
|
|
886
|
-
code === ERROR_CODES.VERSION_NOT_FOUND ||
|
|
887
|
-
code === ERROR_CODES.CLASS_NOT_FOUND) {
|
|
888
|
-
return 404;
|
|
889
|
-
}
|
|
890
|
-
if (code === ERROR_CODES.MAPPING_NOT_APPLIED ||
|
|
891
|
-
code === ERROR_CODES.MAPPING_UNAVAILABLE ||
|
|
892
|
-
code === ERROR_CODES.NAMESPACE_MISMATCH ||
|
|
893
|
-
code === ERROR_CODES.DECOMPILE_DISABLED ||
|
|
894
|
-
code === ERROR_CODES.REMAP_FAILED) {
|
|
895
|
-
return 422;
|
|
896
|
-
}
|
|
897
|
-
if (code === ERROR_CODES.REMAPPER_UNAVAILABLE ||
|
|
898
|
-
code === ERROR_CODES.JAVA_PROCESS_FAILED) {
|
|
899
|
-
return 503;
|
|
900
|
-
}
|
|
901
|
-
if (code === ERROR_CODES.LIMIT_EXCEEDED) {
|
|
902
|
-
return 413;
|
|
903
|
-
}
|
|
904
|
-
if (code === ERROR_CODES.REPO_FETCH_FAILED) {
|
|
905
|
-
return 502;
|
|
906
|
-
}
|
|
907
|
-
if (code === ERROR_CODES.DECOMPILER_UNAVAILABLE ||
|
|
908
|
-
code === ERROR_CODES.DECOMPILER_FAILED ||
|
|
909
|
-
code === ERROR_CODES.JAVA_UNAVAILABLE ||
|
|
910
|
-
code === ERROR_CODES.REGISTRY_GENERATION_FAILED) {
|
|
911
|
-
return 503;
|
|
912
|
-
}
|
|
913
|
-
return 500;
|
|
914
|
-
}
|
|
915
|
-
function extractFailedStageFromDetails(details) {
|
|
916
|
-
if (typeof details !== "object" || details == null) {
|
|
917
|
-
return undefined;
|
|
918
|
-
}
|
|
919
|
-
const maybeStage = details.failedStage;
|
|
920
|
-
if (typeof maybeStage === "string" && maybeStage.trim().length > 0) {
|
|
921
|
-
return maybeStage;
|
|
922
|
-
}
|
|
923
|
-
return undefined;
|
|
924
|
-
}
|
|
925
|
-
function extractFieldErrorsFromDetails(details) {
|
|
926
|
-
if (typeof details !== "object" || details == null) {
|
|
927
|
-
return undefined;
|
|
928
|
-
}
|
|
929
|
-
const maybeFieldErrors = details.fieldErrors;
|
|
930
|
-
if (!Array.isArray(maybeFieldErrors)) {
|
|
931
|
-
return undefined;
|
|
932
|
-
}
|
|
933
|
-
const normalized = maybeFieldErrors
|
|
934
|
-
.map((entry) => {
|
|
935
|
-
if (typeof entry !== "object" || entry == null) {
|
|
936
|
-
return undefined;
|
|
937
|
-
}
|
|
938
|
-
const asRecord = entry;
|
|
939
|
-
const path = asRecord.path;
|
|
940
|
-
const message = asRecord.message;
|
|
941
|
-
const code = asRecord.code;
|
|
942
|
-
if (typeof path !== "string" || typeof message !== "string") {
|
|
943
|
-
return undefined;
|
|
944
|
-
}
|
|
945
|
-
return {
|
|
946
|
-
path,
|
|
947
|
-
message,
|
|
948
|
-
code: typeof code === "string" ? code : undefined
|
|
949
|
-
};
|
|
950
|
-
})
|
|
951
|
-
.filter((entry) => entry != null);
|
|
952
|
-
return normalized.length > 0 ? normalized : undefined;
|
|
953
|
-
}
|
|
954
|
-
function asObjectRecord(value) {
|
|
955
|
-
return typeof value === "object" && value != null && !Array.isArray(value)
|
|
956
|
-
? value
|
|
957
|
-
: undefined;
|
|
958
|
-
}
|
|
959
|
-
function asNonEmptyString(value) {
|
|
960
|
-
return typeof value === "string" && value.trim() ? value : undefined;
|
|
961
|
-
}
|
|
962
|
-
function asStringArray(value) {
|
|
963
|
-
return Array.isArray(value) && value.every((entry) => typeof entry === "string" && entry.trim())
|
|
964
|
-
? value
|
|
965
|
-
: undefined;
|
|
966
|
-
}
|
|
967
|
-
function truncateSuggestionText(value, maxLength = 500) {
|
|
968
|
-
return value.length > maxLength
|
|
969
|
-
? `${value.slice(0, maxLength)}...`
|
|
970
|
-
: value;
|
|
971
|
-
}
|
|
972
|
-
function parseJsonObjectString(value) {
|
|
973
|
-
if (!value.trim().startsWith("{")) {
|
|
974
|
-
return undefined;
|
|
975
|
-
}
|
|
976
|
-
try {
|
|
977
|
-
const parsed = JSON.parse(value);
|
|
978
|
-
return asObjectRecord(parsed);
|
|
979
|
-
}
|
|
980
|
-
catch {
|
|
981
|
-
return undefined;
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
function inferTargetKindFromString(value) {
|
|
985
|
-
if (/[\\/]/.test(value) || /\.jar$/i.test(value)) {
|
|
986
|
-
return "jar";
|
|
987
|
-
}
|
|
988
|
-
if (value.split(":").length >= 3) {
|
|
989
|
-
return "coordinate";
|
|
990
|
-
}
|
|
991
|
-
return "version";
|
|
992
|
-
}
|
|
993
|
-
function copySourceLookupSuggestionFields(tool, source) {
|
|
994
|
-
const result = {};
|
|
995
|
-
const stringFields = tool === "get-class-source"
|
|
996
|
-
? ["className", "mode", "mapping", "sourcePriority", "projectPath", "scope", "outputFile"]
|
|
997
|
-
: ["className", "mapping", "sourcePriority", "projectPath", "scope", "access", "memberPattern"];
|
|
998
|
-
for (const field of stringFields) {
|
|
999
|
-
const value = source[field];
|
|
1000
|
-
if (typeof value === "string" &&
|
|
1001
|
-
value.trim() &&
|
|
1002
|
-
(!Object.prototype.hasOwnProperty.call(SUGGESTED_CALL_DEFAULTS, field) ||
|
|
1003
|
-
!isSuggestedCallDefault(field, value))) {
|
|
1004
|
-
result[field] = value;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
const numericFields = tool === "get-class-source"
|
|
1008
|
-
? ["startLine", "endLine", "maxLines", "maxChars"]
|
|
1009
|
-
: ["maxMembers"];
|
|
1010
|
-
for (const field of numericFields) {
|
|
1011
|
-
const value = source[field];
|
|
1012
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1013
|
-
result[field] = value;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
const booleanFields = tool === "get-class-source"
|
|
1017
|
-
? ["allowDecompile", "preferProjectVersion", "strictVersion"]
|
|
1018
|
-
: ["allowDecompile", "preferProjectVersion", "strictVersion", "includeSynthetic", "includeInherited"];
|
|
1019
|
-
for (const field of booleanFields) {
|
|
1020
|
-
const value = source[field];
|
|
1021
|
-
if (typeof value === "boolean" &&
|
|
1022
|
-
(!Object.prototype.hasOwnProperty.call(SUGGESTED_CALL_DEFAULTS, field) ||
|
|
1023
|
-
!isSuggestedCallDefault(field, value))) {
|
|
1024
|
-
result[field] = value;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
return result;
|
|
1028
|
-
}
|
|
1029
|
-
function copyValidateMixinSharedParams(source) {
|
|
1030
|
-
const result = {};
|
|
1031
|
-
const stringFields = [
|
|
1032
|
-
"version",
|
|
1033
|
-
"mapping",
|
|
1034
|
-
"sourcePriority",
|
|
1035
|
-
"scope",
|
|
1036
|
-
"projectPath",
|
|
1037
|
-
"minSeverity",
|
|
1038
|
-
"warningMode",
|
|
1039
|
-
"reportMode"
|
|
1040
|
-
];
|
|
1041
|
-
for (const field of stringFields) {
|
|
1042
|
-
const value = source[field];
|
|
1043
|
-
if (typeof value === "string" &&
|
|
1044
|
-
value.trim() &&
|
|
1045
|
-
(!Object.prototype.hasOwnProperty.call(SUGGESTED_CALL_DEFAULTS, field) ||
|
|
1046
|
-
!isSuggestedCallDefault(field, value))) {
|
|
1047
|
-
result[field] = value;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
const booleanFields = [
|
|
1051
|
-
"preferProjectVersion",
|
|
1052
|
-
"hideUncertain",
|
|
1053
|
-
"explain",
|
|
1054
|
-
"preferProjectMapping",
|
|
1055
|
-
"treatInfoAsWarning",
|
|
1056
|
-
"includeIssues"
|
|
1057
|
-
];
|
|
1058
|
-
for (const field of booleanFields) {
|
|
1059
|
-
const value = source[field];
|
|
1060
|
-
if (typeof value === "boolean" &&
|
|
1061
|
-
(!Object.prototype.hasOwnProperty.call(SUGGESTED_CALL_DEFAULTS, field) ||
|
|
1062
|
-
!isSuggestedCallDefault(field, value))) {
|
|
1063
|
-
result[field] = value;
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
const sourceRoots = asStringArray(source.sourceRoots);
|
|
1067
|
-
if (sourceRoots) {
|
|
1068
|
-
result.sourceRoots = sourceRoots;
|
|
1069
|
-
}
|
|
1070
|
-
const warningCategoryFilter = asStringArray(source.warningCategoryFilter);
|
|
1071
|
-
if (warningCategoryFilter) {
|
|
1072
|
-
result.warningCategoryFilter = warningCategoryFilter;
|
|
1073
|
-
}
|
|
1074
|
-
return result;
|
|
1075
|
-
}
|
|
1076
|
-
function buildValidateMixinSuggestedParams(normalizedInput) {
|
|
1077
|
-
const record = asObjectRecord(normalizedInput);
|
|
1078
|
-
if (!record) {
|
|
1079
|
-
return {
|
|
1080
|
-
input: {
|
|
1081
|
-
mode: "inline",
|
|
1082
|
-
source: "<Mixin Java source>"
|
|
1083
|
-
},
|
|
1084
|
-
version: "<minecraft-version>"
|
|
1085
|
-
};
|
|
1086
|
-
}
|
|
1087
|
-
const inputRecord = asObjectRecord(record.input);
|
|
1088
|
-
const shared = copyValidateMixinSharedParams(record);
|
|
1089
|
-
const version = asNonEmptyString(record.version) ?? "<minecraft-version>";
|
|
1090
|
-
const inlineSource = asNonEmptyString(record.input) ??
|
|
1091
|
-
asNonEmptyString(inputRecord?.source) ??
|
|
1092
|
-
asNonEmptyString(record.source);
|
|
1093
|
-
if (inlineSource) {
|
|
1094
|
-
const parsedInlineObject = parseJsonObjectString(inlineSource);
|
|
1095
|
-
if (parsedInlineObject && typeof parsedInlineObject.mode === "string") {
|
|
1096
|
-
return {
|
|
1097
|
-
...shared,
|
|
1098
|
-
input: parsedInlineObject,
|
|
1099
|
-
version
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
return {
|
|
1103
|
-
...shared,
|
|
1104
|
-
input: {
|
|
1105
|
-
mode: "inline",
|
|
1106
|
-
source: truncateSuggestionText(inlineSource)
|
|
1107
|
-
},
|
|
1108
|
-
version
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
const path = asNonEmptyString(inputRecord?.path) ??
|
|
1112
|
-
asNonEmptyString(record.sourcePath);
|
|
1113
|
-
if (path) {
|
|
1114
|
-
return {
|
|
1115
|
-
...shared,
|
|
1116
|
-
input: {
|
|
1117
|
-
mode: "path",
|
|
1118
|
-
path
|
|
1119
|
-
},
|
|
1120
|
-
version
|
|
1121
|
-
};
|
|
1122
|
-
}
|
|
1123
|
-
const paths = asStringArray(inputRecord?.paths) ??
|
|
1124
|
-
asStringArray(record.sourcePaths);
|
|
1125
|
-
if (paths) {
|
|
1126
|
-
return {
|
|
1127
|
-
...shared,
|
|
1128
|
-
input: {
|
|
1129
|
-
mode: "paths",
|
|
1130
|
-
paths
|
|
1131
|
-
},
|
|
1132
|
-
version
|
|
1133
|
-
};
|
|
1134
|
-
}
|
|
1135
|
-
const configPaths = asStringArray(inputRecord?.configPaths) ??
|
|
1136
|
-
(asNonEmptyString(record.mixinConfigPath) ? [record.mixinConfigPath] : undefined);
|
|
1137
|
-
if (configPaths) {
|
|
1138
|
-
return {
|
|
1139
|
-
...shared,
|
|
1140
|
-
input: {
|
|
1141
|
-
mode: "config",
|
|
1142
|
-
configPaths
|
|
1143
|
-
},
|
|
1144
|
-
version
|
|
1145
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
const projectPath = asNonEmptyString(record.projectPath) ??
|
|
1148
|
-
(inputRecord?.mode === "project" ? asNonEmptyString(inputRecord.path) : undefined);
|
|
1149
|
-
if (projectPath) {
|
|
1150
|
-
return {
|
|
1151
|
-
...shared,
|
|
1152
|
-
input: {
|
|
1153
|
-
mode: "project",
|
|
1154
|
-
path: projectPath
|
|
1155
|
-
},
|
|
1156
|
-
version
|
|
1157
|
-
};
|
|
1158
|
-
}
|
|
1159
|
-
return {
|
|
1160
|
-
...shared,
|
|
1161
|
-
input: {
|
|
1162
|
-
mode: "inline",
|
|
1163
|
-
source: "<Mixin Java source>"
|
|
1164
|
-
},
|
|
1165
|
-
version
|
|
1166
|
-
};
|
|
1167
|
-
}
|
|
1168
|
-
function buildResolveArtifactSuggestedParams(normalizedInput) {
|
|
1169
|
-
const record = asObjectRecord(normalizedInput);
|
|
1170
|
-
if (!record) {
|
|
1171
|
-
return {
|
|
1172
|
-
target: {
|
|
1173
|
-
kind: "version",
|
|
1174
|
-
value: "<minecraft-version>"
|
|
1175
|
-
}
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
const targetValue = asNonEmptyString(record.target);
|
|
1179
|
-
const result = {
|
|
1180
|
-
target: targetValue
|
|
1181
|
-
? {
|
|
1182
|
-
kind: inferTargetKindFromString(targetValue),
|
|
1183
|
-
value: targetValue
|
|
1184
|
-
}
|
|
1185
|
-
: {
|
|
1186
|
-
kind: "version",
|
|
1187
|
-
value: "<minecraft-version>"
|
|
1188
|
-
}
|
|
1189
|
-
};
|
|
1190
|
-
const stringFields = ["mapping", "sourcePriority", "projectPath", "scope"];
|
|
1191
|
-
for (const field of stringFields) {
|
|
1192
|
-
const value = record[field];
|
|
1193
|
-
if (typeof value === "string" && value.trim()) {
|
|
1194
|
-
result[field] = value;
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
const booleanFields = ["allowDecompile", "preferProjectVersion", "strictVersion"];
|
|
1198
|
-
for (const field of booleanFields) {
|
|
1199
|
-
const value = record[field];
|
|
1200
|
-
if (typeof value === "boolean" &&
|
|
1201
|
-
!isSuggestedCallDefault(field, value)) {
|
|
1202
|
-
result[field] = value;
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
return result;
|
|
1206
|
-
}
|
|
1207
|
-
function buildSourceLookupSuggestedParams(tool, normalizedInput) {
|
|
1208
|
-
const record = asObjectRecord(normalizedInput);
|
|
1209
|
-
const result = record ? copySourceLookupSuggestionFields(tool, record) : {};
|
|
1210
|
-
const targetValue = asNonEmptyString(record?.target);
|
|
1211
|
-
result.target = targetValue
|
|
1212
|
-
? {
|
|
1213
|
-
type: "resolve",
|
|
1214
|
-
kind: inferTargetKindFromString(targetValue),
|
|
1215
|
-
value: targetValue
|
|
1216
|
-
}
|
|
1217
|
-
: {
|
|
1218
|
-
type: "resolve",
|
|
1219
|
-
kind: "version",
|
|
1220
|
-
value: "<minecraft-version>"
|
|
1221
|
-
};
|
|
1222
|
-
if (!asNonEmptyString(result.className)) {
|
|
1223
|
-
result.className = "<fully-qualified-class-name>";
|
|
1224
|
-
}
|
|
1225
|
-
return result;
|
|
1226
|
-
}
|
|
1227
|
-
function filterAllowedIncludeValues(values, allowed) {
|
|
1228
|
-
if (!values?.length) {
|
|
1229
|
-
return [];
|
|
1230
|
-
}
|
|
1231
|
-
const allowedSet = new Set(allowed);
|
|
1232
|
-
const filtered = values.filter((value) => allowedSet.has(value));
|
|
1233
|
-
return [...new Set(filtered)];
|
|
1234
|
-
}
|
|
1235
|
-
function buildAnalyzeModSuggestedParams(normalizedInput) {
|
|
1236
|
-
const record = asObjectRecord(normalizedInput);
|
|
1237
|
-
if (!record) {
|
|
1238
|
-
return {
|
|
1239
|
-
task: "summary",
|
|
1240
|
-
detail: "standard",
|
|
1241
|
-
subject: {
|
|
1242
|
-
kind: "jar",
|
|
1243
|
-
jarPath: "<mod-jar-path>"
|
|
1244
|
-
}
|
|
1245
|
-
};
|
|
1246
|
-
}
|
|
1247
|
-
const task = asNonEmptyString(record.task) ?? "summary";
|
|
1248
|
-
const result = { task };
|
|
1249
|
-
const subjectRecord = asObjectRecord(record.subject);
|
|
1250
|
-
const include = asStringArray(record.include);
|
|
1251
|
-
const canonicalInclude = filterAllowedIncludeValues(include, ANALYZE_MOD_INCLUDE_GROUPS);
|
|
1252
|
-
const wantsLegacyMetadata = include?.some((value) => ANALYZE_MOD_LEGACY_METADATA_INCLUDES.includes(value)) ?? false;
|
|
1253
|
-
const detail = asNonEmptyString(record.detail);
|
|
1254
|
-
if (task === "summary" && wantsLegacyMetadata) {
|
|
1255
|
-
result.detail = detail && detail !== "summary" ? detail : "standard";
|
|
1256
|
-
}
|
|
1257
|
-
else if (detail && detail !== "summary") {
|
|
1258
|
-
result.detail = detail;
|
|
1259
|
-
}
|
|
1260
|
-
if (canonicalInclude.length > 0) {
|
|
1261
|
-
result.include = canonicalInclude;
|
|
1262
|
-
}
|
|
1263
|
-
if (task === "class-source") {
|
|
1264
|
-
result.subject = {
|
|
1265
|
-
kind: "class",
|
|
1266
|
-
jarPath: asNonEmptyString(subjectRecord?.jarPath) ?? asNonEmptyString(record.subject) ?? "<mod-jar-path>",
|
|
1267
|
-
className: asNonEmptyString(subjectRecord?.className) ?? asNonEmptyString(record.className) ?? "<fully-qualified-class-name>"
|
|
1268
|
-
};
|
|
1269
|
-
}
|
|
1270
|
-
else {
|
|
1271
|
-
result.subject = {
|
|
1272
|
-
kind: "jar",
|
|
1273
|
-
jarPath: asNonEmptyString(subjectRecord?.jarPath) ?? asNonEmptyString(record.subject) ?? asNonEmptyString(record.jarPath) ?? "<mod-jar-path>"
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1276
|
-
const stringFields = ["query", "searchType", "targetMapping", "outputJar", "executionMode"];
|
|
1277
|
-
for (const field of stringFields) {
|
|
1278
|
-
const value = record[field];
|
|
1279
|
-
if (typeof value === "string" && value.trim()) {
|
|
1280
|
-
result[field] = value;
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
const booleanFields = ["includeFiles"];
|
|
1284
|
-
for (const field of booleanFields) {
|
|
1285
|
-
const value = record[field];
|
|
1286
|
-
if (typeof value === "boolean") {
|
|
1287
|
-
result[field] = value;
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
const numericFields = ["limit", "maxFiles", "maxLines", "maxChars"];
|
|
1291
|
-
for (const field of numericFields) {
|
|
1292
|
-
const value = record[field];
|
|
1293
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1294
|
-
result[field] = value;
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
return result;
|
|
1298
|
-
}
|
|
1299
|
-
function buildValidateProjectSuggestedParams(normalizedInput) {
|
|
1300
|
-
const record = asObjectRecord(normalizedInput);
|
|
1301
|
-
if (!record) {
|
|
1302
|
-
return {
|
|
1303
|
-
task: "project-summary",
|
|
1304
|
-
subject: {
|
|
1305
|
-
kind: "workspace",
|
|
1306
|
-
projectPath: "<workspace-path>"
|
|
1307
|
-
},
|
|
1308
|
-
preferProjectVersion: true
|
|
1309
|
-
};
|
|
1310
|
-
}
|
|
1311
|
-
const task = asNonEmptyString(record.task) ?? "project-summary";
|
|
1312
|
-
const result = { task };
|
|
1313
|
-
const subjectRecord = asObjectRecord(record.subject);
|
|
1314
|
-
const include = asStringArray(record.include);
|
|
1315
|
-
const canonicalInclude = filterAllowedIncludeValues(include, VALIDATE_PROJECT_INCLUDE_GROUPS);
|
|
1316
|
-
const wantsWorkspaceInclude = include?.some((value) => VALIDATE_PROJECT_LEGACY_WORKSPACE_INCLUDES.includes(value)) ?? false;
|
|
1317
|
-
const detail = asNonEmptyString(record.detail);
|
|
1318
|
-
if (detail && detail !== "summary") {
|
|
1319
|
-
result.detail = detail;
|
|
1320
|
-
}
|
|
1321
|
-
const includeSuggestion = wantsWorkspaceInclude
|
|
1322
|
-
? [...new Set([...canonicalInclude, "workspace"])]
|
|
1323
|
-
: canonicalInclude;
|
|
1324
|
-
if (includeSuggestion.length > 0) {
|
|
1325
|
-
result.include = includeSuggestion;
|
|
1326
|
-
}
|
|
1327
|
-
const stringFields = [
|
|
1328
|
-
"version",
|
|
1329
|
-
"mapping",
|
|
1330
|
-
"sourcePriority",
|
|
1331
|
-
"scope",
|
|
1332
|
-
"minSeverity",
|
|
1333
|
-
"warningMode"
|
|
1334
|
-
];
|
|
1335
|
-
for (const field of stringFields) {
|
|
1336
|
-
const value = record[field];
|
|
1337
|
-
if (typeof value === "string" && value.trim()) {
|
|
1338
|
-
result[field] = value;
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
const booleanFields = [
|
|
1342
|
-
"preferProjectVersion",
|
|
1343
|
-
"preferProjectMapping",
|
|
1344
|
-
"hideUncertain",
|
|
1345
|
-
"explain",
|
|
1346
|
-
"treatInfoAsWarning",
|
|
1347
|
-
"includeIssues"
|
|
1348
|
-
];
|
|
1349
|
-
for (const field of booleanFields) {
|
|
1350
|
-
const value = record[field];
|
|
1351
|
-
if (typeof value === "boolean" &&
|
|
1352
|
-
(!Object.prototype.hasOwnProperty.call(SUGGESTED_CALL_DEFAULTS, field) ||
|
|
1353
|
-
!isSuggestedCallDefault(field, value))) {
|
|
1354
|
-
result[field] = value;
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
const sourceRoots = asStringArray(record.sourceRoots);
|
|
1358
|
-
if (sourceRoots?.length) {
|
|
1359
|
-
result.sourceRoots = sourceRoots;
|
|
1360
|
-
}
|
|
1361
|
-
const configPaths = asStringArray(record.configPaths);
|
|
1362
|
-
if (configPaths?.length) {
|
|
1363
|
-
result.configPaths = configPaths;
|
|
1364
|
-
}
|
|
1365
|
-
const warningCategoryFilter = asStringArray(record.warningCategoryFilter);
|
|
1366
|
-
if (warningCategoryFilter?.length) {
|
|
1367
|
-
result.warningCategoryFilter = warningCategoryFilter;
|
|
1368
|
-
}
|
|
1369
|
-
if (task === "project-summary") {
|
|
1370
|
-
const subject = {
|
|
1371
|
-
kind: "workspace",
|
|
1372
|
-
projectPath: asNonEmptyString(subjectRecord?.projectPath) ??
|
|
1373
|
-
asNonEmptyString(record.subject) ??
|
|
1374
|
-
asNonEmptyString(record.projectPath) ??
|
|
1375
|
-
"<workspace-path>"
|
|
1376
|
-
};
|
|
1377
|
-
const discover = asStringArray(subjectRecord?.discover);
|
|
1378
|
-
if (discover?.length) {
|
|
1379
|
-
subject.discover = discover;
|
|
1380
|
-
}
|
|
1381
|
-
result.subject = subject;
|
|
1382
|
-
return result;
|
|
1383
|
-
}
|
|
1384
|
-
if (task === "mixin") {
|
|
1385
|
-
const inputRecord = asObjectRecord(subjectRecord?.input) ?? asObjectRecord(record.input);
|
|
1386
|
-
result.subject = {
|
|
1387
|
-
kind: "mixin",
|
|
1388
|
-
input: inputRecord ?? {
|
|
1389
|
-
mode: "inline",
|
|
1390
|
-
source: "<Mixin Java source>"
|
|
1391
|
-
}
|
|
1392
|
-
};
|
|
1393
|
-
return result;
|
|
1394
|
-
}
|
|
1395
|
-
const inputRecord = asObjectRecord(subjectRecord?.input) ?? asObjectRecord(record.input);
|
|
1396
|
-
result.subject = {
|
|
1397
|
-
kind: "access-widener",
|
|
1398
|
-
input: inputRecord ?? {
|
|
1399
|
-
mode: "inline",
|
|
1400
|
-
content: "<access widener contents>"
|
|
1401
|
-
}
|
|
1402
|
-
};
|
|
1403
|
-
return result;
|
|
1404
|
-
}
|
|
1405
|
-
function buildInvalidInputGuidance(tool, normalizedInput) {
|
|
1406
|
-
if (tool === "validate-mixin") {
|
|
1407
|
-
const hints = [
|
|
1408
|
-
"validate-mixin.input must be an object with input.mode = \"inline\" | \"path\" | \"paths\" | \"config\" | \"project\".",
|
|
1409
|
-
"Whole-project example: {\"input\":{\"mode\":\"project\",\"path\":\"/workspace\"},\"version\":\"1.21.10\",\"preferProjectVersion\":true,\"preferProjectMapping\":true}.",
|
|
1410
|
-
"Legacy top-level source/sourcePath/sourcePaths/mixinConfigPath fields are no longer accepted; wrap them under input.mode instead."
|
|
1411
|
-
];
|
|
1412
|
-
return {
|
|
1413
|
-
hints,
|
|
1414
|
-
suggestedCall: {
|
|
1415
|
-
tool,
|
|
1416
|
-
params: buildValidateMixinSuggestedParams(normalizedInput)
|
|
1417
|
-
}
|
|
1418
|
-
};
|
|
1419
|
-
}
|
|
1420
|
-
if (tool === "resolve-artifact") {
|
|
1421
|
-
return {
|
|
1422
|
-
hints: [
|
|
1423
|
-
"resolve-artifact.target must be an object: {\"kind\":\"version|jar|coordinate\",\"value\":\"...\"}.",
|
|
1424
|
-
"Bare string targets are not accepted; wrap the value under target.kind and target.value."
|
|
1425
|
-
],
|
|
1426
|
-
suggestedCall: {
|
|
1427
|
-
tool,
|
|
1428
|
-
params: buildResolveArtifactSuggestedParams(normalizedInput)
|
|
1429
|
-
}
|
|
1430
|
-
};
|
|
1431
|
-
}
|
|
1432
|
-
if (tool === "get-class-source" || tool === "get-class-members") {
|
|
1433
|
-
return {
|
|
1434
|
-
hints: [
|
|
1435
|
-
`${tool}.target must be an object: {"type":"resolve","kind":"version|jar|coordinate","value":"..."} or {"type":"artifact","artifactId":"..."}.`,
|
|
1436
|
-
"Bare string targets are not accepted; wrap the value under target.type/target.kind/target.value."
|
|
1437
|
-
],
|
|
1438
|
-
suggestedCall: {
|
|
1439
|
-
tool,
|
|
1440
|
-
params: buildSourceLookupSuggestedParams(tool, normalizedInput)
|
|
1441
|
-
}
|
|
1442
|
-
};
|
|
1443
|
-
}
|
|
1444
|
-
if (tool === "validate-project") {
|
|
1445
|
-
return {
|
|
1446
|
-
hints: [
|
|
1447
|
-
"validate-project.subject must be an object with subject.kind=workspace|mixin|access-widener|access-transformer.",
|
|
1448
|
-
"task=\"project-summary\" uses {\"subject\":{\"kind\":\"workspace\",\"projectPath\":\"/workspace\"}}.",
|
|
1449
|
-
"Legacy include names like projectSummary/detectedConfig/validationSummary are not accepted; use include:[\"workspace\"] only when you need discovery details."
|
|
1450
|
-
],
|
|
1451
|
-
suggestedCall: {
|
|
1452
|
-
tool,
|
|
1453
|
-
params: buildValidateProjectSuggestedParams(normalizedInput)
|
|
1454
|
-
}
|
|
1455
|
-
};
|
|
1456
|
-
}
|
|
1457
|
-
if (tool === "analyze-mod") {
|
|
1458
|
-
return {
|
|
1459
|
-
hints: [
|
|
1460
|
-
"analyze-mod.subject must be an object with subject.kind=jar|class.",
|
|
1461
|
-
"task=\"summary\" uses {\"subject\":{\"kind\":\"jar\",\"jarPath\":\"/path/to/mod.jar\"}}.",
|
|
1462
|
-
"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."
|
|
1463
|
-
],
|
|
1464
|
-
suggestedCall: {
|
|
1465
|
-
tool,
|
|
1466
|
-
params: buildAnalyzeModSuggestedParams(normalizedInput)
|
|
1467
|
-
}
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
|
-
return undefined;
|
|
1471
|
-
}
|
|
1472
|
-
function mapErrorToProblem(caughtError, requestId, context) {
|
|
1473
|
-
if (caughtError instanceof ZodError) {
|
|
1474
|
-
const guidance = context?.tool
|
|
1475
|
-
? buildInvalidInputGuidance(context.tool, context.normalizedInput)
|
|
1476
|
-
: undefined;
|
|
1477
|
-
return {
|
|
1478
|
-
type: "https://minecraft-modding-mcp.dev/problems/invalid-input",
|
|
1479
|
-
title: "Invalid input",
|
|
1480
|
-
detail: "Request validation failed.",
|
|
1481
|
-
status: 400,
|
|
1482
|
-
code: ERROR_CODES.INVALID_INPUT,
|
|
1483
|
-
instance: requestId,
|
|
1484
|
-
fieldErrors: toFieldErrorsFromZod(caughtError),
|
|
1485
|
-
hints: guidance?.hints ?? ["Check fieldErrors and submit a valid tool argument payload."],
|
|
1486
|
-
...(guidance?.suggestedCall ? { suggestedCall: guidance.suggestedCall } : {}),
|
|
1487
|
-
...(context?.tool === "validate-mixin" ? { failedStage: "input-validation" } : {})
|
|
1488
|
-
};
|
|
1489
|
-
}
|
|
1490
|
-
if (isAppError(caughtError)) {
|
|
1491
|
-
const suggestedCall = toSuggestedCall(caughtError.details);
|
|
1492
|
-
let failedStage = extractFailedStageFromDetails(caughtError.details);
|
|
1493
|
-
if (!failedStage
|
|
1494
|
-
&& context?.tool === "validate-mixin"
|
|
1495
|
-
&& caughtError.code === ERROR_CODES.INVALID_INPUT) {
|
|
1496
|
-
failedStage = "input-validation";
|
|
1497
|
-
}
|
|
1498
|
-
return {
|
|
1499
|
-
type: `https://minecraft-modding-mcp.dev/problems/${caughtError.code.toLowerCase()}`,
|
|
1500
|
-
title: "Tool execution error",
|
|
1501
|
-
detail: caughtError.message,
|
|
1502
|
-
status: statusForErrorCode(caughtError.code),
|
|
1503
|
-
code: caughtError.code,
|
|
1504
|
-
instance: requestId,
|
|
1505
|
-
fieldErrors: extractFieldErrorsFromDetails(caughtError.details),
|
|
1506
|
-
hints: toHints(caughtError.details),
|
|
1507
|
-
...(suggestedCall ? { suggestedCall } : {}),
|
|
1508
|
-
...(failedStage ? { failedStage } : {})
|
|
1509
|
-
};
|
|
1510
|
-
}
|
|
1511
|
-
return {
|
|
1512
|
-
type: "https://minecraft-modding-mcp.dev/problems/internal",
|
|
1513
|
-
title: "Internal server error",
|
|
1514
|
-
detail: "Unexpected server error.",
|
|
1515
|
-
status: 500,
|
|
1516
|
-
code: ERROR_CODES.INTERNAL,
|
|
1517
|
-
instance: requestId
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
246
|
function splitWarnings(data) {
|
|
1521
247
|
const result = { ...data };
|
|
1522
248
|
const warnings = [];
|
|
@@ -1561,12 +287,12 @@ async function runTool(tool, rawInput, schema, action) {
|
|
|
1561
287
|
code: "invalid_enum_value"
|
|
1562
288
|
})),
|
|
1563
289
|
nextAction: `Replace "official" with "obfuscated" in mapping-related fields and retry.`,
|
|
1564
|
-
|
|
1565
|
-
? {
|
|
290
|
+
...(suggestedReplacementInput
|
|
291
|
+
? buildSuggestedCall({
|
|
1566
292
|
tool,
|
|
1567
293
|
params: suggestedReplacementInput
|
|
1568
|
-
}
|
|
1569
|
-
:
|
|
294
|
+
})
|
|
295
|
+
: {})
|
|
1570
296
|
}
|
|
1571
297
|
});
|
|
1572
298
|
}
|
|
@@ -1662,14 +388,16 @@ async function runTool(tool, rawInput, schema, action) {
|
|
|
1662
388
|
}
|
|
1663
389
|
const errorDurationMs = Date.now() - startedAt;
|
|
1664
390
|
sourceService.recordToolCall(tool, errorDurationMs);
|
|
391
|
+
const errorMeta = {
|
|
392
|
+
requestId,
|
|
393
|
+
tool,
|
|
394
|
+
durationMs: errorDurationMs,
|
|
395
|
+
warnings: []
|
|
396
|
+
};
|
|
397
|
+
applyErrorMetaExtensions(errorMeta, caughtError);
|
|
1665
398
|
return objectResult({
|
|
1666
399
|
error: problem,
|
|
1667
|
-
meta:
|
|
1668
|
-
requestId,
|
|
1669
|
-
tool,
|
|
1670
|
-
durationMs: errorDurationMs,
|
|
1671
|
-
warnings: []
|
|
1672
|
-
}
|
|
400
|
+
meta: errorMeta
|
|
1673
401
|
}, { isError: true });
|
|
1674
402
|
}
|
|
1675
403
|
}
|
|
@@ -1677,12 +405,46 @@ server.tool("list-versions", "List available Minecraft versions from Mojang mani
|
|
|
1677
405
|
includeSnapshots: input.includeSnapshots,
|
|
1678
406
|
limit: input.limit
|
|
1679
407
|
})));
|
|
408
|
+
registerToolSchema("list-versions", listVersionsSchema);
|
|
1680
409
|
server.tool("inspect-minecraft", "High-level v3 entry tool for version discovery, artifact resolution, class inspection, source search, file reads, and file listings.", inspectMinecraftShape, { readOnlyHint: true }, async (args) => runTool("inspect-minecraft", args, inspectMinecraftSchema, async (input) => inspectMinecraftService.execute(input)));
|
|
410
|
+
registerToolSchema("inspect-minecraft", inspectMinecraftSchema);
|
|
1681
411
|
server.tool("analyze-symbol", "High-level v3 entry tool for symbol existence, mapping, lifecycle, workspace analysis, and API overview.", analyzeSymbolShape, { readOnlyHint: true }, async (args) => runTool("analyze-symbol", args, analyzeSymbolSchema, async (input) => analyzeSymbolService.execute(input)));
|
|
412
|
+
registerToolSchema("analyze-symbol", analyzeSymbolSchema);
|
|
1682
413
|
server.tool("compare-minecraft", "High-level v3 entry tool for version comparisons, class diffs, registry diffs, and migration overviews.", compareMinecraftShape, { readOnlyHint: true }, async (args) => runTool("compare-minecraft", args, compareMinecraftSchema, async (input) => compareMinecraftService.execute(input)));
|
|
414
|
+
registerToolSchema("compare-minecraft", compareMinecraftSchema);
|
|
1683
415
|
server.tool("analyze-mod", "High-level v3 entry tool for mod metadata inspection, decompile/search flows, class source, and safe remap previews/applies.", analyzeModShape, { readOnlyHint: false }, async (args) => runTool("analyze-mod", args, analyzeModSchema, async (input) => analyzeModService.execute(input)));
|
|
1684
|
-
|
|
416
|
+
registerToolSchema("analyze-mod", analyzeModSchema);
|
|
417
|
+
server.tool("validate-project", "High-level v3 entry tool for project summary, direct mixin validation, and access widener/access transformer validation.", validateProjectShape, { readOnlyHint: true }, async (args, extra) => runTool("validate-project", args, validateProjectSchema, async (input) => validateProjectService.execute(input, {
|
|
418
|
+
stageEmitter: makeStageEmitter(extra)
|
|
419
|
+
})));
|
|
420
|
+
registerToolSchema("validate-project", validateProjectSchema);
|
|
1685
421
|
server.tool("manage-cache", "High-level v3 entry tool for cache summaries, listing, verification, previewed mutation, and explicit apply operations.", manageCacheShape, { readOnlyHint: false }, async (args) => runTool("manage-cache", args, manageCacheSchema, async (input) => manageCacheService.execute(input)));
|
|
422
|
+
registerToolSchema("manage-cache", manageCacheSchema);
|
|
423
|
+
if (!VERIFY_MIXIN_TARGET_OFF) {
|
|
424
|
+
server.tool("verify-mixin-target", "Single-call probe: does this target owner / member exist and which @Shadow / @Accessor / @Invoker should the mixin use? Reuses target.kind workspace/version/coordinate/dependency/jar.", verifyMixinTargetShape, { readOnlyHint: true }, async (args) => runTool("verify-mixin-target", args, verifyMixinTargetSchema, async (input) => verifyMixinTargetService.execute({
|
|
425
|
+
owner: input.owner,
|
|
426
|
+
member: input.member,
|
|
427
|
+
mixinMemberName: input.mixinMemberName,
|
|
428
|
+
mapping: input.mapping,
|
|
429
|
+
sourcePriority: input.sourcePriority,
|
|
430
|
+
projectPath: input.projectPath,
|
|
431
|
+
target: input.target,
|
|
432
|
+
scope: input.scope,
|
|
433
|
+
preferProjectVersion: input.preferProjectVersion,
|
|
434
|
+
strictVersion: input.strictVersion
|
|
435
|
+
})));
|
|
436
|
+
registerToolSchema("verify-mixin-target", verifyMixinTargetSchema);
|
|
437
|
+
}
|
|
438
|
+
if (!BATCH_TOOLS_OFF) {
|
|
439
|
+
server.tool("batch-class-source", "Batch lookup: read source for many classes in one call, sharing a single resolved artifact. Returns per-entry { status, result?, error? } plus aggregate summary. Per-entry retry suggestions point at get-class-source.", batchClassSourceShape, { readOnlyHint: true }, async (args) => runTool("batch-class-source", args, batchClassSourceSchema, async (input) => batchClassSourceService.execute(input)));
|
|
440
|
+
registerToolSchema("batch-class-source", batchClassSourceSchema);
|
|
441
|
+
server.tool("batch-class-members", "Batch lookup: list members for many classes in one call, sharing a single resolved artifact. Returns per-entry { status, result?, error? } plus aggregate summary. Per-entry retry suggestions point at get-class-members.", batchClassMembersShape, { readOnlyHint: true }, async (args) => runTool("batch-class-members", args, batchClassMembersSchema, async (input) => batchClassMembersService.execute(input)));
|
|
442
|
+
registerToolSchema("batch-class-members", batchClassMembersSchema);
|
|
443
|
+
server.tool("batch-symbol-exists", "Batch existence/mapping query: probe many symbols in one call against a shared Minecraft-version artifact. Accepts target.kind=workspace or version only (other kinds carry library versions, not Minecraft versions). Per-entry retry suggestions point at check-symbol-exists.", batchSymbolExistsShape, { readOnlyHint: true }, async (args) => runTool("batch-symbol-exists", args, batchSymbolExistsSchema, async (input) => batchSymbolExistsService.execute(input)));
|
|
444
|
+
registerToolSchema("batch-symbol-exists", batchSymbolExistsSchema);
|
|
445
|
+
server.tool("batch-mappings", "Batch mapping translation: resolve many symbols across mapping namespaces with one shared Minecraft version. Per-entry retry suggestions point at find-mapping.", batchMappingsShape, { readOnlyHint: true }, async (args) => runTool("batch-mappings", args, batchMappingsSchema, async (input) => batchMappingsService.execute(input)));
|
|
446
|
+
registerToolSchema("batch-mappings", batchMappingsSchema);
|
|
447
|
+
}
|
|
1686
448
|
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({
|
|
1687
449
|
target: input.target,
|
|
1688
450
|
mapping: input.mapping,
|
|
@@ -1694,6 +456,7 @@ server.tool("resolve-artifact", "Resolve source artifact from a target object ({
|
|
|
1694
456
|
strictVersion: input.strictVersion,
|
|
1695
457
|
compact: input.compact
|
|
1696
458
|
})));
|
|
459
|
+
registerToolSchema("resolve-artifact", resolveArtifactSchema);
|
|
1697
460
|
const findClassShape = {
|
|
1698
461
|
className: nonEmptyString.describe("Simple name (e.g. Blocks) or fully-qualified name (e.g. net.minecraft.world.level.block.Blocks)"),
|
|
1699
462
|
artifactId: nonEmptyString,
|
|
@@ -1705,6 +468,7 @@ server.tool("find-class", "Resolve a simple or qualified class name to fully-qua
|
|
|
1705
468
|
artifactId: input.artifactId,
|
|
1706
469
|
limit: input.limit
|
|
1707
470
|
})));
|
|
471
|
+
registerToolSchema("find-class", findClassSchema);
|
|
1708
472
|
server.tool("get-class-source", "Get Java source for a class by target ({ type: 'artifact', artifactId } or { type: 'resolve', kind, value }). Default mode=metadata returns symbol outline only; use mode=snippet for bounded excerpts or mode=full for entire source.", getClassSourceShape, { readOnlyHint: true }, async (args) => runTool("get-class-source", args, getClassSourceSchema, async (input) => {
|
|
1709
473
|
const normalizedTarget = normalizeSourceLookupTarget(input.target);
|
|
1710
474
|
return sourceService.getClassSource({
|
|
@@ -1726,6 +490,7 @@ server.tool("get-class-source", "Get Java source for a class by target ({ type:
|
|
|
1726
490
|
outputFile: input.outputFile
|
|
1727
491
|
});
|
|
1728
492
|
}));
|
|
493
|
+
registerToolSchema("get-class-source", getClassSourceSchema);
|
|
1729
494
|
server.tool("get-class-members", "Get fields/methods/constructors for one class from binary bytecode by target ({ type: 'artifact', artifactId } or { type: 'resolve', kind, value }).", getClassMembersShape, { readOnlyHint: true }, async (args) => runTool("get-class-members", args, getClassMembersSchema, async (input) => {
|
|
1730
495
|
const normalizedTarget = normalizeSourceLookupTarget(input.target);
|
|
1731
496
|
return sourceService.getClassMembers({
|
|
@@ -1746,6 +511,7 @@ server.tool("get-class-members", "Get fields/methods/constructors for one class
|
|
|
1746
511
|
strictVersion: input.strictVersion
|
|
1747
512
|
});
|
|
1748
513
|
}));
|
|
514
|
+
registerToolSchema("get-class-members", getClassMembersSchema);
|
|
1749
515
|
server.tool("search-class-source", "Search indexed class source files for one artifact with symbol/text/path intent and compact hit output.", searchClassSourceShape, { readOnlyHint: true }, async (args) => runTool("search-class-source", args, searchClassSourceSchema, async (input) => {
|
|
1750
516
|
const scope = input.packagePrefix || input.fileGlob || input.symbolKind
|
|
1751
517
|
? {
|
|
@@ -1767,17 +533,20 @@ server.tool("search-class-source", "Search indexed class source files for one ar
|
|
|
1767
533
|
sourcePriority: input.sourcePriority
|
|
1768
534
|
});
|
|
1769
535
|
}));
|
|
536
|
+
registerToolSchema("search-class-source", searchClassSourceSchema);
|
|
1770
537
|
server.tool("get-artifact-file", "Get full source file content by artifactId and file path.", getArtifactFileShape, { readOnlyHint: true }, async (args) => runTool("get-artifact-file", args, getArtifactFileSchema, async (input) => sourceService.getArtifactFile({
|
|
1771
538
|
artifactId: input.artifactId,
|
|
1772
539
|
filePath: input.filePath,
|
|
1773
540
|
maxBytes: input.maxBytes
|
|
1774
541
|
})));
|
|
542
|
+
registerToolSchema("get-artifact-file", getArtifactFileSchema);
|
|
1775
543
|
server.tool("list-artifact-files", "List source file paths in an artifact with optional prefix filter and cursor-based pagination.", listArtifactFilesShape, { readOnlyHint: true }, async (args) => runTool("list-artifact-files", args, listArtifactFilesSchema, async (input) => sourceService.listArtifactFiles({
|
|
1776
544
|
artifactId: input.artifactId,
|
|
1777
545
|
prefix: input.prefix,
|
|
1778
546
|
limit: input.limit,
|
|
1779
547
|
cursor: input.cursor
|
|
1780
548
|
})));
|
|
549
|
+
registerToolSchema("list-artifact-files", listArtifactFilesSchema);
|
|
1781
550
|
server.tool("trace-symbol-lifecycle", "Trace which Minecraft versions contain a specific class method and report first/last seen versions.", traceSymbolLifecycleShape, { readOnlyHint: true }, async (args) => runTool("trace-symbol-lifecycle", args, traceSymbolLifecycleSchema, async (input) => sourceService.traceSymbolLifecycle({
|
|
1782
551
|
symbol: input.symbol,
|
|
1783
552
|
descriptor: input.descriptor,
|
|
@@ -1789,6 +558,7 @@ server.tool("trace-symbol-lifecycle", "Trace which Minecraft versions contain a
|
|
|
1789
558
|
maxVersions: input.maxVersions,
|
|
1790
559
|
includeTimeline: input.includeTimeline
|
|
1791
560
|
})));
|
|
561
|
+
registerToolSchema("trace-symbol-lifecycle", traceSymbolLifecycleSchema);
|
|
1792
562
|
server.tool("diff-class-signatures", "Compare one class signature between two Minecraft versions and report added/removed/modified constructors, methods, and fields.", diffClassSignaturesShape, { readOnlyHint: true }, async (args) => runTool("diff-class-signatures", args, diffClassSignaturesSchema, async (input) => sourceService.diffClassSignatures({
|
|
1793
563
|
className: input.className,
|
|
1794
564
|
fromVersion: input.fromVersion,
|
|
@@ -1797,6 +567,7 @@ server.tool("diff-class-signatures", "Compare one class signature between two Mi
|
|
|
1797
567
|
sourcePriority: input.sourcePriority,
|
|
1798
568
|
includeFullDiff: input.includeFullDiff
|
|
1799
569
|
})));
|
|
570
|
+
registerToolSchema("diff-class-signatures", diffClassSignaturesSchema);
|
|
1800
571
|
server.tool("find-mapping", "Find symbol mapping candidates between namespaces using structured symbol inputs for a specific Minecraft version.", findMappingShape, { readOnlyHint: true }, async (args) => runTool("find-mapping", args, findMappingSchema, async (input) => sourceService.findMapping({
|
|
1801
572
|
version: input.version,
|
|
1802
573
|
kind: input.kind,
|
|
@@ -1810,6 +581,7 @@ server.tool("find-mapping", "Find symbol mapping candidates between namespaces u
|
|
|
1810
581
|
disambiguation: input.disambiguation,
|
|
1811
582
|
maxCandidates: input.maxCandidates
|
|
1812
583
|
})));
|
|
584
|
+
registerToolSchema("find-mapping", findMappingSchema);
|
|
1813
585
|
server.tool("resolve-method-mapping-exact", "Resolve one method mapping exactly by owner+name+descriptor between namespaces and report resolved/not_found/ambiguous.", resolveMethodMappingExactShape, { readOnlyHint: true }, async (args) => runTool("resolve-method-mapping-exact", args, resolveMethodMappingExactSchema, async (input) => sourceService.resolveMethodMappingExact({
|
|
1814
586
|
version: input.version,
|
|
1815
587
|
name: input.name,
|
|
@@ -1820,6 +592,7 @@ server.tool("resolve-method-mapping-exact", "Resolve one method mapping exactly
|
|
|
1820
592
|
sourcePriority: input.sourcePriority,
|
|
1821
593
|
maxCandidates: input.maxCandidates
|
|
1822
594
|
})));
|
|
595
|
+
registerToolSchema("resolve-method-mapping-exact", resolveMethodMappingExactSchema);
|
|
1823
596
|
server.tool("get-class-api-matrix", "List class/member API rows across obfuscated/mojang/intermediary/yarn mappings for one class and Minecraft version.", getClassApiMatrixShape, { readOnlyHint: true }, async (args) => runTool("get-class-api-matrix", args, getClassApiMatrixSchema, async (input) => sourceService.getClassApiMatrix({
|
|
1824
597
|
version: input.version,
|
|
1825
598
|
className: input.className,
|
|
@@ -1828,6 +601,7 @@ server.tool("get-class-api-matrix", "List class/member API rows across obfuscate
|
|
|
1828
601
|
sourcePriority: input.sourcePriority,
|
|
1829
602
|
maxRows: input.maxRows
|
|
1830
603
|
})));
|
|
604
|
+
registerToolSchema("get-class-api-matrix", getClassApiMatrixSchema);
|
|
1831
605
|
server.tool("resolve-workspace-symbol", "Resolve class/field/method names as seen at compile time for a workspace by reading Gradle Loom mapping settings.", resolveWorkspaceSymbolShape, { readOnlyHint: true }, async (args) => runTool("resolve-workspace-symbol", args, resolveWorkspaceSymbolSchema, async (input) => sourceService.resolveWorkspaceSymbol({
|
|
1832
606
|
projectPath: input.projectPath,
|
|
1833
607
|
version: input.version,
|
|
@@ -1839,6 +613,7 @@ server.tool("resolve-workspace-symbol", "Resolve class/field/method names as see
|
|
|
1839
613
|
sourcePriority: input.sourcePriority,
|
|
1840
614
|
maxCandidates: input.maxCandidates
|
|
1841
615
|
})));
|
|
616
|
+
registerToolSchema("resolve-workspace-symbol", resolveWorkspaceSymbolSchema);
|
|
1842
617
|
server.tool("check-symbol-exists", "Check whether a class/field/method symbol exists in a specific mapping namespace for one Minecraft version.", checkSymbolExistsShape, { readOnlyHint: true }, async (args) => runTool("check-symbol-exists", args, checkSymbolExistsSchema, async (input) => sourceService.checkSymbolExists({
|
|
1843
618
|
version: input.version,
|
|
1844
619
|
kind: input.kind,
|
|
@@ -1851,24 +626,30 @@ server.tool("check-symbol-exists", "Check whether a class/field/method symbol ex
|
|
|
1851
626
|
signatureMode: input.signatureMode,
|
|
1852
627
|
maxCandidates: input.maxCandidates
|
|
1853
628
|
})));
|
|
629
|
+
registerToolSchema("check-symbol-exists", checkSymbolExistsSchema);
|
|
1854
630
|
server.tool("nbt-to-json", "Decode Java Edition NBT binary payload (base64) into typed JSON.", nbtToJsonShape, { readOnlyHint: true }, async (args) => runTool("nbt-to-json", args, nbtToJsonSchema, async (input) => Promise.resolve(nbtBase64ToTypedJson({
|
|
1855
631
|
nbtBase64: input.nbtBase64,
|
|
1856
632
|
compression: input.compression
|
|
1857
633
|
}, nbtLimits))));
|
|
634
|
+
registerToolSchema("nbt-to-json", nbtToJsonSchema);
|
|
1858
635
|
server.tool("nbt-apply-json-patch", "Apply RFC6902 add/remove/replace/test operations to typed NBT JSON.", nbtApplyJsonPatchShape, { readOnlyHint: true }, async (args) => runTool("nbt-apply-json-patch", args, nbtApplyJsonPatchSchema, async (input) => Promise.resolve(applyNbtJsonPatch({
|
|
1859
636
|
typedJson: input.typedJson,
|
|
1860
637
|
patch: input.patch
|
|
1861
638
|
}, nbtLimits))));
|
|
639
|
+
registerToolSchema("nbt-apply-json-patch", nbtApplyJsonPatchSchema);
|
|
1862
640
|
server.tool("json-to-nbt", "Encode typed NBT JSON to Java Edition NBT binary payload (base64).", jsonToNbtShape, { readOnlyHint: true }, async (args) => runTool("json-to-nbt", args, jsonToNbtSchema, async (input) => Promise.resolve(typedJsonToNbtBase64({
|
|
1863
641
|
typedJson: input.typedJson,
|
|
1864
642
|
compression: input.compression
|
|
1865
643
|
}, nbtLimits))));
|
|
644
|
+
registerToolSchema("json-to-nbt", jsonToNbtSchema);
|
|
1866
645
|
server.tool("index-artifact", "Rebuild indexed files/symbols metadata for an existing artifactId. Does not resolve new artifacts.", indexArtifactShape, async (args) => runTool("index-artifact", args, indexArtifactSchema, async (input) => sourceService.indexArtifact({
|
|
1867
646
|
artifactId: input.artifactId,
|
|
1868
647
|
force: input.force
|
|
1869
648
|
})));
|
|
649
|
+
registerToolSchema("index-artifact", indexArtifactSchema);
|
|
1870
650
|
server.tool("get-runtime-metrics", "Get runtime service counters and latency snapshots for cache/search/index diagnostics.", { readOnlyHint: true }, async (args) => runTool("get-runtime-metrics", args, emptySchema, async () => Promise.resolve(sourceService.getRuntimeMetrics())));
|
|
1871
|
-
|
|
651
|
+
registerToolSchema("get-runtime-metrics", emptySchema);
|
|
652
|
+
server.tool("validate-mixin", "Validate Mixin source against Minecraft bytecode signatures for a given version.", validateMixinShape, { readOnlyHint: true }, async (args, extra) => runTool("validate-mixin", args, validateMixinSchema, async (input) => sourceService.validateMixin({
|
|
1872
653
|
input: input.input,
|
|
1873
654
|
sourceRoots: input.sourceRoots,
|
|
1874
655
|
version: input.version,
|
|
@@ -1886,7 +667,10 @@ server.tool("validate-mixin", "Validate Mixin source against Minecraft bytecode
|
|
|
1886
667
|
warningCategoryFilter: input.warningCategoryFilter,
|
|
1887
668
|
treatInfoAsWarning: input.treatInfoAsWarning,
|
|
1888
669
|
includeIssues: input.includeIssues
|
|
670
|
+
}, {
|
|
671
|
+
stageEmitter: makeStageEmitter(extra)
|
|
1889
672
|
})));
|
|
673
|
+
registerToolSchema("validate-mixin", validateMixinSchema);
|
|
1890
674
|
server.tool("validate-access-widener", "Validate Access Widener file entries against Minecraft bytecode signatures for a given version.", validateAccessWidenerShape, { readOnlyHint: true }, async (args) => runTool("validate-access-widener", args, validateAccessWidenerSchema, async (input) => sourceService.validateAccessWidener({
|
|
1891
675
|
content: input.content,
|
|
1892
676
|
version: input.version,
|
|
@@ -1896,6 +680,7 @@ server.tool("validate-access-widener", "Validate Access Widener file entries aga
|
|
|
1896
680
|
scope: input.scope,
|
|
1897
681
|
preferProjectVersion: input.preferProjectVersion
|
|
1898
682
|
})));
|
|
683
|
+
registerToolSchema("validate-access-widener", validateAccessWidenerSchema);
|
|
1899
684
|
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({
|
|
1900
685
|
content: input.content,
|
|
1901
686
|
version: input.version,
|
|
@@ -1905,18 +690,21 @@ server.tool("validate-access-transformer", "Validate Access Transformer file ent
|
|
|
1905
690
|
scope: input.scope,
|
|
1906
691
|
preferProjectVersion: input.preferProjectVersion
|
|
1907
692
|
})));
|
|
693
|
+
registerToolSchema("validate-access-transformer", validateAccessTransformerSchema);
|
|
1908
694
|
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) => {
|
|
1909
695
|
const result = await analyzeModJar(input.jarPath, {
|
|
1910
696
|
includeClasses: input.includeClasses ?? false
|
|
1911
697
|
});
|
|
1912
698
|
return result;
|
|
1913
699
|
}));
|
|
700
|
+
registerToolSchema("analyze-mod-jar", analyzeModJarSchema);
|
|
1914
701
|
server.tool("get-registry-data", "Get Minecraft registry data (blocks, items, biomes, etc.) for a specific version by running the server data generator.", getRegistryDataShape, { readOnlyHint: true }, async (args) => runTool("get-registry-data", args, getRegistryDataSchema, async (input) => sourceService.getRegistryData({
|
|
1915
702
|
version: input.version,
|
|
1916
703
|
registry: input.registry,
|
|
1917
704
|
includeData: input.includeData,
|
|
1918
705
|
maxEntriesPerRegistry: input.maxEntriesPerRegistry
|
|
1919
706
|
})));
|
|
707
|
+
registerToolSchema("get-registry-data", getRegistryDataSchema);
|
|
1920
708
|
server.tool("compare-versions", "Compare two Minecraft versions to find added/removed classes and registry entry changes. Useful for understanding what changed between versions during mod migration.", compareVersionsShape, { readOnlyHint: true }, async (args) => runTool("compare-versions", args, compareVersionsSchema, async (input) => sourceService.compareVersions({
|
|
1921
709
|
fromVersion: input.fromVersion,
|
|
1922
710
|
toVersion: input.toVersion,
|
|
@@ -1924,12 +712,14 @@ server.tool("compare-versions", "Compare two Minecraft versions to find added/re
|
|
|
1924
712
|
packageFilter: input.packageFilter,
|
|
1925
713
|
maxClassResults: input.maxClassResults
|
|
1926
714
|
})));
|
|
715
|
+
registerToolSchema("compare-versions", compareVersionsSchema);
|
|
1927
716
|
server.tool("decompile-mod-jar", "Decompile a Minecraft mod JAR using Vineflower and list available classes, or view a specific class source. Builds on analyze-mod-jar by exposing the actual source code.", decompileModJarShape, { readOnlyHint: true }, async (args) => runTool("decompile-mod-jar", args, decompileModJarSchema, async (input) => sourceService.decompileModJar({
|
|
1928
717
|
jarPath: input.jarPath,
|
|
1929
718
|
className: input.className,
|
|
1930
719
|
includeFiles: input.includeFiles,
|
|
1931
720
|
maxFiles: input.maxFiles
|
|
1932
721
|
})));
|
|
722
|
+
registerToolSchema("decompile-mod-jar", decompileModJarSchema);
|
|
1933
723
|
server.tool("get-mod-class-source", "Get decompiled source code for a specific class in a mod JAR. The mod JAR will be decompiled if not already cached.", getModClassSourceShape, { readOnlyHint: true }, async (args) => runTool("get-mod-class-source", args, getModClassSourceSchema, async (input) => sourceService.getModClassSource({
|
|
1934
724
|
jarPath: input.jarPath,
|
|
1935
725
|
className: input.className,
|
|
@@ -1937,12 +727,14 @@ server.tool("get-mod-class-source", "Get decompiled source code for a specific c
|
|
|
1937
727
|
maxChars: input.maxChars,
|
|
1938
728
|
outputFile: input.outputFile
|
|
1939
729
|
})));
|
|
730
|
+
registerToolSchema("get-mod-class-source", getModClassSourceSchema);
|
|
1940
731
|
server.tool("search-mod-source", "Search through decompiled mod JAR source code by class name, method, field, or content pattern. The mod JAR will be decompiled automatically if not already cached.", searchModSourceShape, { readOnlyHint: true }, async (args) => runTool("search-mod-source", args, searchModSourceSchema, async (input) => sourceService.searchModSource({
|
|
1941
732
|
jarPath: input.jarPath,
|
|
1942
733
|
query: input.query,
|
|
1943
734
|
searchType: input.searchType,
|
|
1944
735
|
limit: input.limit
|
|
1945
736
|
})));
|
|
737
|
+
registerToolSchema("search-mod-source", searchModSourceSchema);
|
|
1946
738
|
server.tool("remap-mod-jar", "Remap a Fabric mod JAR from intermediary to yarn/mojang names. Requires Java to be installed.", remapModJarShape, { readOnlyHint: false }, async (args) => runTool("remap-mod-jar", args, remapModJarSchema, async (input) => {
|
|
1947
739
|
const result = await remapModJar({
|
|
1948
740
|
inputJar: input.inputJar,
|
|
@@ -1952,6 +744,7 @@ server.tool("remap-mod-jar", "Remap a Fabric mod JAR from intermediary to yarn/m
|
|
|
1952
744
|
}, config);
|
|
1953
745
|
return result;
|
|
1954
746
|
}));
|
|
747
|
+
registerToolSchema("remap-mod-jar", remapModJarSchema);
|
|
1955
748
|
export async function startServer() {
|
|
1956
749
|
if (serverStarted) {
|
|
1957
750
|
return;
|