opencode-rag-plugin 1.15.1 → 1.17.2

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 (240) hide show
  1. package/ReadMe.md +52 -9
  2. package/dist/api.js +44 -24
  3. package/dist/chunker/base.d.ts +34 -3
  4. package/dist/chunker/base.js +70 -21
  5. package/dist/chunker/factory.d.ts +4 -1
  6. package/dist/chunker/factory.js +12 -1
  7. package/dist/chunker/grammar.js +3 -0
  8. package/dist/chunker/image.js +8 -8
  9. package/dist/chunker/pdf.js +11 -13
  10. package/dist/chunker/xml.d.ts +2 -0
  11. package/dist/chunker/xml.js +2 -0
  12. package/dist/cli/commands/index-command.js +0 -4
  13. package/dist/cli/commands/index.d.ts +1 -0
  14. package/dist/cli/commands/index.js +1 -0
  15. package/dist/cli/commands/init-helpers.d.ts +12 -0
  16. package/dist/cli/commands/init-helpers.js +87 -2
  17. package/dist/cli/commands/init.js +20 -2
  18. package/dist/cli/commands/query.js +1 -0
  19. package/dist/cli/commands/setup.d.ts +2 -0
  20. package/dist/cli/commands/setup.js +113 -0
  21. package/dist/cli/commands/status.js +64 -2
  22. package/dist/cli/commands/update.d.ts +4 -6
  23. package/dist/cli/commands/update.js +44 -58
  24. package/dist/cli/index.js +2 -1
  25. package/dist/content/image.js +24 -3
  26. package/dist/content/reader.d.ts +6 -1
  27. package/dist/content/reader.js +49 -4
  28. package/dist/core/config.d.ts +29 -1
  29. package/dist/core/config.js +105 -8
  30. package/dist/core/desc-cache.d.ts +31 -0
  31. package/dist/core/desc-cache.js +124 -0
  32. package/dist/core/interfaces.d.ts +58 -3
  33. package/dist/core/manifest.d.ts +24 -1
  34. package/dist/core/manifest.js +34 -3
  35. package/dist/core/resolve-api-key.js +4 -2
  36. package/dist/core/runtime-overrides.js +12 -8
  37. package/dist/core/setup-runtime.d.ts +23 -0
  38. package/dist/core/setup-runtime.js +231 -0
  39. package/dist/core/version-check.d.ts +85 -0
  40. package/dist/core/version-check.js +160 -0
  41. package/dist/describer/anthropic.d.ts +2 -2
  42. package/dist/describer/anthropic.js +5 -7
  43. package/dist/describer/describer.d.ts +2 -2
  44. package/dist/describer/describer.js +6 -8
  45. package/dist/describer/gemini.d.ts +2 -2
  46. package/dist/describer/gemini.js +5 -7
  47. package/dist/embedder/cohere.d.ts +1 -1
  48. package/dist/embedder/cohere.js +2 -2
  49. package/dist/embedder/factory.d.ts +3 -1
  50. package/dist/embedder/factory.js +8 -2
  51. package/dist/embedder/health.js +5 -1
  52. package/dist/embedder/http.d.ts +1 -1
  53. package/dist/embedder/http.js +74 -43
  54. package/dist/embedder/ollama.d.ts +1 -1
  55. package/dist/embedder/ollama.js +2 -2
  56. package/dist/embedder/openai.d.ts +1 -1
  57. package/dist/embedder/openai.js +2 -2
  58. package/dist/eval/compare-merge.d.ts +10 -0
  59. package/dist/eval/compare-merge.js +537 -0
  60. package/dist/eval/compare-rankings.d.ts +10 -0
  61. package/dist/eval/compare-rankings.js +245 -0
  62. package/dist/eval/dump-descriptions.d.ts +7 -0
  63. package/dist/eval/dump-descriptions.js +58 -0
  64. package/dist/eval/fast-index.d.ts +8 -0
  65. package/dist/eval/fast-index.js +283 -0
  66. package/dist/eval/run-branch-compare.d.ts +7 -0
  67. package/dist/eval/run-branch-compare.js +220 -0
  68. package/dist/eval/run-token-test.js +1 -0
  69. package/dist/eval/test-kw.d.ts +1 -0
  70. package/dist/eval/test-kw.js +22 -0
  71. package/dist/eval/update-descriptions.d.ts +7 -0
  72. package/dist/eval/update-descriptions.js +84 -0
  73. package/dist/index.d.ts +4 -0
  74. package/dist/index.js +3 -0
  75. package/dist/indexer/embed-stage.js +2 -1
  76. package/dist/indexer/git-diff.js +21 -9
  77. package/dist/indexer/pipeline.d.ts +6 -0
  78. package/dist/indexer/pipeline.js +304 -40
  79. package/dist/indexer/watch.js +1 -3
  80. package/dist/indexer/worker.d.ts +15 -2
  81. package/dist/indexer/worker.js +25 -12
  82. package/dist/mcp/handlers.d.ts +9 -0
  83. package/dist/mcp/handlers.js +23 -6
  84. package/dist/mcp/server.js +2 -0
  85. package/dist/opencode/create-read-tool.d.ts +2 -0
  86. package/dist/opencode/create-read-tool.js +8 -2
  87. package/dist/opencode/read-fallback.d.ts +1 -5
  88. package/dist/opencode/read-fallback.js +1 -18
  89. package/dist/opencode/read-format.js +5 -3
  90. package/dist/opencode/tools.js +5 -7
  91. package/dist/plugin.js +223 -71
  92. package/dist/retriever/keyword-index.d.ts +3 -2
  93. package/dist/retriever/keyword-index.js +25 -1
  94. package/dist/retriever/retriever.d.ts +4 -1
  95. package/dist/retriever/retriever.js +34 -56
  96. package/dist/tui.js +18 -1
  97. package/dist/vectorstore/lancedb.d.ts +35 -4
  98. package/dist/vectorstore/lancedb.js +146 -23
  99. package/dist/vectorstore/memory.d.ts +6 -1
  100. package/dist/vectorstore/memory.js +58 -0
  101. package/dist/watcher.d.ts +2 -0
  102. package/dist/watcher.js +5 -1
  103. package/dist/web/api.js +10 -2
  104. package/dist/web/server.js +18 -3
  105. package/package.json +8 -9
  106. package/scripts/postinstall-setup.js +82 -0
  107. package/dist/api.js.map +0 -1
  108. package/dist/chunker/base.js.map +0 -1
  109. package/dist/chunker/bash.js.map +0 -1
  110. package/dist/chunker/c.js.map +0 -1
  111. package/dist/chunker/cpp.js.map +0 -1
  112. package/dist/chunker/csharp.js.map +0 -1
  113. package/dist/chunker/css.js.map +0 -1
  114. package/dist/chunker/doc.js.map +0 -1
  115. package/dist/chunker/dockerfile.js.map +0 -1
  116. package/dist/chunker/docx.js.map +0 -1
  117. package/dist/chunker/excel.js.map +0 -1
  118. package/dist/chunker/factory.js.map +0 -1
  119. package/dist/chunker/fallback.js.map +0 -1
  120. package/dist/chunker/go.js.map +0 -1
  121. package/dist/chunker/grammar.js.map +0 -1
  122. package/dist/chunker/html.js.map +0 -1
  123. package/dist/chunker/image.js.map +0 -1
  124. package/dist/chunker/ini.js.map +0 -1
  125. package/dist/chunker/java.js.map +0 -1
  126. package/dist/chunker/javascript.js.map +0 -1
  127. package/dist/chunker/json.js.map +0 -1
  128. package/dist/chunker/kotlin.js.map +0 -1
  129. package/dist/chunker/loader.js.map +0 -1
  130. package/dist/chunker/markdown.js.map +0 -1
  131. package/dist/chunker/pdf.js.map +0 -1
  132. package/dist/chunker/php.js.map +0 -1
  133. package/dist/chunker/powershell.js.map +0 -1
  134. package/dist/chunker/python.js.map +0 -1
  135. package/dist/chunker/razor.js.map +0 -1
  136. package/dist/chunker/ruby.js.map +0 -1
  137. package/dist/chunker/rust.js.map +0 -1
  138. package/dist/chunker/sln.js.map +0 -1
  139. package/dist/chunker/sql.js.map +0 -1
  140. package/dist/chunker/ssl.js.map +0 -1
  141. package/dist/chunker/swift.js.map +0 -1
  142. package/dist/chunker/tex.js.map +0 -1
  143. package/dist/chunker/toml.js.map +0 -1
  144. package/dist/chunker/typescript.js.map +0 -1
  145. package/dist/chunker/uuid.js.map +0 -1
  146. package/dist/chunker/xml.js.map +0 -1
  147. package/dist/chunker/yaml.js.map +0 -1
  148. package/dist/cli/commands/clear.js.map +0 -1
  149. package/dist/cli/commands/describe-image.js.map +0 -1
  150. package/dist/cli/commands/dump.js.map +0 -1
  151. package/dist/cli/commands/eval.js.map +0 -1
  152. package/dist/cli/commands/index-command.js.map +0 -1
  153. package/dist/cli/commands/index.js.map +0 -1
  154. package/dist/cli/commands/init-helpers.js.map +0 -1
  155. package/dist/cli/commands/init.js.map +0 -1
  156. package/dist/cli/commands/list.js.map +0 -1
  157. package/dist/cli/commands/mcp.js.map +0 -1
  158. package/dist/cli/commands/query.js.map +0 -1
  159. package/dist/cli/commands/show.js.map +0 -1
  160. package/dist/cli/commands/status.js.map +0 -1
  161. package/dist/cli/commands/ui.js.map +0 -1
  162. package/dist/cli/commands/update.js.map +0 -1
  163. package/dist/cli/format.js.map +0 -1
  164. package/dist/cli/helpers.js.map +0 -1
  165. package/dist/cli/index.js.map +0 -1
  166. package/dist/cli/progress.d.ts +0 -42
  167. package/dist/cli/progress.js +0 -137
  168. package/dist/cli/progress.js.map +0 -1
  169. package/dist/cli/types.js.map +0 -1
  170. package/dist/cli.js.map +0 -1
  171. package/dist/content/doc.js.map +0 -1
  172. package/dist/content/docx.js.map +0 -1
  173. package/dist/content/excel.js.map +0 -1
  174. package/dist/content/image.js.map +0 -1
  175. package/dist/content/pdf.js.map +0 -1
  176. package/dist/content/reader.js.map +0 -1
  177. package/dist/content/types.js.map +0 -1
  178. package/dist/core/bootstrap.js.map +0 -1
  179. package/dist/core/config.js.map +0 -1
  180. package/dist/core/doc-progress.js.map +0 -1
  181. package/dist/core/fileLogger.js.map +0 -1
  182. package/dist/core/interfaces.js.map +0 -1
  183. package/dist/core/manifest.js.map +0 -1
  184. package/dist/core/provider-defaults.js.map +0 -1
  185. package/dist/core/rag-injection-flag.js.map +0 -1
  186. package/dist/core/resolve-api-key.js.map +0 -1
  187. package/dist/core/runtime-overrides.js.map +0 -1
  188. package/dist/describer/anthropic.js.map +0 -1
  189. package/dist/describer/describer.js.map +0 -1
  190. package/dist/describer/factory.js.map +0 -1
  191. package/dist/describer/gemini.js.map +0 -1
  192. package/dist/describer/shared.js.map +0 -1
  193. package/dist/embedder/cohere.js.map +0 -1
  194. package/dist/embedder/factory.js.map +0 -1
  195. package/dist/embedder/health.js.map +0 -1
  196. package/dist/embedder/http.js.map +0 -1
  197. package/dist/embedder/ollama.js.map +0 -1
  198. package/dist/embedder/openai.js.map +0 -1
  199. package/dist/eval/index.js.map +0 -1
  200. package/dist/eval/run-token-test.js.map +0 -1
  201. package/dist/eval/session-logger.js.map +0 -1
  202. package/dist/eval/storage.js.map +0 -1
  203. package/dist/eval/token-analysis.js.map +0 -1
  204. package/dist/eval/token-counter.js.map +0 -1
  205. package/dist/eval/types.js.map +0 -1
  206. package/dist/index.js.map +0 -1
  207. package/dist/indexer/description-stage.js.map +0 -1
  208. package/dist/indexer/embed-stage.js.map +0 -1
  209. package/dist/indexer/git-diff.js.map +0 -1
  210. package/dist/indexer/metadata.js.map +0 -1
  211. package/dist/indexer/pipeline.js.map +0 -1
  212. package/dist/indexer/stats.js.map +0 -1
  213. package/dist/indexer/watch.js.map +0 -1
  214. package/dist/indexer/worker.js.map +0 -1
  215. package/dist/indexer.js.map +0 -1
  216. package/dist/mcp/cli.js.map +0 -1
  217. package/dist/mcp/handlers.js.map +0 -1
  218. package/dist/mcp/server.js.map +0 -1
  219. package/dist/opencode/create-read-tool.js.map +0 -1
  220. package/dist/opencode/read-fallback.js.map +0 -1
  221. package/dist/opencode/read-format.js.map +0 -1
  222. package/dist/opencode/read-query.js.map +0 -1
  223. package/dist/opencode/tool-args.js.map +0 -1
  224. package/dist/opencode/tools.js.map +0 -1
  225. package/dist/plugin-entry.js.map +0 -1
  226. package/dist/plugin.js.map +0 -1
  227. package/dist/retriever/context-optimizer.js.map +0 -1
  228. package/dist/retriever/keyword-index.js.map +0 -1
  229. package/dist/retriever/retriever.js.map +0 -1
  230. package/dist/tui.js.map +0 -1
  231. package/dist/updater.d.ts +0 -45
  232. package/dist/updater.js +0 -175
  233. package/dist/updater.js.map +0 -1
  234. package/dist/vectorstore/factory.js.map +0 -1
  235. package/dist/vectorstore/lancedb.js.map +0 -1
  236. package/dist/vectorstore/memory.js.map +0 -1
  237. package/dist/watcher.js.map +0 -1
  238. package/dist/web/api.js.map +0 -1
  239. package/dist/web/server.js.map +0 -1
  240. package/dist/web/static.js.map +0 -1
