@adhisang/minecraft-modding-mcp 4.2.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +6 -4
  3. package/dist/access-transformer-parser.d.ts +2 -1
  4. package/dist/access-transformer-parser.js +10 -1
  5. package/dist/build-suggested-call.js +31 -10
  6. package/dist/cache-registry.d.ts +8 -0
  7. package/dist/cache-registry.js +99 -6
  8. package/dist/config.d.ts +1 -0
  9. package/dist/config.js +4 -0
  10. package/dist/entry-tools/analyze-mod-service.d.ts +24 -24
  11. package/dist/entry-tools/analyze-symbol-service.d.ts +57 -22
  12. package/dist/entry-tools/analyze-symbol-service.js +124 -28
  13. package/dist/entry-tools/batch-class-members-service.d.ts +3 -1
  14. package/dist/entry-tools/batch-class-members-service.js +6 -6
  15. package/dist/entry-tools/batch-class-source-service.d.ts +3 -1
  16. package/dist/entry-tools/batch-class-source-service.js +5 -6
  17. package/dist/entry-tools/batch-mappings-service.d.ts +3 -1
  18. package/dist/entry-tools/batch-mappings-service.js +4 -5
  19. package/dist/entry-tools/batch-symbol-exists-service.d.ts +3 -1
  20. package/dist/entry-tools/batch-symbol-exists-service.js +4 -5
  21. package/dist/entry-tools/compare-minecraft-service.d.ts +10 -10
  22. package/dist/entry-tools/entry-tool-schema.d.ts +1 -1
  23. package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +1 -3
  24. package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +2 -2
  25. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +0 -5
  26. package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +0 -1
  27. package/dist/entry-tools/inspect-minecraft/handlers/file.js +0 -1
  28. package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +0 -1
  29. package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +8 -0
  30. package/dist/entry-tools/inspect-minecraft/handlers/search.js +13 -2
  31. package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +1 -1
  32. package/dist/entry-tools/inspect-minecraft/handlers/versions.js +1 -1
  33. package/dist/entry-tools/inspect-minecraft/internal.d.ts +90 -89
  34. package/dist/entry-tools/inspect-minecraft/internal.js +30 -14
  35. package/dist/entry-tools/inspect-minecraft-service.d.ts +218 -218
  36. package/dist/entry-tools/inspect-minecraft-service.js +1 -1
  37. package/dist/entry-tools/manage-cache-service.d.ts +4 -4
  38. package/dist/entry-tools/response-contract.d.ts +1 -1
  39. package/dist/entry-tools/response-contract.js +1 -0
  40. package/dist/entry-tools/validate-project/cases/mixin.js +2 -1
  41. package/dist/entry-tools/validate-project/cases/project-summary.js +5 -3
  42. package/dist/entry-tools/validate-project-service.d.ts +42 -36
  43. package/dist/entry-tools/validate-project-service.js +3 -1
  44. package/dist/entry-tools/verify-mixin-target-service.d.ts +30 -0
  45. package/dist/entry-tools/verify-mixin-target-service.js +113 -22
  46. package/dist/error-mapping.d.ts +51 -0
  47. package/dist/error-mapping.js +157 -2
  48. package/dist/errors.js +4 -1
  49. package/dist/index.js +138 -71
  50. package/dist/java-process.d.ts +9 -0
  51. package/dist/java-process.js +11 -5
  52. package/dist/mapping/internal-types.d.ts +7 -0
  53. package/dist/mapping/lookup.d.ts +1 -1
  54. package/dist/mapping/lookup.js +7 -1
  55. package/dist/mapping/types.d.ts +6 -0
  56. package/dist/mapping-service.d.ts +26 -2
  57. package/dist/mapping-service.js +178 -36
  58. package/dist/mcp-helpers.d.ts +1 -0
  59. package/dist/mcp-helpers.js +25 -3
  60. package/dist/minecraft-explorer-service.js +24 -11
  61. package/dist/mixin/access-validators.js +33 -1
  62. package/dist/mixin/annotation-validators.js +53 -7
  63. package/dist/mixin/parsed-validator.js +2 -2
  64. package/dist/mixin-parser.js +48 -4
  65. package/dist/mod-decompile-service.js +2 -1
  66. package/dist/mod-remap-service.d.ts +20 -1
  67. package/dist/mod-remap-service.js +95 -40
  68. package/dist/nbt/java-nbt-codec.js +87 -2
  69. package/dist/observability.d.ts +6 -0
  70. package/dist/observability.js +10 -0
  71. package/dist/page-cursor.d.ts +17 -0
  72. package/dist/page-cursor.js +0 -0
  73. package/dist/registry-service.js +25 -1
  74. package/dist/resources.js +45 -9
  75. package/dist/response-utils.d.ts +29 -4
  76. package/dist/response-utils.js +95 -5
  77. package/dist/source/access-validate.js +12 -2
  78. package/dist/source/artifact-resolver.js +1 -1
  79. package/dist/source/cache-metrics.js +2 -2
  80. package/dist/source/class-source/members-builder.d.ts +44 -1
  81. package/dist/source/class-source/members-builder.js +51 -4
  82. package/dist/source/class-source/snippet-builder.d.ts +13 -0
  83. package/dist/source/class-source/snippet-builder.js +48 -4
  84. package/dist/source/class-source-helpers.js +67 -11
  85. package/dist/source/class-source.js +97 -20
  86. package/dist/source/indexer.d.ts +31 -6
  87. package/dist/source/indexer.js +95 -25
  88. package/dist/source/search.d.ts +1 -1
  89. package/dist/source/search.js +94 -22
  90. package/dist/source/validate-mixin.d.ts +2 -1
  91. package/dist/source/validate-mixin.js +45 -4
  92. package/dist/source/workspace-target.js +15 -9
  93. package/dist/source-jar-reader.d.ts +54 -1
  94. package/dist/source-jar-reader.js +121 -10
  95. package/dist/source-service.d.ts +28 -7
  96. package/dist/storage/files-repo.d.ts +12 -0
  97. package/dist/storage/files-repo.js +24 -0
  98. package/dist/storage/symbols-repo.d.ts +6 -0
  99. package/dist/storage/symbols-repo.js +6 -0
  100. package/dist/symbols/symbol-extractor.js +35 -6
  101. package/dist/text-truncate.d.ts +7 -0
  102. package/dist/text-truncate.js +21 -0
  103. package/dist/tiny-remapper-resolver.js +10 -0
  104. package/dist/tiny-remapper-service.js +3 -3
  105. package/dist/tool-contract-manifest.js +2 -2
  106. package/dist/tool-execution-gate.js +12 -1
  107. package/dist/tool-guidance.d.ts +4 -1
  108. package/dist/tool-guidance.js +37 -12
  109. package/dist/tool-schemas.d.ts +559 -494
  110. package/dist/tool-schemas.js +99 -63
  111. package/dist/types.d.ts +1 -0
  112. package/dist/version-diff-service.js +5 -0
  113. package/dist/version-service.d.ts +3 -0
  114. package/dist/version-service.js +18 -2
  115. package/dist/warning-details.d.ts +18 -0
  116. package/dist/warning-details.js +63 -0
  117. package/docs/README-ja.md +2 -2
  118. package/docs/examples.md +26 -2
  119. package/docs/tool-reference.md +23 -17
  120. package/package.json +1 -1
