@zhijiewang/openharness 2.22.0 → 2.22.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.
@@ -51,7 +51,16 @@ export declare class LspClient {
51
51
  getDefinition(filePath: string, line: number, character: number): Promise<Location[]>;
52
52
  /** Find references */
53
53
  getReferences(filePath: string, line: number, character: number): Promise<Location[]>;
54
+ /**
55
+ * Hover at a position — returns the text content of the LSP hover response,
56
+ * or `null` if the server returned no hover information / doesn't support
57
+ * the `textDocument/hover` capability. The LSP `MarkupContent` envelope is
58
+ * unwrapped so callers see plain text or markdown.
59
+ */
60
+ getHover(filePath: string, line: number, character: number): Promise<string | null>;
54
61
  private guessLanguage;
62
+ /** @internal Exposed for unit tests of the hover-content unwrapper. */
63
+ static unwrapHoverContents(result: unknown): string | null;
55
64
  disconnect(): void;
56
65
  }
57
66
  export {};
@@ -4,6 +4,38 @@
4
4
  */
5
5
  import { spawn } from "node:child_process";
6
6
  import { readFileSync } from "node:fs";
7
+ /**
8
+ * Unwrap a `textDocument/hover` result into a plain string. LSP allows three
9
+ * `contents` shapes: a bare string, a `{ kind, value }` envelope, or an
10
+ * array of either. Returns null when nothing is hoverable. Pure — exposed
11
+ * via `LspClient.unwrapHoverContents` for unit tests.
12
+ */
13
+ function unwrapHoverContents(result) {
14
+ if (!result || typeof result !== "object")
15
+ return null;
16
+ const r = result;
17
+ if (!r.contents)
18
+ return null;
19
+ const c = r.contents;
20
+ if (typeof c === "string")
21
+ return c;
22
+ if (Array.isArray(c)) {
23
+ const parts = c.map((item) => {
24
+ if (typeof item === "string")
25
+ return item;
26
+ if (item && typeof item === "object" && typeof item.value === "string") {
27
+ return item.value;
28
+ }
29
+ return "";
30
+ });
31
+ const joined = parts.filter(Boolean).join("\n");
32
+ return joined || null;
33
+ }
34
+ if (typeof c === "object" && typeof c.value === "string") {
35
+ return c.value;
36
+ }
37
+ return null;
38
+ }
7
39
  export class LspClient {
8
40
  proc;
9
41
  nextId = 1;
@@ -150,6 +182,20 @@ export class LspClient {
150
182
  });
151
183
  return result ?? [];
152
184
  }
185
+ /**
186
+ * Hover at a position — returns the text content of the LSP hover response,
187
+ * or `null` if the server returned no hover information / doesn't support
188
+ * the `textDocument/hover` capability. The LSP `MarkupContent` envelope is
189
+ * unwrapped so callers see plain text or markdown.
190
+ */
191
+ async getHover(filePath, line, character) {
192
+ const uri = `file://${filePath.replace(/\\/g, "/")}`;
193
+ const result = await this.send("textDocument/hover", {
194
+ textDocument: { uri },
195
+ position: { line, character },
196
+ });
197
+ return unwrapHoverContents(result);
198
+ }
153
199
  guessLanguage(path) {
154
200
  if (path.endsWith(".ts") || path.endsWith(".tsx"))
155
201
  return "typescript";
@@ -165,6 +211,10 @@ export class LspClient {
165
211
  return "java";
166
212
  return "plaintext";
167
213
  }
214
+ /** @internal Exposed for unit tests of the hover-content unwrapper. */
215
+ static unwrapHoverContents(result) {
216
+ return unwrapHoverContents(result);
217
+ }
168
218
  disconnect() {
169
219
  this.send("shutdown", {})
170
220
  .then(() => {
@@ -44,7 +44,7 @@ async function getClient(filePath, workingDir) {
44
44
  }
45
45
  export const DiagnosticsTool = {
46
46
  name: "Diagnostics",
47
- description: "Get code diagnostics (errors, warnings), go-to-definition, or find-references using the language server.",
47
+ description: "Language Server Protocol (LSP) code intelligence — pick action: diagnostics (errors/warnings), definition (go-to-def), references (find-refs), or hover (type info / docs). Supports TypeScript, JavaScript, Python, Go, Rust.",
48
48
  inputSchema,
49
49
  riskLevel: "low",
50
50
  isReadOnly() {
@@ -101,22 +101,10 @@ export const DiagnosticsTool = {
101
101
  return { output: "line and character are required for hover.", isError: true };
102
102
  }
103
103
  await client.openFile(input.file_path);
104
- // Hover uses textDocument/hover which returns MarkupContent
105
- try {
106
- const result = await client.send("textDocument/hover", {
107
- textDocument: { uri: `file://${input.file_path.replace(/\\/g, "/")}` },
108
- position: { line: input.line, character: input.character },
109
- });
110
- if (!result?.contents)
111
- return { output: "No hover information.", isError: false };
112
- const content = typeof result.contents === "string"
113
- ? result.contents
114
- : (result.contents.value ?? JSON.stringify(result.contents));
115
- return { output: content, isError: false };
116
- }
117
- catch {
118
- return { output: "Hover not supported by this language server.", isError: false };
119
- }
104
+ const content = await client.getHover(input.file_path, input.line, input.character);
105
+ if (!content)
106
+ return { output: "No hover information.", isError: false };
107
+ return { output: content, isError: false };
120
108
  }
121
109
  return { output: `Unknown action: ${input.action}`, isError: true };
122
110
  }
@@ -128,11 +116,11 @@ export const DiagnosticsTool = {
128
116
  }
129
117
  },
130
118
  prompt() {
131
- return `Get code intelligence from the language server. Supports TypeScript, JavaScript, Python, Go, and Rust. Actions:
132
- - diagnostics: Get errors and warnings for a file
133
- - definition: Go to definition of a symbol at a given position
134
- - references: Find all references to a symbol at a given position
135
- - hover: Get type information and documentation for a symbol
119
+ return `LSP code intelligence diagnostics, go-to-definition, find-references, hover. Supports TypeScript, JavaScript, Python, Go, Rust (a language server must be installed: typescript-language-server / pylsp / gopls / rust-analyzer). Actions:
120
+ - diagnostics: Errors and warnings for the file
121
+ - definition: Resolve the symbol at (line, character) to its declaration
122
+ - references: Find all references to the symbol at (line, character)
123
+ - hover: Type information and documentation for the symbol at (line, character)
136
124
  Parameters:
137
125
  - file_path (string, required): Absolute path to the file
138
126
  - action (string): "diagnostics" | "definition" | "references" | "hover" (default: diagnostics)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhijiewang/openharness",
3
- "version": "2.22.0",
3
+ "version": "2.22.1",
4
4
  "description": "Open-source terminal coding agent. Works with any LLM.",
5
5
  "type": "module",
6
6
  "bin": {