@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.
Files changed (194) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +52 -32
  3. package/dist/build-suggested-call.d.ts +29 -0
  4. package/dist/build-suggested-call.js +58 -0
  5. package/dist/cache-registry.d.ts +3 -1
  6. package/dist/cache-registry.js +59 -7
  7. package/dist/config.d.ts +10 -1
  8. package/dist/config.js +52 -1
  9. package/dist/entry-tools/analyze-symbol-service.d.ts +18 -18
  10. package/dist/entry-tools/analyze-symbol-service.js +13 -2
  11. package/dist/entry-tools/batch-class-members-service.d.ts +34 -0
  12. package/dist/entry-tools/batch-class-members-service.js +97 -0
  13. package/dist/entry-tools/batch-class-source-service.d.ts +37 -0
  14. package/dist/entry-tools/batch-class-source-service.js +100 -0
  15. package/dist/entry-tools/batch-mappings-service.d.ts +36 -0
  16. package/dist/entry-tools/batch-mappings-service.js +66 -0
  17. package/dist/entry-tools/batch-runner.d.ts +72 -0
  18. package/dist/entry-tools/batch-runner.js +90 -0
  19. package/dist/entry-tools/batch-symbol-exists-service.d.ts +46 -0
  20. package/dist/entry-tools/batch-symbol-exists-service.js +113 -0
  21. package/dist/entry-tools/compare-minecraft-service.d.ts +6 -6
  22. package/dist/entry-tools/inspect-minecraft/handlers/artifact.d.ts +5 -0
  23. package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +83 -0
  24. package/dist/entry-tools/inspect-minecraft/handlers/class-members.d.ts +6 -0
  25. package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +80 -0
  26. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.d.ts +5 -0
  27. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +248 -0
  28. package/dist/entry-tools/inspect-minecraft/handlers/class-source.d.ts +5 -0
  29. package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +60 -0
  30. package/dist/entry-tools/inspect-minecraft/handlers/file.d.ts +5 -0
  31. package/dist/entry-tools/inspect-minecraft/handlers/file.js +54 -0
  32. package/dist/entry-tools/inspect-minecraft/handlers/list-files.d.ts +5 -0
  33. package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +100 -0
  34. package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +5 -0
  35. package/dist/entry-tools/inspect-minecraft/handlers/search.js +155 -0
  36. package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +6 -0
  37. package/dist/entry-tools/inspect-minecraft/handlers/versions.js +49 -0
  38. package/dist/entry-tools/inspect-minecraft/internal.d.ts +1042 -0
  39. package/dist/entry-tools/inspect-minecraft/internal.js +448 -0
  40. package/dist/entry-tools/inspect-minecraft-service.d.ts +213 -328
  41. package/dist/entry-tools/inspect-minecraft-service.js +20 -1238
  42. package/dist/entry-tools/manage-cache-service.d.ts +16 -16
  43. package/dist/entry-tools/validate-project/cases/access-transformer.d.ts +6 -0
  44. package/dist/entry-tools/validate-project/cases/access-transformer.js +106 -0
  45. package/dist/entry-tools/validate-project/cases/access-widener.d.ts +6 -0
  46. package/dist/entry-tools/validate-project/cases/access-widener.js +86 -0
  47. package/dist/entry-tools/validate-project/cases/mixin.d.ts +6 -0
  48. package/dist/entry-tools/validate-project/cases/mixin.js +90 -0
  49. package/dist/entry-tools/validate-project/cases/project-summary.d.ts +97 -0
  50. package/dist/entry-tools/validate-project/cases/project-summary.js +346 -0
  51. package/dist/entry-tools/validate-project/internal.d.ts +135 -0
  52. package/dist/entry-tools/validate-project/internal.js +287 -0
  53. package/dist/entry-tools/validate-project-service.d.ts +63 -47
  54. package/dist/entry-tools/validate-project-service.js +12 -482
  55. package/dist/entry-tools/verify-mixin-target-service.d.ts +133 -0
  56. package/dist/entry-tools/verify-mixin-target-service.js +323 -0
  57. package/dist/error-mapping.d.ts +40 -0
  58. package/dist/error-mapping.js +139 -0
  59. package/dist/errors.d.ts +6 -0
  60. package/dist/errors.js +6 -0
  61. package/dist/index.d.ts +2 -0
  62. package/dist/index.js +170 -1314
  63. package/dist/lru-list.d.ts +31 -0
  64. package/dist/lru-list.js +102 -0
  65. package/dist/mapping/internal-types.d.ts +54 -0
  66. package/dist/mapping/internal-types.js +14 -0
  67. package/dist/mapping/loaders/mojang.d.ts +2 -0
  68. package/dist/mapping/loaders/mojang.js +64 -0
  69. package/dist/mapping/loaders/tiny-loom.d.ts +2 -0
  70. package/dist/mapping/loaders/tiny-loom.js +73 -0
  71. package/dist/mapping/loaders/tiny-maven.d.ts +2 -0
  72. package/dist/mapping/loaders/tiny-maven.js +104 -0
  73. package/dist/mapping/loaders/types.d.ts +14 -0
  74. package/dist/mapping/loaders/types.js +2 -0
  75. package/dist/mapping/lookup.d.ts +52 -0
  76. package/dist/mapping/lookup.js +496 -0
  77. package/dist/mapping/parsers/normalize.d.ts +10 -0
  78. package/dist/mapping/parsers/normalize.js +52 -0
  79. package/dist/mapping/parsers/proguard.d.ts +20 -0
  80. package/dist/mapping/parsers/proguard.js +138 -0
  81. package/dist/mapping/parsers/symbol-records.d.ts +27 -0
  82. package/dist/mapping/parsers/symbol-records.js +216 -0
  83. package/dist/mapping/parsers/tiny.d.ts +9 -0
  84. package/dist/mapping/parsers/tiny.js +96 -0
  85. package/dist/mapping/types.d.ts +147 -0
  86. package/dist/mapping/types.js +2 -0
  87. package/dist/mapping-pipeline-service.d.ts +10 -1
  88. package/dist/mapping-pipeline-service.js +16 -3
  89. package/dist/mapping-service.d.ts +15 -144
  90. package/dist/mapping-service.js +179 -1119
  91. package/dist/mixin/access-validators.d.ts +9 -0
  92. package/dist/mixin/access-validators.js +257 -0
  93. package/dist/mixin/annotation-validators.d.ts +5 -0
  94. package/dist/mixin/annotation-validators.js +162 -0
  95. package/dist/mixin/helpers.d.ts +28 -0
  96. package/dist/mixin/helpers.js +315 -0
  97. package/dist/mixin/parsed-validator.d.ts +8 -0
  98. package/dist/mixin/parsed-validator.js +337 -0
  99. package/dist/mixin/types.d.ts +208 -0
  100. package/dist/mixin/types.js +28 -0
  101. package/dist/mixin-validator.d.ts +9 -201
  102. package/dist/mixin-validator.js +8 -1005
  103. package/dist/observability.d.ts +18 -1
  104. package/dist/observability.js +44 -1
  105. package/dist/response-utils.d.ts +44 -10
  106. package/dist/response-utils.js +131 -17
  107. package/dist/source/access-validate.d.ts +4 -0
  108. package/dist/source/access-validate.js +254 -0
  109. package/dist/source/artifact-resolver.d.ts +110 -0
  110. package/dist/source/artifact-resolver.js +1174 -0
  111. package/dist/source/cache-metrics.d.ts +26 -0
  112. package/dist/source/cache-metrics.js +172 -0
  113. package/dist/source/class-source/members-builder.d.ts +34 -0
  114. package/dist/source/class-source/members-builder.js +46 -0
  115. package/dist/source/class-source/snippet-builder.d.ts +19 -0
  116. package/dist/source/class-source/snippet-builder.js +46 -0
  117. package/dist/source/class-source-helpers.d.ts +34 -0
  118. package/dist/source/class-source-helpers.js +140 -0
  119. package/dist/source/class-source.d.ts +42 -0
  120. package/dist/source/class-source.js +883 -0
  121. package/dist/source/descriptor-utils.d.ts +6 -0
  122. package/dist/source/descriptor-utils.js +37 -0
  123. package/dist/source/file-access.d.ts +4 -0
  124. package/dist/source/file-access.js +102 -0
  125. package/dist/source/indexer.d.ts +82 -0
  126. package/dist/source/indexer.js +505 -0
  127. package/dist/source/lifecycle/diff-utils.d.ts +9 -0
  128. package/dist/source/lifecycle/diff-utils.js +107 -0
  129. package/dist/source/lifecycle/diff.d.ts +2 -0
  130. package/dist/source/lifecycle/diff.js +265 -0
  131. package/dist/source/lifecycle/mapping-helpers.d.ts +22 -0
  132. package/dist/source/lifecycle/mapping-helpers.js +327 -0
  133. package/dist/source/lifecycle/runtime-check.d.ts +2 -0
  134. package/dist/source/lifecycle/runtime-check.js +142 -0
  135. package/dist/source/lifecycle/trace.d.ts +2 -0
  136. package/dist/source/lifecycle/trace.js +231 -0
  137. package/dist/source/lifecycle.d.ts +4 -0
  138. package/dist/source/lifecycle.js +5 -0
  139. package/dist/source/search.d.ts +51 -0
  140. package/dist/source/search.js +676 -0
  141. package/dist/source/shared-utils.d.ts +6 -0
  142. package/dist/source/shared-utils.js +55 -0
  143. package/dist/source/state.d.ts +21 -0
  144. package/dist/source/state.js +19 -0
  145. package/dist/source/symbol-resolver.d.ts +3 -0
  146. package/dist/source/symbol-resolver.js +212 -0
  147. package/dist/source/validate-mixin/pipeline/mapping-health.d.ts +3 -0
  148. package/dist/source/validate-mixin/pipeline/mapping-health.js +41 -0
  149. package/dist/source/validate-mixin/pipeline/parse.d.ts +2 -0
  150. package/dist/source/validate-mixin/pipeline/parse.js +10 -0
  151. package/dist/source/validate-mixin/pipeline/resolve.d.ts +3 -0
  152. package/dist/source/validate-mixin/pipeline/resolve.js +78 -0
  153. package/dist/source/validate-mixin/pipeline/target-lookup.d.ts +6 -0
  154. package/dist/source/validate-mixin/pipeline/target-lookup.js +260 -0
  155. package/dist/source/validate-mixin/pipeline-context.d.ts +72 -0
  156. package/dist/source/validate-mixin/pipeline-context.js +93 -0
  157. package/dist/source/validate-mixin.d.ts +22 -0
  158. package/dist/source/validate-mixin.js +799 -0
  159. package/dist/source/workspace-target.d.ts +18 -0
  160. package/dist/source/workspace-target.js +305 -0
  161. package/dist/source-resolver.d.ts +9 -1
  162. package/dist/source-resolver.js +14 -6
  163. package/dist/source-service.d.ts +178 -105
  164. package/dist/source-service.js +72 -5312
  165. package/dist/stage-emitter.d.ts +13 -0
  166. package/dist/stage-emitter.js +30 -0
  167. package/dist/stdio-supervisor.d.ts +61 -0
  168. package/dist/stdio-supervisor.js +326 -9
  169. package/dist/storage/artifacts-repo.d.ts +4 -1
  170. package/dist/storage/artifacts-repo.js +33 -5
  171. package/dist/storage/files-repo.d.ts +0 -2
  172. package/dist/storage/files-repo.js +0 -11
  173. package/dist/storage/migrations.d.ts +1 -1
  174. package/dist/storage/migrations.js +10 -2
  175. package/dist/storage/schema.d.ts +2 -0
  176. package/dist/storage/schema.js +25 -0
  177. package/dist/tool-contract-manifest.d.ts +1 -1
  178. package/dist/tool-contract-manifest.js +23 -6
  179. package/dist/tool-guidance.d.ts +82 -0
  180. package/dist/tool-guidance.js +734 -0
  181. package/dist/tool-schema-registry.d.ts +16 -0
  182. package/dist/tool-schema-registry.js +37 -0
  183. package/dist/tool-schemas.d.ts +3518 -0
  184. package/dist/tool-schemas.js +813 -0
  185. package/dist/types.d.ts +39 -0
  186. package/dist/version-service.js +7 -6
  187. package/dist/workspace-context-cache.d.ts +32 -0
  188. package/dist/workspace-context-cache.js +66 -0
  189. package/dist/workspace-mapping-service.d.ts +16 -0
  190. package/dist/workspace-mapping-service.js +173 -1
  191. package/docs/README-ja.md +414 -0
  192. package/docs/examples.md +483 -0
  193. package/docs/tool-reference.md +459 -0
  194. package/package.json +5 -2
