@adhisang/minecraft-modding-mcp 3.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +25 -18
- package/dist/cache-registry.d.ts +1 -1
- package/dist/cache-registry.js +10 -2
- package/dist/config.d.ts +10 -1
- package/dist/config.js +52 -1
- package/dist/entry-tools/analyze-symbol-service.d.ts +2 -2
- package/dist/entry-tools/analyze-symbol-service.js +13 -2
- package/dist/entry-tools/inspect-minecraft-service.d.ts +20 -20
- package/dist/entry-tools/inspect-minecraft-service.js +8 -2
- package/dist/entry-tools/manage-cache-service.d.ts +4 -4
- package/dist/entry-tools/validate-project-service.js +84 -4
- package/dist/index.js +99 -33
- package/dist/lru-list.d.ts +31 -0
- package/dist/lru-list.js +102 -0
- package/dist/mapping-pipeline-service.d.ts +10 -1
- package/dist/mapping-pipeline-service.js +13 -1
- package/dist/mapping-service.d.ts +12 -0
- package/dist/mapping-service.js +252 -10
- package/dist/mixin-validator.js +22 -7
- package/dist/observability.d.ts +18 -1
- package/dist/observability.js +44 -1
- package/dist/response-utils.d.ts +44 -10
- package/dist/response-utils.js +131 -17
- package/dist/source-resolver.d.ts +9 -1
- package/dist/source-resolver.js +14 -6
- package/dist/source-service.d.ts +97 -1
- package/dist/source-service.js +922 -113
- package/dist/storage/artifacts-repo.d.ts +4 -1
- package/dist/storage/artifacts-repo.js +33 -5
- package/dist/storage/files-repo.d.ts +0 -2
- package/dist/storage/files-repo.js +0 -11
- package/dist/storage/migrations.d.ts +1 -1
- package/dist/storage/migrations.js +10 -2
- package/dist/storage/schema.d.ts +2 -0
- package/dist/storage/schema.js +25 -0
- package/dist/types.d.ts +3 -0
- package/package.json +3 -1
package/dist/response-utils.d.ts
CHANGED
|
@@ -7,29 +7,63 @@
|
|
|
7
7
|
export declare const COMPACT_ENABLED_TOOL_NAMES: Set<string>;
|
|
8
8
|
/** Mapping-oriented tools that get additional field projection via compactMappingResponse. */
|
|
9
9
|
export declare const COMPACT_MAPPING_TOOL_NAMES: Set<string>;
|
|
10
|
+
/** Source-oriented tools (get-class-source) that get compactSourceResponse projection. */
|
|
11
|
+
export declare const COMPACT_SOURCE_TOOL_NAMES: Set<string>;
|
|
12
|
+
/** Member-listing tools (get-class-members) that get compactMembersResponse projection. */
|
|
13
|
+
export declare const COMPACT_MEMBERS_TOOL_NAMES: Set<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Tools that only need the light artifactContents projection (search hits,
|
|
16
|
+
* file listing). The primary payload is already small; the projection just
|
|
17
|
+
* drops the artifact-level summary that callers rarely consume.
|
|
18
|
+
*/
|
|
19
|
+
export declare const COMPACT_LIGHT_TOOL_NAMES: Set<string>;
|
|
10
20
|
/**
|
|
11
21
|
* Double-gated compact check: tool must be in the allowlist AND parsedInput.compact must be true.
|
|
12
22
|
* Prevents activation on passthrough schemas where Zod doesn't strip unknown keys.
|
|
13
23
|
*/
|
|
14
24
|
export declare function isCompactEnabled(tool: string, parsedInput: unknown): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Primary-payload keys that compact mode must preserve per tool, even when
|
|
27
|
+
* the value is an empty array (no hits, no files, no members). Without this
|
|
28
|
+
* the generic {@link compactResponse} path would strip `hits: []` / `items: []`
|
|
29
|
+
* from successful zero-result responses and callers could not distinguish
|
|
30
|
+
* "empty success" from "field missing".
|
|
31
|
+
*
|
|
32
|
+
* Only tools whose primary payload can legitimately be an empty array need
|
|
33
|
+
* an entry here. `get-class-source` returns `sourceText: string` which is
|
|
34
|
+
* never stripped by compactResponse.
|
|
35
|
+
*/
|
|
36
|
+
export declare const TOOL_PRESERVE_PAYLOAD_KEYS: Record<string, ReadonlySet<string>>;
|
|
15
37
|
/**
|
|
16
38
|
* Shallow-strip empty values from a response object.
|
|
17
39
|
* Only operates on the top level — nested structures are preserved as-is.
|
|
18
40
|
* Non-plain objects (Date, Map, class instances) are never treated as empty.
|
|
41
|
+
*
|
|
42
|
+
* `preserveKeys` names keys whose values MUST survive the strip even if
|
|
43
|
+
* empty (used by tools whose primary payload is an array that can legitimately
|
|
44
|
+
* be empty — e.g. zero-hit search, empty file listing). `null` / `undefined`
|
|
45
|
+
* values are still dropped even for preserved keys, so absent optional
|
|
46
|
+
* payload fields do not leak through as explicit nulls.
|
|
19
47
|
*/
|
|
20
|
-
export declare function compactResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
48
|
+
export declare function compactResponse(obj: Record<string, unknown>, preserveKeys?: ReadonlySet<string>): Record<string, unknown>;
|
|
21
49
|
/** resolve-artifact compact: omit debug/diagnostic fields. */
|
|
22
50
|
export declare function compactArtifactResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
51
|
+
/** get-class-source compact: drop provenance, artifactContents, qualityFlags. */
|
|
52
|
+
export declare function compactSourceResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
53
|
+
/** get-class-members compact: drop provenance, artifactContents, qualityFlags, context. */
|
|
54
|
+
export declare function compactMembersResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
55
|
+
/** Light compact projection: drop the artifactContents summary only. */
|
|
56
|
+
export declare function compactLightResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
23
57
|
/**
|
|
24
|
-
* Mapping tool compact:
|
|
58
|
+
* Mapping tool compact: project candidates for size reduction.
|
|
59
|
+
*
|
|
60
|
+
* Resolved-exact path: omit candidates entirely when provably redundant.
|
|
61
|
+
* All of: resolved===true, resolvedSymbol exists, single exact candidate, not truncated,
|
|
62
|
+
* confidence missing or 1.
|
|
25
63
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* 4. candidateCount === 1
|
|
31
|
-
* 5. candidatesTruncated is falsy
|
|
32
|
-
* 6. candidates[0].matchKind === "exact"
|
|
33
|
-
* 7. candidates[0].confidence is undefined or 1
|
|
64
|
+
* Unresolved/ambiguous path: keep top {@link UNRESOLVED_FULL_DETAIL_LIMIT} candidates with full
|
|
65
|
+
* metadata, slim the tail to {kind,symbol,owner,name,descriptor,confidence,matchKind}, and
|
|
66
|
+
* surface `candidatesTruncated:true` + `totalCandidateCount` so the caller knows what it's
|
|
67
|
+
* seeing.
|
|
34
68
|
*/
|
|
35
69
|
export declare function compactMappingResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
package/dist/response-utils.js
CHANGED
|
@@ -9,7 +9,11 @@ export const COMPACT_ENABLED_TOOL_NAMES = new Set([
|
|
|
9
9
|
"find-mapping",
|
|
10
10
|
"resolve-method-mapping-exact",
|
|
11
11
|
"resolve-workspace-symbol",
|
|
12
|
-
"check-symbol-exists"
|
|
12
|
+
"check-symbol-exists",
|
|
13
|
+
"get-class-source",
|
|
14
|
+
"get-class-members",
|
|
15
|
+
"search-class-source",
|
|
16
|
+
"list-artifact-files"
|
|
13
17
|
]);
|
|
14
18
|
/** Mapping-oriented tools that get additional field projection via compactMappingResponse. */
|
|
15
19
|
export const COMPACT_MAPPING_TOOL_NAMES = new Set([
|
|
@@ -18,6 +22,23 @@ export const COMPACT_MAPPING_TOOL_NAMES = new Set([
|
|
|
18
22
|
"resolve-workspace-symbol",
|
|
19
23
|
"check-symbol-exists"
|
|
20
24
|
]);
|
|
25
|
+
/** Source-oriented tools (get-class-source) that get compactSourceResponse projection. */
|
|
26
|
+
export const COMPACT_SOURCE_TOOL_NAMES = new Set([
|
|
27
|
+
"get-class-source"
|
|
28
|
+
]);
|
|
29
|
+
/** Member-listing tools (get-class-members) that get compactMembersResponse projection. */
|
|
30
|
+
export const COMPACT_MEMBERS_TOOL_NAMES = new Set([
|
|
31
|
+
"get-class-members"
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* Tools that only need the light artifactContents projection (search hits,
|
|
35
|
+
* file listing). The primary payload is already small; the projection just
|
|
36
|
+
* drops the artifact-level summary that callers rarely consume.
|
|
37
|
+
*/
|
|
38
|
+
export const COMPACT_LIGHT_TOOL_NAMES = new Set([
|
|
39
|
+
"search-class-source",
|
|
40
|
+
"list-artifact-files"
|
|
41
|
+
]);
|
|
21
42
|
/**
|
|
22
43
|
* Double-gated compact check: tool must be in the allowlist AND parsedInput.compact must be true.
|
|
23
44
|
* Prevents activation on passthrough schemas where Zod doesn't strip unknown keys.
|
|
@@ -39,18 +60,44 @@ function isPlainObject(v) {
|
|
|
39
60
|
const proto = Object.getPrototypeOf(v);
|
|
40
61
|
return proto === Object.prototype || proto === null;
|
|
41
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Primary-payload keys that compact mode must preserve per tool, even when
|
|
65
|
+
* the value is an empty array (no hits, no files, no members). Without this
|
|
66
|
+
* the generic {@link compactResponse} path would strip `hits: []` / `items: []`
|
|
67
|
+
* from successful zero-result responses and callers could not distinguish
|
|
68
|
+
* "empty success" from "field missing".
|
|
69
|
+
*
|
|
70
|
+
* Only tools whose primary payload can legitimately be an empty array need
|
|
71
|
+
* an entry here. `get-class-source` returns `sourceText: string` which is
|
|
72
|
+
* never stripped by compactResponse.
|
|
73
|
+
*/
|
|
74
|
+
export const TOOL_PRESERVE_PAYLOAD_KEYS = {
|
|
75
|
+
"search-class-source": new Set(["hits"]),
|
|
76
|
+
"list-artifact-files": new Set(["items"]),
|
|
77
|
+
"get-class-members": new Set(["members", "counts", "decompiledFallback", "decompiledMemberCounts"])
|
|
78
|
+
};
|
|
42
79
|
/**
|
|
43
80
|
* Shallow-strip empty values from a response object.
|
|
44
81
|
* Only operates on the top level — nested structures are preserved as-is.
|
|
45
82
|
* Non-plain objects (Date, Map, class instances) are never treated as empty.
|
|
83
|
+
*
|
|
84
|
+
* `preserveKeys` names keys whose values MUST survive the strip even if
|
|
85
|
+
* empty (used by tools whose primary payload is an array that can legitimately
|
|
86
|
+
* be empty — e.g. zero-hit search, empty file listing). `null` / `undefined`
|
|
87
|
+
* values are still dropped even for preserved keys, so absent optional
|
|
88
|
+
* payload fields do not leak through as explicit nulls.
|
|
46
89
|
*/
|
|
47
|
-
export function compactResponse(obj) {
|
|
90
|
+
export function compactResponse(obj, preserveKeys) {
|
|
48
91
|
if (!isPlainObject(obj))
|
|
49
92
|
return {};
|
|
50
93
|
const result = {};
|
|
51
94
|
for (const [key, value] of Object.entries(obj)) {
|
|
52
95
|
if (value === null || value === undefined)
|
|
53
96
|
continue;
|
|
97
|
+
if (preserveKeys?.has(key)) {
|
|
98
|
+
result[key] = value;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
54
101
|
if (Array.isArray(value) && value.length === 0)
|
|
55
102
|
continue;
|
|
56
103
|
if (isPlainObject(value) && Object.keys(value).length === 0)
|
|
@@ -59,6 +106,15 @@ export function compactResponse(obj) {
|
|
|
59
106
|
}
|
|
60
107
|
return result;
|
|
61
108
|
}
|
|
109
|
+
function projectOmitKeys(obj, omit) {
|
|
110
|
+
const projected = {};
|
|
111
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
112
|
+
if (omit.has(key))
|
|
113
|
+
continue;
|
|
114
|
+
projected[key] = value;
|
|
115
|
+
}
|
|
116
|
+
return projected;
|
|
117
|
+
}
|
|
62
118
|
/** Fields to omit from resolve-artifact in compact mode. */
|
|
63
119
|
const ARTIFACT_COMPACT_OMIT_KEYS = new Set([
|
|
64
120
|
"provenance",
|
|
@@ -72,25 +128,69 @@ const ARTIFACT_COMPACT_OMIT_KEYS = new Set([
|
|
|
72
128
|
]);
|
|
73
129
|
/** resolve-artifact compact: omit debug/diagnostic fields. */
|
|
74
130
|
export function compactArtifactResponse(obj) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
131
|
+
return projectOmitKeys(obj, ARTIFACT_COMPACT_OMIT_KEYS);
|
|
132
|
+
}
|
|
133
|
+
/** Fields to omit from get-class-source in compact mode. */
|
|
134
|
+
const SOURCE_COMPACT_OMIT_KEYS = new Set([
|
|
135
|
+
"provenance",
|
|
136
|
+
"artifactContents",
|
|
137
|
+
"qualityFlags"
|
|
138
|
+
]);
|
|
139
|
+
/** get-class-source compact: drop provenance, artifactContents, qualityFlags. */
|
|
140
|
+
export function compactSourceResponse(obj) {
|
|
141
|
+
return projectOmitKeys(obj, SOURCE_COMPACT_OMIT_KEYS);
|
|
142
|
+
}
|
|
143
|
+
/** Fields to omit from get-class-members in compact mode. */
|
|
144
|
+
const MEMBERS_COMPACT_OMIT_KEYS = new Set([
|
|
145
|
+
"provenance",
|
|
146
|
+
"artifactContents",
|
|
147
|
+
"qualityFlags",
|
|
148
|
+
"context"
|
|
149
|
+
]);
|
|
150
|
+
/** get-class-members compact: drop provenance, artifactContents, qualityFlags, context. */
|
|
151
|
+
export function compactMembersResponse(obj) {
|
|
152
|
+
return projectOmitKeys(obj, MEMBERS_COMPACT_OMIT_KEYS);
|
|
153
|
+
}
|
|
154
|
+
/** Fields to omit from search-class-source / list-artifact-files in compact mode. */
|
|
155
|
+
const LIGHT_COMPACT_OMIT_KEYS = new Set([
|
|
156
|
+
"artifactContents"
|
|
157
|
+
]);
|
|
158
|
+
/** Light compact projection: drop the artifactContents summary only. */
|
|
159
|
+
export function compactLightResponse(obj) {
|
|
160
|
+
return projectOmitKeys(obj, LIGHT_COMPACT_OMIT_KEYS);
|
|
161
|
+
}
|
|
162
|
+
/** Max number of unresolved candidates that get full metadata in compact mode. */
|
|
163
|
+
const UNRESOLVED_FULL_DETAIL_LIMIT = 3;
|
|
164
|
+
/**
|
|
165
|
+
* Slim projection of a candidate: retains only identification + confidence fields.
|
|
166
|
+
*
|
|
167
|
+
* `kind` and `symbol` are part of the public `SymbolReference` / candidate contract that
|
|
168
|
+
* clients branch on and use as rendering keys, so they MUST survive the slim. The heavy
|
|
169
|
+
* fields removed here are the cycle-local diagnostic metadata (provenance, context,
|
|
170
|
+
* ambiguityReasons, warnings on the candidate, etc.) — not the identity fields.
|
|
171
|
+
*/
|
|
172
|
+
function slimCandidate(candidate) {
|
|
173
|
+
if (!isPlainObject(candidate))
|
|
174
|
+
return candidate;
|
|
175
|
+
const picked = {};
|
|
176
|
+
for (const key of ["kind", "symbol", "owner", "name", "descriptor", "confidence", "matchKind"]) {
|
|
177
|
+
if (candidate[key] !== undefined) {
|
|
178
|
+
picked[key] = candidate[key];
|
|
179
|
+
}
|
|
80
180
|
}
|
|
81
|
-
return
|
|
181
|
+
return picked;
|
|
82
182
|
}
|
|
83
183
|
/**
|
|
84
|
-
* Mapping tool compact:
|
|
184
|
+
* Mapping tool compact: project candidates for size reduction.
|
|
185
|
+
*
|
|
186
|
+
* Resolved-exact path: omit candidates entirely when provably redundant.
|
|
187
|
+
* All of: resolved===true, resolvedSymbol exists, single exact candidate, not truncated,
|
|
188
|
+
* confidence missing or 1.
|
|
85
189
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* 4. candidateCount === 1
|
|
91
|
-
* 5. candidatesTruncated is falsy
|
|
92
|
-
* 6. candidates[0].matchKind === "exact"
|
|
93
|
-
* 7. candidates[0].confidence is undefined or 1
|
|
190
|
+
* Unresolved/ambiguous path: keep top {@link UNRESOLVED_FULL_DETAIL_LIMIT} candidates with full
|
|
191
|
+
* metadata, slim the tail to {kind,symbol,owner,name,descriptor,confidence,matchKind}, and
|
|
192
|
+
* surface `candidatesTruncated:true` + `totalCandidateCount` so the caller knows what it's
|
|
193
|
+
* seeing.
|
|
94
194
|
*/
|
|
95
195
|
export function compactMappingResponse(obj) {
|
|
96
196
|
const projected = { ...obj };
|
|
@@ -106,8 +206,22 @@ export function compactMappingResponse(obj) {
|
|
|
106
206
|
candidate.matchKind === "exact" &&
|
|
107
207
|
(candidate.confidence === undefined || candidate.confidence === 1)) {
|
|
108
208
|
delete projected.candidates;
|
|
209
|
+
return projected;
|
|
109
210
|
}
|
|
110
211
|
}
|
|
212
|
+
if (projected.resolved === false &&
|
|
213
|
+
Array.isArray(candidates) &&
|
|
214
|
+
candidates.length > UNRESOLVED_FULL_DETAIL_LIMIT) {
|
|
215
|
+
const head = candidates.slice(0, UNRESOLVED_FULL_DETAIL_LIMIT);
|
|
216
|
+
const tail = candidates.slice(UNRESOLVED_FULL_DETAIL_LIMIT).map(slimCandidate);
|
|
217
|
+
projected.candidates = [...head, ...tail];
|
|
218
|
+
// Tail slimming keeps the full candidate array; only metadata was dropped. Use a
|
|
219
|
+
// dedicated `candidateDetailsTruncated` signal so clients do not confuse it with the
|
|
220
|
+
// existing `candidatesTruncated` semantics ("more candidates exist than this response
|
|
221
|
+
// contains"). If the upstream already reported list-level truncation via
|
|
222
|
+
// `candidatesTruncated`, that value is preserved unchanged.
|
|
223
|
+
projected.candidateDetailsTruncated = true;
|
|
224
|
+
}
|
|
111
225
|
return projected;
|
|
112
226
|
}
|
|
113
227
|
//# sourceMappingURL=response-utils.js.map
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import type { Config, ResolvedSourceArtifact, SourceTargetInput } from "./types.js";
|
|
1
|
+
import type { Config, MappingVariant, ResolvedSourceArtifact, SourceTargetInput } from "./types.js";
|
|
2
|
+
export type { MappingVariant } from "./types.js";
|
|
2
3
|
export interface ResolveSourceTargetOptions {
|
|
3
4
|
allowDecompile: boolean;
|
|
4
5
|
preferBinaryOnly?: boolean;
|
|
5
6
|
preferredRepos?: string[];
|
|
7
|
+
/**
|
|
8
|
+
* When set to "mojang-remapped", the artifactId hash gets a dedicated
|
|
9
|
+
* suffix so the mojang-remapped variant of an otherwise binary-only artifact
|
|
10
|
+
* occupies its own cache slot. Defaults to "pass" which preserves the
|
|
11
|
+
* legacy hash for obfuscated and source-backed artifacts.
|
|
12
|
+
*/
|
|
13
|
+
mappingVariant?: MappingVariant;
|
|
6
14
|
onRepoFailover?: (event: {
|
|
7
15
|
stage: "source" | "binary";
|
|
8
16
|
repoUrl: string;
|
package/dist/source-resolver.js
CHANGED
|
@@ -133,11 +133,19 @@ async function resolveGradleCacheCoordinateCandidate(coordinate) {
|
|
|
133
133
|
function resolveRemoteBinaryCandidate(coordinate, repos) {
|
|
134
134
|
return buildRemoteBinaryUrls(repos, coordinate);
|
|
135
135
|
}
|
|
136
|
-
function artifactIdForJar(inputKind, artifactPath, signature, suffix) {
|
|
137
|
-
|
|
136
|
+
function artifactIdForJar(inputKind, artifactPath, signature, suffix, mappingVariant = "pass") {
|
|
137
|
+
const parts = [inputKind, artifactPath, signature, suffix ?? "source"];
|
|
138
|
+
if (mappingVariant === "mojang-remapped") {
|
|
139
|
+
parts.push("mojang-remapped");
|
|
140
|
+
}
|
|
141
|
+
return stableArtifactId(parts);
|
|
138
142
|
}
|
|
139
|
-
function artifactIdForCoordinate(coordinate, source, signature) {
|
|
140
|
-
|
|
143
|
+
function artifactIdForCoordinate(coordinate, source, signature, mappingVariant = "pass") {
|
|
144
|
+
const parts = ["coord", coordinate, source, signature];
|
|
145
|
+
if (mappingVariant === "mojang-remapped") {
|
|
146
|
+
parts.push("mojang-remapped");
|
|
147
|
+
}
|
|
148
|
+
return stableArtifactId(parts);
|
|
141
149
|
}
|
|
142
150
|
function resolvedAtNow() {
|
|
143
151
|
return new Date().toISOString();
|
|
@@ -191,7 +199,7 @@ export async function resolveSourceTarget(input, options, explicitConfig) {
|
|
|
191
199
|
});
|
|
192
200
|
}
|
|
193
201
|
return {
|
|
194
|
-
artifactId: artifactIdForJar("jar", resolvedJarPath, `${binarySignature}:decompile
|
|
202
|
+
artifactId: artifactIdForJar("jar", resolvedJarPath, `${binarySignature}:decompile`, undefined, options.mappingVariant ?? "pass"),
|
|
195
203
|
artifactSignature: `${binarySignature}:decompile`,
|
|
196
204
|
origin: "decompiled",
|
|
197
205
|
binaryJarPath: resolvedJarPath,
|
|
@@ -326,7 +334,7 @@ export async function resolveSourceTarget(input, options, explicitConfig) {
|
|
|
326
334
|
}
|
|
327
335
|
const signature = readStatsSignature(downloaded.path);
|
|
328
336
|
return {
|
|
329
|
-
artifactId: artifactIdForCoordinate(coordinate, "decompiled", signature),
|
|
337
|
+
artifactId: artifactIdForCoordinate(coordinate, "decompiled", signature, options.mappingVariant ?? "pass"),
|
|
330
338
|
artifactSignature: signature,
|
|
331
339
|
origin: "decompiled",
|
|
332
340
|
binaryJarPath: downloaded.path,
|
package/dist/source-service.d.ts
CHANGED
|
@@ -18,9 +18,11 @@ export type ResolveArtifactInput = {
|
|
|
18
18
|
scope?: ArtifactScope;
|
|
19
19
|
preferProjectVersion?: boolean;
|
|
20
20
|
strictVersion?: boolean;
|
|
21
|
+
compact?: boolean;
|
|
21
22
|
};
|
|
22
23
|
export type ResolveArtifactOutput = {
|
|
23
24
|
artifactId: string;
|
|
25
|
+
artifactAlias: string;
|
|
24
26
|
origin: "local-jar" | "local-m2" | "remote-repo" | "decompiled";
|
|
25
27
|
isDecompiled: boolean;
|
|
26
28
|
resolvedSourceJarPath?: string;
|
|
@@ -74,6 +76,8 @@ export type SearchClassSourceInput = {
|
|
|
74
76
|
queryMode?: QueryMode;
|
|
75
77
|
limit?: number;
|
|
76
78
|
cursor?: string;
|
|
79
|
+
queryNamespace?: SourceMapping;
|
|
80
|
+
sourcePriority?: MappingSourcePriority;
|
|
77
81
|
};
|
|
78
82
|
export type SearchClassSourceOutput = {
|
|
79
83
|
hits: SearchSourceHit[];
|
|
@@ -81,6 +85,13 @@ export type SearchClassSourceOutput = {
|
|
|
81
85
|
mappingApplied: SourceMapping;
|
|
82
86
|
returnedNamespace: SourceMapping;
|
|
83
87
|
artifactContents: ArtifactContentsSummary;
|
|
88
|
+
translatedQuery?: {
|
|
89
|
+
original: string;
|
|
90
|
+
translated: string;
|
|
91
|
+
fromNamespace: SourceMapping;
|
|
92
|
+
toNamespace: SourceMapping;
|
|
93
|
+
};
|
|
94
|
+
warnings?: string[];
|
|
84
95
|
};
|
|
85
96
|
export type GetArtifactFileInput = {
|
|
86
97
|
artifactId: string;
|
|
@@ -207,6 +218,17 @@ export type GetClassMembersInput = {
|
|
|
207
218
|
preferProjectVersion?: boolean;
|
|
208
219
|
strictVersion?: boolean;
|
|
209
220
|
};
|
|
221
|
+
export type DecompiledMember = {
|
|
222
|
+
name: string;
|
|
223
|
+
line: number;
|
|
224
|
+
kind: "constructor" | "field" | "method";
|
|
225
|
+
};
|
|
226
|
+
export type DecompiledFallback = {
|
|
227
|
+
constructors: DecompiledMember[];
|
|
228
|
+
fields: DecompiledMember[];
|
|
229
|
+
methods: DecompiledMember[];
|
|
230
|
+
origin: "source-extracted";
|
|
231
|
+
};
|
|
210
232
|
export type GetClassMembersOutput = {
|
|
211
233
|
className: string;
|
|
212
234
|
members: {
|
|
@@ -230,6 +252,13 @@ export type GetClassMembersOutput = {
|
|
|
230
252
|
provenance: ArtifactProvenance;
|
|
231
253
|
qualityFlags: string[];
|
|
232
254
|
artifactContents: ArtifactContentsSummary;
|
|
255
|
+
decompiledFallback?: DecompiledFallback;
|
|
256
|
+
decompiledMemberCounts?: {
|
|
257
|
+
constructors: number;
|
|
258
|
+
fields: number;
|
|
259
|
+
methods: number;
|
|
260
|
+
total: number;
|
|
261
|
+
};
|
|
233
262
|
warnings: string[];
|
|
234
263
|
};
|
|
235
264
|
export type TraceSymbolLifecycleInput = {
|
|
@@ -455,7 +484,12 @@ export declare class SourceService {
|
|
|
455
484
|
private readonly versionDiffService;
|
|
456
485
|
private readonly modDecompileService;
|
|
457
486
|
private readonly modSearchService;
|
|
458
|
-
private
|
|
487
|
+
private readonly lru;
|
|
488
|
+
private cacheTotalContentBytes;
|
|
489
|
+
private readonly remappedJarBytes;
|
|
490
|
+
/** In-flight binary-remap jobs keyed by remapped jar path so concurrent
|
|
491
|
+
* resolveArtifact calls for the same artifactId share a single tiny-remapper run. */
|
|
492
|
+
private readonly inflightRemaps;
|
|
459
493
|
constructor(explicitConfig?: Config, metrics?: RuntimeMetrics);
|
|
460
494
|
private discoverVersionSourceJar;
|
|
461
495
|
private discoverAccessWidenerRuntimeCandidates;
|
|
@@ -464,6 +498,19 @@ export declare class SourceService {
|
|
|
464
498
|
private resolveAccessTransformerNamespace;
|
|
465
499
|
private resolveAccessTransformerRuntimeArtifact;
|
|
466
500
|
private buildVersionSourceRecoveryCommand;
|
|
501
|
+
/**
|
|
502
|
+
* Decide whether the upcoming resolveArtifact call may transparently remap a
|
|
503
|
+
* binary-only artifact (obfuscated -> mojang) and decompile it. The gate
|
|
504
|
+
* succeeds only when:
|
|
505
|
+
* - the requested mapping is "mojang" on a still-obfuscated runtime
|
|
506
|
+
* - tiny-remapper jar is downloadable / available locally
|
|
507
|
+
* - the version's Mojang tiny mapping file can be produced
|
|
508
|
+
* - checkMappingHealth reports mojang mappings are usable
|
|
509
|
+
* On any failure the variant defaults to "pass" so the legacy
|
|
510
|
+
* MAPPING_NOT_APPLIED fallback (or the existing source-backed flow) keeps
|
|
511
|
+
* its existing artifactId hash.
|
|
512
|
+
*/
|
|
513
|
+
private computeBinaryRemapGate;
|
|
467
514
|
private buildArtifactContentsSummary;
|
|
468
515
|
private inferVersionFromContext;
|
|
469
516
|
private resolveVersionContext;
|
|
@@ -488,11 +535,14 @@ export declare class SourceService {
|
|
|
488
535
|
findClass(input: FindClassInput): FindClassOutput;
|
|
489
536
|
getClassSource(input: GetClassSourceInput): Promise<GetClassSourceOutput>;
|
|
490
537
|
getClassMembers(input: GetClassMembersInput): Promise<GetClassMembersOutput>;
|
|
538
|
+
private buildDecompiledFallback;
|
|
491
539
|
validateMixin(input: ValidateMixinInput): Promise<ValidateMixinOutput>;
|
|
540
|
+
private runValidateMixinDispatcher;
|
|
492
541
|
private createProjectValidateMixinConfigInput;
|
|
493
542
|
private shouldRetryValidateMixinWithMavenFirst;
|
|
494
543
|
private findValidateMixinClassMapping;
|
|
495
544
|
private validateMixinSingle;
|
|
545
|
+
private runValidateMixinPipeline;
|
|
496
546
|
private resolveMixinInputPath;
|
|
497
547
|
private resolveMixinConfigSources;
|
|
498
548
|
private validateMixinMany;
|
|
@@ -500,6 +550,7 @@ export declare class SourceService {
|
|
|
500
550
|
private buildValidateMixinOutput;
|
|
501
551
|
validateAccessWidener(input: ValidateAccessWidenerInput): Promise<ValidateAccessWidenerOutput>;
|
|
502
552
|
validateAccessTransformer(input: ValidateAccessTransformerInput): Promise<ValidateAccessTransformerOutput>;
|
|
553
|
+
recordToolCall(tool: string, durationMs: number): void;
|
|
503
554
|
getRuntimeMetrics(): RuntimeMetricSnapshot;
|
|
504
555
|
indexArtifact(input: IndexArtifactInput): Promise<IndexArtifactOutput>;
|
|
505
556
|
private searchSymbolIntent;
|
|
@@ -511,6 +562,11 @@ export declare class SourceService {
|
|
|
511
562
|
private indexedCandidateLimit;
|
|
512
563
|
private indexedCandidateLimitForMatch;
|
|
513
564
|
private extractClassMetadata;
|
|
565
|
+
private extractDecompiledMembers;
|
|
566
|
+
private computeLineBraceDepths;
|
|
567
|
+
private computeBraceRange;
|
|
568
|
+
private scanBraceRange;
|
|
569
|
+
private computeNestedTypeRanges;
|
|
514
570
|
private resolveClassFilePath;
|
|
515
571
|
private resolveBinaryFallbackArtifact;
|
|
516
572
|
private buildProvenance;
|
|
@@ -529,13 +585,53 @@ export declare class SourceService {
|
|
|
529
585
|
private buildRebuiltArtifactData;
|
|
530
586
|
getArtifact(artifactId: string): ArtifactRow;
|
|
531
587
|
private ingestIfNeeded;
|
|
588
|
+
/**
|
|
589
|
+
* If the resolved artifact's transformChain promised an "obf -> mojang"
|
|
590
|
+
* binary remap, run tiny-remapper now and return the remapped jar path.
|
|
591
|
+
* Otherwise return the original binaryJarPath unchanged.
|
|
592
|
+
*
|
|
593
|
+
* Cache safety: writes to a per-attempt temp file then atomic-renames into
|
|
594
|
+
* <cacheDir>/remapped/<artifactId>.jar. A per-target inflight Promise map
|
|
595
|
+
* collapses concurrent calls so two simultaneous resolveArtifact calls for
|
|
596
|
+
* the same artifactId share one tiny-remapper run instead of racing on the
|
|
597
|
+
* same output path.
|
|
598
|
+
*/
|
|
599
|
+
private maybeRemapBinaryForMojang;
|
|
600
|
+
private recordRemappedJarBytesFromDisk;
|
|
601
|
+
/**
|
|
602
|
+
* Best-effort structural check that `path` is a non-empty file beginning with
|
|
603
|
+
* the ZIP local-file-header magic (`50 4B 03 04`). Used to drop partial /
|
|
604
|
+
* corrupt remap-cache entries before they reach Vineflower. False positives
|
|
605
|
+
* are acceptable (Vineflower will surface a clearer error); false negatives
|
|
606
|
+
* are not (a corrupt cache hit must be evicted).
|
|
607
|
+
*/
|
|
608
|
+
private isUsableJarFile;
|
|
609
|
+
private runBinaryRemap;
|
|
532
610
|
private loadFromSourceJar;
|
|
533
611
|
private hasAnyFiles;
|
|
612
|
+
/**
|
|
613
|
+
* Best-effort cleanup of `<cacheDir>/remapped/<artifactId>.jar` written by
|
|
614
|
+
* `maybeRemapBinaryForMojang`. Called from cache-eviction paths so the
|
|
615
|
+
* Mojang-remapped binary jar does not outlive the artifact row that owns it.
|
|
616
|
+
* Also releases the jar's bytes from `cacheTotalContentBytes`. Errors are
|
|
617
|
+
* swallowed: orphaned jars remain visible to `manage-cache` under the
|
|
618
|
+
* `binary-remap` cache kind and can be reclaimed there.
|
|
619
|
+
*/
|
|
620
|
+
private unlinkRemappedJarForArtifact;
|
|
621
|
+
/**
|
|
622
|
+
* Add the remapped jar's on-disk size to `cacheTotalContentBytes` so the
|
|
623
|
+
* `enforceCacheLimits` byte gate sees the jar before deciding to evict.
|
|
624
|
+
* Without this, a Mojang-remapped client jar (tens of MB) can accumulate
|
|
625
|
+
* silently while the indexed-source byte total stays below `maxCacheBytes`.
|
|
626
|
+
*/
|
|
627
|
+
private recordRemappedJarBytes;
|
|
628
|
+
private releaseRemappedJarBytes;
|
|
534
629
|
private enforceCacheLimits;
|
|
535
630
|
private refreshCacheMetrics;
|
|
536
631
|
private touchCacheMetrics;
|
|
537
632
|
private upsertCacheMetrics;
|
|
538
633
|
private removeCacheMetrics;
|
|
539
634
|
private publishCacheMetrics;
|
|
635
|
+
private snapshotLruAccounting;
|
|
540
636
|
}
|
|
541
637
|
export {};
|