Skip to content

History / MarkItDown Sidecar

Revisions

  • 📝 docs(markitdown): clarify universal chunk drawer routing State that filename and card clicks open the chunk drawer for every file, while unsupported formats still receive the explanatory empty state.

    @lqdflying lqdflying committed Aug 8, 2026
  • 📝 docs(knowledge): document universal chunk drawer

    @lqdflying lqdflying committed Aug 8, 2026
  • 📝 docs(markitdown): restore chunk provenance sentence Restore the sentence subject after the bounded-table explanation so the chunk viewer documentation reads correctly.

    @lqdflying lqdflying committed Aug 8, 2026
  • 📝 docs(knowledge): document bounded chunk drawer tables Explain bounded Markdown table pages, capability-aware Office empty states, and the provenance-only chunk metadata contract.

    @lqdflying lqdflying committed Aug 8, 2026
  • 📝 docs(knowledge): document chunk drawer pagination Document Markdown-rendered per-chunk navigation, Office zero-chunk parsing, and the re-parse requirement for existing malformed tables.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): per-file MarkItDown icon + content-only chunk viewer Document the new MarkItDown file-row action (re-parse via MarkItDown + open converted content) and that the chunk drawer is now a content-only viewer — Office documents no longer preview via Office Online, and clicking an Office file's name opens the converted-content viewer once chunked.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): document in-UI re-parse action and chunk provenance badge The Verify section now describes the portal affordances instead of implying provenance is only visible via raw metadata: the Chunks tag opens the drawer, each chunk shows a MarkItDown/LangChain provenance badge, clicking a chunk opens a detail modal with converted_by/type, and historical files can be re-chunked via the file row's "Re-parse chunks" action (which routes through the sidecar once MARKITDOWN_SERVICE_URL is set).

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): fix LLM base URL wording, drop output-equivalence claim, distinguish image description from OCR Three wording corrections after d6391d8: - LLM_BASE_URL: "custom or non-OpenAI endpoint that exposes an OpenAI-compatible API" (3 spots: env example, feature table, build-time env block). The old "non-OpenAI-compatible endpoint" was self-contradictory — the openai SDK only talks to OpenAI-compatible APIs. Confirmed against server.py docstring which already calls it an "OpenAI-compatible endpoint". - Alternative images: drop "handles every native-text format identically — verified by importing every converter". Converter imports prove availability, not output equivalence. Replaced with "supports the same native-text input formats" plus a fixture-validation note. - What-it-adds image row: "EXIF metadata, plus an LLM-generated description when configured; OCR is available separately through supported Azure paths" — separates the built-in ImageConverter's description from OCR.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): clarify LLM base URL conditionality and split captioning from OCR plugin Three wording corrections after the structural redesign: - markitdown.env comment: MARKITDOWN_LLM_BASE_URL is set only for a non-OpenAI-compatible endpoint; API_KEY + MODEL are the required pair. - Conditional feature groups: split the bundled "LLM vision" row into standalone image captioning (built-in ImageConverter, no plugin) and the OCR plugin (needs ENABLE_PLUGINS + INSTALL_OCR_PLUGIN). Standalone captioning never required ENABLE_PLUGINS. - markitdown-ocr plugin scope: it registers converters for PDF/DOCX/PPTX/XLSX only, not standalone PNG/JPEG. Confirmed against upstream pyproject.toml (v0.1.7): description lists PDF, DOCX, PPTX, XLSX; no standalone image format in keywords. Standalone images go through the built-in ImageConverter, which uses the same llm_client without plugins.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): redesign page structure — unified Quick start, env_file compose Consolidates the two parallel "Run" flows (prebuilt + build) that had grown to duplicate topology, verify, and ChatHub-wiring sections into one Quick start with a shared markitdown.env and two options (A pull, B build). Moves the build-path docker-compose.yml to env_file: so it matches the prebuilt one and ChatHub's component-scoped env convention — no inline environment: block remains. Gathers all ChatHub-side wiring into a single Connect ChatHub section. No factual changes; same HTTP contract, same OCR coverage, same Dockerfile/requirements/server.py.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): apply review corrections — plugin enablement, recipe scope, Azure boundary, output, reproducibility Five review findings, all verified against the markitdown v0.1.7 source and the running production image before applying. 1. Plugin enablement needs MARKITDOWN_ENABLE_PLUGINS=true, not just the build arg. MarkItDown loads entry points only when enable_plugins=True, and the sidecar defaults MARKITDOWN_ENABLE_PLUGINS to false. Building with INSTALL_OCR_PLUGIN=true without the runtime flag leaves the markitdown-ocr entry point unregistered. The full LLM-OCR path needs all three: INSTALL_OCR_PLUGIN=true + MARKITDOWN_ENABLE_PLUGINS=true + MARKITDOWN_LLM_*. Corrected in Build-time only and OCR for scanned documents and pictures. 2. INSTALL_OCR_PLUGIN is Debian-recipe only. The current prebuilt Wolfi image does not define or consume it, so "off by default on every recipe" was too broad. The component table now has separate Debian and Wolfi columns, and the intro notes the Wolfi recipe must be extended before the arg can be used. Verified from the image's docker history. 3. Azure Document Intelligence is not equivalent to markitdown-ocr for embedded Office images. In markitdown v0.1.7 the DocumentIntelligenceFileType enum marks DOCX/PPTX/XLSX/HTML as "# No OCR" and PDF/JPEG/PNG/BMP/TIFF as "# OCR", so Azure runs Office formats without OCRing their embedded images. Reworded the Azure path to state the boundary; noted Content Understanding is a separate path, not identical to Document Intelligence. Verified from converters/_doc_intel_converter.py. 4. Scanned PDFs return empty Markdown, not EXIF. EXIF metadata is an image-input concept (exiftool converter); PDFs go through text extractors which return empty for image-only pages. Distinguished the two cases with the verified {"chars":0,"markdown":"","title":null} output for an image-only PDF. 5. Reproducibility and compatibility claims softened. Removed "unpinning produces a working image", "converts files identically", and "pin for byte-for-byte output" — upgrades may change behaviour and top-level pins do not guarantee reproducibility. Replacement states upgrades are supported but require HTTP-contract tests, conversion fixtures, and a fresh CVE scan; true reproducibility needs a full lock, pinned base-image digest, pinned upstream revision, and controlled build environment. Confirmed-correct conclusions left in place: native-text completeness, no LLM/Azure needed for basic conversion, text-PDFs-with-images supported, image contents ignorable, markitdown-ocr optional not missing, PyMuPDF is a renderer not the OCR engine.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): correct OCR architecture — LLM vision is the engine, PyMuPDF only renders The page conflated PyMuPDF/fitz with the OCR capability, implying the library itself does the OCR. Per the markitdown-ocr source at v0.1.7, PyMuPDF is only a page-rendering dependency (and only a fallback after pdfplumber); the actual OCR engine is the OpenAI-compatible vision LLM configured at runtime via MARKITDOWN_LLM_*. The package's own description is "Extracts text from images in PDF, DOCX, PPTX, and XLSX via LLM Vision," and its OCR service class is LLMVisionOCRService, which base64-encodes a page image and sends it to a chat.completions.create vision call. Practical consequence: building with INSTALL_OCR_PLUGIN=true but leaving MARKITDOWN_LLM_* unset produces no OCR — there is no engine to call. The plugin needs both the build arg and the runtime LLM config to function. - Size-table note: reworded from "pulls PyMuPDF" to "adds the markitdown-ocr plugin, including its PyMuPDF rendering dependency." - Component table OCR row: "the LLM vision model is the OCR engine, PyMuPDF only renders pages." - Dockerfile comment: same correction inside the code block. - Build-time only section: state explicitly that the plugin needs BOTH the build arg and runtime MARKITDOWN_LLM_*, and that standalone image captioning works via MARKITDOWN_LLM_* alone (no plugin needed). - Plugin probe: import markitdown_ocr, not pymupdf — PyMuPDF is a transitive rendering dep and is the wrong thing to test for plugin presence. Verified the probe against an image built without the plugin: the import traceback is the expected "not baked in" signal.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): reframe OCR/picture handling as optional, not a gap The page framed scanned-PDF / picture OCR as a "caveat" and a "gap" of alternative images, which reads as a deficiency. It is an optional feature: off by default on every recipe (Debian ARG default, Compose args default), and the only input class any default build does not handle. Deployments that never ingest scanned or picture-only input — the common case — can ignore it entirely and the sidecar is complete as built. - Reframe the size-table paragraph: the OCR plugin is "an optional feature, not something any default build ships," with a forward link instead of warning about a shared gap. - Rename "What's not in alternative images (and the default Debian build)" to "Alternative images (Chainguard Wolfi, multi-stage, prebuilt, CVE-pinned)". Drop the caveat/gap language; keep the component-presence table but reword the OCR row as "optional — off by default on every recipe" and mark the runtime opt-in rows (image captioning, Azure OCR) accordingly. - Rename "Scanned documents" to "OCR for scanned documents and pictures" (matches the two intro link anchors) and lead with "this is an optional capability: if your deployment never ingests scanned or picture-only input, you can ignore this section entirely and the sidecar is complete as built." - Reword "Build-time only" to consistent optional framing.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): correct OCR-plugin attribution — it is opt-in everywhere The previous round implied the OCR plugin (markitdown-ocr / PyMuPDF) ships in the documented Debian build but is absent from alternative recipes. The Dockerfile ARG default and the Compose args value are both INSTALL_OCR_PLUGIN=false, so the wiki's own `docker compose up -d --build` omits the plugin too. A default-args alternative image (e.g. img.aksg.net/markitdown/markitdown:0.1.7) is missing nothing the default Debian build has — only an explicit INSTALL_OCR_PLUGIN=true rebuild adds the plugin on either side. - Fix the size table: ~1.07 GB is the default-args Debian build, the INSTALL_OCR_PLUGIN=true variant is ~80 MB heavier (~1.15 GB), and state explicitly that the plugin is off by default in both the ARG and the Compose. - Reword "What's not in alternative images" to "What's not in alternative images (and the default Debian build)" so the gap is correctly attributed to the opt-in plugin across all recipes, not to the choice of base image. Same recovery paths (AZURE_DOC_INTEL_ENDPOINT, or INSTALL_OCR_PLUGIN=true rebuild).

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): cover alternative recipes and the OCR-plugin caveat The page documented one Debian build and one 1.07 GB size, so readers using a prebuilt / Chainguard-Wolfi / multi-stage image (e.g. img.aksg.net/markitdown/markitdown:0.1.7, 732 MB, 0 CVE) had no guidance for what to expect and no explanation for the size gap. Recipes that pin deps to patched versions for CVE hygiene were also left implicit. - Replace the single-row size table with a range across recipes, and a sentence attributing the gap to base image and INSTALL_OCR_PLUGIN. - Note on requirements.txt that the pins are for reproducibility, not correctness — the HTTP wire format is stable across these minor versions, so unpinning for CVE hygiene produces a working image. Verified against an image that resolved fastapi to 0.141.1, openai to 1.68.2: every markitdown[all] converter imports, multipart upload semantics are unchanged. - Add a "What's not in alternative images" subsection under Run a prebuilt image, listing what a Chainguard-Wolfi / multi-stage build leaves out: only the markitdown-ocr plugin (PyMuPDF). Native-text converters, audio, image captioning and Azure OCR are all present. Scanned-PDF OCR is the sole gap, with two recovery paths (AZURE_DOC_INTEL_ENDPOINT, or rebuild with INSTALL_OCR_PLUGIN=true) and a one-line probe for the plugin.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): split mandatory from optional, add prebuilt-image path Readers with a built image (e.g. img.aksg.net/markitdown/markitdown:0.1.7) had to translate the build-path Compose to remove `build:` themselves, and the env table did not separate the truly-required vars (an API key when the port is exposed past loopback) from overrides. Mirror ChatHub's component-scoped env convention: the sidecar's vars go in markitdown.env loaded with env_file:, ChatHub's own MARKITDOWN_* vars stay in its existing .env next to its compose, so each component owns its env and the compose carries no secrets. - Add a Run a prebuilt image section with the env file template split into Mandatory / Non-mandatory / Optional feature groups, the prebuilt Compose, network topology, ChatHub-side wiring and verification steps. - Restructure Configure it into Mandatory (only MARKITDOWN_API_KEY, gated on network exposure), Conditional feature groups (set each fully or not at all), Non-mandatory (built-in defaults), Build-time only (INSTALL_OCR_PLUGIN is a Docker arg, not an env), and a dedicated ChatHub-side vars table covering MARKITDOWN_SERVICE_URL/API_KEY/ MAX_FILE_SIZE/TIMEOUT. No code, runtime or test change; build path and HTTP contract unchanged.

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): harden the sidecar and complete the Compose pass-through Review fixes for the page's embedded files, applied here since the page is the sidecar's only home: - server.py no longer reads the whole upload into memory before checking MARKITDOWN_MAX_FILE_SIZE. A middleware rejects a declared-oversize body before the form parser spools it, and /convert reads the spooled file in 1 MiB pieces, refusing once the cap is passed — so the cap now actually bounds memory, and a body with a lying or absent Content-Length is caught too. - The bearer-token check uses secrets.compare_digest over bytes: constant-time, and immune to the TypeError the str form raises on non-ASCII input. - docker-compose.yml now passes through MARKITDOWN_LOG_LEVEL, MARKITDOWN_LLM_PROMPT and AZURE_CU_ANALYZER_ID, which the Configure-it table documents but the container never received; the log level also survives an empty-string value now. - The HTTP-contract note no longer claims every error falls back to the built-in loaders: a FILE_TYPE_CHUNKING_RULES entry that pins a format to markitdown alone surfaces its errors directly, and the sidecar's reason reaches the surfaced error only when the fallback also fails. Wire contract unchanged: same endpoints, fields and status codes. Verified by extracting the four blocks, building the image and driving it live: csv converts with auth (200); wrong/missing/non-ASCII token all 401; a 500 KB upload over a 100 KB cap 413s from the bounded read; a 2 MB upload 413s from the middleware before parsing; empty upload 400; unknown format 415. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

    @lqdflying lqdflying committed Aug 7, 2026
  • 📝 docs(markitdown): add the sidecar as a supplementary page The sidecar's build files were removed from the main repository, where they were Python clutter that no CI workflow built and no ChatHub image shipped. Carry them here instead, so the sidecar stays rebuildable without a checkout. MarkItDown-Sidecar.md holds the Dockerfile, requirements.txt, server.py and docker-compose.yml verbatim, plus how to build, run and update it, the format table, the configuration reference, the OCR guidance and the security notes. Two additions the old in-repo README did not have: - An HTTP contract section. src/libs/markitdown/index.ts depends on the wire format, and nothing in the ChatHub repository tests the server side — the client's suite mocks fetch and the chunking suite mocks the client — so either side can change and every test still passes. Documented as frozen, next to the code it constrains. - A note that the format table is the authority for MARKITDOWN_EXTENSIONS in packages/utils/src/isChunkableFile.ts, which drives the upload picker. Also re-point Knowledge-Base-and-RAG.md at this page in place of the deleted docker/markitdown/README.md, including the compose command that no longer resolves, and add the page to the sidebar after Knowledge Base and RAG. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

    @lqdflying lqdflying committed Aug 6, 2026