@adhisang/minecraft-modding-mcp 4.0.0 → 4.1.1

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 (176) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +40 -23
  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 +50 -6
  7. package/dist/entry-tools/analyze-symbol-service.d.ts +16 -16
  8. package/dist/entry-tools/batch-class-members-service.d.ts +34 -0
  9. package/dist/entry-tools/batch-class-members-service.js +97 -0
  10. package/dist/entry-tools/batch-class-source-service.d.ts +37 -0
  11. package/dist/entry-tools/batch-class-source-service.js +100 -0
  12. package/dist/entry-tools/batch-mappings-service.d.ts +36 -0
  13. package/dist/entry-tools/batch-mappings-service.js +66 -0
  14. package/dist/entry-tools/batch-runner.d.ts +72 -0
  15. package/dist/entry-tools/batch-runner.js +90 -0
  16. package/dist/entry-tools/batch-symbol-exists-service.d.ts +46 -0
  17. package/dist/entry-tools/batch-symbol-exists-service.js +113 -0
  18. package/dist/entry-tools/compare-minecraft-service.d.ts +6 -6
  19. package/dist/entry-tools/inspect-minecraft/handlers/artifact.d.ts +5 -0
  20. package/dist/entry-tools/inspect-minecraft/handlers/artifact.js +83 -0
  21. package/dist/entry-tools/inspect-minecraft/handlers/class-members.d.ts +6 -0
  22. package/dist/entry-tools/inspect-minecraft/handlers/class-members.js +80 -0
  23. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.d.ts +5 -0
  24. package/dist/entry-tools/inspect-minecraft/handlers/class-overview.js +248 -0
  25. package/dist/entry-tools/inspect-minecraft/handlers/class-source.d.ts +5 -0
  26. package/dist/entry-tools/inspect-minecraft/handlers/class-source.js +60 -0
  27. package/dist/entry-tools/inspect-minecraft/handlers/file.d.ts +5 -0
  28. package/dist/entry-tools/inspect-minecraft/handlers/file.js +54 -0
  29. package/dist/entry-tools/inspect-minecraft/handlers/list-files.d.ts +5 -0
  30. package/dist/entry-tools/inspect-minecraft/handlers/list-files.js +100 -0
  31. package/dist/entry-tools/inspect-minecraft/handlers/search.d.ts +5 -0
  32. package/dist/entry-tools/inspect-minecraft/handlers/search.js +155 -0
  33. package/dist/entry-tools/inspect-minecraft/handlers/versions.d.ts +6 -0
  34. package/dist/entry-tools/inspect-minecraft/handlers/versions.js +49 -0
  35. package/dist/entry-tools/inspect-minecraft/internal.d.ts +1042 -0
  36. package/dist/entry-tools/inspect-minecraft/internal.js +448 -0
  37. package/dist/entry-tools/inspect-minecraft-service.d.ts +193 -308
  38. package/dist/entry-tools/inspect-minecraft-service.js +20 -1244
  39. package/dist/entry-tools/manage-cache-service.d.ts +16 -16
  40. package/dist/entry-tools/validate-project/cases/access-transformer.d.ts +6 -0
  41. package/dist/entry-tools/validate-project/cases/access-transformer.js +106 -0
  42. package/dist/entry-tools/validate-project/cases/access-widener.d.ts +6 -0
  43. package/dist/entry-tools/validate-project/cases/access-widener.js +86 -0
  44. package/dist/entry-tools/validate-project/cases/mixin.d.ts +6 -0
  45. package/dist/entry-tools/validate-project/cases/mixin.js +90 -0
  46. package/dist/entry-tools/validate-project/cases/project-summary.d.ts +102 -0
  47. package/dist/entry-tools/validate-project/cases/project-summary.js +415 -0
  48. package/dist/entry-tools/validate-project/internal.d.ts +142 -0
  49. package/dist/entry-tools/validate-project/internal.js +303 -0
  50. package/dist/entry-tools/validate-project-service.d.ts +67 -47
  51. package/dist/entry-tools/validate-project-service.js +13 -563
  52. package/dist/entry-tools/verify-mixin-target-service.d.ts +133 -0
  53. package/dist/entry-tools/verify-mixin-target-service.js +323 -0
  54. package/dist/error-mapping.d.ts +40 -0
  55. package/dist/error-mapping.js +139 -0
  56. package/dist/errors.d.ts +6 -0
  57. package/dist/errors.js +6 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.js +147 -1354
  60. package/dist/mapping/internal-types.d.ts +54 -0
  61. package/dist/mapping/internal-types.js +14 -0
  62. package/dist/mapping/loaders/mojang.d.ts +2 -0
  63. package/dist/mapping/loaders/mojang.js +64 -0
  64. package/dist/mapping/loaders/tiny-loom.d.ts +2 -0
  65. package/dist/mapping/loaders/tiny-loom.js +73 -0
  66. package/dist/mapping/loaders/tiny-maven.d.ts +2 -0
  67. package/dist/mapping/loaders/tiny-maven.js +104 -0
  68. package/dist/mapping/loaders/types.d.ts +14 -0
  69. package/dist/mapping/loaders/types.js +2 -0
  70. package/dist/mapping/lookup.d.ts +52 -0
  71. package/dist/mapping/lookup.js +496 -0
  72. package/dist/mapping/parsers/normalize.d.ts +10 -0
  73. package/dist/mapping/parsers/normalize.js +52 -0
  74. package/dist/mapping/parsers/proguard.d.ts +20 -0
  75. package/dist/mapping/parsers/proguard.js +138 -0
  76. package/dist/mapping/parsers/symbol-records.d.ts +27 -0
  77. package/dist/mapping/parsers/symbol-records.js +216 -0
  78. package/dist/mapping/parsers/tiny.d.ts +9 -0
  79. package/dist/mapping/parsers/tiny.js +96 -0
  80. package/dist/mapping/types.d.ts +147 -0
  81. package/dist/mapping/types.js +2 -0
  82. package/dist/mapping-pipeline-service.js +3 -2
  83. package/dist/mapping-service.d.ts +8 -145
  84. package/dist/mapping-service.js +30 -1207
  85. package/dist/mixin/access-validators.d.ts +9 -0
  86. package/dist/mixin/access-validators.js +257 -0
  87. package/dist/mixin/annotation-validators.d.ts +5 -0
  88. package/dist/mixin/annotation-validators.js +162 -0
  89. package/dist/mixin/helpers.d.ts +28 -0
  90. package/dist/mixin/helpers.js +315 -0
  91. package/dist/mixin/parsed-validator.d.ts +8 -0
  92. package/dist/mixin/parsed-validator.js +337 -0
  93. package/dist/mixin/types.d.ts +208 -0
  94. package/dist/mixin/types.js +28 -0
  95. package/dist/mixin-validator.d.ts +9 -201
  96. package/dist/mixin-validator.js +8 -1020
  97. package/dist/source/access-validate.d.ts +4 -0
  98. package/dist/source/access-validate.js +254 -0
  99. package/dist/source/artifact-resolver.d.ts +111 -0
  100. package/dist/source/artifact-resolver.js +1271 -0
  101. package/dist/source/cache-metrics.d.ts +26 -0
  102. package/dist/source/cache-metrics.js +172 -0
  103. package/dist/source/class-source/members-builder.d.ts +34 -0
  104. package/dist/source/class-source/members-builder.js +46 -0
  105. package/dist/source/class-source/snippet-builder.d.ts +19 -0
  106. package/dist/source/class-source/snippet-builder.js +46 -0
  107. package/dist/source/class-source-helpers.d.ts +34 -0
  108. package/dist/source/class-source-helpers.js +140 -0
  109. package/dist/source/class-source.d.ts +42 -0
  110. package/dist/source/class-source.js +883 -0
  111. package/dist/source/descriptor-utils.d.ts +6 -0
  112. package/dist/source/descriptor-utils.js +37 -0
  113. package/dist/source/file-access.d.ts +4 -0
  114. package/dist/source/file-access.js +102 -0
  115. package/dist/source/indexer.d.ts +82 -0
  116. package/dist/source/indexer.js +522 -0
  117. package/dist/source/lifecycle/diff-utils.d.ts +9 -0
  118. package/dist/source/lifecycle/diff-utils.js +107 -0
  119. package/dist/source/lifecycle/diff.d.ts +2 -0
  120. package/dist/source/lifecycle/diff.js +265 -0
  121. package/dist/source/lifecycle/mapping-helpers.d.ts +22 -0
  122. package/dist/source/lifecycle/mapping-helpers.js +327 -0
  123. package/dist/source/lifecycle/runtime-check.d.ts +2 -0
  124. package/dist/source/lifecycle/runtime-check.js +142 -0
  125. package/dist/source/lifecycle/trace.d.ts +2 -0
  126. package/dist/source/lifecycle/trace.js +231 -0
  127. package/dist/source/lifecycle.d.ts +4 -0
  128. package/dist/source/lifecycle.js +5 -0
  129. package/dist/source/search.d.ts +51 -0
  130. package/dist/source/search.js +676 -0
  131. package/dist/source/shared-utils.d.ts +6 -0
  132. package/dist/source/shared-utils.js +55 -0
  133. package/dist/source/state.d.ts +26 -0
  134. package/dist/source/state.js +24 -0
  135. package/dist/source/symbol-resolver.d.ts +3 -0
  136. package/dist/source/symbol-resolver.js +212 -0
  137. package/dist/source/validate-mixin/pipeline/mapping-health.d.ts +3 -0
  138. package/dist/source/validate-mixin/pipeline/mapping-health.js +41 -0
  139. package/dist/source/validate-mixin/pipeline/parse.d.ts +2 -0
  140. package/dist/source/validate-mixin/pipeline/parse.js +10 -0
  141. package/dist/source/validate-mixin/pipeline/resolve.d.ts +3 -0
  142. package/dist/source/validate-mixin/pipeline/resolve.js +78 -0
  143. package/dist/source/validate-mixin/pipeline/target-lookup.d.ts +6 -0
  144. package/dist/source/validate-mixin/pipeline/target-lookup.js +260 -0
  145. package/dist/source/validate-mixin/pipeline-context.d.ts +72 -0
  146. package/dist/source/validate-mixin/pipeline-context.js +93 -0
  147. package/dist/source/validate-mixin.d.ts +22 -0
  148. package/dist/source/validate-mixin.js +799 -0
  149. package/dist/source/workspace-target.d.ts +18 -0
  150. package/dist/source/workspace-target.js +305 -0
  151. package/dist/source-resolver.d.ts +1 -0
  152. package/dist/source-resolver.js +1 -1
  153. package/dist/source-service.d.ts +164 -170
  154. package/dist/source-service.js +70 -6116
  155. package/dist/stage-emitter.d.ts +13 -0
  156. package/dist/stage-emitter.js +30 -0
  157. package/dist/stdio-supervisor.d.ts +61 -0
  158. package/dist/stdio-supervisor.js +326 -9
  159. package/dist/tool-contract-manifest.d.ts +1 -1
  160. package/dist/tool-contract-manifest.js +23 -6
  161. package/dist/tool-guidance.d.ts +82 -0
  162. package/dist/tool-guidance.js +734 -0
  163. package/dist/tool-schema-registry.d.ts +16 -0
  164. package/dist/tool-schema-registry.js +37 -0
  165. package/dist/tool-schemas.d.ts +3518 -0
  166. package/dist/tool-schemas.js +813 -0
  167. package/dist/types.d.ts +36 -0
  168. package/dist/version-service.js +7 -6
  169. package/dist/workspace-context-cache.d.ts +32 -0
  170. package/dist/workspace-context-cache.js +66 -0
  171. package/dist/workspace-mapping-service.d.ts +16 -0
  172. package/dist/workspace-mapping-service.js +173 -1
  173. package/docs/README-ja.md +416 -0
  174. package/docs/examples.md +483 -0
  175. package/docs/tool-reference.md +462 -0
  176. package/package.json +17 -4
