@intentic/claude-plugin 1.322.0 → 1.323.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/.claude-plugin/plugin.json +1 -1
- package/dist/fileq.mjs +34 -16
- package/generated/skills/fileq/SKILL.md +4 -3
- package/package.json +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intentic",
|
|
3
3
|
"displayName": "Intentic",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.323.0",
|
|
5
5
|
"description": "Cheaper, sharper Claude Code sessions: Bash output trimmed before Claude reads it, a project map and this project's field notes at session start, iq code search and fileq document reading taught, and /intentic:stats to show what each one saved. Every mechanism is a switch in /config.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "intentic"
|
package/dist/fileq.mjs
CHANGED
|
@@ -87118,8 +87118,8 @@ var require_body_reader = __commonJS({
|
|
|
87118
87118
|
if (checkboxResult) {
|
|
87119
87119
|
var checkboxElement = fldChar.firstOrEmpty("w:ffData").firstOrEmpty("w:checkBox");
|
|
87120
87120
|
var checkedElement = checkboxElement.first("w:checked");
|
|
87121
|
-
var
|
|
87122
|
-
return { type: "checkbox", checked };
|
|
87121
|
+
var checked2 = checkedElement == null ? readBooleanElement(checkboxElement.first("w:default")) : readBooleanElement(checkedElement);
|
|
87122
|
+
return { type: "checkbox", checked: checked2 };
|
|
87123
87123
|
}
|
|
87124
87124
|
return { type: "unknown" };
|
|
87125
87125
|
}
|
|
@@ -105433,12 +105433,12 @@ var init_pdf_furniture = __esm({
|
|
|
105433
105433
|
});
|
|
105434
105434
|
|
|
105435
105435
|
// ../fileq/src/lib/derivers/pdf.ts
|
|
105436
|
-
import { execFile as execFile2 } from "node:child_process";
|
|
105436
|
+
import { execFile as execFile2, spawnSync } from "node:child_process";
|
|
105437
105437
|
import { mkdtemp, readdir, readFile as readFile10, rm } from "node:fs/promises";
|
|
105438
105438
|
import { tmpdir } from "node:os";
|
|
105439
105439
|
import { join as join3 } from "node:path";
|
|
105440
105440
|
import { promisify as promisify2 } from "node:util";
|
|
105441
|
-
var SCAN_THRESHOLD_CHARS_PER_PAGE, MAX_OCR_PAGES, OCR_DPI, run3, ocrAvailable, recognisePages, pagesToMarkdown, furnitureNotes, withoutFurniture, pdfDeriver;
|
|
105441
|
+
var SCAN_THRESHOLD_CHARS_PER_PAGE, MAX_OCR_PAGES, OCR_DPI, OCR_TIMEOUT_MS, run3, checked, ocrAvailable, readPages, recognisePages, pagesToMarkdown, furnitureNotes, withoutFurniture, pdfDeriver;
|
|
105442
105442
|
var init_pdf = __esm({
|
|
105443
105443
|
"../fileq/src/lib/derivers/pdf.ts"() {
|
|
105444
105444
|
"use strict";
|
|
@@ -105448,8 +105448,27 @@ var init_pdf = __esm({
|
|
|
105448
105448
|
SCAN_THRESHOLD_CHARS_PER_PAGE = 24;
|
|
105449
105449
|
MAX_OCR_PAGES = 20;
|
|
105450
105450
|
OCR_DPI = "200";
|
|
105451
|
+
OCR_TIMEOUT_MS = 6e4 + MAX_OCR_PAGES * 15e3;
|
|
105451
105452
|
run3 = promisify2(execFile2);
|
|
105452
|
-
|
|
105453
|
+
checked = /* @__PURE__ */ new Map();
|
|
105454
|
+
ocrAvailable = () => {
|
|
105455
|
+
const path = process.env["PATH"] ?? "";
|
|
105456
|
+
let available = checked.get(path);
|
|
105457
|
+
if (available === void 0) {
|
|
105458
|
+
available = onPath("pdftoppm") && onPath("ocr") && spawnSync("ocr", ["--check"], { stdio: "ignore", timeout: 1e4 }).status === 0;
|
|
105459
|
+
checked.set(path, available);
|
|
105460
|
+
}
|
|
105461
|
+
return available;
|
|
105462
|
+
};
|
|
105463
|
+
readPages = (images) => new Promise((resolve6, reject) => {
|
|
105464
|
+
execFile2("ocr", [...images], { timeout: OCR_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024 }, (error2, stdout) => {
|
|
105465
|
+
if (error2 === null || error2.code === 1) {
|
|
105466
|
+
resolve6(stdout);
|
|
105467
|
+
} else {
|
|
105468
|
+
reject(error2);
|
|
105469
|
+
}
|
|
105470
|
+
});
|
|
105471
|
+
});
|
|
105453
105472
|
recognisePages = async (absPath, totalPages) => {
|
|
105454
105473
|
const dir = await mkdtemp(join3(tmpdir(), "fileq-ocr-"));
|
|
105455
105474
|
try {
|
|
@@ -105457,12 +105476,11 @@ var init_pdf = __esm({
|
|
|
105457
105476
|
timeout: 12e4
|
|
105458
105477
|
});
|
|
105459
105478
|
const images = (await readdir(dir)).filter((name) => name.endsWith(".png")).toSorted();
|
|
105460
|
-
|
|
105461
|
-
|
|
105462
|
-
const { stdout } = await run3("tesseract", [join3(dir, image), "stdout", "-l", "eng"], { timeout: 12e4, maxBuffer: 16 * 1024 * 1024 });
|
|
105463
|
-
pages.push(stdout.replaceAll(/[ \t]+/g, " ").trim());
|
|
105479
|
+
if (images.length === 0) {
|
|
105480
|
+
return [];
|
|
105464
105481
|
}
|
|
105465
|
-
|
|
105482
|
+
const pages = (await readPages(images.map((image) => join3(dir, image)))).split("\f");
|
|
105483
|
+
return images.map((_3, index) => (pages[index] ?? "").replaceAll(/[ \t]+/g, " ").trim());
|
|
105466
105484
|
} finally {
|
|
105467
105485
|
await rm(dir, { recursive: true, force: true });
|
|
105468
105486
|
}
|
|
@@ -105478,11 +105496,11 @@ ${page === "" ? "(no text on this page)" : page}`).join("\n\n");
|
|
|
105478
105496
|
return { markdown: pagesToMarkdown(kept), notes: furnitureNotes(removed, example) };
|
|
105479
105497
|
};
|
|
105480
105498
|
pdfDeriver = {
|
|
105481
|
-
// The stamp names OCR capability, since a sidecar written before
|
|
105482
|
-
// that it's here.
|
|
105483
|
-
//
|
|
105499
|
+
// The stamp names OCR capability, since a sidecar written before the reader was available must read as stale now
|
|
105500
|
+
// that it's here. A static name would leave a pre-OCR sidecar looking current forever. It names the reader too:
|
|
105501
|
+
// `pdf+ocr` was tesseract's, whose pages PaddleOCR reads again.
|
|
105484
105502
|
get name() {
|
|
105485
|
-
return ocrAvailable() ? "pdf+
|
|
105503
|
+
return ocrAvailable() ? "pdf+ppocr" : "pdf";
|
|
105486
105504
|
},
|
|
105487
105505
|
version: 2,
|
|
105488
105506
|
derive: async (absPath) => {
|
|
@@ -105504,10 +105522,10 @@ ${page === "" ? "(no text on this page)" : page}`).join("\n\n");
|
|
|
105504
105522
|
}
|
|
105505
105523
|
const recognised = await recognisePages(absPath, totalPages);
|
|
105506
105524
|
const notes = [
|
|
105507
|
-
`scanned: text recognised by OCR (
|
|
105525
|
+
`scanned: text recognised by OCR (PaddleOCR) on ${recognised.length} of ${totalPages} page${plural3} \u2014 recognised, not exact; check figures against the page image`
|
|
105508
105526
|
];
|
|
105509
105527
|
if (totalPages > MAX_OCR_PAGES) {
|
|
105510
|
-
notes.push(`OCR stops at ${MAX_OCR_PAGES} pages:
|
|
105528
|
+
notes.push(`OCR stops at ${MAX_OCR_PAGES} pages: draw the rest with pdftoppm and read them with \`ocr <page.png>...\` if they matter`);
|
|
105511
105529
|
}
|
|
105512
105530
|
const { markdown, notes: stripped } = withoutFurniture(recognised);
|
|
105513
105531
|
return { markdown, title, notes: [...notes, ...stripped] };
|
|
@@ -13,7 +13,7 @@ cached by content, so a repeat read of unchanged content is instant.
|
|
|
13
13
|
- Prints a capsule (format, token cost), the content up to the budget, and `saved:` — the markdown file
|
|
14
14
|
carrying the whole thing. Over budget, the cut is announced with that exact path to Read.
|
|
15
15
|
- Formats: docx and odt (headings, lists, tables), xlsx (capped tables), pptx (slides + speaker notes),
|
|
16
|
-
pdf (text layer; a scan is OCR'd when `
|
|
16
|
+
pdf (text layer; a scan is OCR'd when an `ocr` command is on PATH, and the note says the words are
|
|
17
17
|
recognised, not exact), epub (chapters in reading order), ipynb (cells, fenced code, capped outputs),
|
|
18
18
|
png/jpg/gif/webp (dimensions + EXIF), mp3/wav/flac/mp4/… (duration + tags), html, and V8 profiles
|
|
19
19
|
(`.cpuprofile` from `node --cpu-prof`, `.heapprofile` from `--heap-prof`) as functions ranked by self and total cost.
|
|
@@ -29,9 +29,10 @@ without parsing it again. Run it again rather than opening a sidecar under `.int
|
|
|
29
29
|
checks the hash for you.
|
|
30
30
|
|
|
31
31
|
## What it refuses, and why
|
|
32
|
-
- A scanned PDF with no `
|
|
32
|
+
- A scanned PDF with no `ocr` on PATH answers "no usable text layer … OCR is not part of this tier"
|
|
33
33
|
rather than an empty page; images say "no visual description". Treat those notes as "not generated",
|
|
34
|
-
never as "nothing there".
|
|
34
|
+
never as "nothing there". An `ocr` command that prints each image's text, a form feed between images (the
|
|
35
|
+
Intentic sandbox's PaddleOCR reader), turns the first into OCR.
|
|
35
36
|
- Plain text (md, csv, txt, code) is not fileq's business: Read it directly — but see below for the big ones.
|
|
36
37
|
- Web pages belong to `webq`; images for a vision model belong to the Read tool, which shows the pixels.
|
|
37
38
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentic/claude-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.323.0",
|
|
4
4
|
"description": "The intentic Claude Code plugin: trimmed Bash output, a project map and field notes at session start, iq search and fileq teaching, and a /intentic:stats report of what each saved",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@intentic/agent-context": "0.0.0",
|
|
43
|
-
"@intentic/fileq": "1.
|
|
44
|
-
"@intentic/iq": "1.
|
|
43
|
+
"@intentic/fileq": "1.323.0",
|
|
44
|
+
"@intentic/iq": "1.323.0",
|
|
45
45
|
"@intentic/output-cleaners": "0.0.0",
|
|
46
46
|
"@intentic/testing": "0.0.0",
|
|
47
47
|
"@intentic/tsconfig": "0.0.0",
|