@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
|
@@ -4,6 +4,7 @@ import { dirname, join } from "node:path";
|
|
|
4
4
|
import { buildSuggestedCall } from "../build-suggested-call.js";
|
|
5
5
|
import { ERROR_CODES, createError } from "../errors.js";
|
|
6
6
|
import { collectNestedJars } from "../mod-analyzer.js";
|
|
7
|
+
import { isSecureJarEntryPath } from "../path-resolver.js";
|
|
7
8
|
import { listJarEntries, readJarEntryAsBuffer, readJarEntryAsUtf8 } from "../source-jar-reader.js";
|
|
8
9
|
/**
|
|
9
10
|
* A jar with at most this many own `.class` entries can qualify as a
|
|
@@ -29,6 +30,84 @@ function rememberClassSet(key, value) {
|
|
|
29
30
|
classSetCache.delete(oldest);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
33
|
+
async function loadNestedJarClassSet(args) {
|
|
34
|
+
let extractedPath;
|
|
35
|
+
try {
|
|
36
|
+
extractedPath = await extractNestedJar(args.cacheDir, args.outerJarPath, args.outerSignature, args.entryName);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
let classSet = classSetCache.get(extractedPath);
|
|
42
|
+
if (!classSet) {
|
|
43
|
+
try {
|
|
44
|
+
const entries = await listJarEntries(extractedPath);
|
|
45
|
+
classSet = new Set(entries.filter((entry) => entry.endsWith(".class") && isSecureJarEntryPath(entry)));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
rememberClassSet(extractedPath, classSet);
|
|
51
|
+
}
|
|
52
|
+
return { extractedPath, classSet };
|
|
53
|
+
}
|
|
54
|
+
function nestedClassMatch(entry) {
|
|
55
|
+
const internalName = entry.slice(0, -".class".length);
|
|
56
|
+
if (internalName.startsWith("META-INF/versions/")) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const binarySimpleName = internalName.split("/").at(-1) ?? internalName;
|
|
60
|
+
if (binarySimpleName === "module-info" || binarySimpleName === "package-info") {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const innerSegments = binarySimpleName.split("$").slice(1);
|
|
64
|
+
if (innerSegments.some((segment) => segment.length === 0 || /^\d/.test(segment))) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
qualifiedName: internalName.replaceAll("/", ".").replaceAll("$", "."),
|
|
69
|
+
filePath: `${internalName.split("$")[0]}.java`,
|
|
70
|
+
line: 1,
|
|
71
|
+
symbolKind: "class"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Finds exact class-name matches across a shell's nested bytecode inventory.
|
|
76
|
+
* Results use the same binary-backed class representation as entry-tool search:
|
|
77
|
+
* an inferred outer Java path, line 1, and the broad class symbol kind.
|
|
78
|
+
*/
|
|
79
|
+
export async function findNestedJarClasses(args) {
|
|
80
|
+
const normalizedQuery = args.className.trim().replaceAll("/", ".").replaceAll("$", ".");
|
|
81
|
+
const isQualified = normalizedQuery.includes(".");
|
|
82
|
+
const matches = new Map();
|
|
83
|
+
inventory: for (const entryName of args.inventory) {
|
|
84
|
+
const loaded = await loadNestedJarClassSet({
|
|
85
|
+
cacheDir: args.cacheDir,
|
|
86
|
+
outerJarPath: args.outerJarPath,
|
|
87
|
+
outerSignature: args.outerSignature,
|
|
88
|
+
entryName
|
|
89
|
+
});
|
|
90
|
+
if (!loaded) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
for (const classEntry of [...loaded.classSet].sort((left, right) => left.localeCompare(right))) {
|
|
94
|
+
const match = nestedClassMatch(classEntry);
|
|
95
|
+
if (!match) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const simpleName = match.qualifiedName.split(".").at(-1) ?? match.qualifiedName;
|
|
99
|
+
if ((isQualified && match.qualifiedName !== normalizedQuery) ||
|
|
100
|
+
(!isQualified && simpleName !== normalizedQuery)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
matches.set(match.qualifiedName, match);
|
|
104
|
+
if (isQualified || matches.size >= args.limit) {
|
|
105
|
+
break inventory;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return [...matches.values()];
|
|
110
|
+
}
|
|
32
111
|
/**
|
|
33
112
|
* Shell detection with both required signals: near-zero own classes AND
|
|
34
113
|
* bundled nested jars (META-INF/jars scan or fabric.mod.json "jars"
|
|
@@ -128,29 +207,19 @@ export async function extractNestedJar(cacheDir, outerJarPath, outerSignature, e
|
|
|
128
207
|
*/
|
|
129
208
|
export async function findNestedJarsContainingClass(args) {
|
|
130
209
|
const classEntry = `${args.internalName}.class`;
|
|
210
|
+
const qualifiedName = args.internalName.replaceAll("/", ".").replaceAll("$", ".");
|
|
131
211
|
const matches = [];
|
|
132
212
|
for (const entryName of args.inventory) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
const entries = await listJarEntries(extractedPath);
|
|
145
|
-
classSet = new Set(entries.filter((entry) => entry.endsWith(".class")));
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
rememberClassSet(extractedPath, classSet);
|
|
151
|
-
}
|
|
152
|
-
if (classSet.has(classEntry)) {
|
|
153
|
-
matches.push({ entryName, extractedPath });
|
|
213
|
+
const loaded = await loadNestedJarClassSet({
|
|
214
|
+
cacheDir: args.cacheDir,
|
|
215
|
+
outerJarPath: args.outerJarPath,
|
|
216
|
+
outerSignature: args.outerSignature,
|
|
217
|
+
entryName
|
|
218
|
+
});
|
|
219
|
+
const containsClass = loaded?.classSet.has(classEntry) || [...(loaded?.classSet ?? [])].some((entry) => entry.endsWith(".class") &&
|
|
220
|
+
entry.slice(0, -".class".length).replaceAll("/", ".").replaceAll("$", ".") === qualifiedName);
|
|
221
|
+
if (loaded && containsClass) {
|
|
222
|
+
matches.push({ entryName, extractedPath: loaded.extractedPath });
|
|
154
223
|
}
|
|
155
224
|
}
|
|
156
225
|
return matches;
|
|
@@ -2,5 +2,26 @@ import type { SourceMapping } from "../types.js";
|
|
|
2
2
|
export declare function normalizePathStyle(path: string): string;
|
|
3
3
|
export declare function normalizeOptionalString(value: string | undefined): string | undefined;
|
|
4
4
|
export declare function normalizeMapping(mapping: SourceMapping | undefined): SourceMapping;
|
|
5
|
+
/**
|
|
6
|
+
* The mapping an artifact-targeted call runs in when the caller left `mapping`
|
|
7
|
+
* out.
|
|
8
|
+
*
|
|
9
|
+
* A stored artifact already carries the namespace it was resolved into, so a
|
|
10
|
+
* follow-up call that names it by `artifactId` must inherit that namespace
|
|
11
|
+
* instead of falling back to the version-target default ("obfuscated").
|
|
12
|
+
* Without this, `find-class` -> `get-class-source` -> `get-class-members`
|
|
13
|
+
* split across two namespaces: source came back in mojang names while members
|
|
14
|
+
* came back obfuscated (`ownerFqn: "dlp"`), for the same artifact and the same
|
|
15
|
+
* absent `mapping` argument.
|
|
16
|
+
*
|
|
17
|
+
* `requestedMapping` wins over `mappingApplied` so the echoed request keeps
|
|
18
|
+
* meaning "what was asked for" even on artifacts where the mapping could not
|
|
19
|
+
* be applied; `mappingApplied` is the fallback for rows stored before the
|
|
20
|
+
* requested namespace was persisted.
|
|
21
|
+
*/
|
|
22
|
+
export declare function inheritArtifactMapping(inputMapping: SourceMapping | undefined, artifact: {
|
|
23
|
+
requestedMapping?: SourceMapping;
|
|
24
|
+
mappingApplied?: SourceMapping;
|
|
25
|
+
}): SourceMapping;
|
|
5
26
|
export declare function pathExists(filePath: string): Promise<boolean>;
|
|
6
27
|
export declare function dedupeQualityFlags(qualityFlags: readonly string[]): string[];
|
|
@@ -31,6 +31,29 @@ export function normalizeMapping(mapping) {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The mapping an artifact-targeted call runs in when the caller left `mapping`
|
|
36
|
+
* out.
|
|
37
|
+
*
|
|
38
|
+
* A stored artifact already carries the namespace it was resolved into, so a
|
|
39
|
+
* follow-up call that names it by `artifactId` must inherit that namespace
|
|
40
|
+
* instead of falling back to the version-target default ("obfuscated").
|
|
41
|
+
* Without this, `find-class` -> `get-class-source` -> `get-class-members`
|
|
42
|
+
* split across two namespaces: source came back in mojang names while members
|
|
43
|
+
* came back obfuscated (`ownerFqn: "dlp"`), for the same artifact and the same
|
|
44
|
+
* absent `mapping` argument.
|
|
45
|
+
*
|
|
46
|
+
* `requestedMapping` wins over `mappingApplied` so the echoed request keeps
|
|
47
|
+
* meaning "what was asked for" even on artifacts where the mapping could not
|
|
48
|
+
* be applied; `mappingApplied` is the fallback for rows stored before the
|
|
49
|
+
* requested namespace was persisted.
|
|
50
|
+
*/
|
|
51
|
+
export function inheritArtifactMapping(inputMapping, artifact) {
|
|
52
|
+
if (inputMapping != null) {
|
|
53
|
+
return normalizeMapping(inputMapping);
|
|
54
|
+
}
|
|
55
|
+
return artifact.requestedMapping ?? artifact.mappingApplied ?? normalizeMapping(undefined);
|
|
56
|
+
}
|
|
34
57
|
export async function pathExists(filePath) {
|
|
35
58
|
try {
|
|
36
59
|
await access(filePath);
|
package/dist/source-service.d.ts
CHANGED
|
@@ -268,11 +268,20 @@ export type FindClassMatch = {
|
|
|
268
268
|
filePath: string;
|
|
269
269
|
line: number;
|
|
270
270
|
symbolKind: string;
|
|
271
|
+
/** Set when the match is a type declared INSIDE another type. */
|
|
272
|
+
nested?: boolean;
|
|
273
|
+
/** The enclosing top-level type, present only on a nested match. */
|
|
274
|
+
enclosingClass?: string;
|
|
271
275
|
};
|
|
272
276
|
export type FindClassOutput = {
|
|
273
277
|
matches: FindClassMatch[];
|
|
274
278
|
total: number;
|
|
275
279
|
warnings: string[];
|
|
280
|
+
/** Recovery route when the index legitimately cannot answer (partial coverage). */
|
|
281
|
+
suggestedCall?: {
|
|
282
|
+
tool: string;
|
|
283
|
+
params: Record<string, unknown>;
|
|
284
|
+
};
|
|
276
285
|
};
|
|
277
286
|
type MemberAccess = "public" | "all";
|
|
278
287
|
export type GetClassMembersInput = {
|
|
@@ -638,6 +647,7 @@ export declare class SourceService {
|
|
|
638
647
|
requestedScope: ArtifactScope;
|
|
639
648
|
atNamespace: AccessTransformerNamespace;
|
|
640
649
|
loader: import("./workspace-mapping-service.js").WorkspaceProjectLoader | "unknown";
|
|
650
|
+
projectMinecraftVersion?: string;
|
|
641
651
|
}): ReturnType<typeof artifactResolver.discoverAccessTransformerRuntimeCandidates>;
|
|
642
652
|
buildMappingFallbackSuggestedCall(args: {
|
|
643
653
|
input: ResolveArtifactInput;
|
|
@@ -670,6 +680,7 @@ export declare class SourceService {
|
|
|
670
680
|
traceSymbolLifecycle(input: TraceSymbolLifecycleInput): Promise<TraceSymbolLifecycleOutput>;
|
|
671
681
|
diffClassSignatures(input: DiffClassSignaturesInput): Promise<DiffClassSignaturesOutput>;
|
|
672
682
|
findClass(input: FindClassInput): FindClassOutput;
|
|
683
|
+
findClassIncludingNested(input: FindClassInput): Promise<FindClassOutput>;
|
|
673
684
|
getClassSource(input: GetClassSourceInput): Promise<GetClassSourceOutput>;
|
|
674
685
|
getClassMembers(input: GetClassMembersInput): Promise<GetClassMembersOutput>;
|
|
675
686
|
validateMixin(input: ValidateMixinInput, options?: ValidateMixinOptions): Promise<ValidateMixinOutput>;
|
|
@@ -701,6 +712,7 @@ export declare class SourceService {
|
|
|
701
712
|
mappingApplied: SourceMapping;
|
|
702
713
|
provenance?: ArtifactProvenance;
|
|
703
714
|
qualityFlags: string[];
|
|
715
|
+
allowDecompile?: boolean;
|
|
704
716
|
}): Promise<ResolvedSourceArtifact | undefined>;
|
|
705
717
|
getArtifact(artifactId: string): ArtifactRow;
|
|
706
718
|
ingestIfNeeded(resolved: ResolvedSourceArtifact): Promise<void>;
|
package/dist/source-service.js
CHANGED
|
@@ -215,6 +215,9 @@ export class SourceService {
|
|
|
215
215
|
findClass(input) {
|
|
216
216
|
return classSource.findClass(this, input);
|
|
217
217
|
}
|
|
218
|
+
async findClassIncludingNested(input) {
|
|
219
|
+
return classSource.findClassIncludingNested(this, input);
|
|
220
|
+
}
|
|
218
221
|
async getClassSource(input) {
|
|
219
222
|
return classSource.getClassSource(this, input);
|
|
220
223
|
}
|