@@ -1,104 +1,18 @@
1
1
  import { z } from "zod";
2
- import { createError, ERROR_CODES, isAppError } from "../errors.js";
2
+ import { createError, ERROR_CODES } from "../errors.js";
3
3
  import { buildIncludeSchema, detailSchema, positiveIntSchema } from "./entry-tool-schema.js";
4
- import { buildEntryToolResult, buildEntryToolMeta, createNextAction, createSummarySubject, createTruncationMeta } from "./response-contract.js";
5
- import { capArray, nextActionsOrUndefined, resolveDetail, resolveInclude } from "./request-normalizers.js";
4
+ import { resolveDetail, resolveInclude } from "./request-normalizers.js";
5
+ import { TASKS, resolveTask, subjectSchema } from "./inspect-minecraft/internal.js";
6
+ import { handleVersions } from "./inspect-minecraft/handlers/versions.js";
7
+ import { handleArtifact } from "./inspect-minecraft/handlers/artifact.js";
8
+ import { handleClassOverview } from "./inspect-minecraft/handlers/class-overview.js";
9
+ import { handleClassSource } from "./inspect-minecraft/handlers/class-source.js";
10
+ import { handleClassMembers } from "./inspect-minecraft/handlers/class-members.js";
11
+ import { handleSearch } from "./inspect-minecraft/handlers/search.js";
12
+ import { handleFile } from "./inspect-minecraft/handlers/file.js";
13
+ import { handleListFiles } from "./inspect-minecraft/handlers/list-files.js";
6
14
  const INCLUDE_GROUPS = ["warnings", "provenance", "candidates", "members", "source", "files", "samples", "artifact", "timings"];
7
- const TASKS = ["auto", "versions", "artifact", "class-overview", "class-source", "class-members", "search", "file", "list-files"];
8
- const SUBJECT_KINDS = ["version", "artifact", "class", "file", "search", "workspace"];
9
15
  const nonEmptyString = z.string().trim().min(1);
