pi-readseek 0.4.11 → 0.4.13
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.
- package/index.ts +1 -1
- package/package.json +2 -2
- package/src/edit-output.ts +3 -3
- package/src/edit-syntax-validate.ts +5 -5
- package/src/edit.ts +56 -17
- package/src/file-map.ts +17 -0
- package/src/grep-budget.ts +3 -3
- package/src/grep-output.ts +8 -8
- package/src/grep-render-helpers.ts +3 -3
- package/src/grep-symbol-scope.ts +4 -4
- package/src/grep.ts +7 -7
- package/src/hashline.ts +5 -5
- package/src/pending-diff-preview.ts +3 -3
- package/src/read-output.ts +21 -21
- package/src/read-render-helpers.ts +2 -2
- package/src/read.ts +17 -17
- package/src/readseek/constants.ts +0 -4
- package/src/readseek/formatter.ts +9 -74
- package/src/readseek/symbol-lookup.ts +1 -43
- package/src/readseek/types.ts +0 -20
- package/src/readseek-client.ts +68 -69
- package/src/readseek-settings.ts +17 -17
- package/src/readseek-value.ts +27 -27
- package/src/refs-output.ts +4 -4
- package/src/refs.ts +13 -30
- package/src/register-tool.ts +10 -10
- package/src/replace-symbol.ts +4 -3
- package/src/sg-output.ts +5 -5
- package/src/sg.ts +16 -29
- package/src/stat-search-path.ts +34 -0
- package/src/tool-prompt-metadata.ts +3 -3
- package/src/write.ts +32 -48
- package/src/map-cache.ts +0 -82
package/src/read.ts
CHANGED
|
@@ -13,12 +13,12 @@ import { Text } from "@earendil-works/pi-tui";
|
|
|
13
13
|
import { defineToolPromptMetadata } from "./tool-prompt-metadata.js";
|
|
14
14
|
import { normalizeToLF, stripBom, hasBareCarriageReturn } from "./edit-diff.js";
|
|
15
15
|
import { ensureHashInit, escapeControlCharsForDisplay } from "./hashline.js";
|
|
16
|
-
import {
|
|
16
|
+
import { buildReadSeekWarning, buildToolErrorResult, renderReadSeekLines, type ReadSeekLine, type ReadSeekWarning } from "./readseek-value.js";
|
|
17
17
|
import { looksLikeBinary } from "./binary-detect.js";
|
|
18
18
|
import { isSupportedImageBuffer } from "./image-detect.js";
|
|
19
19
|
import { resolveToCwd } from "./path-utils.js";
|
|
20
20
|
import { throwIfAborted } from "./runtime.js";
|
|
21
|
-
import { getOrGenerateMap } from "./map
|
|
21
|
+
import { getOrGenerateMap } from "./file-map.js";
|
|
22
22
|
import { formatFileMapWithBudget } from "./readseek/formatter.js";
|
|
23
23
|
import { findSymbol, type SymbolMatch } from "./readseek/symbol-lookup.js";
|
|
24
24
|
import { formatAmbiguous, formatNotFound } from "./readseek/symbol-error-format.js";
|
|
@@ -30,7 +30,7 @@ import { readseekRead } from "./readseek-client.js";
|
|
|
30
30
|
import { formatReadCallText, formatReadResultText } from "./read-render-helpers.js";
|
|
31
31
|
import { clampLineToWidth, clampLinesToWidth, linkToolPath, renderPendingResult, renderToolLabel, resolveRenderResultContext, summaryLine, wrapReadHashlinesForWidth } from "./tui-render-utils.js";
|
|
32
32
|
import type { FileAnchoredCallback } from "./tool-types.js";
|
|
33
|
-
import {
|
|
33
|
+
import { registerReadSeekTool } from "./register-tool.js";
|
|
34
34
|
|
|
35
35
|
const READ_PROMPT_METADATA = defineToolPromptMetadata({
|
|
36
36
|
promptUrl: new URL("../prompts/read.md", import.meta.url),
|
|
@@ -176,9 +176,9 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
176
176
|
throwIfAborted(signal);
|
|
177
177
|
const rawText = rawBuffer.toString("utf-8");
|
|
178
178
|
const normalized = normalizeToLF(stripBom(rawText).text);
|
|
179
|
-
const allLines =
|
|
179
|
+
const allLines = splitReadSeekLines(normalized);
|
|
180
180
|
const total = allLines.length;
|
|
181
|
-
const structuredWarnings:
|
|
181
|
+
const structuredWarnings: ReadSeekWarning[] = [];
|
|
182
182
|
let startLine = p.offset !== undefined ? p.offset : 1;
|
|
183
183
|
let endIdx = p.limit !== undefined ? Math.min(startLine - 1 + p.limit, total) : total;
|
|
184
184
|
if (p.offset !== undefined && startLine > total) {
|
|
@@ -203,7 +203,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
203
203
|
};
|
|
204
204
|
lines: string[];
|
|
205
205
|
}>;
|
|
206
|
-
warnings:
|
|
206
|
+
warnings: ReadSeekWarning[];
|
|
207
207
|
}
|
|
208
208
|
| null = null;
|
|
209
209
|
if (p.symbol) {
|
|
@@ -248,7 +248,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
248
248
|
lines.push(` To confirm: ${confirmHint}.]`);
|
|
249
249
|
const bannerText = lines.join("\n");
|
|
250
250
|
structuredWarnings.push(
|
|
251
|
-
|
|
251
|
+
buildReadSeekWarning("fuzzy-symbol-match", bannerText, {
|
|
252
252
|
tier: lookup.tier,
|
|
253
253
|
symbol: lookup.symbol,
|
|
254
254
|
otherCandidates: lookup.otherCandidates,
|
|
@@ -261,7 +261,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
261
261
|
if (p.bundle === "local") {
|
|
262
262
|
if (!symbolFileMap) {
|
|
263
263
|
const extLabel = ext || "unknown";
|
|
264
|
-
const warning =
|
|
264
|
+
const warning = buildReadSeekWarning(
|
|
265
265
|
"bundle-unmappable",
|
|
266
266
|
`[Warning: local bundle unavailable because symbol mapping is not available for .${extLabel} files — showing plain symbol read]`,
|
|
267
267
|
);
|
|
@@ -282,7 +282,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
282
282
|
} else {
|
|
283
283
|
const bundle = buildLocalBundle(symbolFileMap, symbolMatch, allLines);
|
|
284
284
|
if (!bundle) {
|
|
285
|
-
const warning =
|
|
285
|
+
const warning = buildReadSeekWarning(
|
|
286
286
|
"bundle-context-unavailable",
|
|
287
287
|
`[Warning: local bundle context could not be determined for symbol '${symbolMatch.name}' — showing plain symbol read]`,
|
|
288
288
|
);
|
|
@@ -333,7 +333,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
333
333
|
: `readseek returned ${readseekOutput.hashlines.length} lines for requested range ${startLine}-${endIdx} (${expectedLineCount} expected)`;
|
|
334
334
|
return buildToolErrorResult("read", "readseek-output-mismatch", message, { path: rawParams.path });
|
|
335
335
|
}
|
|
336
|
-
const readseekLines:
|
|
336
|
+
const readseekLines: ReadSeekLine[] = readseekOutput.hashlines.map((line) => ({
|
|
337
337
|
line: line.line,
|
|
338
338
|
hash: line.hash,
|
|
339
339
|
anchor: `${line.line}:${line.hash}`,
|
|
@@ -341,7 +341,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
341
341
|
display: escapeControlCharsForDisplay(line.text),
|
|
342
342
|
}));
|
|
343
343
|
const selected = readseekLines.map((line) => line.raw);
|
|
344
|
-
const formatted =
|
|
344
|
+
const formatted = renderReadSeekLines(readseekLines);
|
|
345
345
|
|
|
346
346
|
const truncation = truncateHead(formatted, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES });
|
|
347
347
|
|
|
@@ -363,17 +363,17 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
if (symbolWarning) {
|
|
366
|
-
structuredWarnings.push(
|
|
366
|
+
structuredWarnings.push(buildReadSeekWarning("symbol-warning", symbolWarning.trim()));
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
if (hasBinaryContent) {
|
|
370
370
|
const warning = "[Warning: file appears to be binary — output may be garbled]";
|
|
371
|
-
structuredWarnings.push(
|
|
371
|
+
structuredWarnings.push(buildReadSeekWarning("binary-content", warning));
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
if (hasBareCarriageReturn(rawText)) {
|
|
375
375
|
const warning = "[Warning: file contains bare CR (\\r) line endings — line numbering may be inconsistent with grep and other tools]";
|
|
376
|
-
structuredWarnings.push(
|
|
376
|
+
structuredWarnings.push(buildReadSeekWarning("bare-cr", warning));
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
const readOutput = buildReadOutput({
|
|
@@ -420,14 +420,14 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
|
|
|
420
420
|
});
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
function
|
|
423
|
+
function splitReadSeekLines(text: string): string[] {
|
|
424
424
|
if (text.length === 0) return [];
|
|
425
425
|
const withoutTrailingTerminator = text.endsWith("\n") ? text.slice(0, -1) : text;
|
|
426
426
|
return withoutTrailingTerminator.split("\n");
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
export function registerReadTool(pi: ExtensionAPI, options: ReadToolOptions = {}) {
|
|
430
|
-
const tool =
|
|
430
|
+
const tool = registerReadSeekTool(pi, {
|
|
431
431
|
policy: "read-only",
|
|
432
432
|
pythonName: "read",
|
|
433
433
|
defaultExposure: "safe-by-default",
|
|
@@ -497,7 +497,7 @@ export function registerReadTool(pi: ExtensionAPI, options: ReadToolOptions = {}
|
|
|
497
497
|
return new Text(clampLinesToWidth([summaryLine(errorText)], width).join("\n"), 0, 0);
|
|
498
498
|
}
|
|
499
499
|
|
|
500
|
-
const readseekValue = (result.details as any)?.readseekValue as { range: { startLine: number; endLine: number; totalLines: number }; truncation: any; symbol: any; map: any; warnings:
|
|
500
|
+
const readseekValue = (result.details as any)?.readseekValue as { range: { startLine: number; endLine: number; totalLines: number }; truncation: any; symbol: any; map: any; warnings: ReadSeekWarning[] } | undefined;
|
|
501
501
|
if (!readseekValue) {
|
|
502
502
|
const lines = textContent.split("\n").filter(Boolean).length || textContent.split("\n").length;
|
|
503
503
|
return new Text(summaryLine(`loaded ${lines} ${lines === 1 ? "line" : "lines"}`, { hidden: !!textContent && !expanded }), 0, 0);
|
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
* Constants for thresholds.
|
|
3
3
|
*/
|
|
4
4
|
export const THRESHOLDS = {
|
|
5
|
-
/** Maximum lines before truncation */
|
|
6
|
-
MAX_LINES: 2000,
|
|
7
|
-
/** Maximum bytes before truncation */
|
|
8
|
-
MAX_BYTES: 50 * 1024,
|
|
9
5
|
/** Maximum map size in bytes */
|
|
10
6
|
MAX_MAP_BYTES: 25 * 1024,
|
|
11
7
|
/** Target size for full detail */
|
|
@@ -30,37 +30,14 @@ function formatNumber(n: number): string {
|
|
|
30
30
|
/**
|
|
31
31
|
* Format a symbol for display.
|
|
32
32
|
*/
|
|
33
|
-
function formatSymbol(
|
|
34
|
-
symbol: FileSymbol,
|
|
35
|
-
level: DetailLevel,
|
|
36
|
-
indent = 0
|
|
37
|
-
): string {
|
|
33
|
+
function formatSymbol(symbol: FileSymbol, indent = 0): string {
|
|
38
34
|
const prefix = " ".repeat(indent);
|
|
39
35
|
const lineRange =
|
|
40
36
|
symbol.startLine === symbol.endLine
|
|
41
37
|
? `[${symbol.startLine}]`
|
|
42
38
|
: `[${symbol.startLine}-${symbol.endLine}]`;
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (level === DetailLevel.Full) {
|
|
47
|
-
if (symbol.signature) {
|
|
48
|
-
// Check whether the signature already contains the symbol name.
|
|
49
|
-
// Full-declaration signatures (e.g. Rust "pub fn foo(x: i32) -> bool")
|
|
50
|
-
// include the name; partial signatures (e.g. Python "(x, y) -> None")
|
|
51
|
-
// do not and should be appended.
|
|
52
|
-
if (symbol.signature.includes(name)) {
|
|
53
|
-
name = symbol.signature;
|
|
54
|
-
} else {
|
|
55
|
-
if (symbol.modifiers?.length) {
|
|
56
|
-
name = `${symbol.modifiers.join(" ")} ${name}`;
|
|
57
|
-
}
|
|
58
|
-
name = `${name}${symbol.signature}`;
|
|
59
|
-
}
|
|
60
|
-
} else if (symbol.modifiers?.length) {
|
|
61
|
-
name = `${symbol.modifiers.join(" ")} ${name}`;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
40
|
+
const { name } = symbol;
|
|
64
41
|
|
|
65
42
|
// Format based on kind
|
|
66
43
|
let formatted: string;
|
|
@@ -88,11 +65,6 @@ function formatSymbol(
|
|
|
88
65
|
}
|
|
89
66
|
}
|
|
90
67
|
|
|
91
|
-
// Append docstring at Full detail level
|
|
92
|
-
if (level === DetailLevel.Full && symbol.docstring) {
|
|
93
|
-
formatted += ` — ${symbol.docstring}`;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
68
|
return formatted;
|
|
97
69
|
}
|
|
98
70
|
|
|
@@ -107,7 +79,7 @@ function formatSymbols(
|
|
|
107
79
|
const lines: string[] = [];
|
|
108
80
|
|
|
109
81
|
for (const symbol of symbols) {
|
|
110
|
-
lines.push(formatSymbol(symbol,
|
|
82
|
+
lines.push(formatSymbol(symbol, indent));
|
|
111
83
|
|
|
112
84
|
// Add children for full, compact, and minimal levels (not outline or truncated)
|
|
113
85
|
if (
|
|
@@ -118,7 +90,7 @@ function formatSymbols(
|
|
|
118
90
|
// For minimal, flatten children
|
|
119
91
|
if (level === DetailLevel.Minimal) {
|
|
120
92
|
for (const child of symbol.children) {
|
|
121
|
-
lines.push(formatSymbol(child,
|
|
93
|
+
lines.push(formatSymbol(child, indent + 1));
|
|
122
94
|
}
|
|
123
95
|
} else {
|
|
124
96
|
lines.push(...formatSymbols(symbol.children, level, indent + 1));
|
|
@@ -132,7 +104,7 @@ function formatSymbols(
|
|
|
132
104
|
/**
|
|
133
105
|
* Format a complete file map to a string.
|
|
134
106
|
*/
|
|
135
|
-
|
|
107
|
+
function formatFileMap(map: FileMap, level?: DetailLevel): string {
|
|
136
108
|
const effectiveLevel = level ?? map.detailLevel;
|
|
137
109
|
const fileName = basename(map.path);
|
|
138
110
|
|
|
@@ -165,20 +137,6 @@ export function formatFileMap(map: FileMap, level?: DetailLevel): string {
|
|
|
165
137
|
lines.push("");
|
|
166
138
|
}
|
|
167
139
|
|
|
168
|
-
// Add imports if present and not outline or truncated level
|
|
169
|
-
if (
|
|
170
|
-
effectiveLevel !== DetailLevel.Outline &&
|
|
171
|
-
effectiveLevel !== DetailLevel.Truncated &&
|
|
172
|
-
map.imports.length > 0
|
|
173
|
-
) {
|
|
174
|
-
const importList =
|
|
175
|
-
map.imports.length > 10
|
|
176
|
-
? [...map.imports.slice(0, 10), `...${map.imports.length - 10} more`]
|
|
177
|
-
: map.imports;
|
|
178
|
-
lines.push(`imports: ${importList.join(", ")}`);
|
|
179
|
-
lines.push("");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
140
|
// Add symbols
|
|
183
141
|
if (map.truncatedInfo) {
|
|
184
142
|
// Truncated format: first half, separator, second half
|
|
@@ -236,13 +194,12 @@ export function formatFileMap(map: FileMap, level?: DetailLevel): string {
|
|
|
236
194
|
/**
|
|
237
195
|
* Reduce detail level of a file map.
|
|
238
196
|
*/
|
|
239
|
-
|
|
197
|
+
function reduceToLevel(map: FileMap, level: DetailLevel): FileMap {
|
|
240
198
|
if (level === DetailLevel.Outline) {
|
|
241
|
-
// Remove all children
|
|
199
|
+
// Remove all children
|
|
242
200
|
return {
|
|
243
201
|
...map,
|
|
244
202
|
detailLevel: DetailLevel.Outline,
|
|
245
|
-
imports: [],
|
|
246
203
|
symbols: map.symbols.map((s) => ({
|
|
247
204
|
name: s.name,
|
|
248
205
|
kind: s.kind,
|
|
@@ -253,7 +210,6 @@ export function reduceToLevel(map: FileMap, level: DetailLevel): FileMap {
|
|
|
253
210
|
}
|
|
254
211
|
|
|
255
212
|
if (level === DetailLevel.Minimal) {
|
|
256
|
-
// Remove signatures and docstrings but keep children flattened
|
|
257
213
|
return {
|
|
258
214
|
...map,
|
|
259
215
|
detailLevel: DetailLevel.Minimal,
|
|
@@ -262,48 +218,28 @@ export function reduceToLevel(map: FileMap, level: DetailLevel): FileMap {
|
|
|
262
218
|
kind: s.kind,
|
|
263
219
|
startLine: s.startLine,
|
|
264
220
|
endLine: s.endLine,
|
|
265
|
-
isExported: s.isExported,
|
|
266
221
|
children: s.children?.map((c) => ({
|
|
267
222
|
name: c.name,
|
|
268
223
|
kind: c.kind,
|
|
269
224
|
startLine: c.startLine,
|
|
270
225
|
endLine: c.endLine,
|
|
271
|
-
isExported: c.isExported,
|
|
272
226
|
})),
|
|
273
227
|
})),
|
|
274
228
|
};
|
|
275
229
|
}
|
|
276
230
|
|
|
277
231
|
if (level === DetailLevel.Compact) {
|
|
278
|
-
|
|
279
|
-
return {
|
|
280
|
-
...map,
|
|
281
|
-
detailLevel: DetailLevel.Compact,
|
|
282
|
-
symbols: map.symbols.map((s) => stripSignatures(s)),
|
|
283
|
-
};
|
|
232
|
+
return { ...map, detailLevel: DetailLevel.Compact };
|
|
284
233
|
}
|
|
285
234
|
|
|
286
235
|
return { ...map, detailLevel: DetailLevel.Full };
|
|
287
236
|
}
|
|
288
237
|
|
|
289
|
-
function stripSignatures(symbol: FileSymbol): FileSymbol {
|
|
290
|
-
return {
|
|
291
|
-
name: symbol.name,
|
|
292
|
-
kind: symbol.kind,
|
|
293
|
-
startLine: symbol.startLine,
|
|
294
|
-
endLine: symbol.endLine,
|
|
295
|
-
modifiers: symbol.modifiers,
|
|
296
|
-
docstring: symbol.docstring,
|
|
297
|
-
isExported: symbol.isExported,
|
|
298
|
-
children: symbol.children?.map(stripSignatures),
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
|
|
302
238
|
/**
|
|
303
239
|
* Reduce a file map to truncated form: first N + last N symbols only.
|
|
304
240
|
* Used when even Outline level exceeds budget.
|
|
305
241
|
*/
|
|
306
|
-
|
|
242
|
+
function reduceToTruncated(
|
|
307
243
|
map: FileMap,
|
|
308
244
|
symbolsEach: number = THRESHOLDS.TRUNCATED_SYMBOLS_EACH
|
|
309
245
|
): FileMap {
|
|
@@ -333,7 +269,6 @@ export function reduceToTruncated(
|
|
|
333
269
|
...map,
|
|
334
270
|
symbols: [...firstSymbols, ...lastSymbols],
|
|
335
271
|
detailLevel: DetailLevel.Truncated,
|
|
336
|
-
imports: [],
|
|
337
272
|
truncatedInfo: {
|
|
338
273
|
totalSymbols: total,
|
|
339
274
|
shownSymbols: symbolsEach * 2,
|
|
@@ -9,7 +9,7 @@ export interface SymbolMatch {
|
|
|
9
9
|
parentName?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
type SymbolLookupResult =
|
|
13
13
|
| { type: "found"; symbol: SymbolMatch }
|
|
14
14
|
| { type: "ambiguous"; candidates: SymbolMatch[] }
|
|
15
15
|
| {
|
|
@@ -88,22 +88,6 @@ function preferJavaTopLevelType(map: FileMap, candidates: SymbolCandidate[]): Sy
|
|
|
88
88
|
return topLevelTypes.length === 1 ? topLevelTypes[0] : undefined;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
function javaPackageName(map: FileMap): string | undefined {
|
|
92
|
-
if (map.language !== "Java") return undefined;
|
|
93
|
-
for (const entry of map.imports) {
|
|
94
|
-
const match = /^package\s+([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*;?$/.exec(entry);
|
|
95
|
-
if (match) return match[1];
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function stripJavaPackagePrefix(map: FileMap, query: string): string | undefined {
|
|
101
|
-
const packageName = javaPackageName(map);
|
|
102
|
-
if (!packageName) return undefined;
|
|
103
|
-
const prefix = `${packageName}.`;
|
|
104
|
-
return query.startsWith(prefix) ? query.slice(prefix.length) : undefined;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
91
|
function resolveDotPathSuffix(symbols: FileSymbol[], parts: string[]): SymbolCandidate[] {
|
|
108
92
|
for (let start = 1; start < parts.length; start++) {
|
|
109
93
|
const candidates = resolveDotPath(symbols, parts.slice(start));
|
|
@@ -118,7 +102,6 @@ export function findSymbol(map: FileMap, query: string): SymbolLookupResult {
|
|
|
118
102
|
if (map.symbols.length === 0) return { type: "not-found" };
|
|
119
103
|
|
|
120
104
|
const allSymbols = flattenSymbols(map.symbols);
|
|
121
|
-
const javaRelativeQuery = stripJavaPackagePrefix(map, q);
|
|
122
105
|
|
|
123
106
|
const atLineMatch = /^(.+?)@(\d+)$/.exec(q);
|
|
124
107
|
if (atLineMatch) {
|
|
@@ -189,16 +172,6 @@ export function findSymbol(map: FileMap, query: string): SymbolLookupResult {
|
|
|
189
172
|
return { type: "ambiguous", candidates: toMatches(exact.slice(0, 5)) };
|
|
190
173
|
}
|
|
191
174
|
|
|
192
|
-
if (javaRelativeQuery) {
|
|
193
|
-
const javaExact = allSymbols.filter((c) => c.symbol.name === javaRelativeQuery);
|
|
194
|
-
if (javaExact.length === 1) return { type: "found", symbol: toMatch(javaExact[0].symbol, javaExact[0].parentName) };
|
|
195
|
-
if (javaExact.length > 1) {
|
|
196
|
-
const preferred = preferJavaTopLevelType(map, javaExact);
|
|
197
|
-
if (preferred) return { type: "found", symbol: toMatch(preferred.symbol, preferred.parentName) };
|
|
198
|
-
return { type: "ambiguous", candidates: toMatches(javaExact.slice(0, 5)) };
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
175
|
if (q.includes(".")) {
|
|
203
176
|
const parts = q.split(".").map((p) => p.trim());
|
|
204
177
|
if (parts.length >= 2 && parts.every((p) => p.length > 0)) {
|
|
@@ -212,21 +185,6 @@ export function findSymbol(map: FileMap, query: string): SymbolLookupResult {
|
|
|
212
185
|
candidates: toMatches(candidates.slice(0, 5)),
|
|
213
186
|
};
|
|
214
187
|
}
|
|
215
|
-
const javaParts = javaRelativeQuery?.includes(".")
|
|
216
|
-
? javaRelativeQuery.split(".").map((p) => p.trim())
|
|
217
|
-
: [];
|
|
218
|
-
if (javaParts.length >= 2 && javaParts.every((p) => p.length > 0)) {
|
|
219
|
-
const javaCandidates = resolveDotPath(map.symbols, javaParts);
|
|
220
|
-
if (javaCandidates.length === 1) {
|
|
221
|
-
return { type: "found", symbol: toMatch(javaCandidates[0].symbol, javaCandidates[0].parentName) };
|
|
222
|
-
}
|
|
223
|
-
if (javaCandidates.length > 1) {
|
|
224
|
-
return {
|
|
225
|
-
type: "ambiguous",
|
|
226
|
-
candidates: toMatches(javaCandidates.slice(0, 5)),
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
188
|
const suffixCandidates = resolveDotPathSuffix(map.symbols, parts);
|
|
231
189
|
if (suffixCandidates.length === 1) {
|
|
232
190
|
return { type: "found", symbol: toMatch(suffixCandidates[0].symbol, suffixCandidates[0].parentName) };
|
package/src/readseek/types.ts
CHANGED
|
@@ -12,16 +12,8 @@ export interface FileSymbol {
|
|
|
12
12
|
startLine: number;
|
|
13
13
|
/** Ending line number (1-indexed) */
|
|
14
14
|
endLine: number;
|
|
15
|
-
/** Optional signature (for functions/methods) */
|
|
16
|
-
signature?: string;
|
|
17
15
|
/** Child symbols (for nested structures like methods in classes) */
|
|
18
16
|
children?: FileSymbol[];
|
|
19
|
-
/** Additional modifiers (async, static, etc.) */
|
|
20
|
-
modifiers?: string[];
|
|
21
|
-
/** First line of JSDoc / docstring (if present) */
|
|
22
|
-
docstring?: string;
|
|
23
|
-
/** Whether this symbol is exported from its module */
|
|
24
|
-
isExported?: boolean;
|
|
25
17
|
}
|
|
26
18
|
|
|
27
19
|
/**
|
|
@@ -50,20 +42,8 @@ export interface FileMap {
|
|
|
50
42
|
language: string;
|
|
51
43
|
/** Extracted symbols */
|
|
52
44
|
symbols: FileSymbol[];
|
|
53
|
-
/** Module imports / dependencies */
|
|
54
|
-
imports: string[];
|
|
55
45
|
/** Detail level used for this map */
|
|
56
46
|
detailLevel: DetailLevel;
|
|
57
47
|
/** Truncation metadata (present when symbols are truncated) */
|
|
58
48
|
truncatedInfo?: TruncatedInfo;
|
|
59
49
|
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Language information.
|
|
63
|
-
*/
|
|
64
|
-
export interface LanguageInfo {
|
|
65
|
-
/** Language identifier */
|
|
66
|
-
id: string;
|
|
67
|
-
/** Display name */
|
|
68
|
-
name: string;
|
|
69
|
-
}
|