@adhisang/minecraft-modding-mcp 3.2.0 → 4.1.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 +72 -0
- package/README.md +52 -32
- package/dist/build-suggested-call.d.ts +29 -0
- package/dist/build-suggested-call.js +58 -0
- package/dist/cache-registry.d.ts +3 -1
- package/dist/cache-registry.js +59 -7
- package/dist/config.d.ts +10 -1
- package/dist/config.js +52 -1
- package/dist/entry-tools/analyze-symbol-service.d.ts +18 -18
- package/dist/entry-tools/analyze-symbol-service.js +13 -2
- package/dist/entry-tools/batch-class-members-service.d.ts +34 -0
- package/dist/entry-tools/batch-class-members-service.js +97 -0
- package/dist/entry-tools/batch-class-source-service.d.ts +37 -0
- package/dist/entry-tools/batch-class-source-service.js +100 -0
- package/dist/entry-tools/batch-mappings-service.d.ts +36 -0
- package/dist/entry-tools/batch-mappings-service.js +66 -0
- package/dist/entry-tools/batch-runner.d.ts +72 -0
- package/dist/entry-tools/batch-runner.js +90 -0
- package/dist/entry-tools/batch-symbol-exists-service.d.ts +46 -0
- package/dist/entry-tools/batch-symbol-exists-service.js +113 -0
- package/dist/entry-tools/compare-minecraft-service.d.ts +6 -6
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +83 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.d.ts +6 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +80 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +248 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +60 -0
- package/dist/entry-tools/inspect-minecraft/handlers/file.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/file.js +54 -0
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +100 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +5 -0
- package/dist/entry-tools/inspect-minecraft/handlers/search.js +155 -0
- package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +6 -0
- package/dist/entry-tools/inspect-minecraft/handlers/versions.js +49 -0
- package/dist/entry-tools/inspect-minecraft/internal.d.ts +1042 -0
- package/dist/entry-tools/inspect-minecraft/internal.js +448 -0
- package/dist/entry-tools/inspect-minecraft-service.d.ts +213 -328
- package/dist/entry-tools/inspect-minecraft-service.js +20 -1238
- package/dist/entry-tools/manage-cache-service.d.ts +16 -16
- package/dist/entry-tools/validate-project/cases/access-transformer.d.ts +6 -0
- package/dist/entry-tools/validate-project/cases/access-transformer.js +106 -0
- package/dist/entry-tools/validate-project/cases/access-widener.d.ts +6 -0
- package/dist/entry-tools/validate-project/cases/access-widener.js +86 -0
- package/dist/entry-tools/validate-project/cases/mixin.d.ts +6 -0
- package/dist/entry-tools/validate-project/cases/mixin.js +90 -0
- package/dist/entry-tools/validate-project/cases/project-summary.d.ts +97 -0
- package/dist/entry-tools/validate-project/cases/project-summary.js +346 -0
- package/dist/entry-tools/validate-project/internal.d.ts +135 -0
- package/dist/entry-tools/validate-project/internal.js +287 -0
- package/dist/entry-tools/validate-project-service.d.ts +63 -47
- package/dist/entry-tools/validate-project-service.js +12 -482
- package/dist/entry-tools/verify-mixin-target-service.d.ts +133 -0
- package/dist/entry-tools/verify-mixin-target-service.js +323 -0
- package/dist/error-mapping.d.ts +40 -0
- package/dist/error-mapping.js +139 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +6 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +170 -1314
- package/dist/lru-list.d.ts +31 -0
- package/dist/lru-list.js +102 -0
- package/dist/mapping/internal-types.d.ts +54 -0
- package/dist/mapping/internal-types.js +14 -0
- package/dist/mapping/loaders/mojang.d.ts +2 -0
- package/dist/mapping/loaders/mojang.js +64 -0
- package/dist/mapping/loaders/tiny-loom.d.ts +2 -0
- package/dist/mapping/loaders/tiny-loom.js +73 -0
- package/dist/mapping/loaders/tiny-maven.d.ts +2 -0
- package/dist/mapping/loaders/tiny-maven.js +104 -0
- package/dist/mapping/loaders/types.d.ts +14 -0
- package/dist/mapping/loaders/types.js +2 -0
- package/dist/mapping/lookup.d.ts +52 -0
- package/dist/mapping/lookup.js +496 -0
- package/dist/mapping/parsers/normalize.d.ts +10 -0
- package/dist/mapping/parsers/normalize.js +52 -0
- package/dist/mapping/parsers/proguard.d.ts +20 -0
- package/dist/mapping/parsers/proguard.js +138 -0
- package/dist/mapping/parsers/symbol-records.d.ts +27 -0
- package/dist/mapping/parsers/symbol-records.js +216 -0
- package/dist/mapping/parsers/tiny.d.ts +9 -0
- package/dist/mapping/parsers/tiny.js +96 -0
- package/dist/mapping/types.d.ts +147 -0
- package/dist/mapping/types.js +2 -0
- package/dist/mapping-pipeline-service.d.ts +10 -1
- package/dist/mapping-pipeline-service.js +16 -3
- package/dist/mapping-service.d.ts +15 -144
- package/dist/mapping-service.js +179 -1119
- package/dist/mixin/access-validators.d.ts +9 -0
- package/dist/mixin/access-validators.js +257 -0
- package/dist/mixin/annotation-validators.d.ts +5 -0
- package/dist/mixin/annotation-validators.js +162 -0
- package/dist/mixin/helpers.d.ts +28 -0
- package/dist/mixin/helpers.js +315 -0
- package/dist/mixin/parsed-validator.d.ts +8 -0
- package/dist/mixin/parsed-validator.js +337 -0
- package/dist/mixin/types.d.ts +208 -0
- package/dist/mixin/types.js +28 -0
- package/dist/mixin-validator.d.ts +9 -201
- package/dist/mixin-validator.js +8 -1005
- 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/access-validate.d.ts +4 -0
- package/dist/source/access-validate.js +254 -0
- package/dist/source/artifact-resolver.d.ts +110 -0
- package/dist/source/artifact-resolver.js +1174 -0
- package/dist/source/cache-metrics.d.ts +26 -0
- package/dist/source/cache-metrics.js +172 -0
- package/dist/source/class-source/members-builder.d.ts +34 -0
- package/dist/source/class-source/members-builder.js +46 -0
- package/dist/source/class-source/snippet-builder.d.ts +19 -0
- package/dist/source/class-source/snippet-builder.js +46 -0
- package/dist/source/class-source-helpers.d.ts +34 -0
- package/dist/source/class-source-helpers.js +140 -0
- package/dist/source/class-source.d.ts +42 -0
- package/dist/source/class-source.js +883 -0
- package/dist/source/descriptor-utils.d.ts +6 -0
- package/dist/source/descriptor-utils.js +37 -0
- package/dist/source/file-access.d.ts +4 -0
- package/dist/source/file-access.js +102 -0
- package/dist/source/indexer.d.ts +82 -0
- package/dist/source/indexer.js +505 -0
- package/dist/source/lifecycle/diff-utils.d.ts +9 -0
- package/dist/source/lifecycle/diff-utils.js +107 -0
- package/dist/source/lifecycle/diff.d.ts +2 -0
- package/dist/source/lifecycle/diff.js +265 -0
- package/dist/source/lifecycle/mapping-helpers.d.ts +22 -0
- package/dist/source/lifecycle/mapping-helpers.js +327 -0
- package/dist/source/lifecycle/runtime-check.d.ts +2 -0
- package/dist/source/lifecycle/runtime-check.js +142 -0
- package/dist/source/lifecycle/trace.d.ts +2 -0
- package/dist/source/lifecycle/trace.js +231 -0
- package/dist/source/lifecycle.d.ts +4 -0
- package/dist/source/lifecycle.js +5 -0
- package/dist/source/search.d.ts +51 -0
- package/dist/source/search.js +676 -0
- package/dist/source/shared-utils.d.ts +6 -0
- package/dist/source/shared-utils.js +55 -0
- package/dist/source/state.d.ts +21 -0
- package/dist/source/state.js +19 -0
- package/dist/source/symbol-resolver.d.ts +3 -0
- package/dist/source/symbol-resolver.js +212 -0
- package/dist/source/validate-mixin/pipeline/mapping-health.d.ts +3 -0
- package/dist/source/validate-mixin/pipeline/mapping-health.js +41 -0
- package/dist/source/validate-mixin/pipeline/parse.d.ts +2 -0
- package/dist/source/validate-mixin/pipeline/parse.js +10 -0
- package/dist/source/validate-mixin/pipeline/resolve.d.ts +3 -0
- package/dist/source/validate-mixin/pipeline/resolve.js +78 -0
- package/dist/source/validate-mixin/pipeline/target-lookup.d.ts +6 -0
- package/dist/source/validate-mixin/pipeline/target-lookup.js +260 -0
- package/dist/source/validate-mixin/pipeline-context.d.ts +72 -0
- package/dist/source/validate-mixin/pipeline-context.js +93 -0
- package/dist/source/validate-mixin.d.ts +22 -0
- package/dist/source/validate-mixin.js +799 -0
- package/dist/source/workspace-target.d.ts +18 -0
- package/dist/source/workspace-target.js +305 -0
- package/dist/source-resolver.d.ts +9 -1
- package/dist/source-resolver.js +14 -6
- package/dist/source-service.d.ts +178 -105
- package/dist/source-service.js +72 -5312
- package/dist/stage-emitter.d.ts +13 -0
- package/dist/stage-emitter.js +30 -0
- package/dist/stdio-supervisor.d.ts +61 -0
- package/dist/stdio-supervisor.js +326 -9
- package/dist/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/tool-contract-manifest.d.ts +1 -1
- package/dist/tool-contract-manifest.js +23 -6
- package/dist/tool-guidance.d.ts +82 -0
- package/dist/tool-guidance.js +734 -0
- package/dist/tool-schema-registry.d.ts +16 -0
- package/dist/tool-schema-registry.js +37 -0
- package/dist/tool-schemas.d.ts +3518 -0
- package/dist/tool-schemas.js +813 -0
- package/dist/types.d.ts +39 -0
- package/dist/version-service.js +7 -6
- package/dist/workspace-context-cache.d.ts +32 -0
- package/dist/workspace-context-cache.js +66 -0
- package/dist/workspace-mapping-service.d.ts +16 -0
- package/dist/workspace-mapping-service.js +173 -1
- package/docs/README-ja.md +414 -0
- package/docs/examples.md +483 -0
- package/docs/tool-reference.md +459 -0
- package/package.json +5 -2
package/dist/observability.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface RuntimeMetricSnapshot {
|
|
|
22
22
|
get_file_duration_ms: MetricTimingSnapshot;
|
|
23
23
|
list_files_duration_ms: MetricTimingSnapshot;
|
|
24
24
|
decompile_duration_ms: MetricTimingSnapshot;
|
|
25
|
+
binary_remap_duration_ms: MetricTimingSnapshot;
|
|
25
26
|
search_intent_symbol_duration_ms: MetricTimingSnapshot;
|
|
26
27
|
search_intent_text_duration_ms: MetricTimingSnapshot;
|
|
27
28
|
search_intent_path_duration_ms: MetricTimingSnapshot;
|
|
@@ -47,8 +48,13 @@ export interface RuntimeMetricSnapshot {
|
|
|
47
48
|
cache_artifact_bytes_lru: CacheArtifactByteAccountingRow[];
|
|
48
49
|
cache_hit_rate: number;
|
|
49
50
|
repo_failover_count: number;
|
|
51
|
+
tool_call_counts: Record<string, number>;
|
|
52
|
+
tool_call_duration_ms: Record<string, MetricTimingSnapshot>;
|
|
53
|
+
mapping_resolution_cache_hits: number;
|
|
54
|
+
mapping_resolution_cache_misses: number;
|
|
55
|
+
mapping_resolution_cache_size: number;
|
|
50
56
|
}
|
|
51
|
-
type DurationMetricName = keyof Pick<RuntimeMetricSnapshot, "resolve_duration_ms" | "search_duration_ms" | "get_file_duration_ms" | "list_files_duration_ms" | "decompile_duration_ms" | "search_intent_symbol_duration_ms" | "search_intent_text_duration_ms" | "search_intent_path_duration_ms">;
|
|
57
|
+
type DurationMetricName = keyof Pick<RuntimeMetricSnapshot, "resolve_duration_ms" | "search_duration_ms" | "get_file_duration_ms" | "list_files_duration_ms" | "decompile_duration_ms" | "binary_remap_duration_ms" | "search_intent_symbol_duration_ms" | "search_intent_text_duration_ms" | "search_intent_path_duration_ms">;
|
|
52
58
|
export declare class RuntimeMetrics {
|
|
53
59
|
private readonly timings;
|
|
54
60
|
private cacheHits;
|
|
@@ -74,6 +80,11 @@ export declare class RuntimeMetrics {
|
|
|
74
80
|
private cacheEntries;
|
|
75
81
|
private cacheTotalContentBytes;
|
|
76
82
|
private cacheArtifactBytesLruRef;
|
|
83
|
+
private toolCallCounts;
|
|
84
|
+
private toolCallTimings;
|
|
85
|
+
private mappingResolutionCacheHits;
|
|
86
|
+
private mappingResolutionCacheMisses;
|
|
87
|
+
private mappingResolutionCacheSize;
|
|
77
88
|
constructor();
|
|
78
89
|
recordDuration(name: DurationMetricName, durationMs: number): void;
|
|
79
90
|
recordArtifactCacheHit(): void;
|
|
@@ -97,6 +108,12 @@ export declare class RuntimeMetrics {
|
|
|
97
108
|
setCacheEntries(entries: number): void;
|
|
98
109
|
setCacheTotalContentBytes(totalBytes: number): void;
|
|
99
110
|
setCacheArtifactByteAccountingRef(entries: ReadonlyArray<CacheArtifactByteAccountingRefRow>): void;
|
|
111
|
+
recordToolCall(tool: string, durationMs: number): void;
|
|
112
|
+
setMappingResolutionCacheStats(stats: {
|
|
113
|
+
hits: number;
|
|
114
|
+
misses: number;
|
|
115
|
+
size: number;
|
|
116
|
+
}): void;
|
|
100
117
|
snapshot(): RuntimeMetricSnapshot;
|
|
101
118
|
private toSnapshot;
|
|
102
119
|
private resolveCacheHitRate;
|
package/dist/observability.js
CHANGED
|
@@ -32,6 +32,11 @@ export class RuntimeMetrics {
|
|
|
32
32
|
cacheEntries = 0;
|
|
33
33
|
cacheTotalContentBytes = 0;
|
|
34
34
|
cacheArtifactBytesLruRef = [];
|
|
35
|
+
toolCallCounts = new Map();
|
|
36
|
+
toolCallTimings = new Map();
|
|
37
|
+
mappingResolutionCacheHits = 0;
|
|
38
|
+
mappingResolutionCacheMisses = 0;
|
|
39
|
+
mappingResolutionCacheSize = 0;
|
|
35
40
|
constructor() {
|
|
36
41
|
const names = [
|
|
37
42
|
"resolve_duration_ms",
|
|
@@ -39,6 +44,7 @@ export class RuntimeMetrics {
|
|
|
39
44
|
"get_file_duration_ms",
|
|
40
45
|
"list_files_duration_ms",
|
|
41
46
|
"decompile_duration_ms",
|
|
47
|
+
"binary_remap_duration_ms",
|
|
42
48
|
"search_intent_symbol_duration_ms",
|
|
43
49
|
"search_intent_text_duration_ms",
|
|
44
50
|
"search_intent_path_duration_ms"
|
|
@@ -140,6 +146,27 @@ export class RuntimeMetrics {
|
|
|
140
146
|
setCacheArtifactByteAccountingRef(entries) {
|
|
141
147
|
this.cacheArtifactBytesLruRef = entries;
|
|
142
148
|
}
|
|
149
|
+
recordToolCall(tool, durationMs) {
|
|
150
|
+
this.toolCallCounts.set(tool, (this.toolCallCounts.get(tool) ?? 0) + 1);
|
|
151
|
+
let timing = this.toolCallTimings.get(tool);
|
|
152
|
+
if (!timing) {
|
|
153
|
+
timing = { count: 0, totalMs: 0, lastMs: 0, samples: [] };
|
|
154
|
+
this.toolCallTimings.set(tool, timing);
|
|
155
|
+
}
|
|
156
|
+
const normalizedDuration = Math.max(0, Math.trunc(durationMs));
|
|
157
|
+
timing.count += 1;
|
|
158
|
+
timing.totalMs += normalizedDuration;
|
|
159
|
+
timing.lastMs = normalizedDuration;
|
|
160
|
+
timing.samples.push(normalizedDuration);
|
|
161
|
+
if (timing.samples.length > MAX_TIMING_SAMPLES) {
|
|
162
|
+
timing.samples.shift();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
setMappingResolutionCacheStats(stats) {
|
|
166
|
+
this.mappingResolutionCacheHits = stats.hits;
|
|
167
|
+
this.mappingResolutionCacheMisses = stats.misses;
|
|
168
|
+
this.mappingResolutionCacheSize = stats.size;
|
|
169
|
+
}
|
|
143
170
|
snapshot() {
|
|
144
171
|
return {
|
|
145
172
|
resolve_duration_ms: this.toSnapshot("resolve_duration_ms"),
|
|
@@ -147,6 +174,7 @@ export class RuntimeMetrics {
|
|
|
147
174
|
get_file_duration_ms: this.toSnapshot("get_file_duration_ms"),
|
|
148
175
|
list_files_duration_ms: this.toSnapshot("list_files_duration_ms"),
|
|
149
176
|
decompile_duration_ms: this.toSnapshot("decompile_duration_ms"),
|
|
177
|
+
binary_remap_duration_ms: this.toSnapshot("binary_remap_duration_ms"),
|
|
150
178
|
search_intent_symbol_duration_ms: this.toSnapshot("search_intent_symbol_duration_ms"),
|
|
151
179
|
search_intent_text_duration_ms: this.toSnapshot("search_intent_text_duration_ms"),
|
|
152
180
|
search_intent_path_duration_ms: this.toSnapshot("search_intent_path_duration_ms"),
|
|
@@ -175,7 +203,22 @@ export class RuntimeMetrics {
|
|
|
175
203
|
updated_at: entry.updatedAt
|
|
176
204
|
})),
|
|
177
205
|
cache_hit_rate: this.resolveCacheHitRate(),
|
|
178
|
-
repo_failover_count: this.repoFailoverCount
|
|
206
|
+
repo_failover_count: this.repoFailoverCount,
|
|
207
|
+
tool_call_counts: Object.fromEntries(this.toolCallCounts),
|
|
208
|
+
tool_call_duration_ms: Object.fromEntries([...this.toolCallTimings].map(([tool, timing]) => [
|
|
209
|
+
tool,
|
|
210
|
+
{
|
|
211
|
+
count: timing.count,
|
|
212
|
+
totalMs: timing.totalMs,
|
|
213
|
+
avgMs: timing.count > 0 ? timing.totalMs / timing.count : 0,
|
|
214
|
+
lastMs: timing.lastMs,
|
|
215
|
+
p95Ms: percentile(timing.samples, 95),
|
|
216
|
+
p99Ms: percentile(timing.samples, 99)
|
|
217
|
+
}
|
|
218
|
+
])),
|
|
219
|
+
mapping_resolution_cache_hits: this.mappingResolutionCacheHits,
|
|
220
|
+
mapping_resolution_cache_misses: this.mappingResolutionCacheMisses,
|
|
221
|
+
mapping_resolution_cache_size: this.mappingResolutionCacheSize
|
|
179
222
|
};
|
|
180
223
|
}
|
|
181
224
|
toSnapshot(name) {
|
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
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SourceService } from "../source-service.js";
|
|
2
|
+
import type { ValidateAccessTransformerInput, ValidateAccessTransformerOutput, ValidateAccessWidenerInput, ValidateAccessWidenerOutput } from "../source-service.js";
|
|
3
|
+
export declare function validateAccessWidener(svc: SourceService, input: ValidateAccessWidenerInput): Promise<ValidateAccessWidenerOutput>;
|
|
4
|
+
export declare function validateAccessTransformer(svc: SourceService, input: ValidateAccessTransformerInput): Promise<ValidateAccessTransformerOutput>;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { parseAccessTransformer } from "../access-transformer-parser.js";
|
|
2
|
+
import { parseAccessWidener } from "../access-widener-parser.js";
|
|
3
|
+
import { ERROR_CODES, createError } from "../errors.js";
|
|
4
|
+
import { validateParsedAccessTransformer, validateParsedAccessWidener } from "../mixin-validator.js";
|
|
5
|
+
import { normalizeMapping, normalizeOptionalString } from "./shared-utils.js";
|
|
6
|
+
function normalizeAccessWidenerNamespace(namespace) {
|
|
7
|
+
const normalized = namespace?.trim().toLowerCase();
|
|
8
|
+
if (!normalized) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
if (normalized === "named") {
|
|
12
|
+
return "yarn";
|
|
13
|
+
}
|
|
14
|
+
if (normalized === "obfuscated" ||
|
|
15
|
+
normalized === "mojang" ||
|
|
16
|
+
normalized === "intermediary" ||
|
|
17
|
+
normalized === "yarn") {
|
|
18
|
+
return normalized;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
function isSourceMappingNamespace(namespace) {
|
|
23
|
+
return (namespace === "obfuscated" ||
|
|
24
|
+
namespace === "mojang" ||
|
|
25
|
+
namespace === "intermediary" ||
|
|
26
|
+
namespace === "yarn");
|
|
27
|
+
}
|
|
28
|
+
export async function validateAccessWidener(svc, input) {
|
|
29
|
+
const version = input.version.trim();
|
|
30
|
+
if (!version) {
|
|
31
|
+
throw createError({ code: ERROR_CODES.INVALID_INPUT, message: "version must be non-empty." });
|
|
32
|
+
}
|
|
33
|
+
const content = input.content;
|
|
34
|
+
if (!content.trim()) {
|
|
35
|
+
throw createError({ code: ERROR_CODES.INVALID_INPUT, message: "content must be non-empty." });
|
|
36
|
+
}
|
|
37
|
+
const warnings = [];
|
|
38
|
+
const parsed = parseAccessWidener(content);
|
|
39
|
+
const headerNamespaceRaw = normalizeOptionalString(parsed.namespace);
|
|
40
|
+
const overrideMapping = input.mapping ? normalizeMapping(input.mapping) : undefined;
|
|
41
|
+
const headerNamespace = normalizeAccessWidenerNamespace(headerNamespaceRaw);
|
|
42
|
+
if (!headerNamespace && headerNamespaceRaw && !overrideMapping) {
|
|
43
|
+
warnings.push(`Unsupported access widener namespace "${headerNamespaceRaw}". Assuming intermediary.`);
|
|
44
|
+
}
|
|
45
|
+
const awNamespace = overrideMapping ?? headerNamespace ?? "intermediary";
|
|
46
|
+
if (overrideMapping && headerNamespace && overrideMapping !== headerNamespace) {
|
|
47
|
+
warnings.push(`Using mapping override "${overrideMapping}" instead of header namespace "${headerNamespaceRaw}".`);
|
|
48
|
+
}
|
|
49
|
+
const runtimeAware = input.projectPath != null || input.scope != null || input.preferProjectVersion === true;
|
|
50
|
+
let resolvedVersion = version;
|
|
51
|
+
let jarPath;
|
|
52
|
+
let lookupMapping = "obfuscated";
|
|
53
|
+
let provenance;
|
|
54
|
+
if (runtimeAware) {
|
|
55
|
+
provenance = await svc.resolveAccessWidenerRuntimeArtifact({
|
|
56
|
+
version,
|
|
57
|
+
awNamespace,
|
|
58
|
+
projectPath: input.projectPath,
|
|
59
|
+
scope: input.scope,
|
|
60
|
+
preferProjectVersion: input.preferProjectVersion
|
|
61
|
+
});
|
|
62
|
+
resolvedVersion = provenance.version;
|
|
63
|
+
jarPath = provenance.jarPath;
|
|
64
|
+
lookupMapping = provenance.mappingApplied;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
({ jarPath } = await svc.versionService.resolveVersionJar(version));
|
|
68
|
+
}
|
|
69
|
+
const needsLookupMapping = awNamespace !== lookupMapping;
|
|
70
|
+
// Collect unique class FQNs from entries
|
|
71
|
+
const classFqns = new Set();
|
|
72
|
+
for (const entry of parsed.entries) {
|
|
73
|
+
const fqn = entry.target.replace(/\//g, ".");
|
|
74
|
+
classFqns.add(fqn);
|
|
75
|
+
}
|
|
76
|
+
const membersByClass = new Map();
|
|
77
|
+
for (const fqn of classFqns) {
|
|
78
|
+
let lookupFqn = fqn;
|
|
79
|
+
if (needsLookupMapping) {
|
|
80
|
+
try {
|
|
81
|
+
const mapped = await svc.mappingService.findMapping({
|
|
82
|
+
version: resolvedVersion,
|
|
83
|
+
kind: "class",
|
|
84
|
+
name: fqn,
|
|
85
|
+
sourceMapping: awNamespace,
|
|
86
|
+
targetMapping: lookupMapping,
|
|
87
|
+
sourcePriority: input.sourcePriority,
|
|
88
|
+
projectPath: input.projectPath
|
|
89
|
+
});
|
|
90
|
+
if (mapped.resolved && mapped.resolvedSymbol) {
|
|
91
|
+
lookupFqn = mapped.resolvedSymbol.name;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
warnings.push(`Could not map class "${fqn}" from ${awNamespace} to ${lookupMapping}.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
warnings.push(`Mapping lookup failed for class "${fqn}".`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const sig = await svc.explorerService.getSignature({
|
|
103
|
+
fqn: lookupFqn,
|
|
104
|
+
jarPath,
|
|
105
|
+
access: "all"
|
|
106
|
+
});
|
|
107
|
+
warnings.push(...sig.warnings);
|
|
108
|
+
let constructors = sig.constructors;
|
|
109
|
+
let methods = sig.methods;
|
|
110
|
+
let fields = sig.fields;
|
|
111
|
+
if (needsLookupMapping) {
|
|
112
|
+
const [ctorResult, methodResult, fieldResult] = await Promise.all([
|
|
113
|
+
svc.remapSignatureMembers(sig.constructors, "method", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath),
|
|
114
|
+
svc.remapSignatureMembers(sig.methods, "method", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath),
|
|
115
|
+
svc.remapSignatureMembers(sig.fields, "field", resolvedVersion, lookupMapping, awNamespace, input.sourcePriority, warnings, input.projectPath)
|
|
116
|
+
]);
|
|
117
|
+
constructors = ctorResult.members;
|
|
118
|
+
methods = methodResult.members;
|
|
119
|
+
fields = fieldResult.members;
|
|
120
|
+
}
|
|
121
|
+
membersByClass.set(fqn, {
|
|
122
|
+
className: fqn,
|
|
123
|
+
classAccessFlags: sig.classAccessFlags,
|
|
124
|
+
constructors,
|
|
125
|
+
methods,
|
|
126
|
+
fields
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
warnings.push(`Could not load signature for class "${lookupFqn}".`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const result = validateParsedAccessWidener(parsed, membersByClass, warnings, {
|
|
134
|
+
includeRuntimeEvidence: runtimeAware
|
|
135
|
+
});
|
|
136
|
+
if (provenance) {
|
|
137
|
+
result.provenance = provenance;
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
export async function validateAccessTransformer(svc, input) {
|
|
142
|
+
const version = input.version.trim();
|
|
143
|
+
if (!version) {
|
|
144
|
+
throw createError({ code: ERROR_CODES.INVALID_INPUT, message: "version must be non-empty." });
|
|
145
|
+
}
|
|
146
|
+
const content = input.content;
|
|
147
|
+
if (!content.trim()) {
|
|
148
|
+
throw createError({ code: ERROR_CODES.INVALID_INPUT, message: "content must be non-empty." });
|
|
149
|
+
}
|
|
150
|
+
const warnings = [];
|
|
151
|
+
const parsed = parseAccessTransformer(content);
|
|
152
|
+
const atNamespace = await svc.resolveAccessTransformerNamespace({
|
|
153
|
+
atNamespace: input.atNamespace,
|
|
154
|
+
projectPath: input.projectPath
|
|
155
|
+
});
|
|
156
|
+
const runtimeAware = input.projectPath != null || input.scope != null || input.preferProjectVersion === true;
|
|
157
|
+
let resolvedVersion = version;
|
|
158
|
+
let jarPath;
|
|
159
|
+
let lookupMapping = "obfuscated";
|
|
160
|
+
let provenance;
|
|
161
|
+
if (runtimeAware) {
|
|
162
|
+
provenance = await svc.resolveAccessTransformerRuntimeArtifact({
|
|
163
|
+
version,
|
|
164
|
+
atNamespace,
|
|
165
|
+
projectPath: input.projectPath,
|
|
166
|
+
scope: input.scope,
|
|
167
|
+
preferProjectVersion: input.preferProjectVersion
|
|
168
|
+
});
|
|
169
|
+
resolvedVersion = provenance.version;
|
|
170
|
+
jarPath = provenance.jarPath;
|
|
171
|
+
lookupMapping = provenance.mappingApplied;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
if (atNamespace === "srg") {
|
|
175
|
+
throw createError({
|
|
176
|
+
code: ERROR_CODES.INVALID_INPUT,
|
|
177
|
+
message: "atNamespace=srg requires projectPath and scope=loader so a Forge runtime jar can be resolved."
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
({ jarPath } = await svc.versionService.resolveVersionJar(version));
|
|
181
|
+
}
|
|
182
|
+
const needsLookupMapping = atNamespace !== lookupMapping;
|
|
183
|
+
const classFqns = new Set(parsed.entries.map((entry) => entry.owner));
|
|
184
|
+
const membersByClass = new Map();
|
|
185
|
+
for (const fqn of classFqns) {
|
|
186
|
+
let lookupFqn = fqn;
|
|
187
|
+
if (needsLookupMapping) {
|
|
188
|
+
if (!isSourceMappingNamespace(atNamespace) || !isSourceMappingNamespace(lookupMapping)) {
|
|
189
|
+
warnings.push(`Could not map class "${fqn}" from ${atNamespace} to ${lookupMapping}.`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
try {
|
|
193
|
+
const mapped = await svc.mappingService.findMapping({
|
|
194
|
+
version: resolvedVersion,
|
|
195
|
+
kind: "class",
|
|
196
|
+
name: fqn,
|
|
197
|
+
sourceMapping: atNamespace,
|
|
198
|
+
targetMapping: lookupMapping,
|
|
199
|
+
sourcePriority: input.sourcePriority,
|
|
200
|
+
projectPath: input.projectPath
|
|
201
|
+
});
|
|
202
|
+
if (mapped.resolved && mapped.resolvedSymbol) {
|
|
203
|
+
lookupFqn = mapped.resolvedSymbol.name;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
warnings.push(`Could not map class "${fqn}" from ${atNamespace} to ${lookupMapping}.`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
warnings.push(`Mapping lookup failed for class "${fqn}".`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const sig = await svc.explorerService.getSignature({
|
|
216
|
+
fqn: lookupFqn,
|
|
217
|
+
jarPath,
|
|
218
|
+
access: "all"
|
|
219
|
+
});
|
|
220
|
+
warnings.push(...sig.warnings);
|
|
221
|
+
let constructors = sig.constructors;
|
|
222
|
+
let methods = sig.methods;
|
|
223
|
+
let fields = sig.fields;
|
|
224
|
+
if (needsLookupMapping && isSourceMappingNamespace(atNamespace) && isSourceMappingNamespace(lookupMapping)) {
|
|
225
|
+
const [ctorResult, methodResult, fieldResult] = await Promise.all([
|
|
226
|
+
svc.remapSignatureMembers(sig.constructors, "method", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath),
|
|
227
|
+
svc.remapSignatureMembers(sig.methods, "method", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath),
|
|
228
|
+
svc.remapSignatureMembers(sig.fields, "field", resolvedVersion, lookupMapping, atNamespace, input.sourcePriority, warnings, input.projectPath)
|
|
229
|
+
]);
|
|
230
|
+
constructors = ctorResult.members;
|
|
231
|
+
methods = methodResult.members;
|
|
232
|
+
fields = fieldResult.members;
|
|
233
|
+
}
|
|
234
|
+
membersByClass.set(fqn, {
|
|
235
|
+
className: fqn,
|
|
236
|
+
classAccessFlags: sig.classAccessFlags,
|
|
237
|
+
constructors,
|
|
238
|
+
methods,
|
|
239
|
+
fields
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
warnings.push(`Could not load signature for class "${lookupFqn}".`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const result = validateParsedAccessTransformer(parsed, membersByClass, warnings, {
|
|
247
|
+
includeRuntimeEvidence: runtimeAware
|
|
248
|
+
});
|
|
249
|
+
if (provenance) {
|
|
250
|
+
result.provenance = provenance;
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=access-validate.js.map
|