10
- const resolveTargetSchema = z.object({
11
- kind: z.enum(["version", "jar", "coordinate"]),
12
- value: nonEmptyString
13
- });
14
- const artifactRefSchema = z.discriminatedUnion("type", [
15
- z.object({
16
- type: z.literal("resolved-id"),
17
- artifactId: nonEmptyString
18
- }),
19
- z.object({
20
- type: z.literal("resolve-target"),
21
- target: resolveTargetSchema
22
- })
23
- ]);
24
- const workspaceFocusSchema = z.discriminatedUnion("kind", [
25
- z.object({
26
- kind: z.literal("class"),
27
- className: nonEmptyString,
28
- artifact: artifactRefSchema.optional()
29
- }),
30
- z.object({
31
- kind: z.literal("file"),
32
- filePath: nonEmptyString,
33
- artifact: artifactRefSchema.optional()
34
- }),
35
- z.object({
36
- kind: z.literal("search"),
37
- query: nonEmptyString,
38
- artifact: artifactRefSchema.optional(),
39
- intent: z.enum(["symbol", "text", "path"]).optional(),
40
- match: z.enum(["exact", "prefix", "contains", "regex"]).optional(),
41
- symbolKind: z.enum(["class", "interface", "enum", "record", "method", "field"]).optional(),
42
- packagePrefix: nonEmptyString.optional(),
43
- fileGlob: nonEmptyString.optional(),
44
- queryMode: z.enum(["auto", "token", "literal"]).default("auto")
45
- })
46
- ]);
47
- const subjectSchema = z.discriminatedUnion("kind", [
48
- z.object({
49
- kind: z.literal("version"),
50
- version: nonEmptyString,
51
- mapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
52
- scope: z.enum(["vanilla", "merged", "loader"]).optional(),
53
- projectPath: nonEmptyString.optional(),
54
- preferProjectVersion: z.boolean().optional(),
55
- strictVersion: z.boolean().optional()
56
- }),
57
- z.object({
58
- kind: z.literal("artifact"),
59
- artifact: artifactRefSchema,
60
- mapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
61
- scope: z.enum(["vanilla", "merged", "loader"]).optional(),
62
- projectPath: nonEmptyString.optional(),
63
- preferProjectVersion: z.boolean().optional(),
64
- strictVersion: z.boolean().optional()
65
- }),
66
- z.object({
67
- kind: z.literal("class"),
68
- className: nonEmptyString,
69
- artifact: artifactRefSchema.optional(),
70
- mapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
71
- scope: z.enum(["vanilla", "merged", "loader"]).optional(),
72
- projectPath: nonEmptyString.optional(),
73
- preferProjectVersion: z.boolean().optional(),
74
- strictVersion: z.boolean().optional()
75
- }),
76
- z.object({
77
- kind: z.literal("file"),
78
- filePath: nonEmptyString,
79
- artifact: artifactRefSchema.optional()
80
- }),
81
- z.object({
82
- kind: z.literal("search"),
83
- query: nonEmptyString,
84
- artifact: artifactRefSchema.optional(),
85
- intent: z.enum(["symbol", "text", "path"]).optional(),
86
- match: z.enum(["exact", "prefix", "contains", "regex"]).optional(),
87
- symbolKind: z.enum(["class", "interface", "enum", "record", "method", "field"]).optional(),
88
- packagePrefix: nonEmptyString.optional(),
89
- fileGlob: nonEmptyString.optional(),
90
- queryMode: z.enum(["auto", "token", "literal"]).default("auto")
91
- }),
92
- z.object({
93
- kind: z.literal("workspace"),
94
- projectPath: nonEmptyString,
95
- mapping: z.enum(["obfuscated", "mojang", "intermediary", "yarn"]).optional(),
96
- scope: z.enum(["vanilla", "merged", "loader"]).optional(),
97
- preferProjectVersion: z.boolean().optional(),
98
- strictVersion: z.boolean().optional(),
99
- focus: workspaceFocusSchema.optional()
100
- })
101
- ]);
102
16
  export const inspectMinecraftShape = {
103
17
  task: z.enum(TASKS).optional(),
104
18
  subject: subjectSchema.optional(),
@@ -124,32 +38,6 @@ export const inspectMinecraftSchema = z.object(inspectMinecraftShape).superRefin
124
38
  });
125
39
  }
126
40
  });
