pi-readseek 0.4.29 → 0.5.0

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/src/read.ts CHANGED
@@ -26,7 +26,7 @@ import { buildReadOutput } from "./read-output.js";
26
26
 
27
27
  import { buildLocalBundle } from "./read-local-bundle.js";
28
28
  import { coerceObviousBase10Int } from "./coerce-obvious-int.js";
29
- import { readseekRead, readseekDetect, type ReadSeekDetection } from "./readseek-client.js";
29
+ import { readSeekRead, readSeekDetect, readSeekImage, type ReadSeekDetection } from "./readseek-client.js";
30
30
  import { formatReadCallText, formatReadResultText } from "./read-render-helpers.js";
31
31
  import { resolveReadSeekOcrMode } from "./readseek-settings.js";
32
32
  import { clampLineToWidth, clampLinesToWidth, linkToolPath, renderPendingResult, renderToolLabel, resolveRenderResultContext, summaryLine, wrapReadHashlinesForWidthCached } from "./tui-render-utils.js";
@@ -65,17 +65,17 @@ export interface ExecuteReadOptions {
65
65
  function hasReadAnchors(result: AgentToolResult<any>): boolean {
66
66
  const details = (result as { details?: unknown }).details;
67
67
  if (!details || typeof details !== "object") return false;
68
- const readseekValue = (details as { readseekValue?: unknown }).readseekValue;
69
- if (!readseekValue || typeof readseekValue !== "object") return false;
70
- const lines = (readseekValue as { lines?: unknown }).lines;
68
+ const readSeekValue = (details as { readSeekValue?: unknown }).readSeekValue;
69
+ if (!readSeekValue || typeof readSeekValue !== "object") return false;
70
+ const lines = (readSeekValue as { lines?: unknown }).lines;
71
71
  return Array.isArray(lines) && lines.length > 0;
72
72
  }
73
73
 
74
74
  function formatImageAnalysis(detection: ReadSeekDetection): string | undefined {
75
75
  if (detection.kind !== "image") return undefined;
76
76
  const sections: string[] = [];
77
- const transcript = detection.transcribe?.text?.trim();
78
- if (transcript) sections.push(`Transcribed text from image:\n${transcript}`);
77
+ const ocr = detection.ocr?.trim();
78
+ if (ocr) sections.push(`OCR text from image:\n${ocr}`);
79
79
  const caption = detection.caption?.trim();
80
80
  if (caption) sections.push(`Image caption:\n${caption}`);
81
81
  if (detection.objects?.length) {
@@ -171,24 +171,19 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
171
171
  if (hasBinaryContent) {
172
172
  let detection: ReadSeekDetection | undefined;
173
173
  try {
174
- detection = await readseekDetect(absolutePath, { signal });
174
+ detection = await readSeekDetect(absolutePath, { signal });
175
175
  } catch {
176
176
  }
177
177
  if (detection?.kind === "image") {
178
178
  const builtinRead = createReadTool(cwd);
179
179
  const builtinResult = await builtinRead.execute(toolCallId, p, signal, onUpdate);
180
180
  const ocrMode = resolveReadSeekOcrMode();
181
- const shouldTranscribe = ocrMode === "on" || (ocrMode === "auto" && !opts.modelSupportsImages);
182
- if (!shouldTranscribe) return succeed(builtinResult);
181
+ const shouldRunVision = ocrMode === "force" || (ocrMode === "auto" && !opts.modelSupportsImages);
182
+ if (!shouldRunVision) return succeed(builtinResult);
183
183
 
184
184
  let ocrFailed = false;
185
185
  try {
186
- const ocrDetection = await readseekDetect(absolutePath, {
187
- transcribe: true,
188
- caption: true,
189
- objects: true,
190
- signal,
191
- });
186
+ const ocrDetection = await readSeekImage(absolutePath, ["ocr", "caption", "objects"], { signal });
192
187
  const imageAnalysis = formatImageAnalysis(ocrDetection);
193
188
  if (imageAnalysis) {
194
189
  return succeed({
@@ -356,33 +351,33 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
356
351
  }
357
352
 
358
353
  throwIfAborted(signal);
359
- let readseekOutput: Awaited<ReturnType<typeof readseekRead>>;
354
+ let readSeekOutput: Awaited<ReturnType<typeof readSeekRead>>;
360
355
  try {
361
- readseekOutput = total === 0
362
- ? await readseekRead(absolutePath)
363
- : await readseekRead(absolutePath, startLine, endIdx);
356
+ readSeekOutput = total === 0
357
+ ? await readSeekRead(absolutePath, undefined, undefined, { signal })
358
+ : await readSeekRead(absolutePath, startLine, endIdx, { signal });
364
359
  } catch (err: any) {
365
360
  const detail = err?.message ? ` — ${err.message}` : "";
366
361
  const message = `readseek failed while reading ${rawPath}${detail}`;
367
362
  return buildToolErrorResult("read", "readseek-error", message, { path: rawParams.path, hint: "Ensure @jarkkojs/readseek and its npm platform package are installed.", details: { message: err?.message } });
368
363
  }
369
364
  const expectedLineCount = Math.max(0, endIdx - startLine + 1);
370
- const invalidLine = readseekOutput.hashlines.find((line, index) => line.line !== startLine + index);
371
- if (readseekOutput.hashlines.length !== expectedLineCount || invalidLine) {
365
+ const invalidLine = readSeekOutput.hashlines.find((line, index) => line.line !== startLine + index);
366
+ if (readSeekOutput.hashlines.length !== expectedLineCount || invalidLine) {
372
367
  const message = invalidLine
373
368
  ? `readseek returned non-sequential line ${invalidLine.line} for requested range ${startLine}-${endIdx}`
374
- : `readseek returned ${readseekOutput.hashlines.length} lines for requested range ${startLine}-${endIdx} (${expectedLineCount} expected)`;
369
+ : `readseek returned ${readSeekOutput.hashlines.length} lines for requested range ${startLine}-${endIdx} (${expectedLineCount} expected)`;
375
370
  return buildToolErrorResult("read", "readseek-output-mismatch", message, { path: rawParams.path });
376
371
  }
377
- const readseekLines: ReadSeekLine[] = readseekOutput.hashlines.map((line) => ({
372
+ const readSeekLines: ReadSeekLine[] = readSeekOutput.hashlines.map((line) => ({
378
373
  line: line.line,
379
374
  hash: line.hash,
380
375
  anchor: `${line.line}:${line.hash}`,
381
376
  raw: line.text,
382
377
  display: escapeControlCharsForDisplay(line.text),
383
378
  }));
384
- const selected = readseekLines.map((line) => line.raw);
385
- const formatted = renderReadSeekLines(readseekLines);
379
+ const selected = readSeekLines.map((line) => line.raw);
380
+ const formatted = renderReadSeekLines(readSeekLines);
386
381
 
387
382
  const truncation = truncateHead(formatted, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES });
388
383
 
@@ -423,7 +418,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
423
418
  endLine: endIdx,
424
419
  totalLines: total,
425
420
  selectedLines: selected,
426
- lines: readseekLines,
421
+ lines: readSeekLines,
427
422
  warnings: structuredWarnings,
428
423
  truncation: truncation.truncated
429
424
  ? {
@@ -456,7 +451,7 @@ export async function executeRead(opts: ExecuteReadOptions): Promise<AgentToolRe
456
451
  content: [{ type: "text", text: readOutput.text }],
457
452
  details: {
458
453
  truncation: truncation.truncated ? truncation : undefined,
459
- readseekValue: readOutput.readseekValue,
454
+ readSeekValue: readOutput.readSeekValue,
460
455
  },
461
456
  });
462
457
  }
@@ -469,11 +464,7 @@ function splitReadSeekLines(text: string): string[] {
469
464
 
470
465
  export function registerReadTool(pi: ExtensionAPI, options: ReadToolOptions = {}) {
471
466
  const tool = registerReadSeekTool(pi, {
472
- policy: "read-only",
473
- pythonName: "read",
474
- defaultExposure: "safe-by-default",
475
- }, {
476
- name: "read",
467
+ name: "readSeek_read",
477
468
  label: "Read",
478
469
  description: READ_PROMPT_METADATA.description,
479
470
  promptSnippet: READ_PROMPT_METADATA.promptSnippet,
@@ -529,16 +520,16 @@ export function registerReadTool(pi: ExtensionAPI, options: ReadToolOptions = {}
529
520
  return new Text(clampLinesToWidth([summaryLine(errorText)], width).join("\n"), 0, 0);
530
521
  }
531
522
 
532
- const readseekValue = (result.details as any)?.readseekValue as { range: { startLine: number; endLine: number; totalLines: number }; truncation: any; symbol: any; map: any; warnings: ReadSeekWarning[] } | undefined;
533
- if (!readseekValue) {
523
+ const readSeekValue = (result.details as any)?.readSeekValue as { range: { startLine: number; endLine: number; totalLines: number }; truncation: any; symbol: any; map: any; warnings: ReadSeekWarning[] } | undefined;
524
+ if (!readSeekValue) {
534
525
  const lines = textContent.split("\n").filter(Boolean).length || textContent.split("\n").length;
535
526
  return new Text(summaryLine(`loaded ${lines} ${lines === 1 ? "line" : "lines"}`, { hidden: !!textContent && !expanded }), 0, 0);
536
527
  }
537
528
 
538
- const info = formatReadResultText({ range: readseekValue.range, truncation: readseekValue.truncation, symbol: readseekValue.symbol, map: readseekValue.map, warnings: readseekValue.warnings });
539
- const visibleLines = info.truncated && readseekValue.truncation ? readseekValue.truncation.outputLines : readseekValue.range.endLine - readseekValue.range.startLine + 1;
529
+ const info = formatReadResultText({ range: readSeekValue.range, truncation: readSeekValue.truncation, symbol: readSeekValue.symbol, map: readSeekValue.map, warnings: readSeekValue.warnings });
530
+ const visibleLines = info.truncated && readSeekValue.truncation ? readSeekValue.truncation.outputLines : readSeekValue.range.endLine - readSeekValue.range.startLine + 1;
540
531
  const loadedWord = visibleLines === 1 ? "line" : "lines";
541
- const summaryParts: string[] = [info.truncated ? `loaded ${visibleLines} of ${readseekValue.truncation?.totalLines ?? readseekValue.range.totalLines} ${loadedWord} (truncated)` : `loaded ${visibleLines} ${loadedWord}`];
532
+ const summaryParts: string[] = [info.truncated ? `loaded ${visibleLines} of ${readSeekValue.truncation?.totalLines ?? readSeekValue.range.totalLines} ${loadedWord} (truncated)` : `loaded ${visibleLines} ${loadedWord}`];
542
533
  if (info.symbolBadge) summaryParts.push(info.symbolBadge);
543
534
  for (const badge of info.badges) summaryParts.push(badge);
544
535
  const summary = summaryParts.join(" • ");