@adhisang/minecraft-modding-mcp 6.1.1 → 6.3.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +40 -1
  2. package/README.md +12 -4
  3. package/dist/cache-registry.d.ts +1 -1
  4. package/dist/cache-registry.js +3 -0
  5. package/dist/entry-tools/analyze-mod-service.d.ts +12 -6
  6. package/dist/entry-tools/analyze-mod-service.js +37 -3
  7. package/dist/entry-tools/analyze-symbol-service.d.ts +6 -4
  8. package/dist/entry-tools/analyze-symbol-service.js +37 -2
  9. package/dist/entry-tools/inspect-minecraft/internal.d.ts +7 -3
  10. package/dist/entry-tools/inspect-minecraft/internal.js +43 -15
  11. package/dist/entry-tools/inspect-minecraft-service.d.ts +12 -12
  12. package/dist/entry-tools/inspect-minecraft-service.js +1 -1
  13. package/dist/entry-tools/manage-cache-service.d.ts +4 -4
  14. package/dist/error-mapping.d.ts +13 -0
  15. package/dist/error-mapping.js +35 -2
  16. package/dist/errors.d.ts +2 -0
  17. package/dist/errors.js +2 -0
  18. package/dist/index.js +39 -20
  19. package/dist/mapping/internal-types.d.ts +7 -0
  20. package/dist/mapping/types.d.ts +18 -0
  21. package/dist/mapping-service.js +16 -3
  22. package/dist/minecraft-explorer-service.d.ts +4 -0
  23. package/dist/minecraft-explorer-service.js +156 -17
  24. package/dist/mod-analyzer.d.ts +7 -0
  25. package/dist/mod-analyzer.js +28 -7
  26. package/dist/source/artifact-resolver.d.ts +2 -0
  27. package/dist/source/artifact-resolver.js +24 -1
  28. package/dist/source/class-source/members-builder.d.ts +4 -0
  29. package/dist/source/class-source/members-builder.js +3 -1
  30. package/dist/source/class-source.d.ts +3 -1
  31. package/dist/source/class-source.js +192 -19
  32. package/dist/source/did-you-mean.d.ts +14 -0
  33. package/dist/source/did-you-mean.js +79 -0
  34. package/dist/source/file-access.js +159 -3
  35. package/dist/source/indexer.js +72 -2
  36. package/dist/source/lifecycle/runtime-check.js +9 -5
  37. package/dist/source/nested-jars.d.ts +78 -0
  38. package/dist/source/nested-jars.js +267 -0
  39. package/dist/source/workspace-target.js +5 -2
  40. package/dist/source-jar-reader.d.ts +16 -0
  41. package/dist/source-jar-reader.js +82 -0
  42. package/dist/source-service.d.ts +37 -0
  43. package/dist/source-service.js +52 -6
  44. package/dist/stage-emitter.js +24 -8
  45. package/dist/stdio-supervisor.d.ts +92 -9
  46. package/dist/stdio-supervisor.js +915 -103
  47. package/dist/tool-contract-manifest.js +2 -2
  48. package/dist/tool-guidance.js +115 -7
  49. package/dist/tool-schemas.d.ts +1343 -149
  50. package/dist/tool-schemas.js +39 -7
  51. package/dist/types.d.ts +23 -0
  52. package/dist/workspace-mapping-service.d.ts +1 -0
  53. package/dist/workspace-mapping-service.js +120 -8
  54. package/docs/README-ja.md +4 -0
  55. package/docs/tool-reference.md +92 -6
  56. package/package.json +5 -5
@@ -3,6 +3,7 @@ import { loadConfig } from "./config.js";
3
3
  import { artifactSignatureFromFile, normalizeJarPath } from "./path-resolver.js";
4
4
  import { createJarEntryReader } from "./source-jar-reader.js";
5
5
  import { matchesMemberPattern } from "./source/member-pattern.js";
6
+ import { isUnobfuscatedVersion } from "./version-service.js";
6
7
  const CLASSFILE_MAGIC = 0xcafebabe;
7
8
  const MAX_INHERITANCE_DEPTH = 64;