@@ -19,6 +19,11 @@ export declare const analyzeSymbolShape: {
19
19
  owner?: string | undefined;
20
20
  }>;
21
21
  version: z.ZodOptional<z.ZodString>;
22
+ fromVersion: z.ZodOptional<z.ZodString>;
23
+ toVersion: z.ZodOptional<z.ZodString>;
24
+ maxVersions: z.ZodOptional<z.ZodNumber>;
25
+ includeTimeline: z.ZodOptional<z.ZodBoolean>;
26
+ includeSnapshots: z.ZodOptional<z.ZodBoolean>;
22
27
  sourceMapping: z.ZodOptional<z.ZodEnum<["obfuscated", "mojang", "intermediary", "yarn"]>>;
23
28
  targetMapping: z.ZodOptional<z.ZodEnum<["obfuscated", "mojang", "intermediary", "yarn"]>>;
24
29
  classNameMapping: z.ZodOptional<z.ZodEnum<["obfuscated", "mojang", "intermediary", "yarn"]>>;
@@ -51,6 +56,11 @@ export declare const analyzeSymbolSchema: z.ZodEffects<z.ZodObject<{
51
56
  owner?: string | undefined;
52
57
  }>;
53
58
  version: z.ZodOptional<z.ZodString>;
59
+ fromVersion: z.ZodOptional<z.ZodString>;
60
+ toVersion: z.ZodOptional<z.ZodString>;
61
+ maxVersions: z.ZodOptional<z.ZodNumber>;
62
+ includeTimeline: z.ZodOptional<z.ZodBoolean>;
63
+ includeSnapshots: z.ZodOptional<z.ZodBoolean>;
54
64
  sourceMapping: z.ZodOptional<z.ZodEnum<["obfuscated", "mojang", "intermediary", "yarn"]>>;
55
65
  targetMapping: z.ZodOptional<z.ZodEnum<["obfuscated", "mojang", "intermediary", "yarn"]>>;
56
66
  classNameMapping: z.ZodOptional<z.ZodEnum<["obfuscated", "mojang", "intermediary", "yarn"]>>;
