@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
@@ -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,1111 +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
- origin: resolved.artifact.origin,
610
- mappingApplied: resolved.artifact.mappingApplied,
611
- version: resolved.artifact.version,
612
- artifactContents: resolved.artifact.artifactContents
613
- }
614
- : { artifactId: resolved.artifactId }
615
- },
616
- alwaysBlocks: ["subject"]
617
- }),
618
- warnings: resolved.warnings
619
- };
620
- }
621
- async handleClassOverview(subject, detail, include) {
622
- if (subject.kind !== "class" && !(subject.kind === "workspace" && subject.focus?.kind === "class")) {
623
- this.invalidTaskSubjectError("class-overview", subject);
624
- }
625
- const classSubject = this.buildClassSubject(subject);
626
- const className = classSubject.className;
627
- const artifact = await this.resolveClassArtifactReference(subject, classSubject, "class-overview");
628
- if (!artifact.artifactId) {
629
- const summary = {
630
- status: "blocked",
631
- headline: `Could not resolve artifact context for ${className}.`,
632
- subject: createSummarySubject({
633
- task: "class-overview",
634
- requested: subject,
635
- className
636
- })
637
- };
638
- return {
639
- ...buildEntryToolResult({
640
- task: "class-overview",
641
- summary,
642
- detail,
643
- include,
644
- blocks: {
645
- subject: {
646
- requested: subject
647
- }
648
- },
649
- alwaysBlocks: ["subject"]
650
- }),
651
- warnings: artifact.warnings
652
- };
653
- }
654
- const matches = await this.deps.findClass({
655
- artifactId: artifact.artifactId,
656
- className,
657
- limit: 10
658
- });
659
- if (matches.total === 0) {
660
- const partialSourceFallback = subject.kind === "workspace" && hasPartialVanillaCoverage(artifact.artifact)
661
- ? await this.resolveBinaryBackedClass(className, {
662
- version: artifact.version,
663
- mapping: classSubject.mapping
664
- })
665
- : undefined;
666
- if (partialSourceFallback) {
667
- const metadata = await this.deps.getClassSource({
668
- className: partialSourceFallback.className,
669
- artifactId: artifact.artifactId,
670
- mapping: classSubject.mapping,
671
- scope: classSubject.scope,
672
- projectPath: classSubject.projectPath,
673
- preferProjectVersion: classSubject.preferProjectVersion,
674
- strictVersion: classSubject.strictVersion,
675
- mode: "metadata"
676
- });
677
- const summary = {
678
- status: "ok",
679
- headline: `Resolved class overview for ${partialSourceFallback.className}.`,
680
- subject: createSummarySubject({
681
- task: "class-overview",
682
- requested: subject,
683
- className: partialSourceFallback.className,
684
- artifactId: metadata.artifactId
685
- }),
686
- counts: {
687
- totalLines: metadata.totalLines
688
- },
689
- notes: [
690
- "Source coverage was partial, so inspect-minecraft confirmed the vanilla class through binary-backed symbol lookup."
691
- ]
692
- };
693
- return {
694
- ...buildEntryToolResult({
695
- task: "class-overview",
696
- summary,
697
- detail,
698
- include,
699
- blocks: {
700
- subject: {
701
- requested: subject,
702
- resolved: {
703
- artifactId: metadata.artifactId,
704
- className: partialSourceFallback.className
705
- }
706
- },
707
- class: {
708
- className: partialSourceFallback.className,
709
- totalLines: metadata.totalLines,
710
- returnedNamespace: metadata.returnedNamespace
711
- }
712
- },
713
- alwaysBlocks: ["subject"]
714
- }),
715
- warnings: [
716
- ...artifact.warnings,
717
- ...matches.warnings,
718
- ...partialSourceFallback.warnings,
719
- ...metadata.warnings
720
- ]
721
- };
722
- }
723
- const summary = {
724
- status: "not_found",
725
- headline: `No class match was found for ${className}.`,
726
- subject: createSummarySubject({
727
- task: "class-overview",
728
- requested: subject,
729
- className,
730
- artifactId: artifact.artifactId
731
- })
732
- };
733
- return {
734
- ...buildEntryToolResult({
735
- task: "class-overview",
736
- summary,
737
- detail,
738
- include,
739
- blocks: {
740
- subject: {
741
- requested: subject,
742
- resolved: {
743
- artifactId: artifact.artifactId
744
- }
745
- }
746
- },
747
- alwaysBlocks: ["subject"]
748
- }),
749
- warnings: [...artifact.warnings, ...matches.warnings]
750
- };
751
- }
752
- if (matches.total > 1) {
753
- const candidateActions = matches.matches.slice(0, 3).map((match) => createNextAction("inspect-minecraft", {
754
- task: "class-source",
755
- subject: {
756
- kind: "class",
757
- className: match.qualifiedName,
758
- artifact: {
759
- type: "resolved-id",
760
- artifactId: artifact.artifactId
761
- }
762
- },
763
- include: ["source"]
764
- }));
765
- const summary = {
766
- status: "ambiguous",
767
- headline: `Found ${matches.total} class matches for ${className}.`,
768
- subject: createSummarySubject({
769
- task: "class-overview",
770
- requested: subject,
771
- className,
772
- artifactId: artifact.artifactId
773
- }),
774
- counts: {
775
- matches: matches.total
776
- },
777
- nextActions: nextActionsOrUndefined(candidateActions)
778
- };
779
- return {
780
- ...buildEntryToolResult({
781
- task: "class-overview",
782
- summary,
783
- detail,
784
- include,
785
- blocks: {
786
- subject: {
787
- requested: subject,
788
- resolved: {
789
- artifactId: artifact.artifactId
790
- }
791
- },
792
- candidates: matches.matches
793
- },
794
- alwaysBlocks: ["subject"]
795
- }),
796
- warnings: [...artifact.warnings, ...matches.warnings]
797
- };
798
- }
799
- const match = matches.matches[0];
800
- const metadata = await this.deps.getClassSource({
801
- className: match.qualifiedName,
802
- artifactId: artifact.artifactId,
803
- mode: "metadata"
804
- });
805
- const summary = {
806
- status: "ok",
807
- headline: `Resolved class overview for ${match.qualifiedName}.`,
808
- subject: createSummarySubject({
809
- task: "class-overview",
810
- requested: subject,
811
- className: match.qualifiedName,
812
- artifactId: artifact.artifactId
813
- }),
814
- counts: {
815
- totalLines: metadata.totalLines
816
- },
817
- nextActions: nextActionsOrUndefined([
818
- createNextAction("inspect-minecraft", {
819
- task: "class-source",
820
- subject: {
821
- kind: "class",
822
- className: match.qualifiedName,
823
- artifact: {
824
- type: "resolved-id",
825
- artifactId: artifact.artifactId
826
- }
827
- },
828
- include: ["source"]
829
- })
830
- ])
831
- };
832
- return {
833
- ...buildEntryToolResult({
834
- task: "class-overview",
835
- summary,
836
- detail,
837
- include,
838
- blocks: {
839
- subject: {
840
- requested: subject,
841
- resolved: {
842
- artifactId: artifact.artifactId,
843
- className: match.qualifiedName
844
- }
845
- },
846
- artifact: artifact.artifact
847
- ? {
848
- artifactId: artifact.artifact.artifactId,
849
- version: artifact.artifact.version,
850
- origin: artifact.artifact.origin
851
- }
852
- : { artifactId: artifact.artifactId },
853
- class: {
854
- className: match.qualifiedName,
855
- filePath: match.filePath,
856
- totalLines: metadata.totalLines,
857
- returnedNamespace: metadata.returnedNamespace
858
- }
859
- },
860
- alwaysBlocks: ["subject"]
861
- }),
862
- warnings: [...artifact.warnings, ...matches.warnings, ...metadata.warnings]
863
- };
864
- }
865
- async handleClassSource(subject, detail, include) {
866
- if (subject.kind !== "class" && !(subject.kind === "workspace" && subject.focus?.kind === "class")) {
867
- this.invalidTaskSubjectError("class-source", subject);
868
- }
869
- const classSubject = this.buildClassSubject(subject);
870
- const className = classSubject.className;
871
- const artifactContext = await this.resolveClassArtifactReference(subject, classSubject, "class-source");
872
- const source = await this.deps.getClassSource({
873
- className,
874
- artifactId: artifactContext.artifactId || undefined,
875
- mapping: classSubject.mapping,
876
- scope: classSubject.scope,
877
- projectPath: classSubject.projectPath,
878
- preferProjectVersion: classSubject.preferProjectVersion,
879
- strictVersion: classSubject.strictVersion,
880
- mode: include.includes("source") || detail === "full" ? "snippet" : "metadata"
881
- });
882
- const summary = {
883
- status: "ok",
884
- headline: `Resolved source for ${source.className}.`,
885
- subject: createSummarySubject({
886
- task: "class-source",
887
- requested: subject,
888
- className: source.className,
889
- artifactId: source.artifactId
890
- }),
891
- counts: {
892
- totalLines: source.totalLines
893
- }
894
- };
895
- return {
896
- ...buildEntryToolResult({
897
- task: "class-source",
898
- summary,
899
- detail,
900
- include,
901
- blocks: {
902
- subject: {
903
- requested: subject,
904
- resolved: {
905
- artifactId: source.artifactId,
906
- className: source.className
907
- }
908
- },
909
- source: {
910
- className: source.className,
911
- mode: source.mode,
912
- returnedRange: source.returnedRange,
913
- totalLines: source.totalLines,
914
- sourceText: source.sourceText
915
- }
916
- },
917
- alwaysBlocks: ["subject"]
918
- }),
919
- warnings: [...artifactContext.warnings, ...source.warnings]
920
- };
921
- }
922
- async handleClassMembers(subject, detail, include, limit) {
923
- if (subject.kind !== "class" && !(subject.kind === "workspace" && subject.focus?.kind === "class")) {
924
- this.invalidTaskSubjectError("class-members", subject);
925
- }
926
- const classSubject = this.buildClassSubject(subject);
927
- const artifact = await this.resolveClassArtifactReference(subject, classSubject, "class-members");
928
- const members = await this.deps.getClassMembers({
929
- className: classSubject.className,
930
- artifactId: artifact.artifactId || undefined,
931
- mapping: classSubject.mapping,
932
- scope: classSubject.scope,
933
- projectPath: classSubject.projectPath,
934
- preferProjectVersion: classSubject.preferProjectVersion,
935
- strictVersion: classSubject.strictVersion,
936
- maxMembers: limit
937
- });
938
- const summary = {
939
- status: members.truncated ? "partial" : "ok",
940
- headline: `Collected ${members.counts.total} members for ${members.className}.`,
941
- subject: createSummarySubject({
942
- task: "class-members",
943
- requested: subject,
944
- className: members.className,
945
- artifactId: members.artifactId
946
- }),
947
- counts: members.counts
948
- };
949
- return {
950
- ...buildEntryToolResult({
951
- task: "class-members",
952
- summary,
953
- detail,
954
- include,
955
- blocks: {
956
- subject: {
957
- requested: subject,
958
- resolved: {
959
- artifactId: members.artifactId,
960
- className: members.className
961
- }
962
- },
963
- members: include.includes("members") || detail !== "summary"
964
- ? members.members
965
- : {
966
- counts: members.counts
967
- }
968
- },
969
- alwaysBlocks: ["subject"]
970
- }),
971
- warnings: [...artifact.warnings, ...members.warnings],
972
- ...(members.truncated
973
- ? {
974
- meta: buildEntryToolMeta({
975
- detail,
976
- include,
977
- warnings: [...artifact.warnings, ...members.warnings],
978
- truncated: createTruncationMeta({
979
- omittedGroups: ["members"],
980
- nextActions: [
981
- createNextAction("inspect-minecraft", {
982
- task: "class-members",
983
- detail: "full",
984
- include: ["members"],
985
- subject
986
- })
987
- ]
988
- })
989
- })
990
- }
991
- : {})
992
- };
993
- }
994
- async handleSearch(subject, detail, include, limit, cursor) {
995
- if (subject.kind !== "search" && !(subject.kind === "workspace" && subject.focus?.kind === "search")) {
996
- this.invalidTaskSubjectError("search", subject);
997
- }
998
- const searchSubject = subject.kind === "search" ? subject : this.requireWorkspaceSearchFocus(subject);
999
- const requestedSubject = this.summarizeRequestedSubject(subject);
1000
- const queryMode = searchSubject.queryMode ?? "auto";
1001
- const artifact = subject.kind === "search"
1002
- ? await this.resolveArtifactReference(subject, "search")
1003
- : await this.resolveWorkspaceArtifactReference(subject, searchSubject.artifact);
1004
- const search = await this.deps.searchClassSource({
1005
- artifactId: artifact.artifactId,
1006
- query: searchSubject.query,
1007
- intent: searchSubject.intent,
1008
- match: searchSubject.match,
1009
- queryMode,
1010
- limit,
1011
- cursor,
1012
- scope: searchSubject.packagePrefix || searchSubject.fileGlob || searchSubject.symbolKind
1013
- ? {
1014
- packagePrefix: searchSubject.packagePrefix,
1015
- fileGlob: searchSubject.fileGlob,
1016
- symbolKind: searchSubject.symbolKind
1017
- }
1018
- : undefined
1019
- });
1020
- const needsBinaryBackedClassHit = subject.kind === "workspace" &&
1021
- hasPartialVanillaCoverage(artifact.artifact) &&
1022
- looksLikeClassQuery(searchSubject.query) &&
1023
- !search.hits.some((hit) => hitTargetsVanillaNamespace(hit));
1024
- const binaryBackedClassHit = needsBinaryBackedClassHit
1025
- ? await this.resolveBinaryBackedClass(searchSubject.query, {
1026
- version: artifact.version,
1027
- mapping: subject.mapping
1028
- })
1029
- : undefined;
1030
- const binaryBackedHitRecord = binaryBackedClassHit == null
1031
- ? undefined
1032
- : {
1033
- filePath: classNameToFilePath(binaryBackedClassHit.className),
1034
- score: 100,
1035
- matchedIn: "symbol",
1036
- reasonCodes: ["binary-class-lookup"],
1037
- symbol: {
1038
- symbolKind: "class",
1039
- symbolName: binaryBackedClassHit.className.split(".").at(-1) ?? binaryBackedClassHit.className,
1040
- qualifiedName: binaryBackedClassHit.className,
1041
- line: 1
1042
- }
1043
- };
1044
- const effectiveHits = binaryBackedHitRecord == null
1045
- ? search.hits
1046
- : [
1047
- binaryBackedHitRecord,
1048
- ...search.hits.filter((hit) => hit.filePath !== binaryBackedHitRecord.filePath)
1049
- ];
1050
- const sampledHits = capArray(effectiveHits, 5);
1051
- const isAutoSeparatorMiss = effectiveHits.length === 0 &&
1052
- queryMode === "auto" &&
1053
- /[._$]/.test(searchSubject.query);
1054
- const literalRetrySubject = subject.kind === "search"
1055
- ? {
1056
- ...subject,
1057
- queryMode: "literal"
1058
- }
1059
- : {
1060
- ...subject,
1061
- focus: {
1062
- ...searchSubject,
1063
- kind: "search",
1064
- queryMode: "literal"
1065
- }
1066
- };
1067
- const summary = {
1068
- status: effectiveHits.length > 0 ? "ok" : "not_found",
1069
- headline: effectiveHits.length > 0
1070
- ? `Found ${effectiveHits.length} source hits for ${searchSubject.query}.`
1071
- : `No source hits were found for ${searchSubject.query}.`,
1072
- subject: createSummarySubject({
1073
- task: "search",
1074
- requested: requestedSubject,
1075
- query: searchSubject.query,
1076
- artifactId: artifact.artifactId
1077
- }),
1078
- counts: {
1079
- hits: effectiveHits.length
1080
- },
1081
- nextActions: nextActionsOrUndefined([
1082
- ...(effectiveHits.length > 0
1083
- ? [
1084
- createNextAction("inspect-minecraft", {
1085
- task: "file",
1086
- subject: {
1087
- kind: "file",
1088
- filePath: effectiveHits[0].filePath,
1089
- artifact: {
1090
- type: "resolved-id",
1091
- artifactId: artifact.artifactId
1092
- }
1093
- },
1094
- include: ["source"]
1095
- })
1096
- ]
1097
- : []),
1098
- ...(isAutoSeparatorMiss
1099
- ? [
1100
- createNextAction("inspect-minecraft", {
1101
- task: "search",
1102
- subject: literalRetrySubject
1103
- })
1104
- ]
1105
- : [])
1106
- ]),
1107
- ...(isAutoSeparatorMiss
1108
- ? {
1109
- notes: [
1110
- "Separator query returned no indexed hits. Retry with queryMode=\"literal\" for an explicit full substring scan."
1111
- ]
1112
- }
1113
- : binaryBackedClassHit
1114
- ? {
1115
- notes: [
1116
- "Source coverage was partial, so inspect-minecraft returned a binary-backed class match for the vanilla symbol."
1117
- ]
1118
- }
1119
- : {})
1120
- };
1121
- return {
1122
- ...buildEntryToolResult({
1123
- task: "search",
1124
- summary,
1125
- detail,
1126
- include,
1127
- blocks: {
1128
- subject: {
1129
- requested: requestedSubject,
1130
- resolved: {
1131
- artifactId: artifact.artifactId
1132
- }
1133
- },
1134
- search: {
1135
- query: searchSubject.query,
1136
- hits: detail === "summary" ? sampledHits.items : effectiveHits,
1137
- nextCursor: search.nextCursor
1138
- }
1139
- },
1140
- alwaysBlocks: ["subject"]
1141
- }),
1142
- warnings: [...artifact.warnings, ...(binaryBackedClassHit?.warnings ?? [])]
1143
- };
1144
- }
1145
- async handleFile(subject, detail, include) {
1146
- if (subject.kind !== "file" && !(subject.kind === "workspace" && subject.focus?.kind === "file")) {
1147
- this.invalidTaskSubjectError("file", subject);
1148
- }
1149
- const fileSubject = subject.kind === "file" ? subject : this.requireWorkspaceFileFocus(subject);
1150
- const artifact = subject.kind === "file"
1151
- ? await this.resolveArtifactReference(subject, "file")
1152
- : await this.resolveWorkspaceArtifactReference(subject, fileSubject.artifact);
1153
- const file = await this.deps.getArtifactFile({
1154
- artifactId: artifact.artifactId,
1155
- filePath: fileSubject.filePath
1156
- });
1157
- const summary = {
1158
- status: "ok",
1159
- headline: `Read ${file.filePath}.`,
1160
- subject: createSummarySubject({
1161
- task: "file",
1162
- requested: subject,
1163
- filePath: file.filePath,
1164
- artifactId: artifact.artifactId
1165
- }),
1166
- counts: {
1167
- bytes: file.contentBytes
1168
- }
1169
- };
1170
- return {
1171
- ...buildEntryToolResult({
1172
- task: "file",
1173
- summary,
1174
- detail,
1175
- include,
1176
- blocks: {
1177
- subject: {
1178
- requested: subject,
1179
- resolved: {
1180
- artifactId: artifact.artifactId,
1181
- filePath: file.filePath
1182
- }
1183
- },
1184
- file: {
1185
- filePath: file.filePath,
1186
- contentBytes: file.contentBytes,
1187
- truncated: file.truncated,
1188
- content: include.includes("source") || detail !== "summary" ? file.content : undefined
1189
- }
1190
- },
1191
- alwaysBlocks: ["subject"]
1192
- }),
1193
- warnings: [...artifact.warnings]
1194
- };
1195
- }
1196
- async handleListFiles(subject, detail, include, limit, cursor) {
1197
- const artifact = await this.resolveArtifactReference(subject, "list-files");
1198
- const files = await this.deps.listArtifactFiles({
1199
- artifactId: artifact.artifactId,
1200
- limit,
1201
- cursor
1202
- });
1203
- const sampled = capArray(files.items, 10);
1204
- const partialCoverage = subject.kind === "workspace" && hasPartialVanillaCoverage(artifact.artifact);
1205
- const nextActions = [
1206
- ...(files.items.length > 0
1207
- ? [
1208
- createNextAction("inspect-minecraft", {
1209
- task: "file",
1210
- subject: {
1211
- kind: "file",
1212
- filePath: files.items[0],
1213
- artifact: {
1214
- type: "resolved-id",
1215
- artifactId: artifact.artifactId
1216
- }
1217
- }
1218
- })
1219
- ]
1220
- : []),
1221
- ...(partialCoverage
1222
- ? [
1223
- createNextAction("inspect-minecraft", {
1224
- task: "class-source",
1225
- subject: {
1226
- kind: "workspace",
1227
- projectPath: subject.projectPath,
1228
- mapping: subject.mapping,
1229
- scope: subject.scope,
1230
- preferProjectVersion: subject.preferProjectVersion,
1231
- strictVersion: subject.strictVersion,
1232
- focus: {
1233
- kind: "class",
1234
- className: "net.minecraft.world.item.Item"
1235
- }
1236
- }
1237
- })
1238
- ]
1239
- : [])
1240
- ];
1241
- const summary = {
1242
- status: partialCoverage ? "partial" : "ok",
1243
- headline: `Listed ${files.items.length} files for ${artifact.artifactId}.`,
1244
- subject: createSummarySubject({
1245
- task: "list-files",
1246
- requested: subject,
1247
- artifactId: artifact.artifactId
1248
- }),
1249
- counts: {
1250
- files: files.items.length
1251
- },
1252
- nextActions: nextActionsOrUndefined(nextActions),
1253
- ...(partialCoverage
1254
- ? {
1255
- notes: [
1256
- "This listing is partial because the resolved source artifact does not contain net.minecraft entries."
1257
- ]
1258
- }
1259
- : {})
1260
- };
1261
- return {
1262
- ...buildEntryToolResult({
1263
- task: "list-files",
1264
- summary,
1265
- detail,
1266
- include,
1267
- blocks: {
1268
- subject: {
1269
- requested: subject,
1270
- resolved: {
1271
- artifactId: artifact.artifactId
1272
- }
1273
- },
1274
- files: {
1275
- items: detail === "summary" ? sampled.items : files.items,
1276
- nextCursor: files.nextCursor,
1277
- ...(partialCoverage
1278
- ? {
1279
- coverage: {
1280
- sourceCoverage: "partial",
1281
- missingNamespaces: ["net.minecraft"]
1282
- }
1283
- }
1284
- : {})
1285
- }
1286
- },
1287
- alwaysBlocks: ["subject"]
1288
- }),
1289
- warnings: [...artifact.warnings, ...files.warnings]
1290
- };
1291
- }
1292
74
  }
1293
75
  //# sourceMappingURL=inspect-minecraft-service.js.map