pi-readseek 0.5.0 → 0.5.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.
package/README.md CHANGED
@@ -38,17 +38,18 @@ npm install --save-dev @jarkkojs/readseek
38
38
 
39
39
  `pi-readseek` reads optional JSON settings from:
40
40
 
41
- - `~/.pi/agent/readseek/settings.json` — Global
42
- - `.pi/readseek/settings.json` — Project
41
+ - `~/.pi/agent/settings.json` — Global
42
+ - `.pi/settings.json` — Project
43
43
 
44
- Project settings override global settings. All settings live in a single
45
- `readseek` section and are optional (defaults shown):
44
+ Project settings override global settings. The `readseek` section lives inside pi's
45
+ shared `settings.json`, alongside other extensions' sections. All settings are
46
+ optional (defaults shown):
46
47
 
47
48
  ```json
48
49
  {
49
50
  "readseek": {
50
51
  "excludeTools": [],
51
- "ocrMode": "force",
52
+ "imageMode": "force",
52
53
  "syntaxValidation": "warn",
53
54
  "timeoutMs": 120000,
54
55
  "grep": {
@@ -62,7 +63,7 @@ Project settings override global settings. All settings live in a single
62
63
  - **excludeTools:** active tool names to hide after activating `readSeek_*`
63
64
  tools. For a readseek-only file surface, use `["read", "edit", "write",
64
65
  "grep"]`.
65
- - **ocrMode:** image OCR/caption/object analysis in `readSeek_read`: `"force"`
66
+ - **imageMode:** image OCR/caption/object analysis in `readSeek_read`: `"force"`
66
67
  (or its alias `"on"`) always runs it, `"off"` returns only the image
67
68
  attachment, and `"auto"` runs it only when the active model does not support
68
69
  native image input.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-readseek",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
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": {
package/prompts/read.md CHANGED
@@ -1,4 +1,4 @@
1
- Read files through readseek. Text output uses `LINE:HASH|content` anchors that can be copied directly into `readSeek_edit`; supported images return attachments and may append OCR/caption/object text depending on `readseek.ocrMode`. Default cap: {{DEFAULT_MAX_LINES}} lines or {{DEFAULT_MAX_BYTES}}.
1
+ Read files through readseek. Text output uses `LINE:HASH|content` anchors that can be copied directly into `readSeek_edit`; supported images return attachments and may append OCR/caption/object text depending on `readseek.imageMode`. Default cap: {{DEFAULT_MAX_LINES}} lines or {{DEFAULT_MAX_BYTES}}.
2
2
 
3
3
  ## Choose the right read
4
4
 
package/src/read.ts CHANGED
@@ -28,14 +28,14 @@ import { buildLocalBundle } from "./read-local-bundle.js";
28
28
  import { coerceObviousBase10Int } from "./coerce-obvious-int.js";
29
29
  import { readSeekRead, readSeekDetect, readSeekImage, type ReadSeekDetection } from "./readseek-client.js";
30
30
  import { formatReadCallText, formatReadResultText } from "./read-render-helpers.js";
31
- import { resolveReadSeekOcrMode } from "./readseek-settings.js";
31
+ import { resolveReadSeekImageMode } from "./readseek-settings.js";
32
32
  import { clampLineToWidth, clampLinesToWidth, linkToolPath, renderPendingResult, renderToolLabel, resolveRenderResultContext, summaryLine, wrapReadHashlinesForWidthCached } from "./tui-render-utils.js";
33
33
  import type { FileAnchoredCallback } from "./tool-types.js";
34
34
  import { filePathParam, mapParam, optionalIntOrString, registerReadSeekTool } from "./register-tool.js";
35
35
 
36
36
  const READ_PROMPT_METADATA = defineToolPromptMetadata({
37
37
  promptUrl: new URL("../prompts/read.md", import.meta.url),
38
- promptSnippet: "Read text files or images; text reads include hashline anchors and optional maps/symbol lookup, image reads include the attachment plus OCR text",
38
+ promptSnippet: "Read text files or images; text reads include hashline anchors and optional maps/symbol lookup, image reads include the attachment plus OCR text, an image caption, and detected objects",
39
39
  });
40
40
 
41
41
  interface ReadParams {
@@ -58,7 +58,7 @@ export interface ExecuteReadOptions {
58
58
  onUpdate: any;
59
59
  cwd: string;
60
60
  onSuccessfulRead?: FileAnchoredCallback;
61
- /** Whether the active model accepts image input natively. Used when OCR mode is auto. */
61
+ /** Whether the active model accepts image input natively. Used when imageMode is auto. */
62
62
  modelSupportsImages?: boolean;
63
63
  }
64
64
 
@@ -177,11 +177,10 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
177
177
  if (detection?.kind === "image") {
178
178
  const builtinRead = createReadTool(cwd);
179
179
  const builtinResult = await builtinRead.execute(toolCallId, p, signal, onUpdate);
180
- const ocrMode = resolveReadSeekOcrMode();
181
- const shouldRunVision = ocrMode === "force" || (ocrMode === "auto" && !opts.modelSupportsImages);
180
+ const imageMode = resolveReadSeekImageMode();
181
+ const shouldRunVision = imageMode === "force" || (imageMode === "auto" && !opts.modelSupportsImages);
182
182
  if (!shouldRunVision) return succeed(builtinResult);
183
183
 
184
- let ocrFailed = false;
185
184
  try {
186
185
  const ocrDetection = await readSeekImage(absolutePath, ["ocr", "caption", "objects"], { signal });
187
186
  const imageAnalysis = formatImageAnalysis(ocrDetection);
@@ -195,14 +194,11 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
195
194
  });
196
195
  }
197
196
  } catch {
198
- ocrFailed = true;
199
- }
200
- if (ocrFailed) {
201
197
  return succeed({
202
198
  ...builtinResult,
203
199
  content: [
204
200
  ...(builtinResult.content ?? []),
205
- { type: "text" as const, text: "[Warning: local image analysis (OCR) unavailable — showing image attachment only]" },
201
+ { type: "text" as const, text: "[Warning: local image analysis unavailable — showing image attachment only]" },
206
202
  ],
207
203
  });
208
204
  }
@@ -2,7 +2,7 @@ import { readFileSync, statSync, type Stats } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
 
5
- export type ReadSeekOcrMode = "force" | "off" | "auto";
5
+ export type ReadSeekImageAnalysisMode = "force" | "off" | "auto";
6
6
  export type ReadSeekSyntaxValidationMode = "warn" | "block" | "off";
7
7
 
8
8
  interface ReadSeekGrepSettings {
@@ -12,7 +12,7 @@ interface ReadSeekGrepSettings {
12
12
 
13
13
  interface ReadSeekJsonSettings {
14
14
  excludeTools?: string[];
15
- ocrMode?: ReadSeekOcrMode;
15
+ imageMode?: ReadSeekImageAnalysisMode;
16
16
  syntaxValidation?: ReadSeekSyntaxValidationMode;
17
17
  timeoutMs?: number;
18
18
  grep?: ReadSeekGrepSettings;
@@ -29,15 +29,15 @@ export interface ReadSeekSettingsResult {
29
29
  warnings: ReadSeekSettingsWarning[];
30
30
  }
31
31
 
32
- const READSEEK_KEYS = ["excludeTools", "ocrMode", "syntaxValidation", "timeoutMs", "grep"];
32
+ const READSEEK_KEYS = ["excludeTools", "imageMode", "syntaxValidation", "timeoutMs", "grep"];
33
33
  const READSEEK_GREP_KEYS = ["maxLines", "maxBytes"];
34
34
 
35
- function defaultGlobalSettingsPath(): string {
36
- return join(homedir(), ".pi/agent/readseek/settings.json");
35
+ function globalSettingsPath(): string {
36
+ return join(homedir(), ".pi/agent/settings.json");
37
37
  }
38
38
 
39
- function defaultProjectSettingsPath(): string {
40
- return join(process.cwd(), ".pi/readseek/settings.json");
39
+ function projectSettingsPath(): string {
40
+ return join(process.cwd(), ".pi/settings.json");
41
41
  }
42
42
 
43
43
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -91,16 +91,16 @@ function readEnum<T extends string>(
91
91
  return undefined;
92
92
  }
93
93
 
94
- function readOcrMode(
94
+ function readImageMode(
95
95
  raw: Record<string, unknown>,
96
96
  source: string,
97
97
  warnings: ReadSeekSettingsWarning[],
98
- ): ReadSeekOcrMode | undefined {
99
- if (!("ocrMode" in raw)) return undefined;
100
- const val = raw.ocrMode;
98
+ ): ReadSeekImageAnalysisMode | undefined {
99
+ if (!("imageMode" in raw)) return undefined;
100
+ const val = raw.imageMode;
101
101
  if (val === "on") return "force";
102
102
  if (val === "force" || val === "off" || val === "auto") return val;
103
- warnings.push(invalid(source, "readseek.ocrMode"));
103
+ warnings.push(invalid(source, "readseek.imageMode"));
104
104
  return undefined;
105
105
  }
106
106
 
@@ -153,8 +153,8 @@ function validateSettings(raw: unknown, source: string): ReadSeekSettingsResult
153
153
  const excludeTools = readStringArray(section, "excludeTools", "readseek.excludeTools", source, warnings);
154
154
  if (excludeTools !== undefined) settings.excludeTools = excludeTools;
155
155
 
156
- const ocrMode = readOcrMode(section, source, warnings);
157
- if (ocrMode !== undefined) settings.ocrMode = ocrMode;
156
+ const imageMode = readImageMode(section, source, warnings);
157
+ if (imageMode !== undefined) settings.imageMode = imageMode;
158
158
 
159
159
  const syntaxValidation = readEnum(
160
160
  section,
@@ -232,16 +232,16 @@ function mergeSettings(base: ReadSeekJsonSettings, override: ReadSeekJsonSetting
232
232
  }
233
233
 
234
234
  export function resolveReadSeekJsonSettings(): ReadSeekSettingsResult {
235
- const globalResult = readSettingsFile(defaultGlobalSettingsPath());
236
- const projectResult = readSettingsFile(defaultProjectSettingsPath());
235
+ const globalResult = readSettingsFile(globalSettingsPath());
236
+ const projectResult = readSettingsFile(projectSettingsPath());
237
237
  return {
238
238
  settings: mergeSettings(globalResult.settings, projectResult.settings),
239
239
  warnings: [...globalResult.warnings, ...projectResult.warnings],
240
240
  };
241
241
  }
242
242
 
243
- export function resolveReadSeekOcrMode(): ReadSeekOcrMode {
244
- return resolveReadSeekJsonSettings().settings.ocrMode ?? "force";
243
+ export function resolveReadSeekImageMode(): ReadSeekImageAnalysisMode {
244
+ return resolveReadSeekJsonSettings().settings.imageMode ?? "force";
245
245
  }
246
246
 
247
247
  export function resolveReadSeekSyntaxValidation(): ReadSeekSyntaxValidationMode | undefined {
@@ -3,7 +3,7 @@ import { readFileSync } from "node:fs";
3
3
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "@earendil-works/pi-coding-agent";
4
4
 
5
5
  const COMPACT_DESCRIPTIONS: Record<string, string> = {
6
- "read.md": "Read text files/images by path; text has LINE:HASH anchors, images return the attachment plus OCR-extracted text.",
6
+ "read.md": "Read text files/images by path; text has LINE:HASH anchors, images return the attachment plus OCR text, a caption, and detected objects.",
7
7
  "edit.md": "Edit existing text files using fresh LINE:HASH anchors from readSeek_read, readSeek_grep, readSeek_search, or readSeek_write.",
8
8
  "grep.md": "Search file contents; non-summary results include LINE:HASH anchors for edits.",
9
9
 
@@ -16,7 +16,7 @@ const COMPACT_GUIDELINES: Record<string, string[]> = {
16
16
  "read.md": [
17
17
  "Use readSeek_read for file contents, images/screenshots, ranges, symbols, and edit anchors.",
18
18
  "Use map or symbol mode before pulling large code files into context.",
19
- "Use readSeek_read for images; it returns the image attachment plus OCR-extracted text, so you don't need separate OCR tools.",
19
+ "Use readSeek_read for images; it returns the image attachment plus OCR text, a caption, and detected objects, so you don't need separate OCR tools.",
20
20
  ],
21
21
  "edit.md": [
22
22
  "Use readSeek_edit with fresh LINE:HASH anchors for existing files.",