@@ -64,7 +74,7 @@ export declare const analyzeSymbolSchema: z.ZodEffects<z.ZodObject<{
64
74
  detail: z.ZodOptional<z.ZodEnum<["summary", "standard", "full"]>>;
65
75
  include: z.ZodOptional<z.ZodArray<z.ZodEnum<[string, ...string[]]>, "many">>;
66
76
  }, "strip", z.ZodTypeAny, {
67
- nameMode: "auto" | "fqcn";
77
+ maxCandidates: number;
68
78
  task: "map" | "workspace" | "exists" | "exact-map" | "lifecycle" | "api-overview";
69
79
  subject: {
70
80
  name: string;
@@ -72,18 +82,23 @@ export declare const analyzeSymbolSchema: z.ZodEffects<z.ZodObject<{
72
82
  descriptor?: string | undefined;
73
83
  owner?: string | undefined;
74
84
  };
85
+ nameMode: "auto" | "fqcn";
75
86
  signatureMode: "exact" | "name-only";
76
- maxCandidates: number;
77
87
  version?: string | undefined;
78
88
  projectPath?: string | undefined;
79
- sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
89
+ maxRows?: number | undefined;
90
+ detail?: "summary" | "standard" | "full" | undefined;
91
+ include?: string[] | undefined;
80
92
  targetMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
93
+ maxVersions?: number | undefined;
94
+ sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
81
95
  classNameMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
82
96
  gradleUserHome?: string | undefined;
83
- detail?: "full" | "summary" | "standard" | undefined;
84
- include?: string[] | undefined;
97
+ includeSnapshots?: boolean | undefined;
98
+ fromVersion?: string | undefined;
99
+ toVersion?: string | undefined;
100
+ includeTimeline?: boolean | undefined;
85
101
  includeKinds?: ("class" | "field" | "method")[] | undefined;
86
- maxRows?: number | undefined;
87
102
  }, {
88
103
  task: "map" | "workspace" | "exists" | "exact-map" | "lifecycle" | "api-overview";
89
104
  subject: {
@@ -94,19 +109,24 @@ export declare const analyzeSymbolSchema: z.ZodEffects<z.ZodObject<{
94
109
  };
95
110
  version?: string | undefined;
96
111
  projectPath?: string | undefined;
97
- sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
112
+ maxRows?: number | undefined;
113
+ maxCandidates?: number | undefined;
114
+ detail?: "summary" | "standard" | "full" | undefined;
115
+ include?: string[] | undefined;
98
116
  targetMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
117
+ maxVersions?: number | undefined;
118
+ sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
99
119
  classNameMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
100
120
  gradleUserHome?: string | undefined;
101
121
  nameMode?: "auto" | "fqcn" | undefined;
102
- detail?: "full" | "summary" | "standard" | undefined;
103
- include?: string[] | undefined;
122
+ includeSnapshots?: boolean | undefined;
123
+ fromVersion?: string | undefined;
124
+ toVersion?: string | undefined;
125
+ includeTimeline?: boolean | undefined;
104
126
  signatureMode?: "exact" | "name-only" | undefined;
105
127
  includeKinds?: ("class" | "field" | "method")[] | undefined;
106
- maxRows?: number | undefined;
107
- maxCandidates?: number | undefined;
108
128
  }>, {
109
- nameMode: "auto" | "fqcn";
129
+ maxCandidates: number;
110
130
  task: "map" | "workspace" | "exists" | "exact-map" | "lifecycle" | "api-overview";
111
131
  subject: {
112
132
  name: string;
@@ -114,18 +134,23 @@ export declare const analyzeSymbolSchema: z.ZodEffects<z.ZodObject<{
114
134
  descriptor?: string | undefined;
115
135
  owner?: string | undefined;
116
136
  };
137
+ nameMode: "auto" | "fqcn";
117
138
  signatureMode: "exact" | "name-only";
118
- maxCandidates: number;
119
139
  version?: string | undefined;
120
140
  projectPath?: string | undefined;
121
- sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
141
+ maxRows?: number | undefined;
142
+ detail?: "summary" | "standard" | "full" | undefined;
143
+ include?: string[] | undefined;
122
144
  targetMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
145
+ maxVersions?: number | undefined;
146
+ sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
123
147
  classNameMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
124
148
  gradleUserHome?: string | undefined;
125
- detail?: "full" | "summary" | "standard" | undefined;
126
- include?: string[] | undefined;
149
+ includeSnapshots?: boolean | undefined;
150
+ fromVersion?: string | undefined;
151
+ toVersion?: string | undefined;
152
+ includeTimeline?: boolean | undefined;
127
153
  includeKinds?: ("class" | "field" | "method")[] | undefined;
128
- maxRows?: number | undefined;
129
154
  }, {
130
155
  task: "map" | "workspace" | "exists" | "exact-map" | "lifecycle" | "api-overview";
131
156
  subject: {
@@ -136,17 +161,22 @@ export declare const analyzeSymbolSchema: z.ZodEffects<z.ZodObject<{
136
161
  };
137
162
  version?: string | undefined;
138
163
  projectPath?: string | undefined;
139
- sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
164
+ maxRows?: number | undefined;
165
+ maxCandidates?: number | undefined;
166
+ detail?: "summary" | "standard" | "full" | undefined;
167
+ include?: string[] | undefined;
140
168
  targetMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
169
+ maxVersions?: number | undefined;
170
+ sourceMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
141
171
  classNameMapping?: "obfuscated" | "mojang" | "intermediary" | "yarn" | undefined;
142
172
  gradleUserHome?: string | undefined;
143
173
  nameMode?: "auto" | "fqcn" | undefined;
144
- detail?: "full" | "summary" | "standard" | undefined;
145
- include?: string[] | undefined;
174
+ includeSnapshots?: boolean | undefined;
175
+ fromVersion?: string | undefined;
176
+ toVersion?: string | undefined;
177
+ includeTimeline?: boolean | undefined;
146
178
  signatureMode?: "exact" | "name-only" | undefined;
147
179
  includeKinds?: ("class" | "field" | "method")[] | undefined;
148
- maxRows?: number | undefined;
149
- maxCandidates?: number | undefined;
150
180
  }>;
151
181
  export type AnalyzeSymbolInput = z.infer<typeof analyzeSymbolSchema>;
152
182
  type AnalyzeSymbolDeps = {
@@ -172,6 +202,7 @@ type AnalyzeSymbolDeps = {
172
202
  sourceMapping: "obfuscated" | "mojang" | "intermediary" | "yarn";
173
203
  targetMapping: "obfuscated" | "mojang" | "intermediary" | "yarn";
174
204
  gradleUserHome?: string;
205
+ nameMode?: "fqcn" | "auto";
175
206
  signatureMode?: "exact" | "name-only";
176
207
  maxCandidates?: number;
177
208
  }) => Promise<FindMappingOutput>;
@@ -189,9 +220,13 @@ type AnalyzeSymbolDeps = {
189
220
  symbol: string;
190
221
  descriptor?: string;
191
222
  mapping?: "obfuscated" | "mojang" | "intermediary" | "yarn";
223
+ sourcePriority?: "loom-first" | "maven-first";
192
224
  gradleUserHome?: string;
225
+ fromVersion?: string;
193
226
  toVersion?: string;
194
227
  maxVersions?: number;
228
+ includeSnapshots?: boolean;
229
+ includeTimeline?: boolean;
195
230
  }) => Promise<TraceSymbolLifecycleOutput>;
196
231
  resolveWorkspaceSymbol: (input: {
197
232
  projectPath: string;
@@ -3,7 +3,21 @@ import { createError, ERROR_CODES } from "../errors.js";
3
3
  import { buildIncludeSchema, detailSchema, positiveIntSchema } from "./entry-tool-schema.js";
4
4
  import { buildEntryToolResult, createSummarySubject } from "./response-contract.js";
5
5
  import { resolveDetail, resolveInclude } from "./request-normalizers.js";
6
+ import { compactMappingResponse } from "../response-utils.js";
6
7
  const nonEmptyString = z.string().trim().min(1);
8
+ /**
9
+ * Reuse the expert-tool compactMappingResponse candidate projection so the entry
10
+ * tool is as terse as the low-level one: drop the lone exact candidate that just
11
+ * duplicates `match` (resolved-exact), and slim the tail of unresolved candidate
12
+ * lists. Returns block fields to spread into buildEntryToolResult's `blocks`.
13
+ */
14
+ function projectMappingCandidates(output) {
15
+ const projected = compactMappingResponse(output);
16
+ return {
17
+ candidates: projected.candidates,
18
+ ...(projected.candidateDetailsTruncated === true ? { candidateDetailsTruncated: true } : {})
19
+ };
20
+ }
7
21
  // Descriptor field that treats empty/whitespace strings as omitted so callers can pass
8
22
  // `descriptor: ""` interchangeably with omitting the field when signatureMode="name-only".
9
23
  const optionalDescriptorString = z
@@ -15,38 +29,114 @@ const optionalDescriptorString = z
15
29
  const trimmed = value.trim();
16
30
  return trimmed.length === 0 ? undefined : trimmed;
17
31
  });
32
+ /**
33
+ * Resolve subject.kind to a concrete kind. `"symbol"` is auto-detected from the
34
+ * selector (owner+descriptor => method, owner only => field, otherwise => class)
35
+ * and the inference is surfaced as a warning so the caller can see what ran.
36
+ */
37
+ function inferSubjectKind(subject) {
38
+ if (subject.kind !== "symbol") {
39
+ return { kind: subject.kind };
40
+ }
41
+ let inferred;
42
+ if (subject.owner && subject.descriptor) {
43
+ inferred = "method";
44
+ }
45
+ else if (subject.owner) {
46
+ inferred = "field";
47
+ }
48
+ else {
49
+ inferred = "class";
50
+ }
51
+ const selectorNote = subject.owner
52
+ ? subject.descriptor
53
+ ? "owner+descriptor"
54
+ : "owner only"
55
+ : "no owner/descriptor";
56
+ return {
57
+ kind: inferred,
58
+ warning: `subject.kind="symbol" was auto-detected as "${inferred}" (${selectorNote}). Pass an explicit kind to override.`
59
+ };
60
+ }
18
61
  const INCLUDE_GROUPS = ["warnings", "candidates", "matrix", "workspace", "timings"];
19
62
  const TASKS = ["exists", "map", "exact-map", "lifecycle", "workspace", "api-overview"];
20
63
  export const analyzeSymbolShape = {
21
64
  task: z.enum(TASKS),
22
65
  subject: z.object({
23
- kind: z.enum(["class", "method", "field", "symbol"]),
66
+ kind: z
67
+ .enum(["class", "method", "field", "symbol"])
68
+ .describe("Symbol kind. Use 'symbol' to auto-detect from the selector: owner+descriptor => method, owner only => field, otherwise => class. The inferred kind is reported as a warning. For task=api-overview the inferred kind must be class."),
24
69
  name: nonEmptyString,
25
70
  owner: nonEmptyString.optional(),
26
71
  descriptor: optionalDescriptorString
27
72
  }),
28
- version: nonEmptyString.optional(),
73
+ version: nonEmptyString
74
+ .optional()
75
+ .describe("Point-in-time MC version for task=exists/map/exact-map/api-overview. For task=lifecycle it is accepted as a back-compat alias for toVersion (range end)."),
76
+ fromVersion: nonEmptyString
77
+ .optional()
78
+ .describe("task=lifecycle only: range start (oldest) version; defaults to the oldest version in the manifest."),
79
+ toVersion: nonEmptyString
80
+ .optional()
81
+ .describe("task=lifecycle only: range end (newest) version; takes precedence over version. Defaults to latest."),
82
+ maxVersions: positiveIntSchema
83
+ .max(400)
84
+ .optional()
85
+ .describe("task=lifecycle only: cap on scanned versions (service default 120, max 400)."),
86
+ includeTimeline: z
87
+ .boolean()
88
+ .optional()
89
+ .describe("task=lifecycle only: include per-version timeline entries."),
90
+ includeSnapshots: z
91
+ .boolean()
92
+ .optional()
93
+ .describe("task=lifecycle only: include snapshot versions in the scan."),
29
94
  sourceMapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
30
95
  targetMapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
31
96
  classNameMapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
32
97
  projectPath: nonEmptyString.optional(),
33
98
  gradleUserHome: nonEmptyString.optional(),
34
99
  signatureMode: z.enum(["exact", "name-only"]).default("exact"),
35
- nameMode: z.enum(["fqcn", "auto"]).default("fqcn"),
100
+ nameMode: z.enum(["fqcn", "auto"]).default("auto"),
36
101
  includeKinds: z.array(z.enum(["class", "field", "method"])).optional(),
37
102
  maxRows: positiveIntSchema.optional(),
38
103
  maxCandidates: positiveIntSchema.default(5),
39
104
  detail: detailSchema.optional(),
40
105
  include: buildIncludeSchema(INCLUDE_GROUPS)
41
106
  };
107
+ const LIFECYCLE_ONLY_FIELDS = [
108
+ "fromVersion",
109
+ "toVersion",
110
+ "maxVersions",
111
+ "includeTimeline",
112
+ "includeSnapshots"
113
+ ];
42
114
  export const analyzeSymbolSchema = z.object(analyzeSymbolShape).superRefine((value, ctx) => {
43
- if (value.task !== "workspace" && !value.version) {
115
+ if (value.task !== "workspace" && value.task !== "lifecycle" && !value.version) {
44
116
  ctx.addIssue({
45
117
  code: z.ZodIssueCode.custom,
46
118
  path: ["version"],
47
119
  message: "version is required for non-workspace tasks."
48
120
  });
49
121
  }
122
+ if (value.task === "lifecycle" && !value.version && !value.toVersion) {
123
+ ctx.addIssue({
124
+ code: z.ZodIssueCode.custom,
125
+ path: ["toVersion"],
126
+ message: "task=lifecycle requires toVersion (or version as a back-compat alias) as the range end."
127
+ });
128
+ }
129
+ if (value.task !== "lifecycle") {
130
+ for (const field of LIFECYCLE_ONLY_FIELDS) {
131
+ if (value[field] !== undefined) {
132
+ ctx.addIssue({
133
+ code: z.ZodIssueCode.custom,
134
+ path: [field],
135
+ message: `${field} is only supported for task=lifecycle.`
136
+ });
137
+ }
138
+ }
139
+ }
50
140
  if (value.task === "workspace" && !value.projectPath) {
51
141
  ctx.addIssue({
52
142
  code: z.ZodIssueCode.custom,
@@ -54,11 +144,13 @@ export const analyzeSymbolSchema = z.object(analyzeSymbolShape).superRefine((val
54
144
  message: "projectPath is required for task=workspace."
55
145
  });
56
146
  }
57
- if (value.task === "api-overview" && value.subject.kind !== "class") {
147
+ if (value.task === "api-overview" &&
148
+ value.subject.kind !== "class" &&
149
+ value.subject.kind !== "symbol") {
58
150
  ctx.addIssue({
59
151
  code: z.ZodIssueCode.custom,
60
152
  path: ["subject", "kind"],
61
- message: "task=api-overview requires subject.kind=class."
153
+ message: "task=api-overview requires subject.kind=class (or 'symbol', which infers class)."
62
154
  });
63
155
  }
64
156
  if (value.task === "api-overview" && value.subject.owner) {
@@ -96,9 +188,7 @@ export class AnalyzeSymbolService {
96
188
  async execute(input) {
97
189
  const detail = resolveDetail(input.detail);
98
190
  const include = resolveInclude(input.include);
99
- const subjectKind = input.subject.kind === "symbol"
100
- ? "class"
101
- : input.subject.kind;
191
+ const { kind: subjectKind, warning: inferenceWarning } = inferSubjectKind(input.subject);
102
192
  switch (input.task) {
103
193
  case "exists": {
104
194
  const output = await this.deps.checkSymbolExists({
@@ -125,7 +215,7 @@ export class AnalyzeSymbolService {
125
215
  : `The symbol could not be resolved in ${output.mappingContext.version}.`,
126
216
  subject: createSummarySubject({
127
217
  task: "exists",
128
- kind: input.subject.kind,
218
+ kind: subjectKind,
129
219
  name: input.subject.name,
130
220
  owner: input.subject.owner,
131
221
  descriptor: input.subject.descriptor,
@@ -138,11 +228,11 @@ export class AnalyzeSymbolService {
138
228
  },
139
229
  blocks: {
140
230
  match: output.resolvedSymbol ?? output.querySymbol,
141
- candidates: output.candidates,
231
+ ...projectMappingCandidates(output),
142
232
  ambiguity: output.ambiguityReasons ? { reasons: output.ambiguityReasons } : undefined
143
233
  }
144
234
  }),
145
- warnings: output.warnings
235
+ warnings: inferenceWarning ? [inferenceWarning, ...output.warnings] : output.warnings
146
236
  };
147
237
  }
148
238
  case "map": {
@@ -155,6 +245,7 @@ export class AnalyzeSymbolService {
155
245
  sourceMapping: input.sourceMapping ?? "obfuscated",
156
246
  targetMapping: input.targetMapping ?? "mojang",
157
247
  ...(input.gradleUserHome !== undefined ? { gradleUserHome: input.gradleUserHome } : {}),
248
+ nameMode: input.nameMode,
158
249
  signatureMode: input.signatureMode,
159
250
  maxCandidates: input.maxCandidates
160
251
  });
@@ -170,7 +261,7 @@ export class AnalyzeSymbolService {
170
261
  : `Found ${output.candidateCount} candidate mappings.`,
171
262
  subject: createSummarySubject({
172
263
  task: "map",
173
- kind: input.subject.kind,
264
+ kind: subjectKind,
174
265
  name: input.subject.name,
175
266
  owner: input.subject.owner,
176
267
  descriptor: input.subject.descriptor,
@@ -184,11 +275,11 @@ export class AnalyzeSymbolService {
184
275
  },
185
276
  blocks: {
186
277
  match: output.resolvedSymbol,
187
- candidates: output.candidates,
278
+ ...projectMappingCandidates(output),
188
279
  ambiguity: output.ambiguityReasons ? { reasons: output.ambiguityReasons } : undefined
189
280
  }
190
281
  }),
191
- warnings: output.warnings
282
+ warnings: inferenceWarning ? [inferenceWarning, ...output.warnings] : output.warnings
192
283
  };
193
284
  }
194
285
  case "exact-map": {
@@ -220,7 +311,7 @@ export class AnalyzeSymbolService {
220
311
  : "Could not resolve the exact method mapping.",
221
312
  subject: createSummarySubject({
222
313
  task: "exact-map",
223
- kind: input.subject.kind,
314
+ kind: subjectKind,
224
315
  name: input.subject.name,
225
316
  owner: input.subject.owner,
226
317
  descriptor: input.subject.descriptor,
@@ -234,10 +325,10 @@ export class AnalyzeSymbolService {
234
325
  },
235
326
  blocks: {
236
327
  match: output.resolvedSymbol,
237
- candidates: output.candidates
328
+ ...projectMappingCandidates(output)
238
329
  }
239
330
  }),
240
- warnings: output.warnings
331
+ warnings: inferenceWarning ? [inferenceWarning, ...output.warnings] : output.warnings
241
332
  };
242
333
  }
243
334
  case "lifecycle": {
@@ -248,8 +339,11 @@ export class AnalyzeSymbolService {
248
339
  descriptor: input.subject.descriptor,
249
340
  mapping: input.sourceMapping,
250
341
  ...(input.gradleUserHome !== undefined ? { gradleUserHome: input.gradleUserHome } : {}),
251
- toVersion: input.version,
252
- maxVersions: 5
342
+ ...(input.fromVersion !== undefined ? { fromVersion: input.fromVersion } : {}),
343
+ toVersion: input.toVersion ?? input.version,
344
+ ...(input.maxVersions !== undefined ? { maxVersions: input.maxVersions } : {}),
345
+ ...(input.includeSnapshots !== undefined ? { includeSnapshots: input.includeSnapshots } : {}),
346
+ ...(input.includeTimeline !== undefined ? { includeTimeline: input.includeTimeline } : {})
253
347
  });
254
348
  return {
255
349
  ...buildEntryToolResult({
@@ -263,11 +357,11 @@ export class AnalyzeSymbolService {
263
357
  : "The symbol was not found in the scanned version range.",
264
358
  subject: createSummarySubject({
265
359
  task: "lifecycle",
266
- kind: input.subject.kind,
360
+ kind: subjectKind,
267
361
  name: input.subject.name,
268
362
  owner: input.subject.owner,
269
363
  descriptor: input.subject.descriptor,
270
- version: input.version,
364
+ version: input.toVersion ?? input.version,
271
365
  sourceMapping: input.sourceMapping ?? "obfuscated"
272
366
  }),
273
367
  counts: {
@@ -279,7 +373,7 @@ export class AnalyzeSymbolService {
279
373
  timeline: output.timeline
280
374
  }
281
375
  }),
282
- warnings: output.warnings
376
+ warnings: inferenceWarning ? [inferenceWarning, ...output.warnings] : output.warnings
283
377
  };
284
378
  }
285
379
  case "workspace": {
@@ -306,7 +400,7 @@ export class AnalyzeSymbolService {
306
400
  : "Workspace compile mapping could not be detected confidently.",
307
401
  subject: createSummarySubject({
308
402
  task: "workspace",
309
- kind: input.subject.kind,
403
+ kind: subjectKind,
310
404
  name: input.subject.name,
311
405
  owner: input.subject.owner,
312
406
  descriptor: input.subject.descriptor,
@@ -320,11 +414,13 @@ export class AnalyzeSymbolService {
320
414
  },
321
415
  blocks: {
322
416
  match: output.resolvedSymbol,
323
- candidates: output.candidates,
417
+ ...projectMappingCandidates(output),
324
418
  workspace: output.workspaceDetection
325
419
  }
326
420
  }),
327
- warnings: [...output.warnings, ...output.workspaceDetection.warnings]
421
+ warnings: inferenceWarning
422
+ ? [inferenceWarning, ...output.warnings, ...output.workspaceDetection.warnings]
423
+ : [...output.warnings, ...output.workspaceDetection.warnings]
328
424
  };
329
425
  }
330
426
  case "api-overview": {
@@ -347,7 +443,7 @@ export class AnalyzeSymbolService {
347
443
  headline: `Built an API overview for ${output.className}.`,
348
444
  subject: createSummarySubject({
349
445
  task: "api-overview",
350
- kind: input.subject.kind,
446
+ kind: subjectKind,
351
447
  name: input.subject.name,
352
448
  version: input.version,
353
449
  classNameMapping
@@ -371,7 +467,7 @@ export class AnalyzeSymbolService {
371
467
  : undefined
372
468
  }
373
469
  }),
374
- warnings: output.warnings
470
+ warnings: inferenceWarning ? [inferenceWarning, ...output.warnings] : output.warnings
375
471
  };
376
472
  }
377
473
  }
@@ -1,3 +1,4 @@
1
+ import { type ResponseDetailLevel } from "../response-utils.js";
1
2
  import type { GetClassMembersInput, GetClassMembersOutput, ResolveArtifactInput, ResolveArtifactOutput } from "../source-service.js";
2
3
  import type { ArtifactScope, MappingSourcePriority, ResolveArtifactTargetInput, SourceMapping } from "../types.js";
3
4
  import { type BatchOutput } from "./batch-runner.js";
@@ -25,7 +26,8 @@ export type BatchClassMembersInput = {
25
26
  strictVersion?: boolean;
26
27
  concurrency?: number;
27
28
  failFast?: boolean;
28
- compact?: boolean;
29
+ detail?: ResponseDetailLevel;
30
+ include?: readonly string[];
29
31
  entries: readonly BatchClassMembersEntry[];
30
32
  };
31
33
  export declare class BatchClassMembersService {
@@ -1,5 +1,5 @@
1
1
  import { buildSuggestedCall } from "../build-suggested-call.js";
2
- import { compactResponse, compactMembersResponse, TOOL_PRESERVE_PAYLOAD_KEYS } from "../response-utils.js";
2
+ import { projectByDetail } from "../response-utils.js";
3
3
  import { runBatch, splitEntryWarnings } from "./batch-runner.js";
4
4
  export class BatchClassMembersService {
5
5
  deps;
@@ -9,7 +9,8 @@ export class BatchClassMembersService {
9
9
  async execute(input) {
10
10
  const concurrency = input.concurrency ?? 4;
11
11
  const failFast = input.failFast ?? false;
12
- const compact = input.compact ?? true;
12
+ const detail = input.detail ?? "summary";
13
+ const include = new Set(input.include ?? []);
13
14
  return runBatch({
14
15
  entries: input.entries,
15
16
  concurrency,
@@ -53,6 +54,7 @@ export class BatchClassMembersService {
53
54
  includeInherited: entry.includeInherited,
54
55
  memberPattern: entry.memberPattern,
55
56
  maxMembers: entry.maxMembers,
57
+ includeDescriptors: include.has("descriptors"),
56
58
  mapping: input.mapping,
57
59
  sourcePriority: input.sourcePriority,
58
60
  allowDecompile: input.allowDecompile,
@@ -63,16 +65,14 @@ export class BatchClassMembersService {
63
65
  strictVersion: input.strictVersion
64
66
  }));
65
67
  const { result, warnings } = splitEntryWarnings(raw);
66
- const projected = compact
67
- ? compactResponse(compactMembersResponse(result), TOOL_PRESERVE_PAYLOAD_KEYS["get-class-members"])
68
- : result;
68
+ const projected = projectByDetail("get-class-members", result, detail, include);
69
69
  return { result: projected, warnings };
70
70
  },
71
71
  buildErrorSuggestedCall: (entry, sharedArtifact) => {
72
72
  if (!sharedArtifact)
73
73
  return undefined;
74
74
  const params = {
75
- target: { type: "artifact", artifactId: sharedArtifact.artifactId },
75
+ target: { kind: "artifact", artifactId: sharedArtifact.artifactId },
76
76
  className: entry.className
77
77
  };
78
78
  if (entry.access !== undefined)
@@ -1,3 +1,4 @@
1
+ import { type ResponseDetailLevel } from "../response-utils.js";
1
2
  import type { GetClassSourceInput, GetClassSourceOutput, ResolveArtifactInput, ResolveArtifactOutput } from "../source-service.js";
2
3
  import type { ArtifactScope, MappingSourcePriority, ResolveArtifactTargetInput, SourceMapping } from "../types.js";
3
4
  import { type BatchOutput } from "./batch-runner.js";
@@ -23,7 +24,8 @@ export type BatchClassSourceInput = {
23
24
  strictVersion?: boolean;
24
25
  concurrency?: number;
25
26
  failFast?: boolean;
26
- compact?: boolean;
27
+ detail?: ResponseDetailLevel;
28
+ include?: readonly string[];
27
29
  entries: readonly BatchClassSourceEntry[];
28
30
  };
29
31
  export type BatchClassSourceDeps = {
@@ -1,5 +1,5 @@
1
1
  import { buildSuggestedCall } from "../build-suggested-call.js";
2
- import { compactResponse, compactSourceResponse, TOOL_PRESERVE_PAYLOAD_KEYS } from "../response-utils.js";
2
+ import { projectByDetail } from "../response-utils.js";
3
3
  import { runBatch, splitEntryWarnings } from "./batch-runner.js";
4
4
  export class BatchClassSourceService {
5
5
  deps;
@@ -9,7 +9,8 @@ export class BatchClassSourceService {
9
9
  async execute(input) {
10
10
  const concurrency = input.concurrency ?? 4;
11
11
  const failFast = input.failFast ?? false;
12
- const compact = input.compact ?? true;
12
+ const detail = input.detail ?? "summary";
13
+ const include = new Set(input.include ?? []);
13
14
  return runBatch({
14
15
  entries: input.entries,
15
16
  concurrency,
@@ -64,16 +65,14 @@ export class BatchClassSourceService {
64
65
  strictVersion: input.strictVersion
65
66
  }));
66
67
  const { result, warnings } = splitEntryWarnings(raw);
67
- const projected = compact
68
- ? compactResponse(compactSourceResponse(result), TOOL_PRESERVE_PAYLOAD_KEYS["get-class-source"])
69
- : result;
68
+ const projected = projectByDetail("get-class-source", result, detail, include);
70
69
  return { result: projected, warnings };
71
70
  },
72
71
  buildErrorSuggestedCall: (entry, sharedArtifact) => {
73
72
  if (!sharedArtifact)
74
73
  return undefined;
75
74
  const params = {
76
- target: { type: "artifact", artifactId: sharedArtifact.artifactId },
75
+ target: { kind: "artifact", artifactId: sharedArtifact.artifactId },
77
76
  className: entry.className
78
77
  };
79
78
  if (entry.mode !== undefined)
@@ -1,3 +1,4 @@
1
+ import { type ResponseDetailLevel } from "../response-utils.js";
1
2
  import type { FindMappingInput, FindMappingOutput } from "../source-service.js";
2
3
  import type { MappingSourcePriority, SourceMapping } from "../types.js";
3
4
  export type BatchMappingsDeps = {
@@ -26,7 +27,8 @@ export type BatchMappingsInput = {
26
27
  gradleUserHome?: string;
27
28
  concurrency?: number;
28
29
  failFast?: boolean;
29
- compact?: boolean;
30
+ detail?: ResponseDetailLevel;
31
+ include?: readonly string[];
30
32
  entries: readonly BatchMappingsEntry[];
31
33
  };
32
34
  export declare class BatchMappingsService {
@@ -1,5 +1,5 @@
1
1
  import { buildSuggestedCall } from "../build-suggested-call.js";
2
- import { compactResponse, compactMappingResponse } from "../response-utils.js";
2
+ import { projectByDetail } from "../response-utils.js";
3
3
  import { runBatch, splitEntryWarnings } from "./batch-runner.js";
4
4
  export class BatchMappingsService {
5
5
  deps;
@@ -9,7 +9,8 @@ export class BatchMappingsService {
9
9
  async execute(input) {
10
10
  const concurrency = input.concurrency ?? 4;
11
11
  const failFast = input.failFast ?? false;
12
- const compact = input.compact ?? true;
12
+ const detail = input.detail ?? "summary";
13
+ const include = new Set(input.include ?? []);
13
14
  return runBatch({
14
15
  entries: input.entries,
15
16
  concurrency,
@@ -32,9 +33,7 @@ export class BatchMappingsService {
32
33
  maxCandidates: entry.maxCandidates
33
34
  }));
34
35
  const { result, warnings } = splitEntryWarnings(raw);
35
- const projected = compact
36
- ? compactResponse(compactMappingResponse(result))
37
- : result;
36
+ const projected = projectByDetail("find-mapping", result, detail, include);
38
37
  return { result: projected, warnings };
39
38
  },
40
39
  buildErrorSuggestedCall: (entry) => {
@@ -1,3 +1,4 @@
1
+ import { type ResponseDetailLevel } from "../response-utils.js";
1
2
  import type { CheckSymbolExistsInput, CheckSymbolExistsOutput, ResolveArtifactInput, ResolveArtifactOutput } from "../source-service.js";
2
3
  import type { ArtifactScope, MappingSourcePriority, SourceMapping, WorkspaceTargetInput, SourceTargetInput } from "../types.js";
3
4
  export type BatchSymbolExistsDeps = {
@@ -36,7 +37,8 @@ export type BatchSymbolExistsInput = {
36
37
  strictVersion?: boolean;
37
38
  concurrency?: number;
38
39
  failFast?: boolean;
39
- compact?: boolean;
40
+ detail?: ResponseDetailLevel;
41
+ include?: readonly string[];
40
42
  entries: readonly BatchSymbolExistsEntry[];
41
43
  };
42
44
  export declare class BatchSymbolExistsService {