docline 0.1.0__tar.gz
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.
- docline-0.1.0/LICENSE +21 -0
- docline-0.1.0/PKG-INFO +277 -0
- docline-0.1.0/README.md +253 -0
- docline-0.1.0/pyproject.toml +57 -0
- docline-0.1.0/setup.cfg +4 -0
- docline-0.1.0/src/docline/__init__.py +1 -0
- docline-0.1.0/src/docline/__main__.py +16 -0
- docline-0.1.0/src/docline/_tools/__init__.py +9 -0
- docline-0.1.0/src/docline/_tools/docling_worker.py +404 -0
- docline-0.1.0/src/docline/app.py +1048 -0
- docline-0.1.0/src/docline/app_models.py +201 -0
- docline-0.1.0/src/docline/cli.py +595 -0
- docline-0.1.0/src/docline/config.py +57 -0
- docline-0.1.0/src/docline/dependencies.py +86 -0
- docline-0.1.0/src/docline/elt/__init__.py +1 -0
- docline-0.1.0/src/docline/elt/config.py +202 -0
- docline-0.1.0/src/docline/elt/execute.py +608 -0
- docline-0.1.0/src/docline/elt/manifest_models.py +93 -0
- docline-0.1.0/src/docline/elt/models.py +82 -0
- docline-0.1.0/src/docline/elt/orchestrate.py +47 -0
- docline-0.1.0/src/docline/elt/paths.py +74 -0
- docline-0.1.0/src/docline/elt/source_keys.py +79 -0
- docline-0.1.0/src/docline/fetch/__init__.py +0 -0
- docline-0.1.0/src/docline/fetch/crawl.py +557 -0
- docline-0.1.0/src/docline/fetch/html_extract.py +290 -0
- docline-0.1.0/src/docline/fetch/html_normalize.py +92 -0
- docline-0.1.0/src/docline/fetch/http.py +159 -0
- docline-0.1.0/src/docline/fetch/models.py +43 -0
- docline-0.1.0/src/docline/fetch/sitemap.py +272 -0
- docline-0.1.0/src/docline/fetch/staging.py +166 -0
- docline-0.1.0/src/docline/fetch/url_canonical.py +127 -0
- docline-0.1.0/src/docline/fetch/url_policy.py +92 -0
- docline-0.1.0/src/docline/mcp/__init__.py +1 -0
- docline-0.1.0/src/docline/mcp/exceptions.py +7 -0
- docline-0.1.0/src/docline/mcp/server.py +113 -0
- docline-0.1.0/src/docline/paths.py +145 -0
- docline-0.1.0/src/docline/process/__init__.py +5 -0
- docline-0.1.0/src/docline/process/assemble.py +162 -0
- docline-0.1.0/src/docline/process/ast_lint.py +65 -0
- docline-0.1.0/src/docline/process/batch_dispatch.py +243 -0
- docline-0.1.0/src/docline/process/canonical_url.py +149 -0
- docline-0.1.0/src/docline/process/correction.py +62 -0
- docline-0.1.0/src/docline/process/cross_doc_links.py +179 -0
- docline-0.1.0/src/docline/process/docfx_includes.py +126 -0
- docline-0.1.0/src/docline/process/docfx_normalize.py +144 -0
- docline-0.1.0/src/docline/process/docfx_tabs.py +105 -0
- docline-0.1.0/src/docline/process/fidelity_scorer.py +870 -0
- docline-0.1.0/src/docline/process/hashing.py +22 -0
- docline-0.1.0/src/docline/process/heading_validation.py +241 -0
- docline-0.1.0/src/docline/process/identity.py +37 -0
- docline-0.1.0/src/docline/process/manifest.py +84 -0
- docline-0.1.0/src/docline/process/metadata.py +86 -0
- docline-0.1.0/src/docline/process/ocr_cap.py +99 -0
- docline-0.1.0/src/docline/process/output.py +25 -0
- docline-0.1.0/src/docline/process/output_contract.py +449 -0
- docline-0.1.0/src/docline/process/page_range.py +199 -0
- docline-0.1.0/src/docline/process/pdf_batch.py +568 -0
- docline-0.1.0/src/docline/process/pdf_triage.py +1114 -0
- docline-0.1.0/src/docline/process/prompts.py +57 -0
- docline-0.1.0/src/docline/process/quality_metrics.py +213 -0
- docline-0.1.0/src/docline/process/quarantine.py +66 -0
- docline-0.1.0/src/docline/process/segment.py +211 -0
- docline-0.1.0/src/docline/process/toc_parser.py +122 -0
- docline-0.1.0/src/docline/process/transcripts.py +134 -0
- docline-0.1.0/src/docline/progress.py +279 -0
- docline-0.1.0/src/docline/quarantine_viewer.py +125 -0
- docline-0.1.0/src/docline/readers/__init__.py +1 -0
- docline-0.1.0/src/docline/readers/documents.py +54 -0
- docline-0.1.0/src/docline/readers/docx.py +692 -0
- docline-0.1.0/src/docline/readers/github.py +207 -0
- docline-0.1.0/src/docline/readers/limits.py +106 -0
- docline-0.1.0/src/docline/readers/mistral.py +201 -0
- docline-0.1.0/src/docline/readers/openapi/__init__.py +11 -0
- docline-0.1.0/src/docline/readers/openapi/convert.py +339 -0
- docline-0.1.0/src/docline/readers/openapi/detect.py +124 -0
- docline-0.1.0/src/docline/readers/openapi/errors.py +29 -0
- docline-0.1.0/src/docline/readers/openapi/loader.py +176 -0
- docline-0.1.0/src/docline/readers/openapi/reader.py +313 -0
- docline-0.1.0/src/docline/readers/openapi/render.py +418 -0
- docline-0.1.0/src/docline/readers/openapi/resolve.py +192 -0
- docline-0.1.0/src/docline/readers/pdf.py +940 -0
- docline-0.1.0/src/docline/readers/pdf_splitter.py +139 -0
- docline-0.1.0/src/docline/readers/picture_sink.py +113 -0
- docline-0.1.0/src/docline/readers/text.py +47 -0
- docline-0.1.0/src/docline/readers/transcripts.py +215 -0
- docline-0.1.0/src/docline/router.py +46 -0
- docline-0.1.0/src/docline/runtime/__init__.py +30 -0
- docline-0.1.0/src/docline/runtime/ocr_budget.py +168 -0
- docline-0.1.0/src/docline/runtime/resource_probe.py +369 -0
- docline-0.1.0/src/docline/schema/__init__.py +0 -0
- docline-0.1.0/src/docline/schema/export.py +43 -0
- docline-0.1.0/src/docline/schema/library.py +200 -0
- docline-0.1.0/src/docline/schema/models.py +71 -0
- docline-0.1.0/src/docline/types.py +36 -0
- docline-0.1.0/src/docline.egg-info/PKG-INFO +277 -0
- docline-0.1.0/src/docline.egg-info/SOURCES.txt +117 -0
- docline-0.1.0/src/docline.egg-info/dependency_links.txt +1 -0
- docline-0.1.0/src/docline.egg-info/entry_points.txt +2 -0
- docline-0.1.0/src/docline.egg-info/requires.txt +14 -0
- docline-0.1.0/src/docline.egg-info/top_level.txt +1 -0
- docline-0.1.0/tests/test_backlog_persistence_contract.py +169 -0
- docline-0.1.0/tests/test_ci_workflow_lint.py +95 -0
- docline-0.1.0/tests/test_cli_fetch.py +91 -0
- docline-0.1.0/tests/test_cli_ingest.py +312 -0
- docline-0.1.0/tests/test_cli_process.py +67 -0
- docline-0.1.0/tests/test_cli_verbosity.py +245 -0
- docline-0.1.0/tests/test_compare_merge_gap.py +191 -0
- docline-0.1.0/tests/test_execute_fetch.py +170 -0
- docline-0.1.0/tests/test_execute_process_progress.py +165 -0
- docline-0.1.0/tests/test_graphtor_ingestion_contract.py +156 -0
- docline-0.1.0/tests/test_graphtor_real_binary_integration.py +94 -0
- docline-0.1.0/tests/test_markitdown_dependency.py +45 -0
- docline-0.1.0/tests/test_ocr_memory_calibration.py +280 -0
- docline-0.1.0/tests/test_pa3_script_flags.py +257 -0
- docline-0.1.0/tests/test_pdf_mode_flag.py +83 -0
- docline-0.1.0/tests/test_posixify_path.py +90 -0
- docline-0.1.0/tests/test_progress.py +324 -0
- docline-0.1.0/tests/test_router.py +84 -0
- docline-0.1.0/tests/test_seam_lint.py +126 -0
docline-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Derek Williams
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
docline-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docline
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Document ingestion and normalization pipeline
|
|
5
|
+
Author: SoftwareSalt
|
|
6
|
+
Project-URL: Homepage, https://github.com/softwaresalt/docline
|
|
7
|
+
Project-URL: Repository, https://github.com/softwaresalt/docline
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: beautifulsoup4<5,>=4.12
|
|
12
|
+
Requires-Dist: defusedxml<1,>=0.7
|
|
13
|
+
Requires-Dist: markdown-it-py<5,>=4
|
|
14
|
+
Requires-Dist: markitdown[pdf]<0.2,>=0.1.6
|
|
15
|
+
Requires-Dist: psutil<8,>=5.9
|
|
16
|
+
Requires-Dist: pydantic<3,>=2
|
|
17
|
+
Requires-Dist: pypdf<6,>=4
|
|
18
|
+
Requires-Dist: PyYAML<7,>=6
|
|
19
|
+
Provides-Extra: pdf
|
|
20
|
+
Requires-Dist: docling<3,>=2; extra == "pdf"
|
|
21
|
+
Provides-Extra: mistral
|
|
22
|
+
Requires-Dist: httpx<1,>=0.27; extra == "mistral"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# docline
|
|
26
|
+
|
|
27
|
+
A document to markdown ingestion and normalization pipeline CLI tool and MCP server.
|
|
28
|
+
|
|
29
|
+
## Quick start: ingest a local docs repo
|
|
30
|
+
|
|
31
|
+
The fastest way to convert a cloned Microsoft Learn (or any DocFx-style)
|
|
32
|
+
docs repository into graphtor-ready Markdown is the `ingest local-dir`
|
|
33
|
+
command:
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
# Clone a docs repo (one-time)
|
|
37
|
+
git clone https://github.com/MicrosoftDocs/powerbi-docs.git E:\Source\powerbi-docs
|
|
38
|
+
|
|
39
|
+
# Convert the whole tree in one command
|
|
40
|
+
docline ingest local-dir E:\Source\powerbi-docs\powerbi-docs --output .elt\output\powerbi
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Each output file carries graphtor-ready frontmatter (`chunk_strategy`,
|
|
44
|
+
`content_sha256`, `doc_type`, `title`, `source_path`, `source`,
|
|
45
|
+
`docline.source_frontmatter`, `docline.cross_doc_links`), preserves source
|
|
46
|
+
directory structure, and follows TOC.yml ingest order when present.
|
|
47
|
+
|
|
48
|
+
The CLI mirrors the equivalent `.elt/config/<name>.sources.yaml` manifest
|
|
49
|
+
form for parity:
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
# .elt/config/powerbi.sources.yaml
|
|
53
|
+
sources:
|
|
54
|
+
- id: powerbi
|
|
55
|
+
type: local
|
|
56
|
+
path: E:\Source\powerbi-docs\powerbi-docs
|
|
57
|
+
include: ["**/*.md", "**/TOC.yml"]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Both surfaces produce identical staging + processing output because they
|
|
61
|
+
share the same `execute_source_configs` and `execute_process` code paths.
|
|
62
|
+
|
|
63
|
+
Other Microsoft Learn docs sources that work out of the box:
|
|
64
|
+
|
|
65
|
+
| Content | Repo | Subpath |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| Power BI | `MicrosoftDocs/powerbi-docs` | `powerbi-docs/` |
|
|
68
|
+
| Microsoft Fabric | `MicrosoftDocs/fabric-docs` | repo root |
|
|
69
|
+
| DAX language reference | `MicrosoftDocs/query-docs` | `query-languages/dax/` |
|
|
70
|
+
| Power Query M language reference | `MicrosoftDocs/query-docs` | `query-languages/m/` |
|
|
71
|
+
| Analysis Services | `MicrosoftDocs/bi-shared-docs` | `docs/analysis-services/` |
|
|
72
|
+
|
|
73
|
+
Useful flags:
|
|
74
|
+
|
|
75
|
+
* `--include PATTERN` (repeatable) — glob to include, default `**/*.md` + `**/TOC.yml`
|
|
76
|
+
* `--exclude PATTERN` (repeatable) — glob to exclude
|
|
77
|
+
* `--staging-dir PATH` — keep staging artifacts under a known path (default: tempdir, removed after run)
|
|
78
|
+
* `--keep-staging` — retain staging directory for debugging
|
|
79
|
+
* `--allow-heading-disorder` — bypass strict H1→H2→H3 validation (for legacy authoring)
|
|
80
|
+
|
|
81
|
+
## Console output and progress
|
|
82
|
+
|
|
83
|
+
`docline fetch` and `docline process` print a single JSON result line to
|
|
84
|
+
**stdout** at the end of a run. Live progress is written separately to
|
|
85
|
+
**stderr**, so the JSON result contract is unchanged in every mode and scripts
|
|
86
|
+
that parse (or pipe) stdout are never affected.
|
|
87
|
+
|
|
88
|
+
Control the stderr progress with a mutually-exclusive verbosity pair on both
|
|
89
|
+
commands (default is normal):
|
|
90
|
+
|
|
91
|
+
* `-q` / `--quiet` — no progress output (the JSON result still prints).
|
|
92
|
+
* *(default)* — a concise, throttled percentage/count line, updated in place on
|
|
93
|
+
a TTY and written as plain newline-terminated lines when redirected.
|
|
94
|
+
* `-v` / `--verbose` — one line per page (fetch) or file (process), including
|
|
95
|
+
the URL or path, followed by a **final completion line** (the last event
|
|
96
|
+
repeated as a permanent line). `docline fetch` additionally emits a count-only
|
|
97
|
+
line with the authoritative number of pages actually staged. These trailing
|
|
98
|
+
lines are expected — they mark completion, not duplicated work.
|
|
99
|
+
|
|
100
|
+
On an interactive terminal, in-place progress updates are coordinated with log
|
|
101
|
+
output: any warning logged mid-run clears the active progress line first and is
|
|
102
|
+
printed on its own line, and the progress line redraws on the next update (so
|
|
103
|
+
warnings never corrupt the live percentage). Piped/redirected output uses plain
|
|
104
|
+
newline-terminated lines and is unaffected.
|
|
105
|
+
|
|
106
|
+
Progress metrics:
|
|
107
|
+
|
|
108
|
+
* **`docline process`** reports `files_done / total`, where `total` is the
|
|
109
|
+
global file count summed across every completed staging job, so the bar stays
|
|
110
|
+
monotonic across multi-job runs.
|
|
111
|
+
* **`docline fetch --execute`** reports *budget-consumed* pages against the
|
|
112
|
+
crawl's `max_pages` budget (web-crawl sources only). Because the budget is a
|
|
113
|
+
ceiling, the crawl may finish early — so completion reports the authoritative
|
|
114
|
+
count of pages actually staged rather than a forced 100%.
|
|
115
|
+
|
|
116
|
+
## Documentation
|
|
117
|
+
|
|
118
|
+
* [docline → graphtor-docs ingestion contract](docs/design-docs/graphtor-docs-ingestion-contract.md) —
|
|
119
|
+
the stable v1 contract surface that downstream consumers ingest.
|
|
120
|
+
* [BaseFrontmatter JSON Schema export workflow](docs/design-docs/schema-export-workflow.md) —
|
|
121
|
+
how to regenerate the exported JSON Schema and how `graphtor-docs` consumes it.
|
|
122
|
+
* [Document ingestion and validation pipeline design](docs/design-docs/DocumentIngestion&ValidationPipelineDesign.md)
|
|
123
|
+
|
|
124
|
+
## OpenAPI / Swagger source type
|
|
125
|
+
|
|
126
|
+
`docline process` ingests OpenAPI 3.x specifications as a first-class source
|
|
127
|
+
type. A staged `.json`, `.yaml`, or `.yml` file is recognized by content-sniff
|
|
128
|
+
(its root declares `openapi: 3.x` or `swagger: 2.0`), so plain config files such
|
|
129
|
+
as `docfx.json` are never misclassified.
|
|
130
|
+
|
|
131
|
+
Rather than flattening the spec through the PDF pipeline, docline traverses the
|
|
132
|
+
typed object model and renders deterministic Markdown:
|
|
133
|
+
|
|
134
|
+
* one document per **operation** at `operations/{operationId}.md`
|
|
135
|
+
(`doc_type: openapi_operation`), with `Parameters`, `Request body`,
|
|
136
|
+
`Responses`, and `Security` sections;
|
|
137
|
+
* one document per named **component schema** at `schemas/{name}.md`
|
|
138
|
+
(`doc_type: openapi_schema`), with a properties table.
|
|
139
|
+
|
|
140
|
+
Each `$ref` to a component schema is emitted as a relative Markdown link, so the
|
|
141
|
+
existing cross-doc link harvester records every `operation → schema` reference as
|
|
142
|
+
a typed graph edge under the `docline.cross_doc_links` frontmatter namespace.
|
|
143
|
+
|
|
144
|
+
### v1 scope
|
|
145
|
+
|
|
146
|
+
The first release is intentionally narrow:
|
|
147
|
+
|
|
148
|
+
* OpenAPI **3.x** (Swagger 2.0 is detected but not yet rendered);
|
|
149
|
+
* a **single spec** (one file, or a directory for one service);
|
|
150
|
+
* **per-operation** granularity;
|
|
151
|
+
* **local** `#/components/*` `$ref` resolution only — external and split-file
|
|
152
|
+
refs are left unresolved (never fetched), because resolving them is a security
|
|
153
|
+
boundary deferred to a follow-up.
|
|
154
|
+
|
|
155
|
+
### Usage
|
|
156
|
+
|
|
157
|
+
Stage a spec and run the compute-bound pass:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
docline ingest local-dir ./azure-rest-api-specs/specification/... \
|
|
161
|
+
--output ./out --include "**/*.json"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The source directory is a positional argument. The MCP `process` tool produces
|
|
165
|
+
identical output; both surfaces share `execute_process`.
|
|
166
|
+
|
|
167
|
+
## PDF processing modes
|
|
168
|
+
|
|
169
|
+
`docline process` supports two PDF processing modes via the `--pdf-mode`
|
|
170
|
+
flag.
|
|
171
|
+
|
|
172
|
+
### `--pdf-mode auto` (default — recommended for technical PDFs)
|
|
173
|
+
|
|
174
|
+
Runs `docling` on every page. Best AST-aware quality (headings, tables,
|
|
175
|
+
code blocks, embedding-chunk-friendly section sizes) for technical
|
|
176
|
+
reference documents — Microsoft / AWS / Kubernetes / framework
|
|
177
|
+
documentation, vendor manuals, scientific papers with dense layout.
|
|
178
|
+
|
|
179
|
+
* Pros: highest structural fidelity; ideal for graph DBs, vector
|
|
180
|
+
embedding stores, and LLM context windows.
|
|
181
|
+
* Cons: ~15-30 sec per page wall-clock; a 3,400-page reference manual
|
|
182
|
+
takes ~4-9 hours.
|
|
183
|
+
|
|
184
|
+
### `--pdf-mode triage` (opt-in — for prose-dominated corpora)
|
|
185
|
+
|
|
186
|
+
Runs a heuristic baseline ([`markitdown`](https://github.com/microsoft/markitdown)
|
|
187
|
+
or `pypdf`) across the whole PDF, scores each page for likely fidelity
|
|
188
|
+
loss, and only invokes `docling` on flagged page ranges. Designed for
|
|
189
|
+
documents that are mostly free-form prose (novels, articles, simple
|
|
190
|
+
documentation, chat exports).
|
|
191
|
+
|
|
192
|
+
* Pros: ~5-10× faster than `auto` on prose corpora.
|
|
193
|
+
* Cons: on technical reference PDFs, triage either over-fires (large
|
|
194
|
+
pages flagged, wall-clock approaches `auto`) or under-fires (table
|
|
195
|
+
pages flattened to broken text). See the
|
|
196
|
+
[2026-06-08 extraction strategy study](docs/decisions/2026-06-08-extraction-strategy-study.md)
|
|
197
|
+
for empirical results: docling wins 14/15 sampled cosmos ranges on
|
|
198
|
+
AST quality.
|
|
199
|
+
|
|
200
|
+
### Choosing a mode
|
|
201
|
+
|
|
202
|
+
* **Technical reference PDFs** (vendor docs, framework docs, scientific
|
|
203
|
+
papers): use `--pdf-mode auto`.
|
|
204
|
+
* **Prose corpora** (novels, articles, transcripts): use `--pdf-mode triage`
|
|
205
|
+
to trade some structural fidelity for speed.
|
|
206
|
+
* **Source markdown available** (Microsoft Learn, AWS Docs, K8s,
|
|
207
|
+
React, Python, most OSS): a future feature (**026-F**) will add a
|
|
208
|
+
`--source-mode` flag that bypasses PDF extraction entirely; see the
|
|
209
|
+
[source-MD ingestion extension](docs/decisions/2026-06-08-source-md-ingestion-extension.md).
|
|
210
|
+
|
|
211
|
+
### Choosing a PDF engine
|
|
212
|
+
|
|
213
|
+
`--pdf-engine` selects *which* layout extractor runs and is orthogonal to
|
|
214
|
+
`--pdf-mode` (which selects whole-document vs. triage). Four choices: `auto`
|
|
215
|
+
(default), `docling`, `mistral_ocr`, and `heuristic`.
|
|
216
|
+
|
|
217
|
+
| Engine | Strengths | Trade-offs | Requirements |
|
|
218
|
+
|---|---|---|---|
|
|
219
|
+
| `auto` (default) | Prefers `docling`; transparently degrades to `heuristic` on failure so one hostile PDF can't abort a batch | Never selects `mistral_ocr` | `docline[pdf]` for docling, else heuristic |
|
|
220
|
+
| `docling` | Best structural fidelity on headings and dense layout; deterministic; fully local/offline | ~360 pages/hour (031-S bench) | `docline[pdf]` extra (raises if missing) |
|
|
221
|
+
| `mistral_ocr` | Wins decisively on tables (mean +33.9% vs. docling, 8/4/2 wins); ~3,732 pages/hour (~10× docling) | Heading depth ~8.4% weaker than docling; per-page cloud cost (~$1 / 1,000 pages); network + credentials; non-deterministic | `docline[mistral]` + `AZURE_AI_FOUNDRY_KEY`/`_ENDPOINT` or `MISTRAL_API_KEY` |
|
|
222
|
+
| `heuristic` | Fastest; no model download; fully local | Flattens tables and complex layout to plain text | None (built in) |
|
|
223
|
+
|
|
224
|
+
**Fidelity vs. throughput — recommended engine by corpus class:**
|
|
225
|
+
|
|
226
|
+
| Corpus class | Throughput priority | Cost sensitivity | Recommended `--pdf-engine` |
|
|
227
|
+
|---|---|---|---|
|
|
228
|
+
| Technical reference (vendor/framework docs, manuals) | Low | Any | `docling` (or `auto`) |
|
|
229
|
+
| Table-heavy (financial reports, spec sheets, data appendices) | Low | Low | `mistral_ocr` |
|
|
230
|
+
| Table-heavy at scale | High | Tolerant of cloud cost | `mistral_ocr` |
|
|
231
|
+
| Scientific papers (dense layout + tables) | Low | Any | `docling`; `mistral_ocr` if tables dominate |
|
|
232
|
+
| Forms / invoices (scanned, OCR-dependent) | Any | Tolerant | `mistral_ocr` (OCR strength) — re-validate per corpus |
|
|
233
|
+
| Prose (novels, articles, transcripts) | High | Any | `heuristic` (or `--pdf-mode triage`) |
|
|
234
|
+
| Offline / air-gapped / deterministic required | Any | Any | `docling` or `heuristic` (never cloud) |
|
|
235
|
+
|
|
236
|
+
Evidence: the
|
|
237
|
+
[031-S Mistral OCR spike](docs/closure/031-S-mistral-ocr-spike.md)
|
|
238
|
+
(PROMOTE-AS-PEER — tables mean +33.9%, ~10× throughput, headings −8.4%) and
|
|
239
|
+
the [2026-06-08 extraction strategy study](docs/decisions/2026-06-08-extraction-strategy-study.md)
|
|
240
|
+
(docling wins 14/15 sampled technical-reference ranges on AST quality).
|
|
241
|
+
`mistral_ocr` is opt-in only and is never auto-selected. Azure Document
|
|
242
|
+
Intelligence was evaluated and removed in 031-S; see
|
|
243
|
+
[029-S](docs/closure/029-S-adi-spike.md) for the historical record.
|
|
244
|
+
|
|
245
|
+
### Compute device (`DOCLINE_ACCELERATOR`)
|
|
246
|
+
|
|
247
|
+
The `docling` engine auto-detects an available accelerator (CUDA, MPS, or
|
|
248
|
+
XPU) and falls back to CPU otherwise, so GPU hosts are used without
|
|
249
|
+
configuration. Set `DOCLINE_ACCELERATOR` to pin the device explicitly:
|
|
250
|
+
|
|
251
|
+
| Value | Effect |
|
|
252
|
+
|---|---|
|
|
253
|
+
| unset or `auto` | docling's default auto-detection (unchanged behavior) |
|
|
254
|
+
| `cpu` | Force CPU — the escape hatch when an auto-detected GPU is unreliable |
|
|
255
|
+
| `cuda` / `mps` / `xpu` | Pin the named accelerator |
|
|
256
|
+
|
|
257
|
+
The variable applies to both the single-file CLI path and the batched
|
|
258
|
+
docling worker. An unrecognized value fails fast with a configuration error.
|
|
259
|
+
|
|
260
|
+
### Calibration & QA
|
|
261
|
+
|
|
262
|
+
`docline process --pdf-mode triage --triage-report-only` emits a
|
|
263
|
+
per-page TSV with both fidelity-signal scores and AST-aware quality
|
|
264
|
+
metrics (heading count, section count, table cell count, structural
|
|
265
|
+
density per 1k chars, median section size). See
|
|
266
|
+
[`docs/compound/2026-06-08-ast-fidelity-metrics.md`](docs/compound/2026-06-08-ast-fidelity-metrics.md)
|
|
267
|
+
for the decision rule on interpreting these metrics.
|
|
268
|
+
|
|
269
|
+
### Triage output retention
|
|
270
|
+
|
|
271
|
+
When `--pdf-mode triage` is used, per-page baseline PDFs
|
|
272
|
+
(`baseline-NNNN.pdf`) and coalesced splice PDFs / outputs
|
|
273
|
+
(`splice-AAAA-BBBB.{pdf,md}`) are preserved by default under
|
|
274
|
+
`{output_dir}/splices/` for offline calibration and diagnostic
|
|
275
|
+
inspection. Plan accordingly for disk usage: a 3,400-page PDF produces
|
|
276
|
+
~3,400 per-page PDFs totaling ~150 MB.
|
|
277
|
+
|
docline-0.1.0/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# docline
|
|
2
|
+
|
|
3
|
+
A document to markdown ingestion and normalization pipeline CLI tool and MCP server.
|
|
4
|
+
|
|
5
|
+
## Quick start: ingest a local docs repo
|
|
6
|
+
|
|
7
|
+
The fastest way to convert a cloned Microsoft Learn (or any DocFx-style)
|
|
8
|
+
docs repository into graphtor-ready Markdown is the `ingest local-dir`
|
|
9
|
+
command:
|
|
10
|
+
|
|
11
|
+
```powershell
|
|
12
|
+
# Clone a docs repo (one-time)
|
|
13
|
+
git clone https://github.com/MicrosoftDocs/powerbi-docs.git E:\Source\powerbi-docs
|
|
14
|
+
|
|
15
|
+
# Convert the whole tree in one command
|
|
16
|
+
docline ingest local-dir E:\Source\powerbi-docs\powerbi-docs --output .elt\output\powerbi
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Each output file carries graphtor-ready frontmatter (`chunk_strategy`,
|
|
20
|
+
`content_sha256`, `doc_type`, `title`, `source_path`, `source`,
|
|
21
|
+
`docline.source_frontmatter`, `docline.cross_doc_links`), preserves source
|
|
22
|
+
directory structure, and follows TOC.yml ingest order when present.
|
|
23
|
+
|
|
24
|
+
The CLI mirrors the equivalent `.elt/config/<name>.sources.yaml` manifest
|
|
25
|
+
form for parity:
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
# .elt/config/powerbi.sources.yaml
|
|
29
|
+
sources:
|
|
30
|
+
- id: powerbi
|
|
31
|
+
type: local
|
|
32
|
+
path: E:\Source\powerbi-docs\powerbi-docs
|
|
33
|
+
include: ["**/*.md", "**/TOC.yml"]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Both surfaces produce identical staging + processing output because they
|
|
37
|
+
share the same `execute_source_configs` and `execute_process` code paths.
|
|
38
|
+
|
|
39
|
+
Other Microsoft Learn docs sources that work out of the box:
|
|
40
|
+
|
|
41
|
+
| Content | Repo | Subpath |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Power BI | `MicrosoftDocs/powerbi-docs` | `powerbi-docs/` |
|
|
44
|
+
| Microsoft Fabric | `MicrosoftDocs/fabric-docs` | repo root |
|
|
45
|
+
| DAX language reference | `MicrosoftDocs/query-docs` | `query-languages/dax/` |
|
|
46
|
+
| Power Query M language reference | `MicrosoftDocs/query-docs` | `query-languages/m/` |
|
|
47
|
+
| Analysis Services | `MicrosoftDocs/bi-shared-docs` | `docs/analysis-services/` |
|
|
48
|
+
|
|
49
|
+
Useful flags:
|
|
50
|
+
|
|
51
|
+
* `--include PATTERN` (repeatable) — glob to include, default `**/*.md` + `**/TOC.yml`
|
|
52
|
+
* `--exclude PATTERN` (repeatable) — glob to exclude
|
|
53
|
+
* `--staging-dir PATH` — keep staging artifacts under a known path (default: tempdir, removed after run)
|
|
54
|
+
* `--keep-staging` — retain staging directory for debugging
|
|
55
|
+
* `--allow-heading-disorder` — bypass strict H1→H2→H3 validation (for legacy authoring)
|
|
56
|
+
|
|
57
|
+
## Console output and progress
|
|
58
|
+
|
|
59
|
+
`docline fetch` and `docline process` print a single JSON result line to
|
|
60
|
+
**stdout** at the end of a run. Live progress is written separately to
|
|
61
|
+
**stderr**, so the JSON result contract is unchanged in every mode and scripts
|
|
62
|
+
that parse (or pipe) stdout are never affected.
|
|
63
|
+
|
|
64
|
+
Control the stderr progress with a mutually-exclusive verbosity pair on both
|
|
65
|
+
commands (default is normal):
|
|
66
|
+
|
|
67
|
+
* `-q` / `--quiet` — no progress output (the JSON result still prints).
|
|
68
|
+
* *(default)* — a concise, throttled percentage/count line, updated in place on
|
|
69
|
+
a TTY and written as plain newline-terminated lines when redirected.
|
|
70
|
+
* `-v` / `--verbose` — one line per page (fetch) or file (process), including
|
|
71
|
+
the URL or path, followed by a **final completion line** (the last event
|
|
72
|
+
repeated as a permanent line). `docline fetch` additionally emits a count-only
|
|
73
|
+
line with the authoritative number of pages actually staged. These trailing
|
|
74
|
+
lines are expected — they mark completion, not duplicated work.
|
|
75
|
+
|
|
76
|
+
On an interactive terminal, in-place progress updates are coordinated with log
|
|
77
|
+
output: any warning logged mid-run clears the active progress line first and is
|
|
78
|
+
printed on its own line, and the progress line redraws on the next update (so
|
|
79
|
+
warnings never corrupt the live percentage). Piped/redirected output uses plain
|
|
80
|
+
newline-terminated lines and is unaffected.
|
|
81
|
+
|
|
82
|
+
Progress metrics:
|
|
83
|
+
|
|
84
|
+
* **`docline process`** reports `files_done / total`, where `total` is the
|
|
85
|
+
global file count summed across every completed staging job, so the bar stays
|
|
86
|
+
monotonic across multi-job runs.
|
|
87
|
+
* **`docline fetch --execute`** reports *budget-consumed* pages against the
|
|
88
|
+
crawl's `max_pages` budget (web-crawl sources only). Because the budget is a
|
|
89
|
+
ceiling, the crawl may finish early — so completion reports the authoritative
|
|
90
|
+
count of pages actually staged rather than a forced 100%.
|
|
91
|
+
|
|
92
|
+
## Documentation
|
|
93
|
+
|
|
94
|
+
* [docline → graphtor-docs ingestion contract](docs/design-docs/graphtor-docs-ingestion-contract.md) —
|
|
95
|
+
the stable v1 contract surface that downstream consumers ingest.
|
|
96
|
+
* [BaseFrontmatter JSON Schema export workflow](docs/design-docs/schema-export-workflow.md) —
|
|
97
|
+
how to regenerate the exported JSON Schema and how `graphtor-docs` consumes it.
|
|
98
|
+
* [Document ingestion and validation pipeline design](docs/design-docs/DocumentIngestion&ValidationPipelineDesign.md)
|
|
99
|
+
|
|
100
|
+
## OpenAPI / Swagger source type
|
|
101
|
+
|
|
102
|
+
`docline process` ingests OpenAPI 3.x specifications as a first-class source
|
|
103
|
+
type. A staged `.json`, `.yaml`, or `.yml` file is recognized by content-sniff
|
|
104
|
+
(its root declares `openapi: 3.x` or `swagger: 2.0`), so plain config files such
|
|
105
|
+
as `docfx.json` are never misclassified.
|
|
106
|
+
|
|
107
|
+
Rather than flattening the spec through the PDF pipeline, docline traverses the
|
|
108
|
+
typed object model and renders deterministic Markdown:
|
|
109
|
+
|
|
110
|
+
* one document per **operation** at `operations/{operationId}.md`
|
|
111
|
+
(`doc_type: openapi_operation`), with `Parameters`, `Request body`,
|
|
112
|
+
`Responses`, and `Security` sections;
|
|
113
|
+
* one document per named **component schema** at `schemas/{name}.md`
|
|
114
|
+
(`doc_type: openapi_schema`), with a properties table.
|
|
115
|
+
|
|
116
|
+
Each `$ref` to a component schema is emitted as a relative Markdown link, so the
|
|
117
|
+
existing cross-doc link harvester records every `operation → schema` reference as
|
|
118
|
+
a typed graph edge under the `docline.cross_doc_links` frontmatter namespace.
|
|
119
|
+
|
|
120
|
+
### v1 scope
|
|
121
|
+
|
|
122
|
+
The first release is intentionally narrow:
|
|
123
|
+
|
|
124
|
+
* OpenAPI **3.x** (Swagger 2.0 is detected but not yet rendered);
|
|
125
|
+
* a **single spec** (one file, or a directory for one service);
|
|
126
|
+
* **per-operation** granularity;
|
|
127
|
+
* **local** `#/components/*` `$ref` resolution only — external and split-file
|
|
128
|
+
refs are left unresolved (never fetched), because resolving them is a security
|
|
129
|
+
boundary deferred to a follow-up.
|
|
130
|
+
|
|
131
|
+
### Usage
|
|
132
|
+
|
|
133
|
+
Stage a spec and run the compute-bound pass:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
docline ingest local-dir ./azure-rest-api-specs/specification/... \
|
|
137
|
+
--output ./out --include "**/*.json"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The source directory is a positional argument. The MCP `process` tool produces
|
|
141
|
+
identical output; both surfaces share `execute_process`.
|
|
142
|
+
|
|
143
|
+
## PDF processing modes
|
|
144
|
+
|
|
145
|
+
`docline process` supports two PDF processing modes via the `--pdf-mode`
|
|
146
|
+
flag.
|
|
147
|
+
|
|
148
|
+
### `--pdf-mode auto` (default — recommended for technical PDFs)
|
|
149
|
+
|
|
150
|
+
Runs `docling` on every page. Best AST-aware quality (headings, tables,
|
|
151
|
+
code blocks, embedding-chunk-friendly section sizes) for technical
|
|
152
|
+
reference documents — Microsoft / AWS / Kubernetes / framework
|
|
153
|
+
documentation, vendor manuals, scientific papers with dense layout.
|
|
154
|
+
|
|
155
|
+
* Pros: highest structural fidelity; ideal for graph DBs, vector
|
|
156
|
+
embedding stores, and LLM context windows.
|
|
157
|
+
* Cons: ~15-30 sec per page wall-clock; a 3,400-page reference manual
|
|
158
|
+
takes ~4-9 hours.
|
|
159
|
+
|
|
160
|
+
### `--pdf-mode triage` (opt-in — for prose-dominated corpora)
|
|
161
|
+
|
|
162
|
+
Runs a heuristic baseline ([`markitdown`](https://github.com/microsoft/markitdown)
|
|
163
|
+
or `pypdf`) across the whole PDF, scores each page for likely fidelity
|
|
164
|
+
loss, and only invokes `docling` on flagged page ranges. Designed for
|
|
165
|
+
documents that are mostly free-form prose (novels, articles, simple
|
|
166
|
+
documentation, chat exports).
|
|
167
|
+
|
|
168
|
+
* Pros: ~5-10× faster than `auto` on prose corpora.
|
|
169
|
+
* Cons: on technical reference PDFs, triage either over-fires (large
|
|
170
|
+
pages flagged, wall-clock approaches `auto`) or under-fires (table
|
|
171
|
+
pages flattened to broken text). See the
|
|
172
|
+
[2026-06-08 extraction strategy study](docs/decisions/2026-06-08-extraction-strategy-study.md)
|
|
173
|
+
for empirical results: docling wins 14/15 sampled cosmos ranges on
|
|
174
|
+
AST quality.
|
|
175
|
+
|
|
176
|
+
### Choosing a mode
|
|
177
|
+
|
|
178
|
+
* **Technical reference PDFs** (vendor docs, framework docs, scientific
|
|
179
|
+
papers): use `--pdf-mode auto`.
|
|
180
|
+
* **Prose corpora** (novels, articles, transcripts): use `--pdf-mode triage`
|
|
181
|
+
to trade some structural fidelity for speed.
|
|
182
|
+
* **Source markdown available** (Microsoft Learn, AWS Docs, K8s,
|
|
183
|
+
React, Python, most OSS): a future feature (**026-F**) will add a
|
|
184
|
+
`--source-mode` flag that bypasses PDF extraction entirely; see the
|
|
185
|
+
[source-MD ingestion extension](docs/decisions/2026-06-08-source-md-ingestion-extension.md).
|
|
186
|
+
|
|
187
|
+
### Choosing a PDF engine
|
|
188
|
+
|
|
189
|
+
`--pdf-engine` selects *which* layout extractor runs and is orthogonal to
|
|
190
|
+
`--pdf-mode` (which selects whole-document vs. triage). Four choices: `auto`
|
|
191
|
+
(default), `docling`, `mistral_ocr`, and `heuristic`.
|
|
192
|
+
|
|
193
|
+
| Engine | Strengths | Trade-offs | Requirements |
|
|
194
|
+
|---|---|---|---|
|
|
195
|
+
| `auto` (default) | Prefers `docling`; transparently degrades to `heuristic` on failure so one hostile PDF can't abort a batch | Never selects `mistral_ocr` | `docline[pdf]` for docling, else heuristic |
|
|
196
|
+
| `docling` | Best structural fidelity on headings and dense layout; deterministic; fully local/offline | ~360 pages/hour (031-S bench) | `docline[pdf]` extra (raises if missing) |
|
|
197
|
+
| `mistral_ocr` | Wins decisively on tables (mean +33.9% vs. docling, 8/4/2 wins); ~3,732 pages/hour (~10× docling) | Heading depth ~8.4% weaker than docling; per-page cloud cost (~$1 / 1,000 pages); network + credentials; non-deterministic | `docline[mistral]` + `AZURE_AI_FOUNDRY_KEY`/`_ENDPOINT` or `MISTRAL_API_KEY` |
|
|
198
|
+
| `heuristic` | Fastest; no model download; fully local | Flattens tables and complex layout to plain text | None (built in) |
|
|
199
|
+
|
|
200
|
+
**Fidelity vs. throughput — recommended engine by corpus class:**
|
|
201
|
+
|
|
202
|
+
| Corpus class | Throughput priority | Cost sensitivity | Recommended `--pdf-engine` |
|
|
203
|
+
|---|---|---|---|
|
|
204
|
+
| Technical reference (vendor/framework docs, manuals) | Low | Any | `docling` (or `auto`) |
|
|
205
|
+
| Table-heavy (financial reports, spec sheets, data appendices) | Low | Low | `mistral_ocr` |
|
|
206
|
+
| Table-heavy at scale | High | Tolerant of cloud cost | `mistral_ocr` |
|
|
207
|
+
| Scientific papers (dense layout + tables) | Low | Any | `docling`; `mistral_ocr` if tables dominate |
|
|
208
|
+
| Forms / invoices (scanned, OCR-dependent) | Any | Tolerant | `mistral_ocr` (OCR strength) — re-validate per corpus |
|
|
209
|
+
| Prose (novels, articles, transcripts) | High | Any | `heuristic` (or `--pdf-mode triage`) |
|
|
210
|
+
| Offline / air-gapped / deterministic required | Any | Any | `docling` or `heuristic` (never cloud) |
|
|
211
|
+
|
|
212
|
+
Evidence: the
|
|
213
|
+
[031-S Mistral OCR spike](docs/closure/031-S-mistral-ocr-spike.md)
|
|
214
|
+
(PROMOTE-AS-PEER — tables mean +33.9%, ~10× throughput, headings −8.4%) and
|
|
215
|
+
the [2026-06-08 extraction strategy study](docs/decisions/2026-06-08-extraction-strategy-study.md)
|
|
216
|
+
(docling wins 14/15 sampled technical-reference ranges on AST quality).
|
|
217
|
+
`mistral_ocr` is opt-in only and is never auto-selected. Azure Document
|
|
218
|
+
Intelligence was evaluated and removed in 031-S; see
|
|
219
|
+
[029-S](docs/closure/029-S-adi-spike.md) for the historical record.
|
|
220
|
+
|
|
221
|
+
### Compute device (`DOCLINE_ACCELERATOR`)
|
|
222
|
+
|
|
223
|
+
The `docling` engine auto-detects an available accelerator (CUDA, MPS, or
|
|
224
|
+
XPU) and falls back to CPU otherwise, so GPU hosts are used without
|
|
225
|
+
configuration. Set `DOCLINE_ACCELERATOR` to pin the device explicitly:
|
|
226
|
+
|
|
227
|
+
| Value | Effect |
|
|
228
|
+
|---|---|
|
|
229
|
+
| unset or `auto` | docling's default auto-detection (unchanged behavior) |
|
|
230
|
+
| `cpu` | Force CPU — the escape hatch when an auto-detected GPU is unreliable |
|
|
231
|
+
| `cuda` / `mps` / `xpu` | Pin the named accelerator |
|
|
232
|
+
|
|
233
|
+
The variable applies to both the single-file CLI path and the batched
|
|
234
|
+
docling worker. An unrecognized value fails fast with a configuration error.
|
|
235
|
+
|
|
236
|
+
### Calibration & QA
|
|
237
|
+
|
|
238
|
+
`docline process --pdf-mode triage --triage-report-only` emits a
|
|
239
|
+
per-page TSV with both fidelity-signal scores and AST-aware quality
|
|
240
|
+
metrics (heading count, section count, table cell count, structural
|
|
241
|
+
density per 1k chars, median section size). See
|
|
242
|
+
[`docs/compound/2026-06-08-ast-fidelity-metrics.md`](docs/compound/2026-06-08-ast-fidelity-metrics.md)
|
|
243
|
+
for the decision rule on interpreting these metrics.
|
|
244
|
+
|
|
245
|
+
### Triage output retention
|
|
246
|
+
|
|
247
|
+
When `--pdf-mode triage` is used, per-page baseline PDFs
|
|
248
|
+
(`baseline-NNNN.pdf`) and coalesced splice PDFs / outputs
|
|
249
|
+
(`splice-AAAA-BBBB.{pdf,md}`) are preserved by default under
|
|
250
|
+
`{output_dir}/splices/` for offline calibration and diagnostic
|
|
251
|
+
inspection. Plan accordingly for disk usage: a 3,400-page PDF produces
|
|
252
|
+
~3,400 per-page PDFs totaling ~150 MB.
|
|
253
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "docline"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Document ingestion and normalization pipeline"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "SoftwareSalt" },
|
|
13
|
+
]
|
|
14
|
+
urls = { Homepage = "https://github.com/softwaresalt/docline", Repository = "https://github.com/softwaresalt/docline" }
|
|
15
|
+
dependencies = [
|
|
16
|
+
"beautifulsoup4>=4.12,<5",
|
|
17
|
+
"defusedxml>=0.7,<1",
|
|
18
|
+
"markdown-it-py>=4,<5",
|
|
19
|
+
"markitdown[pdf]>=0.1.6,<0.2",
|
|
20
|
+
"psutil>=5.9,<8",
|
|
21
|
+
"pydantic>=2,<3",
|
|
22
|
+
"pypdf>=4,<6",
|
|
23
|
+
"PyYAML>=6,<7",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[dependency-groups]
|
|
27
|
+
dev = [
|
|
28
|
+
"ruff>=0.15,<1",
|
|
29
|
+
"pyright>=1.1.400,<2",
|
|
30
|
+
"pytest>=9,<10",
|
|
31
|
+
"build>=1.4,<2",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
docline = "docline.cli:main"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
pdf = ["docling>=2,<3"]
|
|
39
|
+
mistral = ["httpx>=0.27,<1"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
where = ["src"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
testpaths = ["tests"]
|
|
46
|
+
addopts = "-v"
|
|
47
|
+
markers = [
|
|
48
|
+
"integration: marks end-to-end integration coverage",
|
|
49
|
+
"graphtor_integration: opt-in integration test that round-trips docline output through a graphtor-docs ingestion simulator",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
line-length = 100
|
|
54
|
+
target-version = "py312"
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
select = ["E", "F", "I", "UP"]
|
docline-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""docline — document ingestion and normalization pipeline."""
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Package entrypoint for ``python -m docline``."""
|
|
2
|
+
|
|
3
|
+
from docline.cli import main as cli_main
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> int:
|
|
7
|
+
"""Run the package entrypoint.
|
|
8
|
+
|
|
9
|
+
Returns:
|
|
10
|
+
Process exit code.
|
|
11
|
+
"""
|
|
12
|
+
return cli_main()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
if __name__ == "__main__":
|
|
16
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Internal subprocess CLIs invoked by the docline batch processor.
|
|
2
|
+
|
|
3
|
+
These tools are not part of the public docline CLI surface; they exist
|
|
4
|
+
so the batch processor can run docling (which loads heavy PyTorch
|
|
5
|
+
models and can OOM with hard-to-catch C-level errors) in an isolated
|
|
6
|
+
child process. If a child crashes, the OS reaps it cleanly and the
|
|
7
|
+
parent records a non-zero exit code, downgrading that chunk to the
|
|
8
|
+
heuristic engine.
|
|
9
|
+
"""
|