@adhisang/minecraft-modding-mcp 6.2.0 → 7.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -0
- package/README.md +21 -5
- package/dist/cache-policy.d.ts +71 -0
- package/dist/cache-policy.js +83 -0
- package/dist/cache-registry.js +6 -6
- package/dist/cli.js +74 -3
- package/dist/compat-stdio-transport.d.ts +1 -1
- package/dist/compat-stdio-transport.js +13 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +8 -2
- package/dist/decompiler/vineflower.d.ts +1 -0
- package/dist/decompiler/vineflower.js +8 -5
- package/dist/entry-tools/analyze-mod-service.d.ts +70 -136
- package/dist/entry-tools/analyze-symbol-service.d.ts +112 -150
- package/dist/entry-tools/compare-minecraft-service.d.ts +59 -145
- package/dist/entry-tools/entry-tool-schema.d.ts +38 -4
- package/dist/entry-tools/entry-tool-schema.js +4 -1
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +235 -799
- package/dist/entry-tools/inspect-minecraft/internal.js +65 -28
- package/dist/entry-tools/inspect-minecraft-service.d.ts +372 -1736
- package/dist/entry-tools/inspect-minecraft-service.js +1 -1
- package/dist/entry-tools/manage-cache-service.d.ts +81 -91
- package/dist/entry-tools/validate-project/cases/project-summary.d.ts +7 -7
- package/dist/entry-tools/validate-project-service.d.ts +164 -592
- package/dist/entry-tools/verify-mixin-target-service.d.ts +3 -19
- package/dist/era-classifier.d.ts +161 -0
- package/dist/era-classifier.js +292 -0
- package/dist/error-mapping.js +9 -2
- package/dist/index.d.ts +42 -4
- package/dist/index.js +637 -475
- package/dist/java-process.d.ts +2 -0
- package/dist/java-process.js +22 -2
- package/dist/json-rpc-framing.d.ts +77 -1
- package/dist/json-rpc-framing.js +249 -13
- package/dist/mapping/loaders/tiny-loom-selection.d.ts +88 -0
- package/dist/mapping/loaders/tiny-loom-selection.js +223 -0
- package/dist/mapping/loaders/tiny-loom.js +45 -33
- package/dist/mapping/loaders/tiny-maven.js +6 -11
- package/dist/mapping/parsers/tiny.d.ts +57 -0
- package/dist/mapping/parsers/tiny.js +99 -22
- package/dist/mapping-service.d.ts +19 -0
- package/dist/mapping-service.js +93 -9
- package/dist/mcp-helpers.d.ts +19 -2
- package/dist/mcp-helpers.js +48 -6
- package/dist/minecraft-explorer-service.d.ts +1 -1
- package/dist/mixin/types.d.ts +8 -0
- package/dist/mod-analyzer.js +7 -7
- package/dist/mod-decompile-service.js +1 -0
- package/dist/nbt/java-nbt-codec.js +12 -2
- package/dist/nbt/json-patch.js +14 -3
- package/dist/nbt/pipeline.js +40 -3
- package/dist/nbt/typed-json.js +26 -1
- package/dist/registration-adapter.d.ts +32 -0
- package/dist/registration-adapter.js +52 -0
- package/dist/request-context.d.ts +7 -0
- package/dist/request-context.js +9 -0
- package/dist/resources.d.ts +1 -1
- package/dist/resources.js +25 -19
- package/dist/server-identity.d.ts +27 -0
- package/dist/server-identity.js +26 -0
- package/dist/source/access-validate.js +53 -0
- package/dist/source/artifact-resolver.d.ts +69 -1
- package/dist/source/artifact-resolver.js +215 -14
- package/dist/source/class-source.d.ts +22 -0
- package/dist/source/class-source.js +162 -29
- package/dist/source/did-you-mean.d.ts +12 -1
- package/dist/source/did-you-mean.js +6 -2
- package/dist/source/file-access.js +150 -46
- package/dist/source/indexer.js +1 -0
- package/dist/source/nested-jars.d.ts +19 -0
- package/dist/source/nested-jars.js +90 -21
- package/dist/source/shared-utils.d.ts +21 -0
- package/dist/source/shared-utils.js +23 -0
- package/dist/source-service.d.ts +12 -0
- package/dist/source-service.js +3 -0
- package/dist/stdio-supervisor.d.ts +357 -2
- package/dist/stdio-supervisor.js +1031 -80
- package/dist/storage/db.d.ts +2 -1
- package/dist/storage/db.js +15 -8
- package/dist/synthetic-decorator.d.ts +24 -0
- package/dist/synthetic-decorator.js +48 -0
- package/dist/tool-contract-manifest.js +1 -1
- package/dist/tool-guidance.d.ts +17 -1
- package/dist/tool-guidance.js +417 -13
- package/dist/tool-schema-registry.d.ts +2 -0
- package/dist/tool-schema-registry.js +4 -0
- package/dist/tool-schemas.d.ts +2214 -3915
- package/dist/tool-schemas.js +34 -7
- package/dist/types.d.ts +35 -0
- package/dist/v1-parity-schemas.d.ts +7 -0
- package/dist/v1-parity-schemas.js +5584 -0
- package/dist/version-diff-service.d.ts +33 -0
- package/dist/version-diff-service.js +148 -3
- package/dist/version-service.js +36 -14
- package/dist/warning-details.js +18 -1
- package/docs/README-ja.md +9 -3
- package/docs/tool-reference.md +267 -22
- package/package.json +12 -9
package/dist/resources.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ResourceTemplate } from "@modelcontextprotocol/
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/server";
|
|
2
|
+
import { METRICS_READ_CACHE_HINT, RESOURCE_READ_CACHE_HINT, VERSIONS_LIST_READ_CACHE_HINT } from "./cache-policy.js";
|
|
2
3
|
import { createError, ERROR_CODES, isAppError } from "./errors.js";
|
|
3
4
|
import { textResource, objectResource, errorResource } from "./mcp-helpers.js";
|
|
4
5
|
function decodeTemplateParam(params, key) {
|
|
@@ -21,32 +22,37 @@ function decodeTemplateParam(params, key) {
|
|
|
21
22
|
});
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
// Cache-hint rows (adopted policy, src/cache-policy.ts): per-registration
|
|
26
|
+
// hints ride the SDK's never-serialized carrier and only surface on
|
|
27
|
+
// 2026-07-28 results. The errorResource(...) calls also receive the request
|
|
28
|
+
// ctx so the ProblemDetails-read override (ttlMs 0, unconditional precedence
|
|
29
|
+
// over these class rows) can be applied structurally on the error path.
|
|
24
30
|
export function registerResources(server, sourceService) {
|
|
25
31
|
// ── Fixed resources ──────────────────────────────────────────────
|
|
26
|
-
server.
|
|
32
|
+
server.registerResource("versions-list", "mc://versions/list", { description: "List all available Minecraft versions with their metadata.", mimeType: "application/json", cacheHint: VERSIONS_LIST_READ_CACHE_HINT }, async (uri, ctx) => {
|
|
27
33
|
try {
|
|
28
34
|
const result = await sourceService.listVersions();
|
|
29
35
|
return objectResource(uri.href, result);
|
|
30
36
|
}
|
|
31
37
|
catch (e) {
|
|
32
38
|
if (isAppError(e))
|
|
33
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
39
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
34
40
|
throw e;
|
|
35
41
|
}
|
|
36
42
|
});
|
|
37
|
-
server.
|
|
43
|
+
server.registerResource("runtime-metrics", "mc://metrics", { description: "Runtime metrics and performance counters for the MCP server.", mimeType: "application/json", cacheHint: METRICS_READ_CACHE_HINT }, async (uri, ctx) => {
|
|
38
44
|
try {
|
|
39
45
|
const result = sourceService.getRuntimeMetrics();
|
|
40
46
|
return objectResource(uri.href, result);
|
|
41
47
|
}
|
|
42
48
|
catch (e) {
|
|
43
49
|
if (isAppError(e))
|
|
44
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
50
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
45
51
|
throw e;
|
|
46
52
|
}
|
|
47
53
|
});
|
|
48
54
|
// ── Template resources ───────────────────────────────────────────
|
|
49
|
-
server.
|
|
55
|
+
server.registerResource("class-source", new ResourceTemplate("mc://source/{artifactId}/{className}", { list: undefined }), { description: "Java source code for a class within a resolved artifact. className may use dot or slash separators.", mimeType: "text/x-java", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
50
56
|
try {
|
|
51
57
|
const result = await sourceService.getClassSource({
|
|
52
58
|
artifactId: params.artifactId,
|
|
@@ -59,11 +65,11 @@ export function registerResources(server, sourceService) {
|
|
|
59
65
|
}
|
|
60
66
|
catch (e) {
|
|
61
67
|
if (isAppError(e))
|
|
62
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
68
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
63
69
|
throw e;
|
|
64
70
|
}
|
|
65
71
|
});
|
|
66
|
-
server.
|
|
72
|
+
server.registerResource("class-source-json", new ResourceTemplate("mc://source-json/{artifactId}/{className}", { list: undefined }), { description: "JSON envelope of a class's full source plus metadata (artifactId, mappingApplied, totalLines, returnedRange, provenance, warnings) — the structured alternative to the raw-text class-source resource, easier to cite and continue.", mimeType: "application/json", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
67
73
|
try {
|
|
68
74
|
const result = await sourceService.getClassSource({
|
|
69
75
|
artifactId: params.artifactId,
|
|
@@ -74,11 +80,11 @@ export function registerResources(server, sourceService) {
|
|
|
74
80
|
}
|
|
75
81
|
catch (e) {
|
|
76
82
|
if (isAppError(e))
|
|
77
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
83
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
78
84
|
throw e;
|
|
79
85
|
}
|
|
80
86
|
});
|
|
81
|
-
server.
|
|
87
|
+
server.registerResource("artifact-file", new ResourceTemplate("mc://artifact/{artifactId}/files/{filePath}", { list: undefined }), { description: "Raw content of a file within a resolved artifact. filePath is the archive-relative path.", mimeType: "text/plain", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
82
88
|
try {
|
|
83
89
|
const result = await sourceService.getArtifactFile({
|
|
84
90
|
artifactId: params.artifactId,
|
|
@@ -88,11 +94,11 @@ export function registerResources(server, sourceService) {
|
|
|
88
94
|
}
|
|
89
95
|
catch (e) {
|
|
90
96
|
if (isAppError(e))
|
|
91
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
97
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
92
98
|
throw e;
|
|
93
99
|
}
|
|
94
100
|
});
|
|
95
|
-
server.
|
|
101
|
+
server.registerResource("find-mapping", new ResourceTemplate("mc://mappings/{version}/{sourceMapping}/{targetMapping}/{kind}/{name}", { list: undefined }), { description: "Look up a CLASS mapping between two naming namespaces. This URI carries no owner, so field/method lookups (which need an owner) must use the find-member-mapping resource or the find-mapping tool.", mimeType: "application/json", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
96
102
|
try {
|
|
97
103
|
const result = await sourceService.findMapping({
|
|
98
104
|
version: params.version,
|
|
@@ -105,11 +111,11 @@ export function registerResources(server, sourceService) {
|
|
|
105
111
|
}
|
|
106
112
|
catch (e) {
|
|
107
113
|
if (isAppError(e))
|
|
108
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
114
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
109
115
|
throw e;
|
|
110
116
|
}
|
|
111
117
|
});
|
|
112
|
-
server.
|
|
118
|
+
server.registerResource("find-member-mapping", new ResourceTemplate("mc://mappings/{version}/{sourceMapping}/{targetMapping}/{kind}/{owner}/{name}", { list: undefined }), { description: "Look up a FIELD or METHOD mapping between two naming namespaces, including the owner class the member belongs to (required for member lookups). For exact method overload resolution, use the find-mapping tool with a descriptor.", mimeType: "application/json", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
113
119
|
try {
|
|
114
120
|
const result = await sourceService.findMapping({
|
|
115
121
|
version: params.version,
|
|
@@ -123,11 +129,11 @@ export function registerResources(server, sourceService) {
|
|
|
123
129
|
}
|
|
124
130
|
catch (e) {
|
|
125
131
|
if (isAppError(e))
|
|
126
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
132
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
127
133
|
throw e;
|
|
128
134
|
}
|
|
129
135
|
});
|
|
130
|
-
server.
|
|
136
|
+
server.registerResource("class-members", new ResourceTemplate("mc://artifact/{artifactId}/members/{className}", { list: undefined }), { description: "List constructors, methods, and fields for a class within a resolved artifact.", mimeType: "application/json", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
131
137
|
try {
|
|
132
138
|
const result = await sourceService.getClassMembers({
|
|
133
139
|
artifactId: params.artifactId,
|
|
@@ -137,18 +143,18 @@ export function registerResources(server, sourceService) {
|
|
|
137
143
|
}
|
|
138
144
|
catch (e) {
|
|
139
145
|
if (isAppError(e))
|
|
140
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
146
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
141
147
|
throw e;
|
|
142
148
|
}
|
|
143
149
|
});
|
|
144
|
-
server.
|
|
150
|
+
server.registerResource("artifact-metadata", new ResourceTemplate("mc://artifact/{artifactId}", { list: undefined }), { description: "Metadata for a previously resolved artifact (origin, coordinate, mapping, provenance).", mimeType: "application/json", cacheHint: RESOURCE_READ_CACHE_HINT }, async (uri, params, ctx) => {
|
|
145
151
|
try {
|
|
146
152
|
const artifact = sourceService.getArtifact(params.artifactId);
|
|
147
153
|
return objectResource(uri.href, artifact);
|
|
148
154
|
}
|
|
149
155
|
catch (e) {
|
|
150
156
|
if (isAppError(e))
|
|
151
|
-
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
157
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details }, ctx);
|
|
152
158
|
throw e;
|
|
153
159
|
}
|
|
154
160
|
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical server identity — the single source of the {name, version}
|
|
3
|
+
* Implementation this process advertises.
|
|
4
|
+
*
|
|
5
|
+
* Consumers:
|
|
6
|
+
* - src/index.ts constructs the McpServer from these values; the SDK stamps
|
|
7
|
+
* that Implementation verbatim as `_meta["io.modelcontextprotocol/serverInfo"]`
|
|
8
|
+
* on every modern result it produces (and it is the initialize/discover
|
|
9
|
+
* serverInfo).
|
|
10
|
+
* - src/synthetic-decorator.ts stamps the same identity onto modern-era
|
|
11
|
+
* supervisor-synthesized results.
|
|
12
|
+
*
|
|
13
|
+
* Equality between live SDK results and synthetic decoration is therefore by
|
|
14
|
+
* construction; the live-SDK drift-guard test
|
|
15
|
+
* (tests/stdio/stdio-supervisor-synthetic-drift.test.ts) proves it end-to-end.
|
|
16
|
+
*/
|
|
17
|
+
export type ServerIdentity = {
|
|
18
|
+
name: string;
|
|
19
|
+
version: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const SERVER_NAME = "@adhisang/minecraft-modding-mcp";
|
|
22
|
+
export declare function getServerVersionFromPackageJson(): string;
|
|
23
|
+
export declare const SERVER_VERSION: string;
|
|
24
|
+
/** Frozen canonical identity; consumers needing a mutable object must copy. */
|
|
25
|
+
export declare const SERVER_IDENTITY: Readonly<ServerIdentity>;
|
|
26
|
+
/** Fresh, mutation-safe copy of the canonical identity. */
|
|
27
|
+
export declare function serverIdentitySnapshot(): ServerIdentity;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
export const SERVER_NAME = "@adhisang/minecraft-modding-mcp";
|
|
3
|
+
export function getServerVersionFromPackageJson() {
|
|
4
|
+
try {
|
|
5
|
+
const packageJsonUrl = new URL("../package.json", import.meta.url);
|
|
6
|
+
const packageJson = JSON.parse(readFileSync(packageJsonUrl, "utf8"));
|
|
7
|
+
if (typeof packageJson.version === "string" && packageJson.version.trim()) {
|
|
8
|
+
return packageJson.version.trim();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// ignore and fallback
|
|
13
|
+
}
|
|
14
|
+
return "0.3.0";
|
|
15
|
+
}
|
|
16
|
+
export const SERVER_VERSION = getServerVersionFromPackageJson();
|
|
17
|
+
/** Frozen canonical identity; consumers needing a mutable object must copy. */
|
|
18
|
+
export const SERVER_IDENTITY = Object.freeze({
|
|
19
|
+
name: SERVER_NAME,
|
|
20
|
+
version: SERVER_VERSION
|
|
21
|
+
});
|
|
22
|
+
/** Fresh, mutation-safe copy of the canonical identity. */
|
|
23
|
+
export function serverIdentitySnapshot() {
|
|
24
|
+
return { name: SERVER_IDENTITY.name, version: SERVER_IDENTITY.version };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=server-identity.js.map
|
|
@@ -30,6 +30,47 @@ function isSourceMappingNamespace(namespace) {
|
|
|
30
30
|
namespace === "intermediary" ||
|
|
31
31
|
namespace === "yarn");
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Refuses a verdict that would be computed against another loader's bytecode,
|
|
35
|
+
* and marks a cross-version one as approximate.
|
|
36
|
+
*
|
|
37
|
+
* A runtime fallback could serve a NeoForge 1.21.10 AT-patched jar to a Fabric
|
|
38
|
+
* 1.21.11 workspace; validation then reported `valid: true` with a
|
|
39
|
+
* `resolvedRuntimeJavaSignature` taken from bytecode the project never runs.
|
|
40
|
+
* A different loader's access flags are simply not evidence about this one, so
|
|
41
|
+
* that case fails loudly. A same-loader version drift still yields a verdict —
|
|
42
|
+
* flagged, never silent.
|
|
43
|
+
*/
|
|
44
|
+
function guardRuntimeEvidence(provenance, warnings, subject) {
|
|
45
|
+
if (!provenance) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
if (provenance.loaderMismatch) {
|
|
49
|
+
throw createError({
|
|
50
|
+
code: ERROR_CODES.CONTEXT_UNRESOLVED,
|
|
51
|
+
message: `${subject} validation resolved a ${provenance.servedLoader} runtime jar for a ` +
|
|
52
|
+
`${provenance.expectedLoader} workspace; a different loader's bytecode cannot certify these entries.`,
|
|
53
|
+
details: {
|
|
54
|
+
jarPath: provenance.jarPath,
|
|
55
|
+
servedLoader: provenance.servedLoader,
|
|
56
|
+
expectedLoader: provenance.expectedLoader,
|
|
57
|
+
version: provenance.version,
|
|
58
|
+
...(provenance.requestedVersion ? { requestedVersion: provenance.requestedVersion } : {}),
|
|
59
|
+
requestedScope: provenance.requestedScope,
|
|
60
|
+
appliedScope: provenance.appliedScope,
|
|
61
|
+
nextAction: `Point gradleUserHome at the Gradle home holding this workspace's own ${provenance.expectedLoader} runtime jars, ` +
|
|
62
|
+
"or run the Gradle task that generates them. Omitting projectPath validates against the vanilla jar instead of another loader's."
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (!provenance.versionApproximated) {
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
const reason = `Runtime evidence comes from Minecraft ${provenance.version}, not the requested ` +
|
|
70
|
+
`${provenance.requestedVersion}; entries were checked against a different version's bytecode.`;
|
|
71
|
+
warnings.push(reason);
|
|
72
|
+
return { approximate: true, approximationReasons: [reason] };
|
|
73
|
+
}
|
|
33
74
|
export async function validateAccessWidener(svc, input) {
|
|
34
75
|
const version = input.version.trim();
|
|
35
76
|
if (!version) {
|
|
@@ -61,6 +102,7 @@ export async function validateAccessWidener(svc, input) {
|
|
|
61
102
|
let jarPath;
|
|
62
103
|
let lookupMapping = "obfuscated";
|
|
63
104
|
let provenance;
|
|
105
|
+
let approximation = {};
|
|
64
106
|
if (runtimeAware) {
|
|
65
107
|
provenance = await svc.resolveAccessWidenerRuntimeArtifact({
|
|
66
108
|
version,
|
|
@@ -70,6 +112,7 @@ export async function validateAccessWidener(svc, input) {
|
|
|
70
112
|
scope: input.scope,
|
|
71
113
|
preferProjectVersion: input.preferProjectVersion
|
|
72
114
|
});
|
|
115
|
+
approximation = guardRuntimeEvidence(provenance, warnings, "Access Widener");
|
|
73
116
|
resolvedVersion = provenance.version;
|
|
74
117
|
jarPath = provenance.jarPath;
|
|
75
118
|
lookupMapping = provenance.mappingApplied;
|
|
@@ -148,6 +191,10 @@ export async function validateAccessWidener(svc, input) {
|
|
|
148
191
|
if (provenance) {
|
|
149
192
|
result.provenance = provenance;
|
|
150
193
|
}
|
|
194
|
+
if (approximation.approximate) {
|
|
195
|
+
result.approximate = true;
|
|
196
|
+
result.approximationReasons = approximation.approximationReasons;
|
|
197
|
+
}
|
|
151
198
|
return result;
|
|
152
199
|
}
|
|
153
200
|
export async function validateAccessTransformer(svc, input) {
|
|
@@ -170,6 +217,7 @@ export async function validateAccessTransformer(svc, input) {
|
|
|
170
217
|
let jarPath;
|
|
171
218
|
let lookupMapping = "obfuscated";
|
|
172
219
|
let provenance;
|
|
220
|
+
let approximation = {};
|
|
173
221
|
if (runtimeAware) {
|
|
174
222
|
provenance = await svc.resolveAccessTransformerRuntimeArtifact({
|
|
175
223
|
version,
|
|
@@ -179,6 +227,7 @@ export async function validateAccessTransformer(svc, input) {
|
|
|
179
227
|
scope: input.scope,
|
|
180
228
|
preferProjectVersion: input.preferProjectVersion
|
|
181
229
|
});
|
|
230
|
+
approximation = guardRuntimeEvidence(provenance, warnings, "Access Transformer");
|
|
182
231
|
resolvedVersion = provenance.version;
|
|
183
232
|
jarPath = provenance.jarPath;
|
|
184
233
|
lookupMapping = provenance.mappingApplied;
|
|
@@ -263,6 +312,10 @@ export async function validateAccessTransformer(svc, input) {
|
|
|
263
312
|
if (provenance) {
|
|
264
313
|
result.provenance = provenance;
|
|
265
314
|
}
|
|
315
|
+
if (approximation.approximate) {
|
|
316
|
+
result.approximate = true;
|
|
317
|
+
result.approximationReasons = approximation.approximationReasons;
|
|
318
|
+
}
|
|
266
319
|
return result;
|
|
267
320
|
}
|
|
268
321
|
//# sourceMappingURL=access-validate.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SourceService } from "../source-service.js";
|
|
2
2
|
import type { ArtifactContentsSummary, ProbeMinecraftArtifactInput, ProbeMinecraftArtifactOutput, ResolveArtifactInput, ResolveArtifactOutput } from "../source-service.js";
|
|
3
|
-
import type { AccessTransformerNamespace, ArtifactProvenance, ArtifactScope, ArtifactTargetKind, ResolvedSourceArtifact, RuntimeValidationProvenance, SourceMapping } from "../types.js";
|
|
3
|
+
import type { AccessTransformerNamespace, ArtifactProvenance, ArtifactScope, ArtifactTargetKind, ResolvedSourceArtifact, RuntimeLoader, RuntimeValidationProvenance, SourceMapping } from "../types.js";
|
|
4
4
|
import type { WorkspaceProjectLoader } from "../workspace-mapping-service.js";
|
|
5
5
|
export type VersionSourceDiscovery = {
|
|
6
6
|
searchedPaths: string[];
|
|
@@ -16,7 +16,19 @@ type RuntimeJarCandidate = {
|
|
|
16
16
|
appliedScope: ArtifactScope;
|
|
17
17
|
origin: RuntimeValidationProvenance["origin"];
|
|
18
18
|
namespaceHint?: "intermediary" | "mojang" | "named";
|
|
19
|
+
/** How the candidate was tied to the requested Minecraft version. */
|
|
20
|
+
versionEvidence?: RuntimeVersionEvidence;
|
|
19
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Why a runtime jar is believed to belong to the requested Minecraft version.
|
|
24
|
+
*
|
|
25
|
+
* - `exact-token`: the Minecraft version appears verbatim in the path.
|
|
26
|
+
* - `loader-token`: the path carries the loader version that maps 1:1 onto the
|
|
27
|
+
* Minecraft version (NeoForge `21.11.x` <-> Minecraft `1.21.11`).
|
|
28
|
+
* - `project-anchored`: the jar sits inside the caller's own project build
|
|
29
|
+
* directory and the project declares exactly the requested Minecraft version.
|
|
30
|
+
*/
|
|
31
|
+
export type RuntimeVersionEvidence = "exact-token" | "loader-token" | "project-anchored";
|
|
20
32
|
export type MappingFallbackSuggestion = {
|
|
21
33
|
suggestedCall?: {
|
|
22
34
|
tool: string;
|
|
@@ -31,6 +43,58 @@ export type MappingFallbackSuggestion = {
|
|
|
31
43
|
_suggestedCallPrimaryDropped?: boolean;
|
|
32
44
|
};
|
|
33
45
|
export declare function hasExactVersionToken(path: string, version: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* True when a path carries the NeoForge/Forge loader version that corresponds
|
|
48
|
+
* 1:1 to `mcVersion`.
|
|
49
|
+
*
|
|
50
|
+
* ModDevGradle names every artifact after the LOADER version and never after
|
|
51
|
+
* Minecraft: MC 1.21.11 produces `build/moddev/artifacts/neoforge-21.11.38-beta-merged.jar`.
|
|
52
|
+
* A plain `hasExactVersionToken(path, "1.21.11")` therefore rejected every
|
|
53
|
+
* artifact of the canonical NeoForge workspace, which made
|
|
54
|
+
* validate-access-transformer unusable there.
|
|
55
|
+
*
|
|
56
|
+
* NeoForge derives its version from Minecraft as `<minor>.<patch>.<build>`, so
|
|
57
|
+
* `1.21.11` -> `21.11.<build>` and `1.21` -> `21.0.<build>`. The trailing dot
|
|
58
|
+
* before the build number keeps `21.1.` from matching `21.10.5`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function hasLoaderRuntimeVersionToken(path: string, mcVersion: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Minecraft version a runtime jar path carries, or undefined when the path
|
|
63
|
+
* names none. Loom lays its cache out as
|
|
64
|
+
* `<gradle>/caches/fabric-loom/<mcVersion>/...`, so the first `1.x[.y]` token
|
|
65
|
+
* of the path is the version the jar was built for.
|
|
66
|
+
*/
|
|
67
|
+
export declare function inferRuntimeJarMinecraftVersion(path: string): string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Loader a runtime jar belongs to, read from its path.
|
|
70
|
+
*
|
|
71
|
+
* A Loom cache holds NeoForge-patched jars under a `/neoforge/` segment
|
|
72
|
+
* (`caches/fabric-loom/1.21.10/neoforge/21.10.50-beta/minecraft-merged-mojang-at-patched.jar`).
|
|
73
|
+
* Serving one of those to a Fabric workspace silently validated a Fabric access
|
|
74
|
+
* widener against NeoForge bytecode, so the loader has to travel with the jar.
|
|
75
|
+
*/
|
|
76
|
+
export declare function inferRuntimeJarLoader(path: string): RuntimeLoader;
|
|
77
|
+
/**
|
|
78
|
+
* Fills in the truthful version/loader half of a runtime provenance record.
|
|
79
|
+
*
|
|
80
|
+
* `version` becomes the version the SERVED jar carries; the caller's original
|
|
81
|
+
* request is preserved under `requestedVersion` and flagged. A served loader
|
|
82
|
+
* that contradicts a KNOWN expected loader is flagged too — never silently
|
|
83
|
+
* dropped.
|
|
84
|
+
*/
|
|
85
|
+
export declare function describeServedRuntimeJar(input: {
|
|
86
|
+
jarPath: string;
|
|
87
|
+
requestedVersion: string;
|
|
88
|
+
expectedLoader?: RuntimeLoader;
|
|
89
|
+
}): {
|
|
90
|
+
version: string;
|
|
91
|
+
requestedVersion?: string;
|
|
92
|
+
versionApproximated?: boolean;
|
|
93
|
+
servedLoader: RuntimeLoader;
|
|
94
|
+
expectedLoader?: RuntimeLoader;
|
|
95
|
+
loaderMismatch?: boolean;
|
|
96
|
+
notes: string[];
|
|
97
|
+
};
|
|
34
98
|
export declare function discoverVersionSourceJar(_svc: SourceService, input: {
|
|
35
99
|
version: string;
|
|
36
100
|
projectPath?: string;
|
|
@@ -54,6 +118,8 @@ export declare function discoverAccessTransformerRuntimeCandidates(_svc: SourceS
|
|
|
54
118
|
requestedScope: ArtifactScope;
|
|
55
119
|
atNamespace: AccessTransformerNamespace;
|
|
56
120
|
loader: WorkspaceProjectLoader | "unknown";
|
|
121
|
+
/** Minecraft version the workspace itself declares, when it could be read. */
|
|
122
|
+
projectMinecraftVersion?: string;
|
|
57
123
|
}): Promise<{
|
|
58
124
|
searchedPaths: string[];
|
|
59
125
|
candidateArtifacts: string[];
|
|
@@ -100,6 +166,8 @@ export declare function resolveBinaryFallbackArtifact(svc: SourceService, input:
|
|
|
100
166
|
mappingApplied: SourceMapping;
|
|
101
167
|
provenance?: ArtifactProvenance;
|
|
102
168
|
qualityFlags: string[];
|
|
169
|
+
/** Forwarded from the caller; unset keeps the historical decompile-on-demand behaviour. */
|
|
170
|
+
allowDecompile?: boolean;
|
|
103
171
|
}): Promise<ResolvedSourceArtifact | undefined>;
|
|
104
172
|
export declare function buildArtifactContentsSummary(_svc: SourceService, input: {
|
|
105
173
|
origin: ResolvedSourceArtifact["origin"];
|