@adhisang/minecraft-modding-mcp 4.2.1 → 6.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 +69 -0
- package/README.md +5 -4
- package/dist/access-transformer-parser.d.ts +2 -1
- package/dist/access-transformer-parser.js +10 -1
- package/dist/access-widener-parser.d.ts +1 -0
- package/dist/access-widener-parser.js +6 -3
- package/dist/build-suggested-call.js +31 -10
- package/dist/cache-registry.d.ts +8 -0
- package/dist/cache-registry.js +50 -32
- package/dist/config.d.ts +1 -0
- package/dist/config.js +4 -0
- package/dist/decompiler/vineflower.js +8 -2
- package/dist/entry-tools/analyze-mod-service.d.ts +24 -24
- package/dist/entry-tools/analyze-mod-service.js +2 -1
- package/dist/entry-tools/analyze-symbol-service.d.ts +57 -22
- package/dist/entry-tools/analyze-symbol-service.js +139 -34
- package/dist/entry-tools/batch-class-members-service.d.ts +3 -1
- package/dist/entry-tools/batch-class-members-service.js +6 -6
- package/dist/entry-tools/batch-class-source-service.d.ts +3 -1
- package/dist/entry-tools/batch-class-source-service.js +5 -6
- package/dist/entry-tools/batch-mappings-service.d.ts +3 -1
- package/dist/entry-tools/batch-mappings-service.js +4 -5
- package/dist/entry-tools/batch-symbol-exists-service.d.ts +3 -1
- package/dist/entry-tools/batch-symbol-exists-service.js +4 -5
- package/dist/entry-tools/compare-minecraft-service.d.ts +10 -10
- package/dist/entry-tools/compare-minecraft-service.js +1 -1
- package/dist/entry-tools/entry-tool-schema.d.ts +1 -1
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +1 -3
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +4 -3
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +0 -5
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/file.js +26 -2
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +0 -1
- package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +8 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.js +13 -2
- package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +1 -1
- package/dist/entry-tools/inspect-minecraft/handlers/versions.js +3 -2
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +90 -89
- package/dist/entry-tools/inspect-minecraft/internal.js +32 -14
- package/dist/entry-tools/inspect-minecraft-service.d.ts +218 -218
- package/dist/entry-tools/inspect-minecraft-service.js +1 -1
- package/dist/entry-tools/manage-cache-service.d.ts +4 -4
- package/dist/entry-tools/response-contract.d.ts +3 -1
- package/dist/entry-tools/response-contract.js +3 -2
- package/dist/entry-tools/validate-project/cases/mixin.js +2 -1
- package/dist/entry-tools/validate-project/cases/project-summary.js +5 -3
- package/dist/entry-tools/validate-project-service.d.ts +42 -36
- package/dist/entry-tools/validate-project-service.js +3 -1
- package/dist/entry-tools/verify-mixin-target-service.d.ts +30 -0
- package/dist/entry-tools/verify-mixin-target-service.js +120 -29
- package/dist/error-mapping.d.ts +51 -0
- package/dist/error-mapping.js +157 -2
- package/dist/index.js +147 -76
- package/dist/java-process.js +1 -1
- package/dist/json-rpc-framing.d.ts +4 -0
- package/dist/json-rpc-framing.js +23 -1
- package/dist/mapping/internal-types.d.ts +24 -0
- package/dist/mapping/loaders/tiny-maven.js +46 -20
- package/dist/mapping/lookup.d.ts +13 -2
- package/dist/mapping/lookup.js +60 -2
- package/dist/mapping/types.d.ts +6 -0
- package/dist/mapping-service.d.ts +26 -2
- package/dist/mapping-service.js +212 -55
- package/dist/mcp-helpers.d.ts +1 -0
- package/dist/mcp-helpers.js +25 -3
- package/dist/minecraft-explorer-service.js +24 -11
- package/dist/mixin/access-validators.js +33 -1
- package/dist/mixin/annotation-validators.js +73 -9
- package/dist/mixin/parsed-validator.js +3 -2
- package/dist/mixin-parser.js +119 -7
- package/dist/mod-decompile-service.d.ts +2 -0
- package/dist/mod-decompile-service.js +21 -3
- package/dist/mod-remap-service.d.ts +20 -1
- package/dist/mod-remap-service.js +101 -45
- package/dist/mojang-tiny-mapping-service.js +5 -2
- package/dist/nbt/java-nbt-codec.js +46 -16
- package/dist/nbt/json-patch.js +51 -12
- package/dist/nbt/typed-json.d.ts +1 -0
- package/dist/nbt/typed-json.js +12 -2
- package/dist/nbt/types.d.ts +2 -2
- package/dist/observability.d.ts +6 -0
- package/dist/observability.js +10 -0
- package/dist/page-cursor.d.ts +17 -0
- package/dist/page-cursor.js +0 -0
- package/dist/path-converter.js +10 -3
- package/dist/registry-service.d.ts +2 -0
- package/dist/registry-service.js +41 -2
- package/dist/repo-downloader.js +4 -3
- package/dist/resources.js +45 -9
- package/dist/response-utils.d.ts +29 -4
- package/dist/response-utils.js +95 -5
- package/dist/source/access-validate.js +12 -2
- package/dist/source/artifact-resolver.js +2 -2
- package/dist/source/class-source/members-builder.d.ts +44 -1
- package/dist/source/class-source/members-builder.js +51 -4
- package/dist/source/class-source/snippet-builder.d.ts +13 -0
- package/dist/source/class-source/snippet-builder.js +54 -4
- package/dist/source/class-source-helpers.d.ts +4 -4
- package/dist/source/class-source-helpers.js +77 -20
- package/dist/source/class-source.d.ts +19 -0
- package/dist/source/class-source.js +144 -40
- package/dist/source/file-access.js +3 -2
- package/dist/source/indexer.js +29 -9
- package/dist/source/lifecycle/mapping-helpers.js +28 -3
- package/dist/source/lifecycle/runtime-check.js +20 -6
- package/dist/source/search.d.ts +1 -1
- package/dist/source/search.js +117 -30
- package/dist/source/validate-mixin/pipeline/resolve.js +23 -3
- package/dist/source/validate-mixin.d.ts +2 -1
- package/dist/source/validate-mixin.js +45 -4
- package/dist/source/workspace-target.js +17 -10
- package/dist/source-jar-reader.d.ts +54 -1
- package/dist/source-jar-reader.js +121 -10
- package/dist/source-resolver.js +2 -2
- package/dist/source-service.d.ts +28 -7
- package/dist/source-service.js +9 -1
- package/dist/stdio-supervisor.d.ts +2 -2
- package/dist/stdio-supervisor.js +29 -9
- package/dist/storage/db.js +24 -1
- package/dist/storage/files-repo.d.ts +15 -0
- package/dist/storage/files-repo.js +67 -37
- package/dist/storage/symbols-repo.d.ts +15 -0
- package/dist/storage/symbols-repo.js +53 -19
- package/dist/symbols/symbol-extractor.js +35 -6
- package/dist/text-truncate.d.ts +7 -0
- package/dist/text-truncate.js +21 -0
- package/dist/tiny-remapper-resolver.js +10 -0
- package/dist/tool-contract-manifest.js +2 -2
- package/dist/tool-execution-gate.js +12 -1
- package/dist/tool-guidance.d.ts +6 -2
- package/dist/tool-guidance.js +63 -13
- package/dist/tool-schemas.d.ts +561 -496
- package/dist/tool-schemas.js +175 -139
- package/dist/types.d.ts +1 -0
- package/dist/version-diff-service.js +5 -0
- package/dist/version-service.d.ts +3 -0
- package/dist/version-service.js +18 -2
- package/dist/warning-details.d.ts +30 -0
- package/dist/warning-details.js +80 -0
- package/dist/workspace-mapping-service.js +9 -0
- package/docs/README-ja.md +2 -2
- package/docs/examples.md +26 -2
- package/docs/tool-reference.md +22 -17
- package/package.json +1 -1
package/dist/resources.js
CHANGED
|
@@ -30,7 +30,7 @@ export function registerResources(server, sourceService) {
|
|
|
30
30
|
}
|
|
31
31
|
catch (e) {
|
|
32
32
|
if (isAppError(e))
|
|
33
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
33
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
34
34
|
throw e;
|
|
35
35
|
}
|
|
36
36
|
});
|
|
@@ -41,7 +41,7 @@ export function registerResources(server, sourceService) {
|
|
|
41
41
|
}
|
|
42
42
|
catch (e) {
|
|
43
43
|
if (isAppError(e))
|
|
44
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
44
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
45
45
|
throw e;
|
|
46
46
|
}
|
|
47
47
|
});
|
|
@@ -50,13 +50,31 @@ export function registerResources(server, sourceService) {
|
|
|
50
50
|
try {
|
|
51
51
|
const result = await sourceService.getClassSource({
|
|
52
52
|
artifactId: params.artifactId,
|
|
53
|
-
className: decodeTemplateParam(params, "className")
|
|
53
|
+
className: decodeTemplateParam(params, "className"),
|
|
54
|
+
// A "text/x-java" source resource must return real Java, not the default
|
|
55
|
+
// metadata outline; match the sibling class-source-json resource.
|
|
56
|
+
mode: "full"
|
|
54
57
|
});
|
|
55
58
|
return textResource(uri.href, result.sourceText);
|
|
56
59
|
}
|
|
57
60
|
catch (e) {
|
|
58
61
|
if (isAppError(e))
|
|
59
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
62
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
63
|
+
throw e;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
server.resource("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" }, async (uri, params) => {
|
|
67
|
+
try {
|
|
68
|
+
const result = await sourceService.getClassSource({
|
|
69
|
+
artifactId: params.artifactId,
|
|
70
|
+
className: decodeTemplateParam(params, "className"),
|
|
71
|
+
mode: "full"
|
|
72
|
+
});
|
|
73
|
+
return objectResource(uri.href, result);
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
if (isAppError(e))
|
|
77
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
60
78
|
throw e;
|
|
61
79
|
}
|
|
62
80
|
});
|
|
@@ -70,15 +88,33 @@ export function registerResources(server, sourceService) {
|
|
|
70
88
|
}
|
|
71
89
|
catch (e) {
|
|
72
90
|
if (isAppError(e))
|
|
73
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
91
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
92
|
+
throw e;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
server.resource("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" }, async (uri, params) => {
|
|
96
|
+
try {
|
|
97
|
+
const result = await sourceService.findMapping({
|
|
98
|
+
version: params.version,
|
|
99
|
+
kind: params.kind,
|
|
100
|
+
name: decodeTemplateParam(params, "name"),
|
|
101
|
+
sourceMapping: params.sourceMapping,
|
|
102
|
+
targetMapping: params.targetMapping
|
|
103
|
+
});
|
|
104
|
+
return objectResource(uri.href, result);
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
if (isAppError(e))
|
|
108
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
74
109
|
throw e;
|
|
75
110
|
}
|
|
76
111
|
});
|
|
77
|
-
server.resource("find-mapping", new ResourceTemplate("mc://mappings/{version}/{sourceMapping}/{targetMapping}/{kind}/{name}", { list: undefined }), { description: "Look up a mapping
|
|
112
|
+
server.resource("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" }, async (uri, params) => {
|
|
78
113
|
try {
|
|
79
114
|
const result = await sourceService.findMapping({
|
|
80
115
|
version: params.version,
|
|
81
116
|
kind: params.kind,
|
|
117
|
+
owner: decodeTemplateParam(params, "owner"),
|
|
82
118
|
name: decodeTemplateParam(params, "name"),
|
|
83
119
|
sourceMapping: params.sourceMapping,
|
|
84
120
|
targetMapping: params.targetMapping
|
|
@@ -87,7 +123,7 @@ export function registerResources(server, sourceService) {
|
|
|
87
123
|
}
|
|
88
124
|
catch (e) {
|
|
89
125
|
if (isAppError(e))
|
|
90
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
126
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
91
127
|
throw e;
|
|
92
128
|
}
|
|
93
129
|
});
|
|
@@ -101,7 +137,7 @@ export function registerResources(server, sourceService) {
|
|
|
101
137
|
}
|
|
102
138
|
catch (e) {
|
|
103
139
|
if (isAppError(e))
|
|
104
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
140
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
105
141
|
throw e;
|
|
106
142
|
}
|
|
107
143
|
});
|
|
@@ -112,7 +148,7 @@ export function registerResources(server, sourceService) {
|
|
|
112
148
|
}
|
|
113
149
|
catch (e) {
|
|
114
150
|
if (isAppError(e))
|
|
115
|
-
return errorResource(uri.href, { message: e.message, code: e.code });
|
|
151
|
+
return errorResource(uri.href, { message: e.message, code: e.code, details: e.details });
|
|
116
152
|
throw e;
|
|
117
153
|
}
|
|
118
154
|
});
|
package/dist/response-utils.d.ts
CHANGED
|
@@ -46,14 +46,29 @@ export declare const TOOL_PRESERVE_PAYLOAD_KEYS: Record<string, ReadonlySet<stri
|
|
|
46
46
|
* payload fields do not leak through as explicit nulls.
|
|
47
47
|
*/
|
|
48
48
|
export declare function compactResponse(obj: Record<string, unknown>, preserveKeys?: ReadonlySet<string>): Record<string, unknown>;
|
|
49
|
-
/**
|
|
50
|
-
|
|
49
|
+
/**
|
|
50
|
+
* resolve-artifact compact: omit debug/diagnostic fields. When `include` is provided,
|
|
51
|
+
* any field protected by a present include group is kept (re-added).
|
|
52
|
+
*/
|
|
53
|
+
export declare function compactArtifactResponse(obj: Record<string, unknown>, include?: ReadonlySet<string>): Record<string, unknown>;
|
|
51
54
|
/** get-class-source compact: drop provenance, artifactContents, qualityFlags. */
|
|
52
55
|
export declare function compactSourceResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
53
56
|
/** get-class-members compact: drop provenance, artifactContents, qualityFlags, context. */
|
|
54
57
|
export declare function compactMembersResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
55
|
-
/**
|
|
56
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Default diagnostic strip for get-class-source / get-class-members. Drops the
|
|
60
|
+
* three diagnostic fields (provenance, artifactContents, qualityFlags) that the
|
|
61
|
+
* common path never needs, applied unless the caller passes includeProvenance.
|
|
62
|
+
* Unlike compactMembersResponse this KEEPS members' `context` — only compact:true
|
|
63
|
+
* drops context. Reuses SOURCE_COMPACT_OMIT_KEYS (exactly those three keys).
|
|
64
|
+
*/
|
|
65
|
+
export declare function stripSourceDiagnostics(obj: Record<string, unknown>): Record<string, unknown>;
|
|
66
|
+
export declare function stripMembersDiagnostics(obj: Record<string, unknown>): Record<string, unknown>;
|
|
67
|
+
/**
|
|
68
|
+
* Light compact projection: drop the artifactContents summary only. When `include`
|
|
69
|
+
* contains "artifact", the summary is kept (re-added).
|
|
70
|
+
*/
|
|
71
|
+
export declare function compactLightResponse(obj: Record<string, unknown>, include?: ReadonlySet<string>): Record<string, unknown>;
|
|
57
72
|
/**
|
|
58
73
|
* Mapping tool compact: project candidates for size reduction.
|
|
59
74
|
*
|
|
@@ -67,3 +82,13 @@ export declare function compactLightResponse(obj: Record<string, unknown>): Reco
|
|
|
67
82
|
* seeing.
|
|
68
83
|
*/
|
|
69
84
|
export declare function compactMappingResponse(obj: Record<string, unknown>): Record<string, unknown>;
|
|
85
|
+
export type ResponseDetailLevel = "summary" | "standard" | "full";
|
|
86
|
+
/** Expert + batch tools that accept the detail/include response contract. */
|
|
87
|
+
export declare const DETAIL_ENABLED_TOOL_NAMES: Set<string>;
|
|
88
|
+
/** Per-tool default detail level, chosen so default output is byte-identical to the old compact defaults. */
|
|
89
|
+
export declare const DEFAULT_DETAIL_BY_TOOL: Record<string, ResponseDetailLevel>;
|
|
90
|
+
/**
|
|
91
|
+
* Project an expert/batch tool result for the requested detail level + include set.
|
|
92
|
+
* Reuses the existing compact omit-sets; see the block comment above for the mapping.
|
|
93
|
+
*/
|
|
94
|
+
export declare function projectByDetail(tool: string, result: Record<string, unknown>, detail: ResponseDetailLevel, include: ReadonlySet<string>): Record<string, unknown>;
|
package/dist/response-utils.js
CHANGED
|
@@ -126,9 +126,32 @@ const ARTIFACT_COMPACT_OMIT_KEYS = new Set([
|
|
|
126
126
|
"repoUrl",
|
|
127
127
|
"resolvedSourceJarPath"
|
|
128
128
|
]);
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
/**
|
|
130
|
+
* include-group => the resolve-artifact fields that group re-adds (un-omits) when present.
|
|
131
|
+
* Used by the detail/include projection so callers can opt specific diagnostics back in.
|
|
132
|
+
*/
|
|
133
|
+
const ARTIFACT_INCLUDE_PROTECTS = {
|
|
134
|
+
provenance: ["provenance"],
|
|
135
|
+
artifact: ["artifactContents"],
|
|
136
|
+
samples: ["sampleEntries"],
|
|
137
|
+
candidates: ["adjacentSourceCandidates"],
|
|
138
|
+
paths: ["binaryJarPath", "resolvedSourceJarPath", "coordinate", "repoUrl"]
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* resolve-artifact compact: omit debug/diagnostic fields. When `include` is provided,
|
|
142
|
+
* any field protected by a present include group is kept (re-added).
|
|
143
|
+
*/
|
|
144
|
+
export function compactArtifactResponse(obj, include) {
|
|
145
|
+
if (!include || include.size === 0) {
|
|
146
|
+
return projectOmitKeys(obj, ARTIFACT_COMPACT_OMIT_KEYS);
|
|
147
|
+
}
|
|
148
|
+
const omit = new Set(ARTIFACT_COMPACT_OMIT_KEYS);
|
|
149
|
+
for (const group of include) {
|
|
150
|
+
for (const protectedKey of ARTIFACT_INCLUDE_PROTECTS[group] ?? []) {
|
|
151
|
+
omit.delete(protectedKey);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return projectOmitKeys(obj, omit);
|
|
132
155
|
}
|
|
133
156
|
/** Fields to omit from get-class-source in compact mode. */
|
|
134
157
|
const SOURCE_COMPACT_OMIT_KEYS = new Set([
|
|
@@ -151,12 +174,31 @@ const MEMBERS_COMPACT_OMIT_KEYS = new Set([
|
|
|
151
174
|
export function compactMembersResponse(obj) {
|
|
152
175
|
return projectOmitKeys(obj, MEMBERS_COMPACT_OMIT_KEYS);
|
|
153
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Default diagnostic strip for get-class-source / get-class-members. Drops the
|
|
179
|
+
* three diagnostic fields (provenance, artifactContents, qualityFlags) that the
|
|
180
|
+
* common path never needs, applied unless the caller passes includeProvenance.
|
|
181
|
+
* Unlike compactMembersResponse this KEEPS members' `context` — only compact:true
|
|
182
|
+
* drops context. Reuses SOURCE_COMPACT_OMIT_KEYS (exactly those three keys).
|
|
183
|
+
*/
|
|
184
|
+
export function stripSourceDiagnostics(obj) {
|
|
185
|
+
return projectOmitKeys(obj, SOURCE_COMPACT_OMIT_KEYS);
|
|
186
|
+
}
|
|
187
|
+
export function stripMembersDiagnostics(obj) {
|
|
188
|
+
return projectOmitKeys(obj, SOURCE_COMPACT_OMIT_KEYS);
|
|
189
|
+
}
|
|
154
190
|
/** Fields to omit from search-class-source / list-artifact-files in compact mode. */
|
|
155
191
|
const LIGHT_COMPACT_OMIT_KEYS = new Set([
|
|
156
192
|
"artifactContents"
|
|
157
193
|
]);
|
|
158
|
-
/**
|
|
159
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Light compact projection: drop the artifactContents summary only. When `include`
|
|
196
|
+
* contains "artifact", the summary is kept (re-added).
|
|
197
|
+
*/
|
|
198
|
+
export function compactLightResponse(obj, include) {
|
|
199
|
+
if (include?.has("artifact")) {
|
|
200
|
+
return obj;
|
|
201
|
+
}
|
|
160
202
|
return projectOmitKeys(obj, LIGHT_COMPACT_OMIT_KEYS);
|
|
161
203
|
}
|
|
162
204
|
/** Max number of unresolved candidates that get full metadata in compact mode. */
|
|
@@ -224,4 +266,52 @@ export function compactMappingResponse(obj) {
|
|
|
224
266
|
}
|
|
225
267
|
return projected;
|
|
226
268
|
}
|
|
269
|
+
/** Expert + batch tools that accept the detail/include response contract. */
|
|
270
|
+
export const DETAIL_ENABLED_TOOL_NAMES = COMPACT_ENABLED_TOOL_NAMES;
|
|
271
|
+
/** Per-tool default detail level, chosen so default output is byte-identical to the old compact defaults. */
|
|
272
|
+
export const DEFAULT_DETAIL_BY_TOOL = {
|
|
273
|
+
"resolve-artifact": "summary",
|
|
274
|
+
"find-mapping": "summary",
|
|
275
|
+
"resolve-method-mapping-exact": "summary",
|
|
276
|
+
"resolve-workspace-symbol": "summary",
|
|
277
|
+
"check-symbol-exists": "summary",
|
|
278
|
+
"get-class-source": "standard",
|
|
279
|
+
"get-class-members": "standard",
|
|
280
|
+
"search-class-source": "standard",
|
|
281
|
+
"list-artifact-files": "standard"
|
|
282
|
+
};
|
|
283
|
+
/** Extra keys omitted from get-class-members at detail=summary (beyond the diagnostic strip). */
|
|
284
|
+
const MEMBERS_SUMMARY_EXTRA_OMIT = new Set(["context"]);
|
|
285
|
+
/**
|
|
286
|
+
* Project an expert/batch tool result for the requested detail level + include set.
|
|
287
|
+
* Reuses the existing compact omit-sets; see the block comment above for the mapping.
|
|
288
|
+
*/
|
|
289
|
+
export function projectByDetail(tool, result, detail, include) {
|
|
290
|
+
let out = result;
|
|
291
|
+
// Phase-4 diagnostic strip for source/members, now detail/include-aware:
|
|
292
|
+
// kept at detail=full or when include opts provenance back in.
|
|
293
|
+
const keepDiagnostics = detail === "full" || include.has("provenance");
|
|
294
|
+
if (!keepDiagnostics) {
|
|
295
|
+
if (tool === "get-class-source")
|
|
296
|
+
out = stripSourceDiagnostics(out);
|
|
297
|
+
if (tool === "get-class-members")
|
|
298
|
+
out = stripMembersDiagnostics(out);
|
|
299
|
+
}
|
|
300
|
+
if (detail === "summary") {
|
|
301
|
+
if (tool === "resolve-artifact") {
|
|
302
|
+
out = compactArtifactResponse(out, include);
|
|
303
|
+
}
|
|
304
|
+
if (COMPACT_MAPPING_TOOL_NAMES.has(tool) && !include.has("candidates")) {
|
|
305
|
+
out = compactMappingResponse(out);
|
|
306
|
+
}
|
|
307
|
+
if (tool === "get-class-members") {
|
|
308
|
+
out = projectOmitKeys(out, MEMBERS_SUMMARY_EXTRA_OMIT);
|
|
309
|
+
}
|
|
310
|
+
if (COMPACT_LIGHT_TOOL_NAMES.has(tool)) {
|
|
311
|
+
out = compactLightResponse(out, include);
|
|
312
|
+
}
|
|
313
|
+
out = compactResponse(out, TOOL_PRESERVE_PAYLOAD_KEYS[tool]);
|
|
314
|
+
}
|
|
315
|
+
return out;
|
|
316
|
+
}
|
|
227
317
|
//# sourceMappingURL=response-utils.js.map
|
|
@@ -11,6 +11,11 @@ function normalizeAccessWidenerNamespace(namespace) {
|
|
|
11
11
|
if (normalized === "named") {
|
|
12
12
|
return "yarn";
|
|
13
13
|
}
|
|
14
|
+
// Fabric/Loom call the obfuscated namespace "official"; treat it as obfuscated
|
|
15
|
+
// (matches the tiny-parser alias) instead of silently assuming intermediary.
|
|
16
|
+
if (normalized === "official") {
|
|
17
|
+
return "obfuscated";
|
|
18
|
+
}
|
|
14
19
|
if (normalized === "obfuscated" ||
|
|
15
20
|
normalized === "mojang" ||
|
|
16
21
|
normalized === "intermediary" ||
|
|
@@ -39,8 +44,13 @@ export async function validateAccessWidener(svc, input) {
|
|
|
39
44
|
const headerNamespaceRaw = normalizeOptionalString(parsed.namespace);
|
|
40
45
|
const overrideMapping = input.mapping ? normalizeMapping(input.mapping) : undefined;
|
|
41
46
|
const headerNamespace = normalizeAccessWidenerNamespace(headerNamespaceRaw);
|
|
42
|
-
if (!headerNamespace &&
|
|
43
|
-
|
|
47
|
+
if (!headerNamespace && !overrideMapping) {
|
|
48
|
+
// No usable namespace resolved and no override: surface the intermediary
|
|
49
|
+
// assumption so it is never silent (previously only warned when a header
|
|
50
|
+
// namespace was present but unsupported).
|
|
51
|
+
warnings.push(headerNamespaceRaw
|
|
52
|
+
? `Unsupported access widener namespace "${headerNamespaceRaw}". Assuming intermediary.`
|
|
53
|
+
: `Access widener namespace not declared; assuming intermediary. Pass mapping=… to set it explicitly.`);
|
|
44
54
|
}
|
|
45
55
|
const awNamespace = overrideMapping ?? headerNamespace ?? "intermediary";
|
|
46
56
|
if (overrideMapping && headerNamespace && overrideMapping !== headerNamespace) {
|
|
@@ -54,7 +54,7 @@ export function hasExactVersionToken(path, version) {
|
|
|
54
54
|
// Avoid prefix false-positives like "1.21.1" matching "1.21.10".
|
|
55
55
|
const cached = VERSION_TOKEN_REGEX_CACHE.get(normalizedVersion);
|
|
56
56
|
const pattern = cached
|
|
57
|
-
?? rememberCachedRegex(VERSION_TOKEN_REGEX_CACHE, normalizedVersion, new RegExp(`(^|[^0-9a-z])${escapeRegexLiteral(normalizedVersion)}([
|
|
57
|
+
?? rememberCachedRegex(VERSION_TOKEN_REGEX_CACHE, normalizedVersion, new RegExp(`(^|[^0-9a-z])${escapeRegexLiteral(normalizedVersion)}(?![0-9a-z]|\\.[0-9])`, "i"));
|
|
58
58
|
return pattern.test(normalizedPath);
|
|
59
59
|
}
|
|
60
60
|
function inferMergedRuntimeNamespaceHint(path) {
|
|
@@ -1228,7 +1228,7 @@ export async function resolveArtifact(svc, input) {
|
|
|
1228
1228
|
resolved.artifactAlias = artifactAlias;
|
|
1229
1229
|
await svc.ingestIfNeeded(resolved);
|
|
1230
1230
|
let sampleEntries;
|
|
1231
|
-
if (input.
|
|
1231
|
+
if (input.includeSampleEntries && resolved.sourceJarPath) {
|
|
1232
1232
|
try {
|
|
1233
1233
|
const javaEntries = await listJavaEntries(resolved.sourceJarPath);
|
|
1234
1234
|
const MAX_SAMPLE = 10;
|
|
@@ -31,5 +31,48 @@ export type MemberSliceResult = {
|
|
|
31
31
|
methods: SignatureMember[];
|
|
32
32
|
truncated: boolean;
|
|
33
33
|
returnedTotal: number;
|
|
34
|
+
/** Absolute offset to resume from when more members remain after this page. */
|
|
35
|
+
nextOffset?: number;
|
|
34
36
|
};
|
|
35
|
-
export declare function sliceMembersWithLimit(remapped: Omit<RemappedMembers, "counts">, totalCount: number, maxMembers: number, warnings: string[]): MemberSliceResult;
|
|
37
|
+
export declare function sliceMembersWithLimit(remapped: Omit<RemappedMembers, "counts">, totalCount: number, maxMembers: number, warnings: string[], offset?: number): MemberSliceResult;
|
|
38
|
+
/** Slim per-member wire shape: only what an agent reading Java needs. */
|
|
39
|
+
export type WireMember = {
|
|
40
|
+
name: string;
|
|
41
|
+
javaSignature: string;
|
|
42
|
+
/**
|
|
43
|
+
* JVM descriptor. Always present on methods/constructors (overload
|
|
44
|
+
* disambiguation for @At/@Shadow matching); omitted on FIELD members by
|
|
45
|
+
* default (the single type is already in javaSignature) unless
|
|
46
|
+
* keepFieldDescriptors is set.
|
|
47
|
+
*/
|
|
48
|
+
jvmDescriptor?: string;
|
|
49
|
+
/** Present only when members span multiple owners (includeInherited). */
|
|
50
|
+
ownerFqn?: string;
|
|
51
|
+
/** Present only when true. */
|
|
52
|
+
isSynthetic?: boolean;
|
|
53
|
+
};
|
|
54
|
+
export type WireMembersBlock = {
|
|
55
|
+
/** Hoisted owner when every member shares one owner (the common, non-inherited case). */
|
|
56
|
+
ownerFqn?: string;
|
|
57
|
+
constructors: WireMember[];
|
|
58
|
+
fields: WireMember[];
|
|
59
|
+
methods: WireMember[];
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Project the internal six-field SignatureMember arrays to the slim wire shape.
|
|
63
|
+
* `ownerFqn` is hoisted to the block level when all members share a single owner
|
|
64
|
+
* (so it is not repeated per member); when members span multiple owners — the
|
|
65
|
+
* includeInherited case — it stays per member and the block-level field is omitted.
|
|
66
|
+
* `accessFlags` is dropped (javaSignature already encodes the modifiers);
|
|
67
|
+
* `isSynthetic` is emitted only when true. `jvmDescriptor` is always kept on
|
|
68
|
+
* methods/constructors (overload disambiguation) and, on FIELD members, only when
|
|
69
|
+
* keepFieldDescriptors is set (the field's single type is already in javaSignature).
|
|
70
|
+
*
|
|
71
|
+
* The owner anchor is derived from the members themselves (not from the looked-up
|
|
72
|
+
* class name) so it is correct in the requested namespace regardless of remapping.
|
|
73
|
+
*/
|
|
74
|
+
export declare function projectMembersForWire(slice: {
|
|
75
|
+
constructors: SignatureMember[];
|
|
76
|
+
fields: SignatureMember[];
|
|
77
|
+
methods: SignatureMember[];
|
|
78
|
+
}, includeInherited: boolean, keepFieldDescriptors?: boolean): WireMembersBlock;
|
|
@@ -23,13 +23,22 @@ export async function remapAndCountMembers(svc, input) {
|
|
|
23
23
|
};
|
|
24
24
|
return { constructors, fields, methods, counts };
|
|
25
25
|
}
|
|
26
|
-
export function sliceMembersWithLimit(remapped, totalCount, maxMembers, warnings) {
|
|
26
|
+
export function sliceMembersWithLimit(remapped, totalCount, maxMembers, warnings, offset = 0) {
|
|
27
|
+
// Members form a single flat sequence in [constructors, fields, methods]
|
|
28
|
+
// order; offset skips that many from the start before taking maxMembers.
|
|
29
|
+
let toSkip = Math.max(0, offset);
|
|
27
30
|
let remaining = maxMembers;
|
|
28
31
|
const takeWithinLimit = (members) => {
|
|
32
|
+
if (toSkip >= members.length) {
|
|
33
|
+
toSkip -= members.length;
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const afterSkip = toSkip > 0 ? members.slice(toSkip) : members;
|
|
37
|
+
toSkip = 0;
|
|
29
38
|
if (remaining <= 0) {
|
|
30
39
|
return [];
|
|
31
40
|
}
|
|
32
|
-
const slice =
|
|
41
|
+
const slice = afterSkip.slice(0, remaining);
|
|
33
42
|
remaining -= slice.length;
|
|
34
43
|
return slice;
|
|
35
44
|
};
|
|
@@ -37,10 +46,48 @@ export function sliceMembersWithLimit(remapped, totalCount, maxMembers, warnings
|
|
|
37
46
|
const fields = takeWithinLimit(remapped.fields);
|
|
38
47
|
const methods = takeWithinLimit(remapped.methods);
|
|
39
48
|
const returnedTotal = constructors.length + fields.length + methods.length;
|
|
40
|
-
const
|
|
49
|
+
const consumed = Math.min(Math.max(0, offset), totalCount) + returnedTotal;
|
|
50
|
+
const truncated = consumed < totalCount;
|
|
41
51
|
if (truncated) {
|
|
42
52
|
warnings.push(`Member list was truncated to ${returnedTotal} entries (from ${totalCount}).`);
|
|
43
53
|
}
|
|
44
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
constructors,
|
|
56
|
+
fields,
|
|
57
|
+
methods,
|
|
58
|
+
truncated,
|
|
59
|
+
returnedTotal,
|
|
60
|
+
...(truncated ? { nextOffset: consumed } : {})
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Project the internal six-field SignatureMember arrays to the slim wire shape.
|
|
65
|
+
* `ownerFqn` is hoisted to the block level when all members share a single owner
|
|
66
|
+
* (so it is not repeated per member); when members span multiple owners — the
|
|
67
|
+
* includeInherited case — it stays per member and the block-level field is omitted.
|
|
68
|
+
* `accessFlags` is dropped (javaSignature already encodes the modifiers);
|
|
69
|
+
* `isSynthetic` is emitted only when true. `jvmDescriptor` is always kept on
|
|
70
|
+
* methods/constructors (overload disambiguation) and, on FIELD members, only when
|
|
71
|
+
* keepFieldDescriptors is set (the field's single type is already in javaSignature).
|
|
72
|
+
*
|
|
73
|
+
* The owner anchor is derived from the members themselves (not from the looked-up
|
|
74
|
+
* class name) so it is correct in the requested namespace regardless of remapping.
|
|
75
|
+
*/
|
|
76
|
+
export function projectMembersForWire(slice, includeInherited, keepFieldDescriptors = false) {
|
|
77
|
+
const owners = new Set([...slice.constructors, ...slice.fields, ...slice.methods].map((m) => m.ownerFqn));
|
|
78
|
+
const hoistOwner = !includeInherited && owners.size === 1;
|
|
79
|
+
const toWire = (m, keepDescriptor) => ({
|
|
80
|
+
name: m.name,
|
|
81
|
+
javaSignature: m.javaSignature,
|
|
82
|
+
...(keepDescriptor ? { jvmDescriptor: m.jvmDescriptor } : {}),
|
|
83
|
+
...(hoistOwner ? {} : { ownerFqn: m.ownerFqn }),
|
|
84
|
+
...(m.isSynthetic ? { isSynthetic: true } : {})
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
...(hoistOwner ? { ownerFqn: [...owners][0] } : {}),
|
|
88
|
+
constructors: slice.constructors.map((m) => toWire(m, true)),
|
|
89
|
+
fields: slice.fields.map((m) => toWire(m, keepFieldDescriptors)),
|
|
90
|
+
methods: slice.methods.map((m) => toWire(m, true))
|
|
91
|
+
};
|
|
45
92
|
}
|
|
46
93
|
//# sourceMappingURL=members-builder.js.map
|
|
@@ -15,5 +15,18 @@ export type SnippetBuildResult = {
|
|
|
15
15
|
returnedEnd: number;
|
|
16
16
|
truncated: boolean;
|
|
17
17
|
charsTruncated: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* First line the caller has NOT yet fully received, when more source remains.
|
|
20
|
+
* Safe to pass back as `startLine` to continue reading. Undefined when the
|
|
21
|
+
* response already reached the end of the file.
|
|
22
|
+
*/
|
|
23
|
+
nextStartLine?: number;
|
|
24
|
+
/**
|
|
25
|
+
* True when the requested window begins past the end of the file. The returned
|
|
26
|
+
* window is empty (returnedEnd < returnedStart) rather than clamped into the
|
|
27
|
+
* last real line, so paginated readers can detect overshoot instead of silently
|
|
28
|
+
* re-reading the final line.
|
|
29
|
+
*/
|
|
30
|
+
outOfRange?: boolean;
|
|
18
31
|
};
|
|
19
32
|
export declare function buildClassSourceSnippet(input: SnippetBuildInput): SnippetBuildResult;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as classSourceHelpers from "../class-source-helpers.js";
|
|
2
|
+
import { sliceToMaxCharsSafe } from "../../text-truncate.js";
|
|
2
3
|
export function buildClassSourceSnippet(input) {
|
|
3
|
-
const
|
|
4
|
+
const rawLines = input.content.split(/\r?\n/);
|
|
5
|
+
// A trailing newline produces a final empty element that is not a real source
|
|
6
|
+
// line. Drop a single one so totalLines and line addressing reflect the actual
|
|
7
|
+
// source (decompiled Java almost always ends with a trailing newline).
|
|
8
|
+
const lines = rawLines.length > 1 && rawLines[rawLines.length - 1] === ""
|
|
9
|
+
? rawLines.slice(0, -1)
|
|
10
|
+
: rawLines;
|
|
4
11
|
const totalLines = lines.length;
|
|
5
12
|
let sourceText;
|
|
6
13
|
let returnedStart;
|
|
@@ -15,7 +22,20 @@ export function buildClassSourceSnippet(input) {
|
|
|
15
22
|
else {
|
|
16
23
|
const requestedStart = input.startLine ?? 1;
|
|
17
24
|
const requestedEnd = input.endLine ?? totalLines;
|
|
18
|
-
|
|
25
|
+
if (requestedStart > totalLines) {
|
|
26
|
+
// The window begins past EOF: return an empty selection instead of clamping
|
|
27
|
+
// into the last real line, so paginated readers can detect the overshoot.
|
|
28
|
+
return {
|
|
29
|
+
sourceText: "",
|
|
30
|
+
totalLines,
|
|
31
|
+
returnedStart: requestedStart,
|
|
32
|
+
returnedEnd: requestedStart - 1,
|
|
33
|
+
truncated: true,
|
|
34
|
+
charsTruncated: false,
|
|
35
|
+
outOfRange: true
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const normalizedStart = Math.max(1, requestedStart);
|
|
19
39
|
const normalizedEnd = Math.min(Math.max(normalizedStart, requestedEnd), Math.max(totalLines, 1));
|
|
20
40
|
let selectedLines = lines.slice(normalizedStart - 1, normalizedEnd);
|
|
21
41
|
const clippedByRange = normalizedStart !== requestedStart || normalizedEnd !== requestedEnd;
|
|
@@ -30,9 +50,38 @@ export function buildClassSourceSnippet(input) {
|
|
|
30
50
|
truncated = clippedByRange || clippedByMax;
|
|
31
51
|
}
|
|
32
52
|
if (input.maxChars != null && sourceText.length > input.maxChars) {
|
|
33
|
-
sourceText = sourceText
|
|
53
|
+
sourceText = sliceToMaxCharsSafe(sourceText, input.maxChars);
|
|
34
54
|
charsTruncated = true;
|
|
35
55
|
truncated = true;
|
|
56
|
+
if (input.mode !== "metadata") {
|
|
57
|
+
const survivingNewlines = (sourceText.match(/\n/g) ?? []).length;
|
|
58
|
+
returnedEnd = sourceText.endsWith("\n")
|
|
59
|
+
? returnedStart + survivingNewlines - 1
|
|
60
|
+
: returnedStart + survivingNewlines;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let nextStartLine;
|
|
64
|
+
// Metadata mode returns a synthesized outline, not a line window into the
|
|
65
|
+
// source, so its returnedStart/returnedEnd are not line-addressable and a
|
|
66
|
+
// char cut must not yield a (bogus) line continuation.
|
|
67
|
+
if (truncated && input.mode !== "metadata") {
|
|
68
|
+
if (charsTruncated) {
|
|
69
|
+
// A mid-line character cut may leave the final returned line partial.
|
|
70
|
+
// Count only the complete (newline-terminated) lines and resume from the
|
|
71
|
+
// first line not fully returned, re-reading any partial line in full.
|
|
72
|
+
// Require forward progress: when the cut lands inside the first returned
|
|
73
|
+
// line (no complete line returned), resuming at the same startLine with
|
|
74
|
+
// the same maxChars would loop, so emit no continuation — the caller must
|
|
75
|
+
// raise maxChars instead.
|
|
76
|
+
const completeLines = (sourceText.match(/\n/g) ?? []).length;
|
|
77
|
+
const resume = returnedStart + completeLines;
|
|
78
|
+
if (resume > returnedStart && resume <= totalLines) {
|
|
79
|
+
nextStartLine = resume;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (returnedEnd < totalLines) {
|
|
83
|
+
nextStartLine = returnedEnd + 1;
|
|
84
|
+
}
|
|
36
85
|
}
|
|
37
86
|
return {
|
|
38
87
|
sourceText,
|
|
@@ -40,7 +89,8 @@ export function buildClassSourceSnippet(input) {
|
|
|
40
89
|
returnedStart,
|
|
41
90
|
returnedEnd,
|
|
42
91
|
truncated,
|
|
43
|
-
charsTruncated
|
|
92
|
+
charsTruncated,
|
|
93
|
+
...(nextStartLine != null ? { nextStartLine } : {})
|
|
44
94
|
};
|
|
45
95
|
}
|
|
46
96
|
//# sourceMappingURL=snippet-builder.js.map
|
|
@@ -9,16 +9,16 @@ export declare function extractDecompiledMembers(className: string, filePath: st
|
|
|
9
9
|
fields: DecompiledMember[];
|
|
10
10
|
methods: DecompiledMember[];
|
|
11
11
|
};
|
|
12
|
-
export declare function computeLineBraceDepths(lines: string[]): number[];
|
|
12
|
+
export declare function computeLineBraceDepths(lines: string[], strippedLines?: string[]): number[];
|
|
13
13
|
export declare function computeBraceRange(lines: string[], symbols: Array<{
|
|
14
14
|
symbolKind: string;
|
|
15
15
|
symbolName: string;
|
|
16
16
|
line: number;
|
|
17
|
-
}>, simpleName: string): {
|
|
17
|
+
}>, simpleName: string, strippedLines?: string[]): {
|
|
18
18
|
declarationLine: number;
|
|
19
19
|
endLine: number;
|
|
20
20
|
} | undefined;
|
|
21
|
-
export declare function scanBraceRange(lines: string[], declarationLine: number): {
|
|
21
|
+
export declare function scanBraceRange(lines: string[], declarationLine: number, strippedLines?: string[]): {
|
|
22
22
|
declarationLine: number;
|
|
23
23
|
endLine: number;
|
|
24
24
|
};
|
|
@@ -28,7 +28,7 @@ export declare function computeNestedTypeRanges(lines: string[], symbols: Array<
|
|
|
28
28
|
}>, outerBody: {
|
|
29
29
|
declarationLine: number;
|
|
30
30
|
endLine: number;
|
|
31
|
-
}): Array<{
|
|
31
|
+
}, strippedLines?: string[]): Array<{
|
|
32
32
|
declarationLine: number;
|
|
33
33
|
endLine: number;
|
|
34
34
|
}>;
|