@@ -5,6 +5,15 @@ import type { EmbeddingProvider, VectorStore, KeywordIndex, SearchResult } from
5
5
  import type { RagConfig } from "../core/config.js";
6
6
  import { type ImageVisionProvider } from "../chunker/image.js";
7
7
  import { retrieve } from "../retriever/retriever.js";
8
+ /**
9
+ * Resolve a user-supplied file path against the worktree root, refusing to
10
+ * escape the worktree. Absolute paths are accepted only if they already reside
11
+ * under the worktree; relative paths are joined to the worktree and any `..`
12
+ * segments that would escape are rejected.
13
+ *
14
+ * @throws {Error} if the resolved path lies outside `worktree`.
15
+ */
16
+ export declare function resolveFilePath(filePath: string, worktree: string): string;
8
17
  /** Parameters for the search_semantic MCP tool. */
9
18
  export interface SearchSemanticParams {
10
19
  /** Natural language search query. */
@@ -4,7 +4,26 @@ import { optimizeContext, DEFAULT_CONTEXT_OPTIMIZATION } from "../retriever/cont
4
4
  import { Parser } from "web-tree-sitter";
5
5
  import { initParser, loadLanguage, walkTree } from "../chunker/grammar.js";
6
6
  import { readFileSync } from "node:fs";
7
- import { resolve, isAbsolute } from "node:path";
7
+ import { resolve, isAbsolute, relative } from "node:path";
8
+ /**
9
+ * Resolve a user-supplied file path against the worktree root, refusing to
10
+ * escape the worktree. Absolute paths are accepted only if they already reside
11
+ * under the worktree; relative paths are joined to the worktree and any `..`
12
+ * segments that would escape are rejected.
13
+ *
14
+ * @throws {Error} if the resolved path lies outside `worktree`.
15
+ */
16
+ export function resolveFilePath(filePath, worktree) {
17
+ const root = resolve(worktree);
18
+ const candidate = isAbsolute(filePath) ? resolve(filePath) : resolve(root, filePath);
19
+ const rel = relative(root, candidate);
20
+ if (rel === "")
21
+ return root;
22
+ if (rel.startsWith("..") || isAbsolute(rel)) {
23
+ throw new Error(`Path "${filePath}" escapes worktree root "${root}" — access denied.`);
24
+ }
25
+ return candidate;
26
+ }
8
27
  const SKELETON_CONFIGS = {
9
28
  ".ts": { grammarName: "typescript", nodeTypes: ["function_declaration", "method_definition", "class_declaration", "interface_declaration", "type_alias_declaration", "enum_declaration"] },
10
29
  ".tsx": { grammarName: "typescript", nodeTypes: ["function_declaration", "method_definition", "class_declaration", "interface_declaration", "type_alias_declaration", "enum_declaration", "arrow_function"] },
@@ -45,11 +64,6 @@ function getExtension(filePath) {
45
64
  const dot = filePath.lastIndexOf(".");
46
65
  return dot >= 0 ? filePath.slice(dot).toLowerCase() : "";
47
66
  }
48
- function resolveFilePath(filePath, worktree) {
49
- if (isAbsolute(filePath))
50
- return filePath;
51
- return resolve(worktree, filePath);
52
- }
53
67
  async function extractSkeleton(content, ext) {
54
68
  const config = SKELETON_CONFIGS[ext];
55
69
  if (!config) {
@@ -86,6 +100,8 @@ async function extractSkeleton(content, ext) {
86
100
  return [];
87
101
  const nodeTypes = new Set(config.nodeTypes);
88
102
  const astNodes = walkTree(tree.rootNode, nodeTypes, content, 15);
103
+ tree.delete();
104
+ parser.delete();
89
105
  return astNodes.map((node) => ({
90
106
  type: node.type,
91
107
  name: extractNodeName(node.text, node.type),
@@ -160,6 +176,7 @@ export async function handleSearchSemantic(params, embedder, store, cfg, keyword
160
176
  minScore: cfg.retrieval.minScore,
161
177
  keywordIndex,
162
178
  keywordWeight: cfg.retrieval.hybridSearch?.keywordWeight,
179
+ hybridEnabled: cfg.retrieval.hybridSearch?.enabled,
163
180
  queryPrefix: cfg.embedding.queryPrefix,
164
181
  };
165
182
  const rawResults = await retrieveFn_(query, embedder, store, retrieveOpts);
@@ -95,6 +95,8 @@ export async function createMcpServer(options) {
95
95
  server,
96
96
  close: async () => {
97
97
  await server.close();
98
+ await ctx.store.close();
99
+ ctx.keywordIndex.close();
98
100
  },
99
101
  };
100
102
  }
@@ -24,6 +24,8 @@ export interface RagReadToolOptions {
24
24
  }>;
25
25
  /** Optional keyword index for hybrid search. */
26
26
  keywordIndex?: KeywordIndex;
27
+ /** Maximum number of sessions to retain in the retrieval cache. */
28
+ maxSessionCacheSize?: number;
27
29
  }
28
30
  /**
29
31
  * Create the RAG-backed read tool for OpenCode plugin registration.
@@ -63,7 +63,13 @@ export function createRagReadTool(options) {
63
63
  }
64
64
  else {
65
65
  const retrievalQuery = buildSessionQuery(messageText, resolvedPath, normalized);
66
- rawResults = await retrieve(retrievalQuery, embedder, store, { topK: retrievalTopK, keywordIndex, queryPrefix: config.embedding.queryPrefix });
66
+ rawResults = await retrieve(retrievalQuery, embedder, store, { topK: retrievalTopK, keywordIndex, hybridEnabled: config.retrieval.hybridSearch?.enabled, queryPrefix: config.embedding.queryPrefix });
67
+ const maxSize = options.maxSessionCacheSize ?? 50;
68
+ if (!sessionRetrievalCache.has(sessionID) && sessionRetrievalCache.size >= maxSize) {
69
+ const oldest = sessionRetrievalCache.keys().next().value;
70
+ if (oldest !== undefined)
71
+ sessionRetrievalCache.delete(oldest);
72
+ }
67
73
  sessionRetrievalCache.set(sessionID, { messageText, rawResults });
68
74
  }
69
75
  }
@@ -74,7 +80,7 @@ export function createRagReadTool(options) {
74
80
  startLine: normalized.startLine,
75
81
  endLine: normalized.endLine,
76
82
  });
77
- rawResults = await retrieve(retrievalQuery, embedder, store, { topK: retrievalTopK, keywordIndex, queryPrefix: config.embedding.queryPrefix });
83
+ rawResults = await retrieve(retrievalQuery, embedder, store, { topK: retrievalTopK, keywordIndex, hybridEnabled: config.retrieval.hybridSearch?.enabled, queryPrefix: config.embedding.queryPrefix });
78
84
  }
79
85
  // Collect related files from raw results (before filtering)
80
86
  relatedFiles = collectRelatedFiles(rawResults, resolvedPath, readRelatedFilesMax);
@@ -1,12 +1,8 @@
1
1
  /**
2
2
  * @fileoverview Provides fallback error messages and no-results behavior dispatch for the read tool.
3
3
  */
4
- import type { ReadNoResultsBehavior } from "../core/config.js";
5
4
  /**
6
5
  * Error message wrapper for retrieval failures.
7
6
  */
8
7
  export declare function retrievalErrorMessage(shortError: string): string;
9
- /**
10
- * Dispatch to the correct fallback message based on behavior config.
11
- */
12
- export declare function getNoResultsMessage(behavior: ReadNoResultsBehavior, filePath?: string): string;
8
+ /** No results fallback messages are handled inline in create-read-tool.ts. */
@@ -12,22 +12,5 @@ export function retrievalErrorMessage(shortError) {
12
12
  shortError,
13
13
  ].join("\n");
14
14
  }
15
- /**
16
- * Dispatch to the correct fallback message based on behavior config.
17
- */
18
- export function getNoResultsMessage(behavior, filePath) {
19
- switch (behavior) {
20
- case "error":
21
- throw new Error("OpenCodeRAG read: no indexed chunks found." +
22
- (filePath ? ` File: ${filePath}` : ""));
23
- case "empty":
24
- return "No indexed chunks found.";
25
- case "hint":
26
- default:
27
- if (filePath) {
28
- return `No indexed chunks found for ${filePath}.`;
29
- }
30
- return "No relevant chunks found.";
31
- }
32
- }
15
+ /** No results fallback messages are handled inline in create-read-tool.ts. */
33
16
  //# sourceMappingURL=read-fallback.js.map
@@ -124,9 +124,11 @@ function formatChunk(index, result) {
124
124
  lines.push(`Score: ${score.toFixed(4)}`);
125
125
  lines.push("");
126
126
  lines.push("```" + language);
127
- lines.push(chunk.content);
128
- if (!chunk.content.endsWith("\n")) {
129
- // Ensure code block closes on its own line
127
+ if (chunk.content.endsWith("\n")) {
128
+ lines.push(chunk.content.slice(0, -1));
129
+ }
130
+ else {
131
+ lines.push(chunk.content);
130
132
  }
131
133
  lines.push("```");
132
134
  return lines.join("\n");
@@ -19,7 +19,7 @@ import { retrieve } from "../retriever/retriever.js";
19
19
  import { Parser } from "web-tree-sitter";
20
20
  import { initParser, loadLanguage, walkTree } from "../chunker/grammar.js";
21
21
  import { readFileSync } from "node:fs";
22
- import { resolve, isAbsolute } from "node:path";
22
+ import { resolveWorkspacePath } from "./tool-args.js";
23
23
  const SKELETON_CONFIGS = {
24
24
  ".ts": { grammarName: "typescript", nodeTypes: ["function_declaration", "method_definition", "class_declaration", "interface_declaration", "type_alias_declaration", "enum_declaration"] },
25
25
  ".tsx": { grammarName: "typescript", nodeTypes: ["function_declaration", "method_definition", "class_declaration", "interface_declaration", "type_alias_declaration", "enum_declaration", "arrow_function"] },
@@ -68,9 +68,7 @@ function getExtension(filePath) {
68
68
  * Resolve a file path relative to the workspace root.
69
69
  */
70
70
  function resolveFilePath(filePath, worktree) {
71
- if (isAbsolute(filePath))
72
- return filePath;
73
- return resolve(worktree, filePath);
71
+ return resolveWorkspacePath(worktree, filePath);
74
72
  }
75
73
  /**
76
74
  * Extract structural outline from source code using tree-sitter.
@@ -116,6 +114,8 @@ async function extractSkeleton(content, ext) {
116
114
  return [];
117
115
  const nodeTypes = new Set(config.nodeTypes);
118
116
  const astNodes = walkTree(tree.rootNode, nodeTypes, content, 15);
117
+ tree.delete();
118
+ parser.delete();
119
119
  return astNodes.map((node) => ({
120
120
  type: node.type,
121
121
  name: extractNodeName(node.text, node.type),
@@ -262,9 +262,7 @@ export function createDescribeImageTool(options) {
262
262
  try {
263
263
  const { existsSync, readFileSync } = await import("node:fs");
264
264
  const path = await import("node:path");
265
- const resolvedPath = isAbsolute(args.filePath)
266
- ? args.filePath
267
- : resolve(worktree, args.filePath);
265
+ const resolvedPath = resolveWorkspacePath(worktree, args.filePath);
268
266
  if (!existsSync(resolvedPath)) {
269
267
  return {
270
268
  title: "Describe image",