pi-readseek 0.6.6 → 0.6.8

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/README.md CHANGED
@@ -64,7 +64,7 @@ optional (defaults shown):
64
64
  - **replacedTools:** built-in tool names to replace with their `readSeek_*` equivalents.
65
65
  Valid values are `"read"`, `"edit"`, `"write"`, and `"grep"`. For a
66
66
  readseek-only file surface, use `["read", "edit", "write", "grep"]`.
67
- - **imageMode:** `"auto"` exposes `none`, `ocr`, `caption`, and `objects`;
67
+ - **imageMode:** `"auto"` exposes `none`, `all`, `ocr`, `caption`, and `objects`;
68
68
  `"on"` omits `none`; `"off"` removes the `image` parameter and always skips
69
69
  image/PDF files. Omitting `image` also skips visual files.
70
70
  - **syntaxValidation:** pre-write syntax-regression check in `readSeek_edit`:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-readseek",
3
- "version": "0.6.6",
3
+ "version": "0.6.8",
4
4
  "description": "Pi extension for readseek-backed hash-anchored read/edit/grep, structural code maps, structural search, and file exploration",
5
5
  "type": "module",
6
6
  "exports": {
@@ -39,7 +39,7 @@
39
39
  "node": ">=20.0.0"
40
40
  },
41
41
  "dependencies": {
42
- "@jarkkojs/readseek": "^0.6.6",
42
+ "@jarkkojs/readseek": "^0.6.8",
43
43
  "diff": "^8.0.3",
44
44
  "xxhash-wasm": "^1.1.0"
45
45
  },
@@ -76,9 +76,6 @@ function formatWhitespaceOnlyWarning(semanticSummary: SemanticSummary | undefine
76
76
  if (!extractNewTextValues(edits).some((text) => /\S/.test(text))) return undefined;
77
77
  return "⚠ Edit classified as whitespace-only — if you intended a behavior change, re-read to verify.";
78
78
  }
79
- function formatSemanticSuffix(_semanticSummary: SemanticSummary | undefined): string {
80
- return "";
81
- }
82
79
  function formatReplaceHint(edits: unknown[] | undefined, noopEdits: unknown[]): string | undefined {
83
80
  if ((noopEdits ?? []).length > 0) return undefined;
84
81
  const counts = countEditTypes(edits);
@@ -88,7 +85,7 @@ function formatReplaceHint(edits: unknown[] | undefined, noopEdits: unknown[]):
88
85
  }