@@ -0,0 +1,26 @@
1
+ import type { SourceService } from "../source-service.js";
2
+ export declare function hasAnyFiles(svc: SourceService, artifactId: string): boolean;
3
+ /**
4
+ * Best-effort cleanup of `<cacheDir>/remapped/<artifactId>.jar` written by
5
+ * the binary-remap path. Called from cache-eviction so the Mojang-remapped
6
+ * binary jar does not outlive the artifact row that owns it. Also releases
7
+ * the jar's bytes from `state.cacheTotalContentBytes`. Errors are
8
+ * swallowed: orphaned jars remain visible to `manage-cache` under the
9
+ * `binary-remap` cache kind and can be reclaimed there.
10
+ */
11
+ export declare function unlinkRemappedJarForArtifact(svc: SourceService, artifactId: string): void;
12
+ /**
13
+ * Add the remapped jar's on-disk size to `state.cacheTotalContentBytes` so
14
+ * the `enforceCacheLimits` byte gate sees the jar before deciding to evict.
15
+ * Without this, a Mojang-remapped client jar (tens of MB) can accumulate
16
+ * silently while the indexed-source byte total stays below `maxCacheBytes`.
17
+ */
18
+ export declare function recordRemappedJarBytes(svc: SourceService, artifactId: string, sizeBytes: number): void;
19
+ export declare function releaseRemappedJarBytes(svc: SourceService, artifactId: string): void;
20
+ export declare function enforceCacheLimits(svc: SourceService): void;
21
+ export declare function refreshCacheMetrics(svc: SourceService): void;
22
+ export declare function touchCacheMetrics(svc: SourceService, artifactId: string, updatedAt: string): void;
23
+ export declare function upsertCacheMetrics(svc: SourceService, artifactId: string, totalContentBytes: number, updatedAt: string): void;
24
+ export declare function removeCacheMetrics(svc: SourceService, artifactId: string, publish?: boolean): void;
25
+ export declare function publishCacheMetrics(svc: SourceService): void;
26
+ export declare function snapshotLruAccounting(svc: SourceService): void;
@@ -0,0 +1,172 @@
1
+ import { existsSync, readdirSync, statSync, unlinkSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { log } from "../logger.js";
4
+ export function hasAnyFiles(svc, artifactId) {
5
+ return svc.filesRepo.listFiles(artifactId, { limit: 1 }).items.length > 0;
6
+ }
7
+ /**
8
+ * Best-effort cleanup of `<cacheDir>/remapped/<artifactId>.jar` written by
9
+ * the binary-remap path. Called from cache-eviction so the Mojang-remapped
10
+ * binary jar does not outlive the artifact row that owns it. Also releases
11
+ * the jar's bytes from `state.cacheTotalContentBytes`. Errors are
12
+ * swallowed: orphaned jars remain visible to `manage-cache` under the
13
+ * `binary-remap` cache kind and can be reclaimed there.
14
+ */
15
+ export function unlinkRemappedJarForArtifact(svc, artifactId) {
16
+ releaseRemappedJarBytes(svc, artifactId);
17
+ const remappedJarPath = join(svc.config.cacheDir, "remapped", `${artifactId}.jar`);
18
+ try {
19
+ if (existsSync(remappedJarPath)) {
20
+ unlinkSync(remappedJarPath);
21
+ }
22
+ }
23
+ catch {
24
+ // ignore: orphaned jar is still reclaimable via manage-cache binary-remap kind.
25
+ }
26
+ }
27
+ /**
28
+ * Add the remapped jar's on-disk size to `state.cacheTotalContentBytes` so
29
+ * the `enforceCacheLimits` byte gate sees the jar before deciding to evict.
30
+ * Without this, a Mojang-remapped client jar (tens of MB) can accumulate
31
+ * silently while the indexed-source byte total stays below `maxCacheBytes`.
32
+ */
33
+ export function recordRemappedJarBytes(svc, artifactId, sizeBytes) {
34
+ const normalized = Math.max(0, Math.trunc(sizeBytes));
35
+ const existing = svc.state.remappedJarBytes.get(artifactId) ?? 0;
36
+ svc.state.cacheTotalContentBytes = Math.max(0, svc.state.cacheTotalContentBytes - existing + normalized);
37
+ svc.state.remappedJarBytes.set(artifactId, normalized);
38
+ publishCacheMetrics(svc);
39
+ }
40
+ export function releaseRemappedJarBytes(svc, artifactId) {
41
+ const existing = svc.state.remappedJarBytes.get(artifactId);
42
+ if (!existing) {
43
+ return;
44
+ }
45
+ svc.state.cacheTotalContentBytes = Math.max(0, svc.state.cacheTotalContentBytes - existing);
46
+ svc.state.remappedJarBytes.delete(artifactId);
47
+ publishCacheMetrics(svc);
48
+ }
49
+ export function enforceCacheLimits(svc) {
50
+ let artifactCount = svc.state.lru.size;
51
+ let totalBytes = svc.state.cacheTotalContentBytes;
52
+ if (artifactCount <= svc.config.maxArtifacts && totalBytes <= svc.config.maxCacheBytes) {
53
+ return;
54
+ }
55
+ const candidates = svc.state.lru.toArray();
56
+ for (const candidate of candidates) {
57
+ const shouldEvict = artifactCount > svc.config.maxArtifacts || totalBytes > svc.config.maxCacheBytes;
58
+ if (!shouldEvict || artifactCount <= 1) {
59
+ break;
60
+ }
61
+ const artifactCountBefore = artifactCount;
62
+ const totalBytesBefore = totalBytes;
63
+ const remappedBytesForCandidate = svc.state.remappedJarBytes.get(candidate.key) ?? 0;
64
+ svc.filesRepo.deleteFilesForArtifact(candidate.key);
65
+ svc.artifactsRepo.deleteArtifact(candidate.key);
66
+ unlinkRemappedJarForArtifact(svc, candidate.key);
67
+ removeCacheMetrics(svc, candidate.key, false);
68
+ artifactCount = Math.max(0, artifactCount - 1);
69
+ totalBytes = Math.max(0, totalBytes - candidate.value.totalContentBytes - remappedBytesForCandidate);
70
+ svc.metrics.recordCacheEviction();
71
+ log("warn", "cache.evict", {
72
+ artifactId: candidate.key,
73
+ artifactCountBefore,
74
+ totalBytesBefore,
75
+ artifactBytes: candidate.value.totalContentBytes + remappedBytesForCandidate
76
+ });
77
+ }
78
+ publishCacheMetrics(svc);
79
+ }
80
+ export function refreshCacheMetrics(svc) {
81
+ const cacheEntries = svc.artifactsRepo.countArtifacts();
82
+ const totalContentBytes = svc.artifactsRepo.totalContentBytes();
83
+ const lruAccounting = svc.artifactsRepo.listArtifactsByLruWithContentBytes(Math.max(cacheEntries, 1));
84
+ svc.state.lru.clear();
85
+ for (const row of lruAccounting) {
86
+ svc.state.lru.upsert(row.artifactId, {
87
+ totalContentBytes: row.totalContentBytes,
88
+ updatedAt: row.updatedAt
89
+ });
90
+ }
91
+ svc.state.remappedJarBytes.clear();
92
+ let remappedTotal = 0;
93
+ const remappedDir = join(svc.config.cacheDir, "remapped");
94
+ if (existsSync(remappedDir)) {
95
+ // Only count remapped jars whose owning artifact is still in the LRU set.
96
+ // Orphaned jars (artifact deleted, prior unlink lost a race, externally
97
+ // placed) stay visible to manage-cache under the `binary-remap` kind
98
+ // for prune, but must not be folded into `cacheTotalContentBytes` here:
99
+ // enforceCacheLimits cannot evict them, so counting their bytes would
100
+ // force unrelated live artifacts to be evicted to chase orphan bytes.
101
+ const liveArtifactIds = new Set(svc.state.lru.toArray().map((entry) => entry.key));
102
+ try {
103
+ for (const entry of readdirSync(remappedDir, { withFileTypes: true })) {
104
+ if (!entry.isFile() || !entry.name.endsWith(".jar")) {
105
+ continue;
106
+ }
107
+ const artifactId = entry.name.slice(0, -".jar".length);
108
+ if (!liveArtifactIds.has(artifactId)) {
109
+ continue;
110
+ }
111
+ try {
112
+ const fileStat = statSync(join(remappedDir, entry.name));
113
+ const size = Math.max(0, Math.trunc(fileStat.size));
114
+ svc.state.remappedJarBytes.set(artifactId, size);
115
+ remappedTotal += size;
116
+ }
117
+ catch {
118
+ // ignore stat failure on a single jar; total stays best-effort.
119
+ }
120
+ }
121
+ }
122
+ catch {
123
+ // ignore listing failure; remapped accounting stays empty until next remap.
124
+ }
125
+ }
126
+ svc.state.cacheTotalContentBytes = totalContentBytes + remappedTotal;
127
+ publishCacheMetrics(svc);
128
+ }
129
+ export function touchCacheMetrics(svc, artifactId, updatedAt) {
130
+ const entry = svc.state.lru.touch(artifactId);
131
+ if (!entry) {
132
+ refreshCacheMetrics(svc);
133
+ return;
134
+ }
135
+ entry.updatedAt = updatedAt;
136
+ publishCacheMetrics(svc);
137
+ }
138
+ export function upsertCacheMetrics(svc, artifactId, totalContentBytes, updatedAt) {
139
+ const normalizedBytes = Math.max(0, Math.trunc(totalContentBytes));
140
+ const existing = svc.state.lru.remove(artifactId);
141
+ if (existing) {
142
+ svc.state.cacheTotalContentBytes = Math.max(0, svc.state.cacheTotalContentBytes - existing.totalContentBytes + normalizedBytes);
143
+ }
144
+ else {
145
+ svc.state.cacheTotalContentBytes += normalizedBytes;
146
+ }
147
+ svc.state.lru.upsert(artifactId, { totalContentBytes: normalizedBytes, updatedAt });
148
+ publishCacheMetrics(svc);
149
+ }
150
+ export function removeCacheMetrics(svc, artifactId, publish = true) {
151
+ const existing = svc.state.lru.remove(artifactId);
152
+ if (!existing) {
153
+ refreshCacheMetrics(svc);
154
+ return;
155
+ }
156
+ svc.state.cacheTotalContentBytes = Math.max(0, svc.state.cacheTotalContentBytes - existing.totalContentBytes);
157
+ if (publish) {
158
+ publishCacheMetrics(svc);
159
+ }
160
+ }
161
+ export function publishCacheMetrics(svc) {
162
+ svc.metrics.setCacheEntries(svc.state.lru.size);
163
+ svc.metrics.setCacheTotalContentBytes(svc.state.cacheTotalContentBytes);
164
+ }
165
+ export function snapshotLruAccounting(svc) {
166
+ svc.metrics.setCacheArtifactByteAccountingRef(svc.state.lru.toArray().map(({ key, value }) => ({
167
+ artifactId: key,
168
+ totalContentBytes: value.totalContentBytes,
169
+ updatedAt: value.updatedAt
170
+ })));
171
+ }
172
+ //# sourceMappingURL=cache-metrics.js.map
@@ -0,0 +1,34 @@
1
+ import type { SignatureMember } from "../../minecraft-explorer-service.js";
2
+ import type { SourceService } from "../../source-service.js";
3
+ import type { MappingSourcePriority, SourceMapping } from "../../types.js";
4
+ export type RemappedMembers = {
5
+ constructors: SignatureMember[];
6
+ fields: SignatureMember[];
7
+ methods: SignatureMember[];
8
+ counts: {
9
+ constructors: number;
10
+ fields: number;
11
+ methods: number;
12
+ total: number;
13
+ };
14
+ };
15
+ export type RemapMembersInput = {
16
+ signatureConstructors: SignatureMember[];
17
+ signatureFields: SignatureMember[];
18
+ signatureMethods: SignatureMember[];
19
+ version: string | undefined;
20
+ mappingApplied: SourceMapping;
21
+ requestedMapping: SourceMapping;
22
+ sourcePriority: MappingSourcePriority | undefined;
23
+ memberPattern: string | undefined;
24
+ warnings: string[];
25
+ };
26
+ export declare function remapAndCountMembers(svc: SourceService, input: RemapMembersInput): Promise<RemappedMembers>;
27
+ export type MemberSliceResult = {
28
+ constructors: SignatureMember[];
29
+ fields: SignatureMember[];
30
+ methods: SignatureMember[];
31
+ truncated: boolean;
32
+ returnedTotal: number;
33
+ };
34
+ export declare function sliceMembersWithLimit(remapped: Omit<RemappedMembers, "counts">, totalCount: number, maxMembers: number, warnings: string[]): MemberSliceResult;
@@ -0,0 +1,46 @@
1
+ export async function remapAndCountMembers(svc, input) {
2
+ const remap = async (members, kind) => {
3
+ if (input.version == null) {
4
+ return members;
5
+ }
6
+ const result = await svc.remapSignatureMembers(members, kind, input.version, input.mappingApplied, input.requestedMapping, input.sourcePriority, input.warnings);
7
+ return result.members;
8
+ };
9
+ let constructors = await remap(input.signatureConstructors, "method");
10
+ let fields = await remap(input.signatureFields, "field");
11
+ let methods = await remap(input.signatureMethods, "method");
12
+ if (input.requestedMapping !== input.mappingApplied && input.memberPattern) {
13
+ const lowerPattern = input.memberPattern.toLowerCase();
14
+ constructors = constructors.filter((m) => m.name.toLowerCase().includes(lowerPattern));
15
+ fields = fields.filter((m) => m.name.toLowerCase().includes(lowerPattern));
16
+ methods = methods.filter((m) => m.name.toLowerCase().includes(lowerPattern));
17
+ }
18
+ const counts = {
19
+ constructors: constructors.length,
20
+ fields: fields.length,
21
+ methods: methods.length,
22
+ total: constructors.length + fields.length + methods.length
23
+ };
24
+ return { constructors, fields, methods, counts };
25
+ }
26
+ export function sliceMembersWithLimit(remapped, totalCount, maxMembers, warnings) {
27
+ let remaining = maxMembers;
28
+ const takeWithinLimit = (members) => {
29
+ if (remaining <= 0) {
30
+ return [];
31
+ }
32
+ const slice = members.slice(0, remaining);
33
+ remaining -= slice.length;
34
+ return slice;
35
+ };
36
+ const constructors = takeWithinLimit(remapped.constructors);
37
+ const fields = takeWithinLimit(remapped.fields);
38
+ const methods = takeWithinLimit(remapped.methods);
39
+ const returnedTotal = constructors.length + fields.length + methods.length;
40
+ const truncated = returnedTotal < totalCount;
41
+ if (truncated) {
42
+ warnings.push(`Member list was truncated to ${returnedTotal} entries (from ${totalCount}).`);
43
+ }
44
+ return { constructors, fields, methods, truncated, returnedTotal };
45
+ }
46
+ //# sourceMappingURL=members-builder.js.map
@@ -0,0 +1,19 @@
1
+ import type { SourceMode } from "../../source-service.js";
2
+ export type SnippetBuildInput = {
3
+ filePath: string;
4
+ content: string;
5
+ mode: SourceMode;
6
+ startLine: number | undefined;
7
+ endLine: number | undefined;
8
+ maxLines: number | undefined;
9
+ maxChars: number | undefined;
10
+ };
11
+ export type SnippetBuildResult = {
12
+ sourceText: string;
13
+ totalLines: number;
14
+ returnedStart: number;
15
+ returnedEnd: number;
16
+ truncated: boolean;
17
+ charsTruncated: boolean;
18
+ };
19
+ export declare function buildClassSourceSnippet(input: SnippetBuildInput): SnippetBuildResult;
@@ -0,0 +1,46 @@
1
+ import * as classSourceHelpers from "../class-source-helpers.js";
2
+ export function buildClassSourceSnippet(input) {
3
+ const lines = input.content.split(/\r?\n/);
4
+ const totalLines = lines.length;
5
+ let sourceText;
6
+ let returnedStart;
7
+ let returnedEnd;
8
+ let truncated = false;
9
+ let charsTruncated = false;
10
+ if (input.mode === "metadata") {
11
+ sourceText = classSourceHelpers.extractClassMetadata(input.filePath, input.content);
12
+ returnedStart = 1;
13
+ returnedEnd = totalLines;
14
+ }
15
+ else {
16
+ const requestedStart = input.startLine ?? 1;
17
+ const requestedEnd = input.endLine ?? totalLines;
18
+ const normalizedStart = Math.min(Math.max(1, requestedStart), Math.max(totalLines, 1));
19
+ const normalizedEnd = Math.min(Math.max(normalizedStart, requestedEnd), Math.max(totalLines, 1));
20
+ let selectedLines = lines.slice(normalizedStart - 1, normalizedEnd);
21
+ const clippedByRange = normalizedStart !== requestedStart || normalizedEnd !== requestedEnd;
22
+ let clippedByMax = false;
23
+ if (input.maxLines != null && selectedLines.length > input.maxLines) {
24
+ selectedLines = selectedLines.slice(0, input.maxLines);
25
+ clippedByMax = true;
26
+ }
27
+ sourceText = selectedLines.join("\n");
28
+ returnedStart = normalizedStart;
29
+ returnedEnd = normalizedStart + Math.max(0, selectedLines.length - 1);
30
+ truncated = clippedByRange || clippedByMax;
31
+ }
32
+ if (input.maxChars != null && sourceText.length > input.maxChars) {
33
+ sourceText = sourceText.slice(0, input.maxChars);
34
+ charsTruncated = true;
35
+ truncated = true;
36
+ }
37
+ return {
38
+ sourceText,
39
+ totalLines,
40
+ returnedStart,
41
+ returnedEnd,
42
+ truncated,
43
+ charsTruncated
44
+ };
45
+ }
46
+ //# sourceMappingURL=snippet-builder.js.map
@@ -0,0 +1,34 @@
1
+ export type DecompiledMember = {
2
+ name: string;
3
+ line: number;
4
+ kind: "constructor" | "field" | "method";
5
+ };
6
+ export declare function extractClassMetadata(filePath: string, content: string): string;
7
+ export declare function extractDecompiledMembers(className: string, filePath: string, content: string): {
8
+ constructors: DecompiledMember[];
9
+ fields: DecompiledMember[];
10
+ methods: DecompiledMember[];
11
+ };
12
+ export declare function computeLineBraceDepths(lines: string[]): number[];
13
+ export declare function computeBraceRange(lines: string[], symbols: Array<{
14
+ symbolKind: string;
15
+ symbolName: string;
16
+ line: number;
17
+ }>, simpleName: string): {
18
+ declarationLine: number;
19
+ endLine: number;
20
+ } | undefined;
21
+ export declare function scanBraceRange(lines: string[], declarationLine: number): {
22
+ declarationLine: number;
23
+ endLine: number;
24
+ };
25
+ export declare function computeNestedTypeRanges(lines: string[], symbols: Array<{
26
+ symbolKind: string;
27
+ line: number;
28
+ }>, outerBody: {
29
+ declarationLine: number;
30
+ endLine: number;
31
+ }): Array<{
32
+ declarationLine: number;
33
+ endLine: number;
34
+ }>;
@@ -0,0 +1,140 @@
1
+ import { extractSymbolsFromSource } from "../symbols/symbol-extractor.js";
2
+ export function extractClassMetadata(filePath, content) {
3
+ const lines = content.split(/\r?\n/);
4
+ const symbols = extractSymbolsFromSource(filePath, content);
5
+ const outputParts = [];
6
+ // Include package + import header (lines before first symbol declaration)
7
+ const firstSymbolLine = symbols.length > 0 ? symbols[0].line : lines.length + 1;
8
+ for (let i = 0; i < Math.min(firstSymbolLine - 1, lines.length); i++) {
9
+ const line = lines[i];
10
+ const trimmed = line.trim();
11
+ if (trimmed.startsWith("package ") || trimmed.startsWith("import ") || trimmed === "") {
12
+ outputParts.push(line);
13
+ }
14
+ }
15
+ // Add each symbol's declaration line
16
+ for (const symbol of symbols) {
17
+ const lineIndex = symbol.line - 1;
18
+ if (lineIndex >= 0 && lineIndex < lines.length) {
19
+ const prefix = symbol.symbolKind === "class" || symbol.symbolKind === "interface" ||
20
+ symbol.symbolKind === "enum" || symbol.symbolKind === "record"
21
+ ? `\n// [${symbol.symbolKind}] line ${symbol.line}`
22
+ : `// [${symbol.symbolKind}] line ${symbol.line}`;
23
+ outputParts.push(prefix);
24
+ outputParts.push(lines[lineIndex]);
25
+ }
26
+ }
27
+ return outputParts.join("\n");
28
+ }
29
+ export function extractDecompiledMembers(className, filePath, content) {
30
+ const symbols = extractSymbolsFromSource(filePath, content);
31
+ const simpleName = className.split(/[.$]/).at(-1) ?? className;
32
+ const lines = content.split(/\r?\n/);
33
+ const body = computeBraceRange(lines, symbols, simpleName);
34
+ if (!body) {
35
+ return { constructors: [], fields: [], methods: [] };
36
+ }
37
+ const depths = computeLineBraceDepths(lines);
38
+ const baseDepth = depths[body.declarationLine - 1] ?? 0;
39
+ const nestedRanges = computeNestedTypeRanges(lines, symbols, body);
40
+ const constructors = [];
41
+ const fields = [];
42
+ const methods = [];
43
+ for (const symbol of symbols) {
44
+ if (symbol.line <= body.declarationLine || symbol.line > body.endLine) {
45
+ continue;
46
+ }
47
+ if (nestedRanges.some((range) => symbol.line >= range.declarationLine && symbol.line <= range.endLine)) {
48
+ continue;
49
+ }
50
+ const lineDepth = depths[symbol.line - 1] ?? baseDepth;
51
+ // Declarations directly inside the class body sit at baseDepth+1; anything
52
+ // deeper is a method/constructor body, an initializer block, etc.
53
+ if (lineDepth !== baseDepth + 1) {
54
+ continue;
55
+ }
56
+ if (symbol.symbolKind === "method") {
57
+ if (symbol.symbolName === simpleName) {
58
+ constructors.push({ name: "<init>", line: symbol.line, kind: "constructor" });
59
+ }
60
+ else {
61
+ methods.push({ name: symbol.symbolName, line: symbol.line, kind: "method" });
62
+ }
63
+ }
64
+ else if (symbol.symbolKind === "field") {
65
+ fields.push({ name: symbol.symbolName, line: symbol.line, kind: "field" });
66
+ }
67
+ }
68
+ return { constructors, fields, methods };
69
+ }
70
+ export function computeLineBraceDepths(lines) {
71
+ const depths = new Array(lines.length).fill(0);
72
+ let depth = 0;
73
+ for (let i = 0; i < lines.length; i += 1) {
74
+ // Entry depth for this line = depth observed before any brace on it.
75
+ depths[i] = depth;
76
+ const stripped = (lines[i] ?? "")
77
+ .replace(/\/\/.*/g, "")
78
+ .replace(/"(?:\\.|[^"\\])*"/g, "\"\"")
79
+ .replace(/'(?:\\.|[^'\\])*'/g, "''");
80
+ for (const char of stripped) {
81
+ if (char === "{") {
82
+ depth += 1;
83
+ }
84
+ else if (char === "}") {
85
+ depth -= 1;
86
+ }
87
+ }
88
+ }
89
+ return depths;
90
+ }
91
+ export function computeBraceRange(lines, symbols, simpleName) {
92
+ const classSymbol = symbols.find((symbol) => (symbol.symbolKind === "class" || symbol.symbolKind === "interface"
93
+ || symbol.symbolKind === "enum" || symbol.symbolKind === "record")
94
+ && symbol.symbolName === simpleName);
95
+ if (!classSymbol) {
96
+ return undefined;
97
+ }
98
+ return scanBraceRange(lines, classSymbol.line);
99
+ }
100
+ export function scanBraceRange(lines, declarationLine) {
101
+ let depth = 0;
102
+ let started = false;
103
+ for (let i = declarationLine - 1; i < lines.length; i += 1) {
104
+ const stripped = (lines[i] ?? "")
105
+ .replace(/\/\/.*/g, "")
106
+ .replace(/"(?:\\.|[^"\\])*"/g, "\"\"");
107
+ for (const char of stripped) {
108
+ if (char === "{") {
109
+ depth += 1;
110
+ started = true;
111
+ }
112
+ else if (char === "}") {
113
+ depth -= 1;
114
+ if (started && depth === 0) {
115
+ return { declarationLine, endLine: i + 1 };
116
+ }
117
+ }
118
+ }
119
+ }
120
+ return { declarationLine, endLine: lines.length };
121
+ }
122
+ export function computeNestedTypeRanges(lines, symbols, outerBody) {
123
+ const ranges = [];
124
+ for (const candidate of symbols) {
125
+ if (candidate.symbolKind !== "class" && candidate.symbolKind !== "interface"
126
+ && candidate.symbolKind !== "enum" && candidate.symbolKind !== "record") {
127
+ continue;
128
+ }
129
+ if (candidate.line <= outerBody.declarationLine || candidate.line > outerBody.endLine) {
130
+ continue;
131
+ }
132
+ if (ranges.some((range) => candidate.line >= range.declarationLine && candidate.line <= range.endLine)) {
133
+ continue;
134
+ }
135
+ const nestedRange = scanBraceRange(lines, candidate.line);
136
+ ranges.push(nestedRange);
137
+ }
138
+ return ranges;
139
+ }
140
+ //# sourceMappingURL=class-source-helpers.js.map
@@ -0,0 +1,42 @@
1
+ import { type AppError } from "../errors.js";
2
+ import type { SourceService } from "../source-service.js";
3
+ import type { DecompiledFallback, FindClassInput, FindClassOutput, GetClassMembersInput, GetClassMembersOutput, GetClassSourceInput, GetClassSourceOutput } from "../source-service.js";
4
+ import type { ArtifactProvenance, ArtifactScope, MappingSourcePriority, ResolvedSourceArtifact, SourceMapping } from "../types.js";
5
+ export declare function resolveClassFilePath(svc: SourceService, artifactId: string, className: string): string | undefined;
6
+ export declare function resolveClassNameForLookup(svc: SourceService, input: {
7
+ className: string;
8
+ version?: string;
9
+ sourceMapping: SourceMapping;
10
+ targetMapping: SourceMapping;
11
+ sourcePriority: MappingSourcePriority | undefined;
12
+ warnings: string[];
13
+ context: string;
14
+ }): Promise<string>;
15
+ export declare function buildFallbackProvenance(svc: SourceService, input: {
16
+ artifactId: string;
17
+ origin: ResolvedSourceArtifact["origin"];
18
+ requestedMapping: SourceMapping;
19
+ mappingApplied: SourceMapping;
20
+ }): ArtifactProvenance;
21
+ export declare function buildClassSourceNotFoundError(_svc: SourceService, input: {
22
+ className: string;
23
+ lookupClassName: string;
24
+ artifactId: string;
25
+ mappingApplied: SourceMapping;
26
+ requestedMapping: SourceMapping;
27
+ qualityFlags: string[];
28
+ attemptedBinaryFallback: boolean;
29
+ filePath?: string;
30
+ targetKind?: string;
31
+ targetValue?: string;
32
+ scope?: ArtifactScope;
33
+ projectPath?: string;
34
+ version?: string;
35
+ }): AppError;
36
+ export declare function buildDecompiledFallback(svc: SourceService, artifactId: string, lookupClassName: string, memberPattern: string | undefined, maxMembers: number): {
37
+ fallback: DecompiledFallback;
38
+ counts: NonNullable<GetClassMembersOutput["decompiledMemberCounts"]>;
39
+ } | undefined;
40
+ export declare function findClass(svc: SourceService, input: FindClassInput): FindClassOutput;
41
+ export declare function getClassSource(svc: SourceService, input: GetClassSourceInput): Promise<GetClassSourceOutput>;
42
+ export declare function getClassMembers(svc: SourceService, input: GetClassMembersInput): Promise<GetClassMembersOutput>;