mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(tools): 2.0 phase 5 wave 2 - pdf depth (21 tools) (#220)
This commit is contained in:
@@ -9,3 +9,113 @@ export async function pdfPageCountPy(absPath: string): Promise<number> {
|
||||
}
|
||||
return parsed.pages;
|
||||
}
|
||||
|
||||
/** Flatten forms/annotations into page content (PyMuPDF bake). */
|
||||
export async function pdfFlattenPy(inPath: string, outPath: string): Promise<void> {
|
||||
const stdout = await runDocsScript("doc_flatten", { path: inPath, out: outPath });
|
||||
const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_flatten failed: ${parsed.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** True redaction with verification pass (PyMuPDF search + apply_redactions). */
|
||||
export async function pdfRedactPy(
|
||||
inPath: string,
|
||||
outPath: string,
|
||||
terms: string[],
|
||||
caseSensitive: boolean,
|
||||
): Promise<{ found: number }> {
|
||||
const stdout = await runDocsScript("doc_redact", {
|
||||
path: inPath,
|
||||
out: outPath,
|
||||
terms,
|
||||
caseSensitive,
|
||||
});
|
||||
const parsed = JSON.parse(stdout.trim()) as {
|
||||
found?: number;
|
||||
verified?: boolean;
|
||||
error?: string;
|
||||
};
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_redact failed: ${parsed.error}`);
|
||||
}
|
||||
if (typeof parsed.found !== "number") {
|
||||
throw new Error(`doc_redact failed: ${stdout.slice(0, 200)}`);
|
||||
}
|
||||
return { found: parsed.found };
|
||||
}
|
||||
|
||||
/** Extract plain text from a PDF (PyMuPDF get_text). */
|
||||
export async function pdfTextPy(inPath: string, outTxtPath: string): Promise<{ chars: number }> {
|
||||
const stdout = await runDocsScript("doc_text", { path: inPath, out: outTxtPath });
|
||||
const parsed = JSON.parse(stdout.trim()) as { chars?: number; error?: string };
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_text failed: ${parsed.error}`);
|
||||
}
|
||||
if (typeof parsed.chars !== "number") {
|
||||
throw new Error(`doc_text failed: ${stdout.slice(0, 200)}`);
|
||||
}
|
||||
return { chars: parsed.chars };
|
||||
}
|
||||
|
||||
/** PDF to DOCX conversion (pdf2docx). Long-running: 5 min timeout. */
|
||||
export async function pdfToWordPy(inPath: string, outPath: string): Promise<void> {
|
||||
const stdout = await runDocsScript(
|
||||
"doc_to_word",
|
||||
{ path: inPath, out: outPath },
|
||||
{ timeoutMs: 300_000 },
|
||||
);
|
||||
const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_to_word failed: ${parsed.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** Read PDF document metadata (pikepdf docinfo). */
|
||||
export async function pdfMetadataGetPy(inPath: string): Promise<Record<string, string>> {
|
||||
const stdout = await runDocsScript("doc_metadata", { path: inPath, mode: "get" });
|
||||
const parsed = JSON.parse(stdout.trim()) as { metadata?: Record<string, string>; error?: string };
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_metadata get failed: ${parsed.error}`);
|
||||
}
|
||||
if (!parsed.metadata || typeof parsed.metadata !== "object") {
|
||||
throw new Error(`doc_metadata get failed: ${stdout.slice(0, 200)}`);
|
||||
}
|
||||
return parsed.metadata;
|
||||
}
|
||||
|
||||
/** Write PDF document metadata (pikepdf docinfo). */
|
||||
export async function pdfMetadataSetPy(
|
||||
inPath: string,
|
||||
outPath: string,
|
||||
metadata: Record<string, string>,
|
||||
): Promise<void> {
|
||||
const stdout = await runDocsScript("doc_metadata", {
|
||||
path: inPath,
|
||||
out: outPath,
|
||||
mode: "set",
|
||||
metadata,
|
||||
});
|
||||
const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_metadata set failed: ${parsed.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** HTML or Markdown to PDF (WeasyPrint, SSRF-hardened). 2 min timeout. */
|
||||
export async function htmlToPdfPy(
|
||||
inPath: string,
|
||||
outPath: string,
|
||||
mode: "html" | "markdown",
|
||||
): Promise<void> {
|
||||
const stdout = await runDocsScript(
|
||||
"doc_html_pdf",
|
||||
{ path: inPath, out: outPath, mode },
|
||||
{ timeoutMs: 120_000 },
|
||||
);
|
||||
const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
|
||||
if (parsed.error) {
|
||||
throw new Error(`doc_html_pdf failed: ${parsed.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user