import { readFile, writeFile, unlink } from "fs/promises"; import { join } from "path"; import { tmpdir } from "os"; import { GlmOcrResponse } from "../types"; import RemarkablePlugin from "../main"; import { runCommand } from "../utils/process"; export class GlmOcrClient { plugin: RemarkablePlugin; constructor(plugin: RemarkablePlugin) { this.plugin = plugin; } async parseImages(pngPaths: string[]): Promise { const url = `${this.plugin.settings.glmocrServerUrl}/glmocr/parse`; const apiKey = this.plugin.settings.glmocrApiKey; const images: string[] = []; for (const pngPath of pngPaths) { const data = await readFile(pngPath); images.push(`data:image/png;base64,${data.toString("base64")}`); } const bodyPath = join(tmpdir(), `glmocr-body-${Date.now()}.json`); await writeFile(bodyPath, JSON.stringify({ images })); try { const args = [ "-s", "-X", "POST", "-H", "Content-Type: application/json", "-H", `Authorization: Bearer ${apiKey}`, "--max-time", "60", "--data-binary", `@${bodyPath}`, url, ]; const { stdout, stderr, code } = await runCommand("curl", args); if (code !== 0) { throw new Error(`GLM-OCR request failed: ${stderr || stdout}`); } try { return JSON.parse(stdout) as GlmOcrResponse; } catch (e) { throw new Error(`Failed to parse GLM-OCR response: ${e}\nRaw: ${stdout}`); } } finally { await unlink(bodyPath).catch(() => {}); } } }