pi-read-map
Advanced tools
+7
-0
@@ -5,2 +5,9 @@ # Changelog | ||
| ## [1.2.4] - 2026-02-15 | ||
| ### Fixed | ||
| - Binary/image files (`.jpg`, `.png`, `.gif`, `.webp`, etc.) no longer enter the map generation pipeline — they are delegated directly to the built-in read tool. Previously, a >50 KB image would pass the size threshold, run `wc -l` on binary data, and trigger ctags/grep fallback. When multiple image reads ran in parallel, the resulting `sendMessage` calls broke the Claude API's `tool_use`/`tool_result` pairing requirement. | ||
| - Fallback mapper now returns `null` when grep finds zero symbols instead of returning an empty `FileMap`. This prevents unnecessary `sendMessage` calls for unmappable files. | ||
| ## [1.2.2] - 2026-02-14 | ||
@@ -7,0 +14,0 @@ |
+1
-1
| { | ||
| "name": "pi-read-map", | ||
| "version": "1.2.3", | ||
| "version": "1.2.4", | ||
| "description": "Pi extension that adds structural file maps for large files", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+4
-3
@@ -160,5 +160,6 @@ # pi-read-map | ||
| 1. **Small files** (≤2,000 lines, ≤50 KB): Delegate to built-in read tool | ||
| 2. **Targeted reads** (offset or limit provided): Delegate to built-in read tool | ||
| 3. **Large files:** | ||
| 1. **Binary files** (images, audio, video, archives, etc.): Delegate to built-in read tool | ||
| 2. **Small files** (≤2,000 lines, ≤50 KB): Delegate to built-in read tool | ||
| 3. **Targeted reads** (offset or limit provided): Delegate to built-in read tool | ||
| 4. **Large files:** | ||
| - Call built-in read for the first chunk | ||
@@ -165,0 +166,0 @@ - Detect language from file extension |
+60
-1
@@ -13,3 +13,3 @@ import type { ExtensionAPI, Theme } from "@mariozechner/pi-coding-agent"; | ||
| import { stat } from "node:fs/promises"; | ||
| import { basename, resolve } from "node:path"; | ||
| import { basename, extname, resolve } from "node:path"; | ||
| import { promisify } from "node:util"; | ||
@@ -26,2 +26,56 @@ | ||
| /** | ||
| * File extensions that are binary/image files and should be | ||
| * delegated directly to the built-in read tool without map generation. | ||
| */ | ||
| const BINARY_EXTENSIONS = new Set([ | ||
| ".jpg", | ||
| ".jpeg", | ||
| ".png", | ||
| ".gif", | ||
| ".webp", | ||
| ".bmp", | ||
| ".ico", | ||
| ".tiff", | ||
| ".tif", | ||
| ".svg", | ||
| ".avif", | ||
| ".heic", | ||
| ".heif", | ||
| // Audio/video | ||
| ".mp3", | ||
| ".mp4", | ||
| ".wav", | ||
| ".avi", | ||
| ".mov", | ||
| ".mkv", | ||
| ".flac", | ||
| ".ogg", | ||
| ".webm", | ||
| // Archives | ||
| ".zip", | ||
| ".tar", | ||
| ".gz", | ||
| ".bz2", | ||
| ".xz", | ||
| ".7z", | ||
| ".rar", | ||
| // Binary data | ||
| ".bin", | ||
| ".exe", | ||
| ".dll", | ||
| ".so", | ||
| ".dylib", | ||
| ".o", | ||
| ".a", | ||
| ".wasm", | ||
| ".pdf", | ||
| ".doc", | ||
| ".docx", | ||
| ".xls", | ||
| ".xlsx", | ||
| ".ppt", | ||
| ".pptx", | ||
| ]); | ||
| // In-memory cache for maps | ||
@@ -262,2 +316,7 @@ const mapCache = new Map<string, { mtime: number; map: string }>(); | ||
| // Skip binary/image files — delegate directly without map generation | ||
| if (BINARY_EXTENSIONS.has(extname(absPath).toLowerCase())) { | ||
| return builtInRead.execute(toolCallId, params, signal, onUpdate); | ||
| } | ||
| // Check file size and line count | ||
@@ -264,0 +323,0 @@ let stats; |
@@ -144,2 +144,7 @@ import { exec } from "node:child_process"; | ||
| // No symbols found — nothing useful to map | ||
| if (symbols.length === 0) { | ||
| return null; | ||
| } | ||
| // Get language info | ||
@@ -146,0 +151,0 @@ const langInfo = detectLanguage(filePath); |
215042
0.82%6826
0.9%201
0.5%