127
- function hasPartialVanillaCoverage(artifact) {
128
- return artifact?.qualityFlags.includes("partial-source-no-net-minecraft") === true
129
- || artifact?.artifactContents.sourceCoverage === "partial";
130
- }
131
- function looksLikeClassQuery(query) {
132
- const trimmed = query.trim();
133
- if (!/^[A-Za-z_$][A-Za-z0-9_$.]*$/.test(trimmed)) {
134
- return false;
135
- }
136
- const simpleName = trimmed.split(".").at(-1) ?? trimmed;
137
- return /^[A-Z_$]/.test(simpleName) || /^class_\d+(?:\$class_\d+)*$/.test(simpleName);
138
- }
139
- function classNameToFilePath(className) {
140
- const topLevelClassName = className.split("$")[0] ?? className;
141
- return `${topLevelClassName.replace(/\./g, "/")}.java`;
142
- }
143
- function isVanillaNamespacePath(filePath) {
144
- return filePath.startsWith("net/minecraft/") || filePath.startsWith("com/mojang/");
145
- }
146
- function hitTargetsVanillaNamespace(hit) {
147
- if (isVanillaNamespacePath(hit.filePath)) {
148
- return true;
149
- }
150
- const qualifiedName = hit.symbol?.qualifiedName;
151
- return qualifiedName?.startsWith("net.minecraft.") === true || qualifiedName?.startsWith("com.mojang.") === true;
152
- }
153
41
  export class InspectMinecraftService {
154
42
  deps;
155
43
  constructor(deps) {
@@ -158,24 +46,24 @@ export class InspectMinecraftService {
158
46
  async execute(input) {
159
47
  const detail = resolveDetail(input.detail);
160
48
  const include = resolveInclude(input.include);
161
- const task = this.resolveTask(input.task, input.subject);
49
+ const task = resolveTask(input.task, input.subject);
162
50
  switch (task) {
163
51
  case "versions":
164
- return this.handleVersions(input, detail, include);
52
+ return handleVersions(this.deps, input, detail, include);
165
53
  case "artifact":
166
- return this.handleArtifact(input.subject, detail, include);
54
+ return handleArtifact(this.deps, input.subject, detail, include);
167
55
  case "class-overview":
168
- return this.handleClassOverview(input.subject, detail, include);
56
+ return handleClassOverview(this.deps, input.subject, detail, include);
169
57
  case "class-source":
170
- return this.handleClassSource(input.subject, detail, include);
58
+ return handleClassSource(this.deps, input.subject, detail, include);
171
59
  case "class-members":
172
- return this.handleClassMembers(input.subject, detail, include, input.limit);
60
+ return handleClassMembers(this.deps, input.subject, detail, include, input.limit);
173
61
  case "search":
174
- return this.handleSearch(input.subject, detail, include, input.limit, input.cursor);
62
+ return handleSearch(this.deps, input.subject, detail, include, input.limit, input.cursor);
175
63
  case "file":
176
- return this.handleFile(input.subject, detail, include);
64
+ return handleFile(this.deps, input.subject, detail, include);
177
65
  case "list-files":
178
- return this.handleListFiles(input.subject, detail, include, input.limit, input.cursor);
66
+ return handleListFiles(this.deps, input.subject, detail, include, input.limit, input.cursor);
179
67
  default:
180
68
  throw createError({
181
69
  code: ERROR_CODES.INVALID_INPUT,
@@ -183,1117 +71,5 @@ export class InspectMinecraftService {
183
71
  });
184
72
  }
185
73
  }
186
- requireWorkspaceClassFocus(subject) {
187
- if (subject.kind !== "workspace" || subject.focus?.kind !== "class") {
188
- throw createError({
189
- code: ERROR_CODES.INVALID_INPUT,
190
- message: "Workspace focus must be kind=class for this task."
191
- });
192
- }
193
- return subject.focus;
194
- }
195
- requireWorkspaceSearchFocus(subject) {
196
- if (subject.kind !== "workspace" || subject.focus?.kind !== "search") {
197
- throw createError({
198
- code: ERROR_CODES.INVALID_INPUT,
199
- message: "Workspace focus must be kind=search for this task."
200
- });
201
- }
202
- return subject.focus;
203
- }
204
- requireWorkspaceFileFocus(subject) {
205
- if (subject.kind !== "workspace" || subject.focus?.kind !== "file") {
206
- throw createError({
207
- code: ERROR_CODES.INVALID_INPUT,
208
- message: "Workspace focus must be kind=file for this task."
209
- });
210
- }
211
- return subject.focus;
212
- }
213
- buildClassSubject(subject) {
214
- if (subject.kind === "class") {
215
- return subject;
216
- }
217
- const workspaceFocus = this.requireWorkspaceClassFocus(subject);
218
- return {
219
- kind: "class",
220
- className: workspaceFocus.className,
221
- artifact: workspaceFocus.artifact,
222
- projectPath: subject.projectPath,
223
- mapping: subject.mapping,
224
- scope: subject.scope,
225
- preferProjectVersion: subject.preferProjectVersion,
226
- strictVersion: subject.strictVersion
227
- };
228
- }
229
- async resolveClassArtifactReference(subject, classSubject, task) {
230
- if (subject.kind === "workspace") {
231
- return this.resolveWorkspaceArtifactReference(subject, classSubject.artifact);
232
- }
233
- return this.resolveArtifactReference(classSubject, task);
234
- }
235
- async resolveWorkspaceArtifactReference(subject, artifactRef) {
236
- if (!artifactRef) {
237
- return this.resolveArtifactReference(subject);
238
- }
239
- if (artifactRef.type === "resolved-id") {
240
- return {
241
- artifactId: artifactRef.artifactId,
242
- warnings: []
243
- };
244
- }
245
- const artifact = await this.deps.resolveArtifact({
246
- target: artifactRef.target,
247
- mapping: subject.mapping,
248
- scope: subject.scope,
249
- projectPath: subject.projectPath,
250
- preferProjectVersion: subject.preferProjectVersion,
251
- strictVersion: subject.strictVersion
252
- });
253
- return {
254
- artifactId: artifact.artifactId,
255
- artifact,
256
- warnings: [...artifact.warnings]
257
- };
258
- }
259
- resolveTask(task, subject) {
260
- if (task && task !== "auto") {
261
- return task;
262
- }
263
- if (!subject) {
264
- return "versions";
265
- }
266
- switch (subject.kind) {
267
- case "version":
268
- case "artifact":
269
- return "artifact";
270
- case "workspace":
271
- switch (subject.focus?.kind) {
272
- case "class":
273
- return "class-overview";
274
- case "search":
275
- return "search";
276
- case "file":
277
- return "file";
278
- default:
279
- return "artifact";
280
- }
281
- case "class":
282
- return "class-overview";
283
- case "file":
284
- return "file";
285
- case "search":
286
- return "search";
287
- }
288
- }
289
- summarizeRequestedSubject(subject) {
290
- if (subject.kind === "search") {
291
- if (subject.queryMode !== "auto") {
292
- return subject;
293
- }
294
- const { queryMode: _queryMode, ...requestedSubject } = subject;
295
- return requestedSubject;
296
- }
297
- if (subject.kind === "workspace" && subject.focus?.kind === "search") {
298
- if (subject.focus.queryMode !== "auto") {
299
- return subject;
300
- }
301
- const { queryMode: _queryMode, ...requestedFocus } = subject.focus;
302
- return {
303
- ...subject,
304
- focus: requestedFocus
305
- };
306
- }
307
- return subject;
308
- }
309
- async exampleVersionForSubject(subject) {
310
- if ("projectPath" in subject && typeof subject.projectPath === "string") {
311
- const detectedVersion = await this.deps.detectProjectMinecraftVersion(subject.projectPath);
312
- if (detectedVersion) {
313
- return detectedVersion;
314
- }
315
- }
316
- return "<version>";
317
- }
318
- async buildArtifactContextSuggestedCall(task, subject) {
319
- return {
320
- tool: "inspect-minecraft",
321
- params: {
322
- task,
323
- subject: {
324
- ...subject,
325
- artifact: {
326
- type: "resolve-target",
327
- target: {
328
- kind: "version",
329
- value: await this.exampleVersionForSubject(subject)
330
- }
331
- }
332
- }
333
- }
334
- };
335
- }
336
- taskForSubject(subject) {
337
- return this.resolveTask(undefined, subject);
338
- }
339
- invalidTaskSubjectError(task, subject) {
340
- if (task === "class-source" && subject.kind === "version") {
341
- throw createError({
342
- code: ERROR_CODES.INVALID_INPUT,
343
- message: "class-source requires a class subject; version subjects resolve artifacts, not class names.",
344
- details: {
345
- nextAction: "Retry class-source with subject.kind=class and attach artifact context, or use task=artifact to inspect the version first.",
346
- suggestedCall: {
347
- tool: "inspect-minecraft",
348
- params: {
349
- task: "class-source",
350
- subject: {
351
- kind: "class",
352
- className: "net.minecraft.world.item.Item",
353
- artifact: {
354
- type: "resolve-target",
355
- target: {
356
- kind: "version",
357
- value: subject.version
358
- }
359
- }
360
- }
361
- }
362
- }
363
- }
364
- });
365
- }
366
- const suggestedTask = this.taskForSubject(subject);
367
- throw createError({
368
- code: ERROR_CODES.INVALID_INPUT,
369
- message: `${task} is not compatible with subject.kind="${subject.kind}".`,
370
- details: {
371
- nextAction: suggestedTask === "artifact"
372
- ? `Retry with task=artifact for this ${subject.kind} subject, or reshape the subject so it supplies the input that ${task} needs.`
373
- : `Retry with task=${suggestedTask} for this subject, or reshape the subject so it supplies the input that ${task} needs.`,
374
- suggestedCall: {
375
- tool: "inspect-minecraft",
376
- params: {
377
- task: suggestedTask,
378
- subject
379
- }
380
- }
381
- }
382
- });
383
- }
384
- async resolveBinaryBackedClass(className, input) {
385
- if (!this.deps.checkSymbolExists || !input.version) {
386
- return undefined;
387
- }
388
- let lookup;
389
- try {
390
- lookup = await this.deps.checkSymbolExists({
391
- version: input.version,
392
- kind: "class",
393
- name: className,
394
- sourceMapping: input.mapping ?? "obfuscated",
395
- nameMode: className.includes(".") ? "fqcn" : "auto",
396
- maxCandidates: 10
397
- });
398
- }
399
- catch (caughtError) {
400
- if (isAppError(caughtError)) {
401
- return undefined;
402
- }
403
- throw caughtError;
404
- }
405
- const resolvedClassName = lookup.resolvedSymbol?.name;
406
- if (!resolvedClassName) {
407
- return undefined;
408
- }
409
- return {
410
- className: resolvedClassName,
411
- warnings: lookup.warnings
412
- };
413
- }
414
- async resolveArtifactReference(subject, task) {
415
- if (subject.kind === "artifact") {
416
- return this.resolveArtifactRef(subject.artifact, subject);
417
- }
418
- if (subject.kind === "class" || subject.kind === "file" || subject.kind === "search") {
419
- if (!subject.artifact) {
420
- const suggestedTask = task
421
- ?? (subject.kind === "class"
422
- ? "class-overview"
423
- : subject.kind === "search"
424
- ? "search"
425
- : "file");
426
- throw createError({
427
- code: ERROR_CODES.INVALID_INPUT,
428
- message: `${subject.kind} subject requires artifact context.`,
429
- details: {
430
- nextAction: "Add subject.artifact or use subject.kind=workspace so inspect-minecraft can resolve the artifact first.",
431
- suggestedCall: await this.buildArtifactContextSuggestedCall(suggestedTask, subject)
432
- }
433
- });
434
- }
435
- return this.resolveArtifactRef(subject.artifact, subject);
436
- }
437
- if (subject.kind === "version") {
438
- const artifact = await this.deps.resolveArtifact({
439
- target: { kind: "version", value: subject.version },
440
- mapping: subject.mapping,
441
- scope: subject.scope,
442
- projectPath: subject.projectPath,
443
- preferProjectVersion: subject.preferProjectVersion,
444
- strictVersion: subject.strictVersion
445
- });
446
- return {
447
- artifactId: artifact.artifactId,
448
- artifact,
449
- version: subject.version,
450
- warnings: [...artifact.warnings]
451
- };
452
- }
453
- const version = await this.deps.detectProjectMinecraftVersion(subject.projectPath);
454
- if (!version) {
455
- return {
456
- artifactId: "",
457
- version: undefined,
458
- warnings: [`Could not infer Minecraft version from ${subject.projectPath}.`]
459
- };
460
- }
461
- const artifact = await this.deps.resolveArtifact({
462
- target: { kind: "version", value: version },
463
- mapping: subject.mapping,
464
- scope: subject.scope,
465
- projectPath: subject.projectPath,
466
- preferProjectVersion: subject.preferProjectVersion ?? true,
467
- strictVersion: subject.strictVersion
468
- });
469
- return {
470
- artifactId: artifact.artifactId,
471
- artifact,
472
- version,
473
- warnings: [...artifact.warnings]
474
- };
475
- }
476
- async resolveArtifactRef(ref, subject) {
477
- if (ref.type === "resolved-id") {
478
- return {
479
- artifactId: ref.artifactId,
480
- warnings: []
481
- };
482
- }
483
- const artifact = await this.deps.resolveArtifact({
484
- target: ref.target,
485
- mapping: "mapping" in subject ? subject.mapping : undefined,
486
- scope: "scope" in subject ? subject.scope : undefined,
487
- projectPath: "projectPath" in subject ? subject.projectPath : undefined,
488
- preferProjectVersion: "preferProjectVersion" in subject ? subject.preferProjectVersion : undefined,
489
- strictVersion: "strictVersion" in subject ? subject.strictVersion : undefined
490
- });
491
- return {
492
- artifactId: artifact.artifactId,
493
- artifact,
494
- warnings: [...artifact.warnings]
495
- };
496
- }
497
- async handleVersions(input, detail, include) {
498
- const versions = await this.deps.listVersions({
499
- includeSnapshots: input.includeSnapshots,
500
- limit: input.limit
501
- });
502
- const summary = {
503
- status: "ok",
504
- headline: `Found ${versions.totalAvailable} Minecraft versions.`,
505
- subject: createSummarySubject({
506
- task: "versions",
507
- kind: "versions",
508
- includeSnapshots: input.includeSnapshots === false ? undefined : input.includeSnapshots,
509
- limit: input.limit
510
- }),
511
- counts: {
512
- releases: versions.releases.length,
513
- snapshots: versions.snapshots?.length ?? 0
514
- },
515
- nextActions: nextActionsOrUndefined([
516
- createNextAction("inspect-minecraft", {
517
- task: "artifact",
518
- subject: {
519
- kind: "version",
520
- version: versions.latest.release ?? versions.releases[0]?.id
521
- }
522
- })
523
- ])
524
- };
525
- return {
526
- ...buildEntryToolResult({
527
- task: "versions",
528
- summary,
529
- detail,
530
- include,
531
- blocks: {
532
- versions: {
533
- latest: versions.latest,
534
- releases: detail === "summary" ? versions.releases.slice(0, 5) : versions.releases,
535
- snapshots: input.includeSnapshots ? versions.snapshots : undefined,
536
- cached: versions.cached
537
- }
538
- }
539
- }),
540
- warnings: []
541
- };
542
- }
543
- async handleArtifact(subject, detail, include) {
544
- const resolved = await this.resolveArtifactReference(subject);
545
- if (!resolved.artifactId) {
546
- const summary = {
547
- status: "blocked",
548
- headline: "Could not resolve an artifact without a Minecraft version.",
549
- subject: createSummarySubject({
550
- task: "artifact",
551
- requested: subject
552
- }),
553
- nextActions: nextActionsOrUndefined([
554
- createNextAction("inspect-minecraft", {
555
- task: "artifact",
556
- subject: {
557
- kind: "version",
558
- version: "1.21.10"
559
- }
560
- })
561
- ])
562
- };
563
- return {
564
- ...buildEntryToolResult({
565
- task: "artifact",
566
- summary,
567
- detail,
568
- include,
569
- blocks: {
570
- subject: {
571
- requested: subject
572
- }
573
- },
574
- alwaysBlocks: ["subject"]
575
- }),
576
- warnings: resolved.warnings
577
- };
578
- }
579
- const summary = {
580
- status: "ok",
581
- headline: `Resolved artifact ${resolved.artifactId}.`,
582
- subject: createSummarySubject({
583
- task: "artifact",
584
- requested: subject,
585
- artifactId: resolved.artifactId,
586
- version: resolved.version
587
- }),
588
- counts: {
589
- warnings: resolved.warnings.length
590
- }
591
- };
592
- return {
593
- ...buildEntryToolResult({
594
- task: "artifact",
595
- summary,
596
- detail,
597
- include,
598
- blocks: {
599
- subject: {
600
- requested: subject,
601
- resolved: {
602
- artifactId: resolved.artifactId,
603
- version: resolved.version
604
- }
605
- },
606
- artifact: resolved.artifact
607
- ? {
608
- artifactId: resolved.artifact.artifactId,
609
- artifactAlias: resolved.artifact.artifactAlias,
610
- origin: resolved.artifact.origin,
611
- mappingApplied: resolved.artifact.mappingApplied,
612
- version: resolved.artifact.version,
613
- artifactContents: resolved.artifact.artifactContents
614
- }
615
- : { artifactId: resolved.artifactId }
616
- },
617
- alwaysBlocks: ["subject"]
618
- }),
619
- warnings: resolved.warnings
620
- };
621
- }
622
- async handleClassOverview(subject, detail, include) {
623
- if (subject.kind !== "class" && !(subject.kind === "workspace" && subject.focus?.kind === "class")) {
624
- this.invalidTaskSubjectError("class-overview", subject);
625
- }
626
- const classSubject = this.buildClassSubject(subject);
627
- const className = classSubject.className;
628
- const artifact = await this.resolveClassArtifactReference(subject, classSubject, "class-overview");
629
- if (!artifact.artifactId) {
630
- const summary = {
631
- status: "blocked",
632
- headline: `Could not resolve artifact context for ${className}.`,
633
- subject: createSummarySubject({
634
- task: "class-overview",
635
- requested: subject,
636
- className
637
- })
638
- };
639
- return {
640
- ...buildEntryToolResult({
641
- task: "class-overview",
642
- summary,
643
- detail,
644
- include,
645
- blocks: {
646
- subject: {
647
- requested: subject
648
- }
649
- },
650
- alwaysBlocks: ["subject"]
651
- }),
652
- warnings: artifact.warnings
653
- };
654
- }
655
- const matches = await this.deps.findClass({
656
- artifactId: artifact.artifactId,
657
- className,
658
- limit: 10
659
- });
660
- if (matches.total === 0) {
661
- const partialSourceFallback = subject.kind === "workspace" && hasPartialVanillaCoverage(artifact.artifact)
662
- ? await this.resolveBinaryBackedClass(className, {
663
- version: artifact.version,
664
- mapping: classSubject.mapping
665
- })
666
- : undefined;
667
- if (partialSourceFallback) {
668
- const metadata = await this.deps.getClassSource({
669
- className: partialSourceFallback.className,
670
- artifactId: artifact.artifactId,
671
- mapping: classSubject.mapping,
672
- scope: classSubject.scope,
673
- projectPath: classSubject.projectPath,
674
- preferProjectVersion: classSubject.preferProjectVersion,
675
- strictVersion: classSubject.strictVersion,
676
- mode: "metadata"
677
- });
678
- const summary = {
679
- status: "ok",
680
- headline: `Resolved class overview for ${partialSourceFallback.className}.`,
681
- subject: createSummarySubject({
682
- task: "class-overview",
683
- requested: subject,
684
- className: partialSourceFallback.className,
685
- artifactId: metadata.artifactId
686
- }),
687
- counts: {
688
- totalLines: metadata.totalLines
689
- },
690
- notes: [
691
- "Source coverage was partial, so inspect-minecraft confirmed the vanilla class through binary-backed symbol lookup."
692
- ]
693
- };
694
- return {
695
- ...buildEntryToolResult({
696
- task: "class-overview",
697
- summary,
698
- detail,
699
- include,
700
- blocks: {
701
- subject: {
702
- requested: subject,
703
- resolved: {
704
- artifactId: metadata.artifactId,
705
- className: partialSourceFallback.className
706
- }
707
- },
708
- class: {
709
- className: partialSourceFallback.className,
710
- totalLines: metadata.totalLines,
711
- returnedNamespace: metadata.returnedNamespace
712
- }
713
- },
714
- alwaysBlocks: ["subject"]
715
- }),
716
- warnings: [
717
- ...artifact.warnings,
718
- ...matches.warnings,
719
- ...partialSourceFallback.warnings,
720
- ...metadata.warnings
721
- ]
722
- };
723
- }
724
- const summary = {
725
- status: "not_found",
726
- headline: `No class match was found for ${className}.`,
727
- subject: createSummarySubject({
728
- task: "class-overview",
729
- requested: subject,
730
- className,
731
- artifactId: artifact.artifactId
732
- })
733
- };
734
- return {
735
- ...buildEntryToolResult({
736
- task: "class-overview",
737
- summary,
738
- detail,
739
- include,
740
- blocks: {
741
- subject: {
742
- requested: subject,
743
- resolved: {
744
- artifactId: artifact.artifactId
745
- }
746
- }
747
- },
748
- alwaysBlocks: ["subject"]
749
- }),
750
- warnings: [...artifact.warnings, ...matches.warnings]
751
- };
752
- }
753
- if (matches.total > 1) {
754
- const candidateActions = matches.matches.slice(0, 3).map((match) => createNextAction("inspect-minecraft", {
755
- task: "class-source",
756
- subject: {
757
- kind: "class",
758
- className: match.qualifiedName,
759
- artifact: {
760
- type: "resolved-id",
761
- artifactId: artifact.artifactId
762
- }
763
- },
764
- include: ["source"]
765
- }));
766
- const summary = {
767
- status: "ambiguous",
768
- headline: `Found ${matches.total} class matches for ${className}.`,
769
- subject: createSummarySubject({
770
- task: "class-overview",
771
- requested: subject,
772
- className,
773
- artifactId: artifact.artifactId
774
- }),
775
- counts: {
776
- matches: matches.total
777
- },
778
- nextActions: nextActionsOrUndefined(candidateActions)
779
- };
780
- return {
781
- ...buildEntryToolResult({
782
- task: "class-overview",
783
- summary,
784
- detail,
785
- include,
786
- blocks: {
787
- subject: {
788
- requested: subject,
789
- resolved: {
790
- artifactId: artifact.artifactId
791
- }
792
- },
793
- candidates: matches.matches
794
- },
795
- alwaysBlocks: ["subject"]
796
- }),
797
- warnings: [...artifact.warnings, ...matches.warnings]
798
- };
799
- }
800
- const match = matches.matches[0];
801
- const metadata = await this.deps.getClassSource({
802
- className: match.qualifiedName,
803
- artifactId: artifact.artifactId,
804
- mode: "metadata"
805
- });
806
- const summary = {
807
- status: "ok",
808
- headline: `Resolved class overview for ${match.qualifiedName}.`,
809
- subject: createSummarySubject({
810
- task: "class-overview",
811
- requested: subject,
812
- className: match.qualifiedName,
813
- artifactId: artifact.artifactId
814
- }),
815
- counts: {
816
- totalLines: metadata.totalLines
817
- },
818
- nextActions: nextActionsOrUndefined([
819
- createNextAction("inspect-minecraft", {
820
- task: "class-source",
821
- subject: {
822
- kind: "class",
823
- className: match.qualifiedName,
824
- artifact: {
825
- type: "resolved-id",
826
- artifactId: artifact.artifactId
827
- }
828
- },
829
- include: ["source"]
830
- })
831
- ])
832
- };
833
- return {
834
- ...buildEntryToolResult({
835
- task: "class-overview",
836
- summary,
837
- detail,
838
- include,
839
- blocks: {
840
- subject: {
841
- requested: subject,
842
- resolved: {
843
- artifactId: artifact.artifactId,
844
- className: match.qualifiedName
845
- }
846
- },
847
- artifact: artifact.artifact
848
- ? {
849
- artifactId: artifact.artifact.artifactId,
850
- version: artifact.artifact.version,
851
- origin: artifact.artifact.origin
852
- }
853
- : { artifactId: artifact.artifactId },
854
- class: {
855
- className: match.qualifiedName,
856
- filePath: match.filePath,
857
- totalLines: metadata.totalLines,
858
- returnedNamespace: metadata.returnedNamespace
859
- }
860
- },
861
- alwaysBlocks: ["subject"]
862
- }),
863
- warnings: [...artifact.warnings, ...matches.warnings, ...metadata.warnings]
864
- };
865
- }
866
- async handleClassSource(subject, detail, include) {
867
- if (subject.kind !== "class" && !(subject.kind === "workspace" && subject.focus?.kind === "class")) {
868
- this.invalidTaskSubjectError("class-source", subject);
869
- }
870
- const classSubject = this.buildClassSubject(subject);
871
- const className = classSubject.className;
872
- const artifactContext = await this.resolveClassArtifactReference(subject, classSubject, "class-source");
873
- const source = await this.deps.getClassSource({
874
- className,
875
- artifactId: artifactContext.artifactId || undefined,
876
- mapping: classSubject.mapping,
877
- scope: classSubject.scope,
878
- projectPath: classSubject.projectPath,
879
- preferProjectVersion: classSubject.preferProjectVersion,
880
- strictVersion: classSubject.strictVersion,
881
- mode: include.includes("source") || detail === "full" ? "snippet" : "metadata"
882
- });
883
- const summary = {
884
- status: "ok",
885
- headline: `Resolved source for ${source.className}.`,
886
- subject: createSummarySubject({
887
- task: "class-source",
888
- requested: subject,
889
- className: source.className,
890
- artifactId: source.artifactId
891
- }),
892
- counts: {
893
- totalLines: source.totalLines
894
- }
895
- };
896
- return {
897
- ...buildEntryToolResult({
898
- task: "class-source",
899
- summary,
900
- detail,
901
- include,
902
- blocks: {
903
- subject: {
904
- requested: subject,
905
- resolved: {
906
- artifactId: source.artifactId,
907
- className: source.className
908
- }
909
- },
910
- source: {
911
- className: source.className,
912
- mode: source.mode,
913
- returnedRange: source.returnedRange,
914
- totalLines: source.totalLines,
915
- sourceText: source.sourceText
916
- }
917
- },
918
- alwaysBlocks: ["subject"]
919
- }),
920
- warnings: [...artifactContext.warnings, ...source.warnings]
921
- };
922
- }
923
- async handleClassMembers(subject, detail, include, limit) {
924
- if (subject.kind !== "class" && !(subject.kind === "workspace" && subject.focus?.kind === "class")) {
925
- this.invalidTaskSubjectError("class-members", subject);
926
- }
927
- const classSubject = this.buildClassSubject(subject);
928
- const artifact = await this.resolveClassArtifactReference(subject, classSubject, "class-members");
929
- const members = await this.deps.getClassMembers({
930
- className: classSubject.className,
931
- artifactId: artifact.artifactId || undefined,
932
- mapping: classSubject.mapping,
933
- scope: classSubject.scope,
934
- projectPath: classSubject.projectPath,
935
- preferProjectVersion: classSubject.preferProjectVersion,
936
- strictVersion: classSubject.strictVersion,
937
- maxMembers: limit
938
- });
939
- const summary = {
940
- status: members.truncated ? "partial" : "ok",
941
- headline: `Collected ${members.counts.total} members for ${members.className}.`,
942
- subject: createSummarySubject({
943
- task: "class-members",
944
- requested: subject,
945
- className: members.className,
946
- artifactId: members.artifactId
947
- }),
948
- counts: members.counts
949
- };
950
- return {
951
- ...buildEntryToolResult({
952
- task: "class-members",
953
- summary,
954
- detail,
955
- include,
956
- blocks: {
957
- subject: {
958
- requested: subject,
959
- resolved: {
960
- artifactId: members.artifactId,
961
- className: members.className
962
- }
963
- },
964
- members: include.includes("members") || detail !== "summary"
965
- ? {
966
- ...members.members,
967
- ...(members.decompiledFallback ? { decompiledFallback: members.decompiledFallback } : {}),
968
- ...(members.decompiledMemberCounts ? { decompiledMemberCounts: members.decompiledMemberCounts } : {})
969
- }
970
- : {
971
- counts: members.counts,
972
- ...(members.decompiledMemberCounts ? { decompiledMemberCounts: members.decompiledMemberCounts } : {})
973
- }
974
- },
975
- alwaysBlocks: ["subject"]
976
- }),
977
- warnings: [...artifact.warnings, ...members.warnings],
978
- ...(members.truncated
979
- ? {
980
- meta: buildEntryToolMeta({
981
- detail,
982
- include,
983
- warnings: [...artifact.warnings, ...members.warnings],
984
- truncated: createTruncationMeta({
985
- omittedGroups: ["members"],
986
- nextActions: [
987
- createNextAction("inspect-minecraft", {
988
- task: "class-members",
989
- detail: "full",
990
- include: ["members"],
991
- subject
992
- })
993
- ]
994
- })
995
- })
996
- }
997
- : {})
998
- };
999
- }
1000
- async handleSearch(subject, detail, include, limit, cursor) {
1001
- if (subject.kind !== "search" && !(subject.kind === "workspace" && subject.focus?.kind === "search")) {
1002
- this.invalidTaskSubjectError("search", subject);
1003
- }
1004
- const searchSubject = subject.kind === "search" ? subject : this.requireWorkspaceSearchFocus(subject);
1005
- const requestedSubject = this.summarizeRequestedSubject(subject);
1006
- const queryMode = searchSubject.queryMode ?? "auto";
1007
- const artifact = subject.kind === "search"
1008
- ? await this.resolveArtifactReference(subject, "search")
1009
- : await this.resolveWorkspaceArtifactReference(subject, searchSubject.artifact);
1010
- const search = await this.deps.searchClassSource({
1011
- artifactId: artifact.artifactId,
1012
- query: searchSubject.query,
1013
- intent: searchSubject.intent,
1014
- match: searchSubject.match,
1015
- queryMode,
1016
- limit,
1017
- cursor,
1018
- scope: searchSubject.packagePrefix || searchSubject.fileGlob || searchSubject.symbolKind
1019
- ? {
1020
- packagePrefix: searchSubject.packagePrefix,
1021
- fileGlob: searchSubject.fileGlob,
1022
- symbolKind: searchSubject.symbolKind
1023
- }
1024
- : undefined
1025
- });
1026
- const needsBinaryBackedClassHit = subject.kind === "workspace" &&
1027
- hasPartialVanillaCoverage(artifact.artifact) &&
1028
- looksLikeClassQuery(searchSubject.query) &&
1029
- !search.hits.some((hit) => hitTargetsVanillaNamespace(hit));
1030
- const binaryBackedClassHit = needsBinaryBackedClassHit
1031
- ? await this.resolveBinaryBackedClass(searchSubject.query, {
1032
- version: artifact.version,
1033
- mapping: subject.mapping
1034
- })
1035
- : undefined;
1036
- const binaryBackedHitRecord = binaryBackedClassHit == null
1037
- ? undefined
1038
- : {
1039
- filePath: classNameToFilePath(binaryBackedClassHit.className),
1040
- score: 100,
1041
- matchedIn: "symbol",
1042
- reasonCodes: ["binary-class-lookup"],
1043
- symbol: {
1044
- symbolKind: "class",
1045
- symbolName: binaryBackedClassHit.className.split(".").at(-1) ?? binaryBackedClassHit.className,
1046
- qualifiedName: binaryBackedClassHit.className,
1047
- line: 1
1048
- }
1049
- };
1050
- const effectiveHits = binaryBackedHitRecord == null
1051
- ? search.hits
1052
- : [
1053
- binaryBackedHitRecord,
1054
- ...search.hits.filter((hit) => hit.filePath !== binaryBackedHitRecord.filePath)
1055
- ];
1056
- const sampledHits = capArray(effectiveHits, 5);
1057
- const isAutoSeparatorMiss = effectiveHits.length === 0 &&
1058
- queryMode === "auto" &&
1059
- /[._$]/.test(searchSubject.query);
1060
- const literalRetrySubject = subject.kind === "search"
1061
- ? {
1062
- ...subject,
1063
- queryMode: "literal"
1064
- }
1065
- : {
1066
- ...subject,
1067
- focus: {
1068
- ...searchSubject,
1069
- kind: "search",
1070
- queryMode: "literal"
1071
- }
1072
- };
1073
- const summary = {
1074
- status: effectiveHits.length > 0 ? "ok" : "not_found",
1075
- headline: effectiveHits.length > 0
1076
- ? `Found ${effectiveHits.length} source hits for ${searchSubject.query}.`
1077
- : `No source hits were found for ${searchSubject.query}.`,
1078
- subject: createSummarySubject({
1079
- task: "search",
1080
- requested: requestedSubject,
1081
- query: searchSubject.query,
1082
- artifactId: artifact.artifactId
1083
- }),
1084
- counts: {
1085
- hits: effectiveHits.length
1086
- },
1087
- nextActions: nextActionsOrUndefined([
1088
- ...(effectiveHits.length > 0
1089
- ? [
1090
- createNextAction("inspect-minecraft", {
1091
- task: "file",
1092
- subject: {
1093
- kind: "file",
1094
- filePath: effectiveHits[0].filePath,
1095
- artifact: {
1096
- type: "resolved-id",
1097
- artifactId: artifact.artifactId
1098
- }
1099
- },
1100
- include: ["source"]
1101
- })
1102
- ]
1103
- : []),
1104
- ...(isAutoSeparatorMiss
1105
- ? [
1106
- createNextAction("inspect-minecraft", {
1107
- task: "search",
1108
- subject: literalRetrySubject
1109
- })
1110
- ]
1111
- : [])
1112
- ]),
1113
- ...(isAutoSeparatorMiss
1114
- ? {
1115
- notes: [
1116
- "Separator query returned no indexed hits. Retry with queryMode=\"literal\" for an explicit full substring scan."
1117
- ]
1118
- }
1119
- : binaryBackedClassHit
1120
- ? {
1121
- notes: [
1122
- "Source coverage was partial, so inspect-minecraft returned a binary-backed class match for the vanilla symbol."
1123
- ]
1124
- }
1125
- : {})
1126
- };
1127
- return {
1128
- ...buildEntryToolResult({
1129
- task: "search",
1130
- summary,
1131
- detail,
1132
- include,
1133
- blocks: {
1134
- subject: {
1135
- requested: requestedSubject,
1136
- resolved: {
1137
- artifactId: artifact.artifactId
1138
- }
1139
- },
1140
- search: {
1141
- query: searchSubject.query,
1142
- hits: detail === "summary" ? sampledHits.items : effectiveHits,
1143
- nextCursor: search.nextCursor
1144
- }
1145
- },
1146
- alwaysBlocks: ["subject"]
1147
- }),
1148
- warnings: [...artifact.warnings, ...(binaryBackedClassHit?.warnings ?? [])]
1149
- };
1150
- }
1151
- async handleFile(subject, detail, include) {
1152
- if (subject.kind !== "file" && !(subject.kind === "workspace" && subject.focus?.kind === "file")) {
1153
- this.invalidTaskSubjectError("file", subject);
1154
- }
1155
- const fileSubject = subject.kind === "file" ? subject : this.requireWorkspaceFileFocus(subject);
1156
- const artifact = subject.kind === "file"
1157
- ? await this.resolveArtifactReference(subject, "file")
1158
- : await this.resolveWorkspaceArtifactReference(subject, fileSubject.artifact);
1159
- const file = await this.deps.getArtifactFile({
1160
- artifactId: artifact.artifactId,
1161
- filePath: fileSubject.filePath
1162
- });
1163
- const summary = {
1164
- status: "ok",
1165
- headline: `Read ${file.filePath}.`,
1166
- subject: createSummarySubject({
1167
- task: "file",
1168
- requested: subject,
1169
- filePath: file.filePath,
1170
- artifactId: artifact.artifactId
1171
- }),
1172
- counts: {
1173
- bytes: file.contentBytes
1174
- }
1175
- };
1176
- return {
1177
- ...buildEntryToolResult({
1178
- task: "file",
1179
- summary,
1180
- detail,
1181
- include,
1182
- blocks: {
1183
- subject: {
1184
- requested: subject,
1185
- resolved: {
1186
- artifactId: artifact.artifactId,
1187
- filePath: file.filePath
1188
- }
1189
- },
1190
- file: {
1191
- filePath: file.filePath,
1192
- contentBytes: file.contentBytes,
1193
- truncated: file.truncated,
1194
- content: include.includes("source") || detail !== "summary" ? file.content : undefined
1195
- }
1196
- },
1197
- alwaysBlocks: ["subject"]
1198
- }),
1199
- warnings: [...artifact.warnings]
1200
- };
1201
- }
1202
- async handleListFiles(subject, detail, include, limit, cursor) {
1203
- const artifact = await this.resolveArtifactReference(subject, "list-files");
1204
- const files = await this.deps.listArtifactFiles({
1205
- artifactId: artifact.artifactId,
1206
- limit,
1207
- cursor
1208
- });
1209
- const sampled = capArray(files.items, 10);
1210
- const partialCoverage = subject.kind === "workspace" && hasPartialVanillaCoverage(artifact.artifact);
1211
- const nextActions = [
1212
- ...(files.items.length > 0
1213
- ? [
1214
- createNextAction("inspect-minecraft", {
1215
- task: "file",
1216
- subject: {
1217
- kind: "file",
1218
- filePath: files.items[0],
1219
- artifact: {
1220
- type: "resolved-id",
1221
- artifactId: artifact.artifactId
1222
- }
1223
- }
1224
- })
1225
- ]
1226
- : []),
1227
- ...(partialCoverage
1228
- ? [
1229
- createNextAction("inspect-minecraft", {
1230
- task: "class-source",
1231
- subject: {
1232
- kind: "workspace",
1233
- projectPath: subject.projectPath,
1234
- mapping: subject.mapping,
1235
- scope: subject.scope,
1236
- preferProjectVersion: subject.preferProjectVersion,
1237
- strictVersion: subject.strictVersion,
1238
- focus: {
1239
- kind: "class",
1240
- className: "net.minecraft.world.item.Item"
1241
- }
1242
- }
1243
- })
1244
- ]
1245
- : [])
1246
- ];
1247
- const summary = {
1248
- status: partialCoverage ? "partial" : "ok",
1249
- headline: `Listed ${files.items.length} files for ${artifact.artifactId}.`,
1250
- subject: createSummarySubject({
1251
- task: "list-files",
1252
- requested: subject,
1253
- artifactId: artifact.artifactId
1254
- }),
1255
- counts: {
1256
- files: files.items.length
1257
- },
1258
- nextActions: nextActionsOrUndefined(nextActions),
1259
- ...(partialCoverage
1260
- ? {
1261
- notes: [
1262
- "This listing is partial because the resolved source artifact does not contain net.minecraft entries."
1263
- ]
1264
- }
1265
- : {})
1266
- };
1267
- return {
1268
- ...buildEntryToolResult({
1269
- task: "list-files",
1270
- summary,
1271
- detail,
1272
- include,
1273
- blocks: {
1274
- subject: {
1275
- requested: subject,
1276
- resolved: {
1277
- artifactId: artifact.artifactId
1278
- }
1279
- },
1280
- files: {
1281
- items: detail === "summary" ? sampled.items : files.items,
1282
- nextCursor: files.nextCursor,
1283
- ...(partialCoverage
1284
- ? {
1285
- coverage: {
1286
- sourceCoverage: "partial",
1287
- missingNamespaces: ["net.minecraft"]
1288
- }
1289
- }
1290
- : {})
1291
- }
1292
- },
1293
- alwaysBlocks: ["subject"]
1294
- }),
1295
- warnings: [...artifact.warnings, ...files.warnings]
1296
- };
1297
- }
1298
74
  }
1299
75
  //# sourceMappingURL=inspect-minecraft-service.js.map