89
86
  export function buildEditOutput(input: BuildEditOutputInput): EditOutputResult {
90
87
  const summary = `Updated ${input.displayPath}`;
91
- const visibleSummary = `${buildVisibleSummary(input.displayPath, input.diff, input.edits)}${formatSemanticSuffix(input.semanticSummary)}`;
88
+ const visibleSummary = buildVisibleSummary(input.displayPath, input.diff, input.edits);
92
89
  const semanticWarning = formatWhitespaceOnlyWarning(input.semanticSummary, input.edits);
93
90
  const warningText = input.warnings.length ? `\n\nWarnings:\n${input.warnings.join("\n")}` : "";
94
91
  const replaceHint = formatReplaceHint(input.edits, input.noopEdits);
package/src/read.ts CHANGED
@@ -66,7 +66,7 @@ function hasReadAnchors(result: AgentToolResult<any>): boolean {
66
66
  return Array.isArray(lines) && lines.length > 0;
67
67
  }
68
68
 
69
- function formatImageAnalysis(detection: ReadSeekDetection, mode: "ocr" | "caption" | "objects"): string | undefined {
69
+ function formatImageAnalysis(detection: ReadSeekDetection, mode: "all" | "ocr" | "caption" | "objects"): string | undefined {
70
70
  if (detection.kind !== "image") return undefined;
71
71
  const sections: string[] = [];
72
72
  const ocr = detection.ocr?.trim();
@@ -80,6 +80,7 @@ function formatImageAnalysis(detection: ReadSeekDetection, mode: "ocr" | "captio
80
80
  if (sections.length > 0) return sections.join("\n\n");
81
81
  if (mode === "ocr") return "No OCR text detected in image.";
82
82
  if (mode === "objects") return "No objects detected in image.";
83
+ if (mode === "all") return "No image analysis returned.";
83
84
  return "Image caption returned no text.";
84
85
  }
85
86
 
@@ -524,7 +525,7 @@ function splitReadSeekLines(text: string): string[] {
524
525
  export function registerReadTool(pi: ExtensionAPI, options: ReadToolOptions = {}) {
525
526
  const name = options.name ?? "readSeek_read";
526
527
  const imageMode = resolveReadSeekImageMode();
527
- const imageModes = imageMode === "auto" ? ["none", "ocr", "caption", "objects"] as const : ["ocr", "caption", "objects"] as const;
528
+ const imageModes = imageMode === "auto" ? ["none", "all", "ocr", "caption", "objects"] as const : ["all", "ocr", "caption", "objects"] as const;
528
529
  const promptMetadata = defineToolPromptMetadata({
529
530
  promptUrl: new URL("../prompts/read.md", import.meta.url),
530
531
  promptSnippet: "Read anchored text, symbols, maps, images, or PDFs",
@@ -116,7 +116,7 @@ export interface ReadSeekDetectedObject {
116
116
  bbox: [number, number, number, number];
117
117
  }
118
118
 
119
- export type ReadSeekImageMode = "ocr" | "caption" | "objects";
119
+ export type ReadSeekImageMode = "all" | "ocr" | "caption" | "objects";
120
120
 
121
121
  export interface ReadSeekPreparedImage {
122
122
  mime: string;
@@ -851,8 +851,9 @@ export async function readSeekImage(
851
851
  modes: ReadSeekImageMode[],
852
852
  options: { signal?: AbortSignal } = {},
853
853
  ): Promise<ReadSeekDetection> {
854
+ const requestedModes = modes.length > 1 ? ["all"] : modes;
854
855
  const results = await Promise.allSettled(
855
- modes.map(async (mode) =>
856
+ requestedModes.map(async (mode) =>
856
857
  parseDetectOutput(await runReadSeekVision(["read", "--image", mode, filePath], { signal: options.signal })),
857
858
  ),
858
859
  );
@@ -892,7 +893,7 @@ function parsePdfImage(value: unknown): ReadSeekPdfImage {
892
893
  if (!value || typeof value !== "object") throw new Error("invalid readseek PDF image");
893
894
  const image = value as Record<string, unknown>;
894
895
  const mode = requireString(image.mode, "PDF image.mode");
895
- if (mode !== "none" && mode !== "ocr" && mode !== "caption" && mode !== "objects") {
896
+ if (mode !== "none" && mode !== "all" && mode !== "ocr" && mode !== "caption" && mode !== "objects") {
896
897
  throw new Error("invalid readseek PDF image.mode");
897
898
  }
898
899
  return {
@@ -76,12 +76,8 @@ export function buildReadSeekLines(startLine: number, rawLines: string[]): ReadS
76
76
  return rawLines.map((raw, index) => buildReadSeekLine(startLine + index, raw));
77
77
  }
78
78
 
79
- function renderReadSeekLine(line: ReadSeekLine): string {
80
- return `${line.anchor}|${line.display}`;
81
- }
82
-
83
79
  export function renderReadSeekLines(lines: ReadSeekLine[]): string {
84
- return lines.map(renderReadSeekLine).join("\n");
80
+ return lines.map((line) => `${line.anchor}|${line.display}`).join("\n");
85
81
  }
86
82
 
87
83
  /**
package/src/search.ts CHANGED
@@ -7,7 +7,7 @@ import { defineToolPromptMetadata } from "./tool-prompt-metadata.js";
7
7
  import { buildReadSeekLineWithHash, buildToolErrorResult, type ReadSeekLine } from "./readseek-value.js";
8
8
  import { resolveToCwd } from "./path-utils.js";
9
9
  import { statSearchPathOrError } from "./stat-search-path.js";
10
- import { classifyReadSeekFailure, readSeekSearch, type ReadSeekHashline, type ReadSeekSearchFileOutput } from "./readseek-client.js";
10
+ import { classifyReadSeekFailure, readSeekSearch, type ReadSeekSearchFileOutput } from "./readseek-client.js";
11
11
  import { buildSearchOutput } from "./search-output.js";
12
12
  import type { FileAnchoredCallback } from "./tool-types.js";
13
13
  import { langParam, readSeekGitSearchParams, searchPathParam, validateIgnoredRequiresOthers } from "./readseek-params.js";
@@ -66,15 +66,11 @@ export interface ExecuteSearchOptions {
66
66
  onFileAnchored?: FileAnchoredCallback;
67
67
  }
68
68
 
69
- function readSeekLineFromSearch(line: ReadSeekHashline): ReadSeekLine {
70
- return buildReadSeekLineWithHash(line.line, line.hash, line.text);
71
- }
72
-
73
69
  function linesFromSearchResult(result: ReadSeekSearchFileOutput, ranges: SearchRange[]): ReadSeekLine[] {
74
70
  const lineMap = new Map<number, ReadSeekLine>();
75
71
  for (const match of result.matches) {
76
72
  for (const line of match.hashlines) {
77
- lineMap.set(line.line, readSeekLineFromSearch(line));
73
+ lineMap.set(line.line, buildReadSeekLineWithHash(line.line, line.hash, line.text));
78
74
  }
79
75
  }
80
76