8
9
  const ACC_PUBLIC = 0x0001;
@@ -173,6 +174,21 @@ function toInternalName(fqn) {
173
174
  function extractVersionFromPath(inputPath) {
174
175
  return inputPath.match(/(\d+\.\d+(?:\.\d+)?)/)?.[1];
175
176
  }
177
+ // Super classes/interfaces from these packages are never inside a Minecraft
178
+ // jar, so failing to resolve them during inherited-member expansion is
179
+ // expected, not a signal. Suppression is allowlist-only and per-prefix
180
+ // verified: JDK packages by definition, com.mojang.serialization because the
181
+ // DataFixerUpper serialization library ships as its own dependency jar
182
+ // (checked against 26.x client-only/common and 1.21.10 client jars). A broad
183
+ // com.mojang.* entry would be wrong — com.mojang.blaze3d.* IS client-jar
184
+ // content and its resolution failures must stay visible.
185
+ const KNOWN_ABSENT_PLATFORM_PREFIXES = [
186
+ "java/",
187
+ "javax/",
188
+ "jdk/",
189
+ "sun/",
190
+ "com/mojang/serialization/"
191
+ ];
176
192
  class SignatureCacheStore {
177
193
  maxEntries;
178
194
  nodes = new Map();
@@ -305,16 +321,111 @@ function readOptionalClassName(cp, index) {
305
321
  }
306
322
  return readClassName(cp, index);
307
323
  }
324
+ function descriptorToClassName(descriptor) {
325
+ if (descriptor.startsWith("L") && descriptor.endsWith(";")) {
326
+ return descriptor.slice(1, -1).replace(/\//g, ".");
327
+ }
328
+ return descriptor;
329
+ }
330
+ function readNumericConstant(cp, index) {
331
+ const entry = cp[index];
332
+ if (entry && (entry.tag === 3 || entry.tag === 4 || entry.tag === 5 || entry.tag === 6)) {
333
+ return String(entry.numericValue);
334
+ }
335
+ return "<unknown-constant>";
336
+ }
337
+ // JVMS 4.7.16.1 element_value, rendered as compact Java-ish text. Every
338
+ // branch reads exactly its encoded bytes so nested/array values stay aligned.
339
+ function readElementValue(reader, cp) {
340
+ const tag = String.fromCharCode(reader.readU1());
341
+ switch (tag) {
342
+ case "B":
343
+ case "I":
344
+ case "S":
345
+ case "D":
346
+ case "F":
347
+ case "J":
348
+ return readNumericConstant(cp, reader.readU2());
349
+ case "C": {
350
+ const raw = readNumericConstant(cp, reader.readU2());
351
+ const code = Number(raw);
352
+ return Number.isFinite(code) ? `'${String.fromCharCode(code)}'` : raw;
353
+ }
354
+ case "Z": {
355
+ const raw = readNumericConstant(cp, reader.readU2());
356
+ return raw === "1" ? "true" : raw === "0" ? "false" : raw;
357
+ }
358
+ case "s":
359
+ return JSON.stringify(readUtf8(cp, reader.readU2()));
360
+ case "e": {
361
+ const typeDescriptor = readUtf8(cp, reader.readU2());
362
+ const constantName = readUtf8(cp, reader.readU2());
363
+ return `${descriptorToClassName(typeDescriptor)}.${constantName}`;
364
+ }
365
+ case "c":
366
+ return `${descriptorToClassName(readUtf8(cp, reader.readU2()))}.class`;
367
+ case "@":
368
+ return readAnnotationText(reader, cp);
369
+ case "[": {
370
+ const count = reader.readU2();
371
+ const parts = [];
372
+ for (let index = 0; index < count; index += 1) {
373
+ parts.push(readElementValue(reader, cp));
374
+ }
375
+ return `{${parts.join(", ")}}`;
376
+ }
377
+ default:
378
+ return "<unsupported-element-value>";
379
+ }
380
+ }
381
+ function readAnnotationText(reader, cp) {
382
+ const typeDescriptor = readUtf8(cp, reader.readU2());
383
+ const pairCount = reader.readU2();
384
+ const pairs = [];
385
+ for (let index = 0; index < pairCount; index += 1) {
386
+ const name = readUtf8(cp, reader.readU2());
387
+ pairs.push(`${name} = ${readElementValue(reader, cp)}`);
388
+ }
389
+ return `@${descriptorToClassName(typeDescriptor)}${pairs.length > 0 ? `(${pairs.join(", ")})` : ""}`;
390
+ }
308
391
  function readAttributes(reader, cp, count) {
309
392
  const names = [];
393
+ let annotationDefault;
394
+ let annotations;
310
395
  for (let index = 0; index < count; index += 1) {
311
396
  const nameIndex = reader.readU2();
312
397
  const length = reader.readU4();
313
398
  const attributeName = readUtf8(cp, nameIndex);
314
399
  names.push(attributeName);
315
- reader.skip(length);
400
+ const body = reader.readBytes(length);
401
+ // Malformed attribute bodies must never fail the whole class parse; the
402
+ // rendered value is best-effort metadata, not a structural field.
403
+ if (attributeName === "AnnotationDefault") {
404
+ try {
405
+ annotationDefault = readElementValue(new ByteReader(body), cp);
406
+ }
407
+ catch {
408
+ annotationDefault = undefined;
409
+ }
410
+ }
411
+ else if (attributeName === "RuntimeVisibleAnnotations") {
412
+ try {
413
+ const bodyReader = new ByteReader(body);
414
+ const annotationCount = bodyReader.readU2();
415
+ const rendered = [];
416
+ for (let a = 0; a < annotationCount; a += 1) {
417
+ rendered.push(readAnnotationText(bodyReader, cp));
418
+ }
419
+ if (rendered.length > 0) {
420
+ annotations = rendered;
421
+ }
422
+ }
423
+ catch {
424
+ annotations = undefined;
425
+ }
426
+ }
316
427
  }
317
- return names;
428
+ return { names, annotationDefault, annotations };
318
429
  }
319
430
  function parseClassFile(buffer) {
320
431
  const reader = new ByteReader(buffer);
@@ -336,17 +447,28 @@ function parseClassFile(buffer) {
336
447
  cp[index] = { tag: 1, value: reader.readBytes(length).toString("utf8") };
337
448
  break;
338
449
  }
339
- case 3:
340
- case 4:
341
- reader.skip(4);
342
- cp[index] = { tag };
450
+ case 3: {
451
+ const bytes = reader.readBytes(4);
452
+ cp[index] = { tag, numericValue: bytes.readInt32BE(0) };
453
+ break;
454
+ }
455
+ case 4: {
456
+ const bytes = reader.readBytes(4);
457
+ cp[index] = { tag, numericValue: bytes.readFloatBE(0) };
343
458
  break;
344
- case 5:
345
- case 6:
346
- reader.skip(8);
347
- cp[index] = { tag };
459
+ }
460
+ case 5: {
461
+ const bytes = reader.readBytes(8);
462
+ cp[index] = { tag, numericValue: bytes.readBigInt64BE(0).toString() };
348
463
  index += 1;
349
464
  break;
465
+ }
466
+ case 6: {
467
+ const bytes = reader.readBytes(8);
468
+ cp[index] = { tag, numericValue: bytes.readDoubleBE(0) };
469
+ index += 1;
470
+ break;
471
+ }
350
472
  case 7:
351
473
  case 8:
352
474
  case 16:
@@ -389,13 +511,17 @@ function parseClassFile(buffer) {
389
511
  const nameIndex = reader.readU2();
390
512
  const descriptorIndex = reader.readU2();
391
513
  const attributesCount = reader.readU2();
392
- const attributeNames = readAttributes(reader, cp, attributesCount);
514
+ const attributeResult = readAttributes(reader, cp, attributesCount);
393
515
  members.push({
394
516
  name: readUtf8(cp, nameIndex),
395
517
  descriptor: readUtf8(cp, descriptorIndex),
396
518
  accessFlags,
397
519
  isSynthetic: (accessFlags & ACC_SYNTHETIC) !== 0 ||
398
- attributeNames.some((attributeName) => attributeName === "Synthetic")
520
+ attributeResult.names.some((attributeName) => attributeName === "Synthetic"),
521
+ ...(attributeResult.annotationDefault !== undefined
522
+ ? { annotationDefault: attributeResult.annotationDefault }
523
+ : {}),
524
+ ...(attributeResult.annotations ? { annotations: attributeResult.annotations } : {})
399
525
  });
400
526
  }
401
527
  return members;
@@ -478,6 +604,9 @@ export class MinecraftExplorerService {
478
604
  const parsedClassCache = new Map([[parsed.internalName, parsed]]);
479
605
  const warnings = [];
480
606
  const warnMissingInheritedClass = (internalName, relation) => {
607
+ if (KNOWN_ABSENT_PLATFORM_PREFIXES.some((prefix) => internalName.startsWith(prefix))) {
608
+ return;
609
+ }
481
610
  warnings.push(`Could not resolve ${relation} class "${internalName.replace(/\//g, ".")}" while expanding inherited members.`);
482
611
  };
483
612
  const readParsedClassByInternalName = async (internalName, relation) => {
@@ -572,7 +701,9 @@ export class MinecraftExplorerService {
572
701
  javaSignature: `${modifiers ? `${modifiers} ` : ""}${fieldType} ${member.name}`.trim(),
573
702
  jvmDescriptor: member.descriptor,
574
703
  accessFlags: member.accessFlags,
575
- isSynthetic: member.isSynthetic
704
+ isSynthetic: member.isSynthetic,
705
+ ...(member.annotationDefault !== undefined ? { annotationDefault: member.annotationDefault } : {}),
706
+ ...(member.annotations ? { annotations: member.annotations } : {})
576
707
  };
577
708
  }
578
709
  const parsedMethod = parseMethodDescriptor(member.descriptor);
@@ -585,7 +716,9 @@ export class MinecraftExplorerService {
585
716
  javaSignature: `${modifiers ? `${modifiers} ` : ""}${ownerSimpleClassName}(${args})`.trim(),
586
717
  jvmDescriptor: member.descriptor,
587
718
  accessFlags: member.accessFlags,
588
- isSynthetic: member.isSynthetic
719
+ isSynthetic: member.isSynthetic,
720
+ ...(member.annotationDefault !== undefined ? { annotationDefault: member.annotationDefault } : {}),
721
+ ...(member.annotations ? { annotations: member.annotations } : {})
589
722
  };
590
723
  }
591
724
  return {
@@ -594,7 +727,9 @@ export class MinecraftExplorerService {
594
727
  javaSignature: `${modifiers ? `${modifiers} ` : ""}${parsedMethod.returnType} ${member.name}(${args})`.trim(),
595
728
  jvmDescriptor: member.descriptor,
596
729
  accessFlags: member.accessFlags,
597
- isSynthetic: member.isSynthetic
730
+ isSynthetic: member.isSynthetic,
731
+ ...(member.annotationDefault !== undefined ? { annotationDefault: member.annotationDefault } : {}),
732
+ ...(member.annotations ? { annotations: member.annotations } : {})
598
733
  };
599
734
  };
600
735
  const shouldIncludeMember = (member) => {
@@ -652,10 +787,14 @@ export class MinecraftExplorerService {
652
787
  };
653
788
  }
654
789
  contextForJar(jarPath) {
790
+ const minecraftVersion = extractVersionFromPath(jarPath);
655
791
  return {
656
- minecraftVersion: extractVersionFromPath(jarPath) ?? "unknown",
792
+ minecraftVersion: minecraftVersion ?? "unknown",
657
793
  mappingType: "unknown",
658
- mappingNamespace: "obfuscated",
794
+ // Unobfuscated releases ship mojang names in their bytecode; claiming
795
+ // "obfuscated" for them misled namespace reconciliation downstream.
796
+ // With no derivable version the conservative "obfuscated" stands.
797
+ mappingNamespace: minecraftVersion && isUnobfuscatedVersion(minecraftVersion) ? "mojang" : "obfuscated",
659
798
  jarHash: artifactSignatureFromFile(jarPath).sourceArtifactId,
660
799
  generatedAt: new Date().toISOString()
661
800
  };
@@ -19,8 +19,15 @@ export interface ModAnalysisResult {
19
19
  dependencies?: ModDependency[];
20
20
  classCount: number;
21
21
  classes?: string[];
22
+ /**
23
+ * In-archive paths of bundled Jar-in-Jar nested jars (META-INF/jars scan
24
+ * plus present-and-safe fabric.mod.json "jars" declarations). Absent when
25
+ * the mod bundles none.
26
+ */
27
+ nestedJars?: string[];
22
28
  }
23
29
  export interface AnalyzeModOptions {
24
30
  includeClasses?: boolean;
25
31
  }
32
+ export declare function collectNestedJars(entries: string[], declared: string[] | undefined): string[];
26
33
  export declare function analyzeModJar(jarPath: string, options?: AnalyzeModOptions): Promise<ModAnalysisResult>;
@@ -1,7 +1,7 @@
1
1
  import { parse as parseToml } from "smol-toml";
2
2
  import { z } from "zod";
3
3
  import { AppError, ERROR_CODES } from "./errors.js";
4
- import { normalizeJarPath } from "./path-resolver.js";
4
+ import { isSecureJarEntryPath, normalizeJarPath } from "./path-resolver.js";
5
5
  import { listJarEntries, readJarEntryAsUtf8 } from "./source-jar-reader.js";
6
6
  function toErrorMessage(value) {
7
7
  if (value instanceof Error) {
@@ -32,7 +32,8 @@ const fabricModJsonSchema = z
32
32
  depends: z.record(z.union([z.string(), z.array(z.string())])).optional(),
33
33
  recommends: z.record(z.union([z.string(), z.array(z.string())])).optional(),
34
34
  conflicts: z.record(z.union([z.string(), z.array(z.string())])).optional(),
35
- suggests: z.record(z.union([z.string(), z.array(z.string())])).optional()
35
+ suggests: z.record(z.union([z.string(), z.array(z.string())])).optional(),
36
+ jars: z.array(z.object({ file: z.string() }).passthrough()).optional()
36
37
  })
37
38
  .passthrough();
38
39
  const quiltModJsonSchema = z
@@ -120,6 +121,7 @@ function parseFabricMod(content) {
120
121
  ...collectFabricDeps(mod.conflicts, "conflicts"),
121
122
  ...collectFabricDeps(mod.suggests, "optional")
122
123
  ];
124
+ const declaredNestedJars = mod.jars?.map((entry) => entry.file);
123
125
  return {
124
126
  modId: mod.id,
125
127
  modName: mod.name,
@@ -128,9 +130,25 @@ function parseFabricMod(content) {
128
130
  entrypoints,
129
131
  mixinConfigs,
130
132
  accessWidener: mod.accessWidener,
131
- dependencies: dependencies.length > 0 ? dependencies : undefined
133
+ dependencies: dependencies.length > 0 ? dependencies : undefined,
134
+ ...(declaredNestedJars && declaredNestedJars.length > 0 ? { declaredNestedJars } : {})
132
135
  };
133
136
  }
137
+ // Nested-jar inventory: every real `.jar` entry directly under META-INF/jars/
138
+ // plus declared fabric.mod.json "jars" files that actually exist in the
139
+ // archive under a safe (non-escaping) path. Declared-but-absent or escaping
140
+ // paths are dropped — the inventory never names content the archive cannot
141
+ // safely serve.
142
+ export function collectNestedJars(entries, declared) {
143
+ const present = new Set(entries);
144
+ const collected = new Set(entries.filter((entry) => /^META-INF\/jars\/[^/]+\.jar$/.test(entry)));
145
+ for (const file of declared ?? []) {
146
+ if (isSecureJarEntryPath(file) && present.has(file) && file.endsWith(".jar")) {
147
+ collected.add(file);
148
+ }
149
+ }
150
+ return [...collected].sort((left, right) => left.localeCompare(right));
151
+ }
134
152
  // ---------------------------------------------------------------------------
135
153
  // Parser: Quilt
136
154
  // ---------------------------------------------------------------------------
@@ -350,20 +368,23 @@ export async function analyzeModJar(jarPath, options) {
350
368
  // graceful fallback
351
369
  }
352
370
  }
371
+ const { declaredNestedJars, ...metadataRest } = metadata;
372
+ const nestedJars = collectNestedJars(entries, declaredNestedJars);
353
373
  return {
354
374
  loader,
355
375
  jarKind,
356
- ...metadata,
357
- ...(packagedAccessTransformers.length > 0 || metadata.accessTransformers
376
+ ...metadataRest,
377
+ ...(packagedAccessTransformers.length > 0 || metadataRest.accessTransformers
358
378
  ? {
359
379
  accessTransformers: [...new Set([
360
- ...(metadata.accessTransformers ?? []),
380
+ ...(metadataRest.accessTransformers ?? []),
361
381
  ...packagedAccessTransformers
362
382
  ])]
363
383
  }
364
384
  : {}),
365
385
  classCount,
366
- ...(classes !== undefined ? { classes } : {})
386
+ ...(classes !== undefined ? { classes } : {}),
387
+ ...(nestedJars.length > 0 ? { nestedJars } : {})
367
388
  };
368
389
  }
369
390
  //# sourceMappingURL=mod-analyzer.js.map
@@ -7,6 +7,8 @@ export type VersionSourceDiscovery = {
7
7
  candidateArtifacts: string[];
8
8
  selectedSourceJarPath?: string;
9
9
  selectedHasMinecraftNamespace?: boolean;
10
+ /** The other half of a Loom split-source pair (common/clientOnly), when present. */
11
+ companionSourceJarPaths?: string[];
10
12
  };
11
13
  type RuntimeJarCandidate = {
12
14
  jarPath: string;
@@ -206,13 +206,32 @@ export async function discoverVersionSourceJar(_svc, input) {
206
206
  const candidateArtifacts = candidates
207
207
  .slice(0, 20)
208
208
  .map((candidate) => `${candidate.jarPath}#java=${candidate.javaEntryCount}#net_minecraft=${candidate.hasMinecraftNamespace ? 1 : 0}`);
209
+ // Loom split-source workspaces publish the version as a common/clientOnly
210
+ // PAIR with no merged jar; selecting one loses the other half's classes
211
+ // (e.g. net.minecraft.client.* when common wins). Surface the best-scored
212
+ // jar of the other half so ingestion can index both.
213
+ const selectedHalf = selected ? splitSourceHalf(selected.jarPath) : undefined;
214
+ const companion = selectedHalf
215
+ ? candidates.find((candidate) => candidate !== selected &&
216
+ candidate.looksLikeMinecraftArtifact &&
217
+ splitSourceHalf(candidate.jarPath) !== undefined &&
218
+ splitSourceHalf(candidate.jarPath) !== selectedHalf &&
219
+ // Version affinity: a leftover other-half jar from a different
220
+ // version must never be spliced into this version's index.
221
+ hasExactVersionToken(candidate.jarPath, input.version))
222
+ : undefined;
209
223
  return {
210
224
  searchedPaths,
211
225
  candidateArtifacts,
212
226
  selectedSourceJarPath: selected?.jarPath,
213
- selectedHasMinecraftNamespace: selected?.hasMinecraftNamespace
227
+ selectedHasMinecraftNamespace: selected?.hasMinecraftNamespace,
228
+ ...(companion ? { companionSourceJarPaths: [companion.jarPath] } : {})
214
229
  };
215
230
  }
231
+ function splitSourceHalf(jarPath) {
232
+ const match = /minecraft-(common|clientonly)/i.exec(jarPath);
233
+ return match ? match[1].toLowerCase() : undefined;
234
+ }
216
235
  export async function probeMinecraftArtifact(svc, input) {
217
236
  let value = input.target.value.trim();
218
237
  const warnings = [];
@@ -1171,6 +1190,10 @@ export async function resolveArtifact(svc, input) {
1171
1190
  if (dependencyProvenance) {
1172
1191
  provenance.dependencyResolution = dependencyProvenance;
1173
1192
  }
1193
+ if (versionSourceDiscovery?.companionSourceJarPaths?.length &&
1194
+ resolved.sourceJarPath === versionSourceDiscovery.selectedSourceJarPath) {
1195
+ provenance.companionSourceJars = versionSourceDiscovery.companionSourceJarPaths;
1196
+ }
1174
1197
  if (dependencyOrigin && dependencyRequestedMapping && dependencyRequestedMapping !== "obfuscated") {
1175
1198
  const coord = resolved.coordinate ?? value;
1176
1199
  warnings.push(`Dependency artifact ${coord} mapping "${dependencyRequestedMapping}" is not enforced (binary remap is disabled for non-vanilla artifacts); the JAR is returned in its native namespace and mappingApplied is reported as "obfuscated" with qualityFlag "dependency-mapping-unverified". Caller must validate symbol availability.`);
@@ -50,6 +50,10 @@ export type WireMember = {
50
50
  ownerFqn?: string;
51
51
  /** Present only when true. */
52
52
  isSynthetic?: boolean;
53
+ /** Rendered default value of an annotation-type member. */
54
+ annotationDefault?: string;
55
+ /** Runtime-visible annotations; present only under the opt-in projection. */
56
+ annotations?: string[];
53
57
  };
54
58
  export type WireMembersBlock = {
55
59
  /** Hoisted owner when every member shares one owner (the common, non-inherited case). */
@@ -82,7 +82,9 @@ export function projectMembersForWire(slice, includeInherited, keepFieldDescript
82
82
  javaSignature: m.javaSignature,
83
83
  ...(keepDescriptor ? { jvmDescriptor: m.jvmDescriptor } : {}),
84
84
  ...(hoistOwner ? {} : { ownerFqn: m.ownerFqn }),
85
- ...(m.isSynthetic ? { isSynthetic: true } : {})
85
+ ...(m.isSynthetic ? { isSynthetic: true } : {}),
86
+ ...(m.annotationDefault !== undefined ? { annotationDefault: m.annotationDefault } : {}),
87
+ ...(m.annotations?.length ? { annotations: m.annotations } : {})
86
88
  });
87
89
  return {
88
90
  ...(hoistOwner ? { ownerFqn: [...owners][0] } : {}),
@@ -37,7 +37,7 @@ export declare function buildFallbackProvenance(svc: SourceService, input: {
37
37
  requestedMapping: SourceMapping;
38
38
  mappingApplied: SourceMapping;
39
39
  }): ArtifactProvenance;
40
- export declare function buildClassSourceNotFoundError(_svc: SourceService, input: {
40
+ export declare function buildClassSourceNotFoundError(svc: SourceService, input: {
41
41
  className: string;
42
42
  lookupClassName: string;
43
43
  artifactId: string;
@@ -51,6 +51,7 @@ export declare function buildClassSourceNotFoundError(_svc: SourceService, input
51
51
  scope?: ArtifactScope;
52
52
  projectPath?: string;
53
53
  version?: string;
54
+ nestedJars?: string[];
54
55
  }): AppError;
55
56
  export declare function buildDecompiledFallback(svc: SourceService, artifactId: string, lookupClassName: string, memberPattern: string | undefined, maxMembers: number): {
56
57
  fallback: DecompiledFallback;
@@ -58,5 +59,6 @@ export declare function buildDecompiledFallback(svc: SourceService, artifactId:
58
59
  truncated: boolean;
59
60
  } | undefined;
60
61
  export declare function findClass(svc: SourceService, input: FindClassInput): FindClassOutput;
62
+ export declare function findClassIncludingNested(svc: SourceService, input: FindClassInput): Promise<FindClassOutput>;
61
63
  export declare function getClassSource(svc: SourceService, input: GetClassSourceInput): Promise<GetClassSourceOutput>;
62
64
  export declare function getClassMembers(svc: SourceService, input: GetClassMembersInput): Promise<GetClassMembersOutput>;