Metadata-Version: 2.4
Name: fabricatio-typst
Version: 1.0.0.dev0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Framework :: AsyncIO
Classifier: Framework :: Pydantic :: 2
Classifier: Typing :: Typed
Requires-Dist: fabricatio-core
Requires-Dist: fabricatio-tool
Requires-Dist: fabricatio-capabilities
Requires-Dist: fabricatio-context
Requires-Dist: fabricatio-skill
Requires-Dist: typst>=0.15.0
Requires-Dist: fabricatio-improve ; extra == 'actions'
Requires-Dist: fabricatio-rule ; extra == 'actions'
Requires-Dist: fabricatio-typst[workflows,actions,rag] ; extra == 'full'
Requires-Dist: fabricatio-lancedb ; extra == 'lancedb'
Requires-Dist: fabricatio-actions ; extra == 'workflows'
Provides-Extra: actions
Provides-Extra: full
Provides-Extra: lancedb
Provides-Extra: workflows
License-File: LICENSE
Summary: A Python library for generating, validating and converting academic content using Typst format.
Author-email: Whth <zettainspector@foxmail.com>
Requires-Python: >=3.12, <3.15
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://github.com/Whth/fabricatio
Project-URL: Issues, https://github.com/Whth/fabricatio/issues
Project-URL: Repository, https://github.com/Whth/fabricatio

# `fabricatio-typst`

[MIT](https://img.shields.io/badge/license-MIT-blue.svg)
![Python Versions](https://img.shields.io/pypi/pyversions/fabricatio-typst)
[![PyPI Version](https://img.shields.io/pypi/v/fabricatio-typst)](https://pypi.org/project/fabricatio-typst/)
[![PyPI Downloads](https://static.pepy.tech/badge/fabricatio-typst/week)](https://pepy.tech/projects/fabricatio-typst)
[![PyPI Downloads](https://static.pepy.tech/badge/fabricatio-typst)](https://pepy.tech/projects/fabricatio-typst)
[![Bindings: PyO3](https://img.shields.io/badge/bindings-pyo3-green)](https://github.com/PyO3/pyo3)
[![Build Tool: uv + maturin](https://img.shields.io/badge/built%20with-uv%20%2B%20maturin-orange)](https://github.com/astral-sh/uv)

Academic article generation and Typst document tooling, built on Fabricatio's event-based agent framework.

## Installation

```bash
pip install fabricatio[typst]
```

For RAG-backed article writing:

```bash
pip install fabricatio[typst,rag]
```

## Overview

Two layers compose this package:

**Rust extension** (`fabricatio_typst.rust`) — performance-critical utilities:
- TeX-to-Typst math conversion (raw LaTeX and delimited `$`/`$$`/`\(`/`\[` math)
- BibTeX bibliography management with fuzzy citation lookup
- Typst comment manipulation and YAML front-matter handling
- Markdown section extraction

**Python layer** — staged, typed academic content generation:
- Extract paper essences and propose structured research proposals
- Plan an article level by level — article, chapters, sections, subsections — then write every subsection against the running text
- RAG-backed composition that retrieves each subsection's own references and cites them inline
- Store and query article chunks in LanceDB
- Compile `.typ` documents to PDF, PNG, or SVG via the `typst` compiler

## Rust API

```python
from fabricatio_typst.rust import (
    BibManager,
    tex_to_typst,
    convert_all_tex_math,
    comment,
    uncomment,
    strip_comment,
    split_out_metadata,
    to_metadata,
    extract_body,
    replace_thesis_body,
    extract_sections,
    fix_misplaced_labels,
)
```

### TeX Conversion

| Function | Description |
|---|---|
| `tex_to_typst(string)` | Convert raw LaTeX code to Typst math |
| `convert_all_tex_math(string)` | Convert `$`, `$$`, `\(`, `\[` math delimiters to Typst `$` |

```python
tex_to_typst(r"\frac{1}{\sqrt{x^2 + 1}}")
# => '#frac(1, sqrt(x^2 + 1))'

convert_all_tex_math("Einstein's $E = mc^2$ is famous.")
# => "Einstein's $E = m c^2$ is famous."
```

### Comment Utilities

| Function | Description |
|---|---|
| `comment(string)` | Prepend `//` to every line |
| `uncomment(string)` | Remove `//` prefix from every line |
| `strip_comment(string)` | Strip leading and trailing comment lines |

### BibManager

Loads a BibTeX bibliography file and provides fuzzy citation lookup.

```python
bib = BibManager("references.bib")
cite_key = bib.get_cite_key_by_title("Attention Is All You Need")
# => "vaswani2017attention"

key = bib.get_cite_key_fuzzy("transformers attention mechanism")
authors = bib.get_author_by_key(key)
abstract = bib.get_abstract_by_key(key)
```

| Method | Description |
|---|---|
| `get_cite_key_by_title(title)` | Exact-match citation key by title |
| `get_cite_key_by_title_fuzzy(title)` | Fuzzy-match citation key by title |
| `get_cite_key_fuzzy(query)` | Fuzzy-match citation key by arbitrary query |
| `list_titles(is_verbatim=False)` | List all bibliography titles |
| `get_author_by_key(key)` | Authors for a citation key |
| `get_year_by_key(key)` | Publication year for a citation key |
| `get_abstract_by_key(key)` | Abstract for a citation key |
| `get_title_by_key(key)` | Title for a citation key |
| `get_field_by_key(key, field)` | Arbitrary BibTeX field for a citation key |

### Document Utilities

| Function | Description |
|---|---|
| `split_out_metadata(string)` | Extract YAML front matter as `(metadata, rest)` |
| `to_metadata(data)` | Serialize Python object to YAML comment block |
| `extract_body(string, wrapper)` | Extract content between wrapper markers |
| `replace_thesis_body(string, wrapper, new_body)` | Replace content between wrapper markers |
| `extract_sections(string, level=1, section_char="#")` | Parse markdown sections at given header level |
| `fix_misplaced_labels(string)` | Move `\<label\>` tags outside display math blocks |

## Python Models

Hierarchical article representation from proposal through completed paper:

| Model | Description |
|---|---|
| `ArticleProposal` | Research proposal: problems, approaches, methods, aims, keywords |
| `ArticleEssence` | Semantic fingerprint: title, authors, equations, figures, contributions |
| `ArticleOutline` | Hierarchical outline: chapters → sections → subsections |
| `ArticleChapterOutline` | Chapter-level outline node |
| `ArticleSectionOutline` | Section-level outline node |
| `ArticleSubsectionOutline` | Subsection-level outline node |
| `Article` | Complete paper with full content and validation |
| `ArticleChapter` | Chapter with sections |
| `ArticleSection` | Section with subsections |
| `ArticleSubsection` | Subsection with paragraphs |
| `Paragraph` | Structured paragraph blueprint with word count |
| `ArticleChunk` | LanceDB-storable chunk with bibtex metadata |
| `ArticleEssenceStorable` | ArticleEssence with LanceDB storage capability |
| `CitationManager` | Deduplicated, iteratively expanded citation set for RAG |
| `ChunkKwargs` | TypedDict for chunking parameters |

The staged pipeline plans through one flat plan model per level and writes into a typed
context tree; the outline ladder above is the artifact that tree assembles into:

| Model | Description |
|---|---|
| `WeightedPlan` | One unit's plan: heading, elaboration, aims, weight, and its writing styles and constraints |
| `ArticlePlan` / `ChapterPlan` / `SectionPlan` / `SubsectionPlan` | Per-level plans, each carrying its own expected-count band for the planner model |
| `ArticleContext` / `ChapterContext` / `SectionContext` / `SubsectionContext` | The typed context tree the pipeline plans and writes into; a leaf holds the composed prose |

## Actions

Each action is a Fabricatio `Action` — an async callable unit in the agent workflow. Available actions:

### Content Extraction

| Action | Description |
|---|---|
| `ExtractArticleEssence` | Extract article essences from files on disk |
| `FixArticleEssence` | Fix extracted essences using BibTeX reference data |
| `ExtractOutlineFromRaw` | Parse an outline from raw text |

### Staged Composition

Every stage runs one segment of the `compose_article` chain and then persists a
whole-tree snapshot under `<persist_dir>/stage_<name>`, so a wrong result can be traced
back to the stage that produced it.

| Stage | Description |
|---|---|
| `InitArticleContext` | Build the root context from the briefing, resolve the run's skills, fire the before hook |
| `ProposeArticleProposalStage` | Propose the research proposal from the briefing |
| `ProposeArticlePlanStage` | Propose the article's own plan: title, description, styles, constraints, word count |
| `PlanArticleChaptersStage` | Plan the chapters and allocate the article's word count across them |
| `PlanSectionsStage` | Plan every chapter's sections |
| `PlanSubsectionsStage` | Plan every section's subsections |
| `ComposeSubsectionsStage` | Write every subsection in prefix order |
| `AssembleArticleStage` | Assemble the context tree into an `Article` and record its outline |
| `DumpArticleStage` | Dump the article's typst source to `article_output_path` |
| `DumpOutlineStage` | Dump the planned outline alone: the structure-only deliverable |

The actions below are the run's side utilities:

| Action | Description |
|---|---|
| `LoadArticle` | Load a complete article from outline + Typst code |
| `ExtractOutlineFromRaw` | Parse an outline from raw text |
| `FixIntrospectedErrors` | Repair the errors an outline's own checks report, against a ruleset |
| `WriteChapterSummary` | Write summaries for each chapter |
| `WriteResearchContentSummary` | Write a research content summary |

### RAG-Backed Writing

| Action | Description |
|---|---|
| `RagComposeSubsectionsStage` | The content stage with citation-aware RAG: every subsection retrieves its own references |
| `TweakArticleLancedbRAG` | Refine article content using LanceDB RAG |
| `ChunkArticle` | Split an article into storeable chunks |
| `StoreArticleEssence` | Store article essences into LanceDB |

### Compilation

| Action | Description |
|---|---|
| `CompileTypstDocument` | Compile a `.typ` file or source string to PDF/PNG/SVG |
| `CompileArticle` | Compile a previously dumped article `.typ` to PDF |

```python
from pathlib import Path
from fabricatio_typst.actions.article import CompileArticle, CompileTypstDocument

# Compile a standalone .typ file
result = await CompileTypstDocument().act({
    "typst_source": Path("paper.typ"),
    "output_path": Path("paper.pdf"),
})
# result["compiled_path"] → Path("paper.pdf")

# Compile a generated article (after DumpFinalizedOutput)
result = await CompileArticle().act({
    "article_path": Path("output.typ"),
})
# result["compiled_path"] → Path("output.pdf")
```

### Citation Capability

`CitationLancedbRAG` — citation-aware iterative search that expands queries over multiple rounds and deduplicates by bibtex key.

`CitationSubsectionCompose` — the composition leaf that mixes that search into a
subsection's write: retrieval is seeded with the running text and the subsection's own
plan, the model writes `[[n]]` markers, and the manager rewrites them into typst `@cite`
notation paragraph by paragraph.

## Workflows

Pre-composed action pipelines:

| Workflow | Steps |
|---|---|
| `ArticleWorkflow` | The nine stages above: a briefing in, `article.typ` out |
| `OutlineArticleWorkflow` | The planning stages, then `DumpOutlineStage` |
| `RagArticleWorkflow` | `ArticleWorkflow` with `RagComposeSubsectionsStage` as the content stage |
| `CompileArticleWorkflow` | Compile a `.typ` article to PDF |
| `StoreArticle` | `ExtractArticleEssence` → `StoreArticleEssence` |

The task init context carries the run's inputs: `article_briefing` or
`article_briefing_path`, `article_language` (detected from the briefing when unset),
`writing_constraint`, `skills`, `persist_dir` (the stage snapshots) and
`article_output_path` (the dumped deliverable). Driving the stages directly keeps the
same inputs and writes into the same context:

```python
from pathlib import Path

from fabricatio_typst.workflows.article import ArticleWorkflow

cxt = {
    "article_briefing_path": Path("article_briefing.txt"),
    "article_output_path": Path("article.typ"),
    "persist_dir": Path("persistent"),
}
for stage in ArticleWorkflow.iter_actions():
    cxt = await stage.act(cxt)

print(cxt["task_output"])  # Path("article.typ")
```

## Dependencies

- `fabricatio-core` — agent framework and core models
- `fabricatio-tool` — filesystem utilities
- `fabricatio-capabilities` — capability mixins (Extract, WordCount, FinalizedDumpAble, etc.)
- `fabricatio-context` — the typed context log the pipeline's trees narrow
- `fabricatio-skill` — skill documents the planning and writing prompts render
- `typst` — Typst compiler Python bindings (for compilation actions)

Optional for the staged pipeline:

- `fabricatio-improve`, `fabricatio-rule` — the ruleset-driven repair pass (`CensoredSubsectionRepair`)

Optional for RAG features:

- `fabricatio-lancedb` — vector storage and retrieval

## CLI

The package includes the `ttm` (TeX to Typst Math) binary:

```bash
# Convert math in a file
ttm file input.md -o output.md

# Convert raw LaTeX string
ttm raw "\frac{a}{b}"

# Convert a string with math delimiters
ttm string "The formula $\int_0^\infty e^{-x} dx$ is useful."
```

## Configuration

All options below are read through the fabricatio configuration chain (see the
[Configuration Guide](../../docs/source/configuration.rst)). Set them under the
`[ext.typst]` table in `fabricatio.toml`, equivalently under
`[tool.fabricatio.ext.typst]` in `pyproject.toml`, or via
`FABRICATIO_EXT__TYPST__<FIELD_UPPER>` environment variables.

```toml
[ext.typst]
chap_summary_template = "built-in/chap_summary"
```

| Option | Type | Default | Description |
|---|---|---|---|
| `chap_summary_template` | `str` | `"built-in/chap_summary"` | The name of the chap summary template which will be used to generate a chapter summary. |
| `research_content_summary_template` | `str` | `"built-in/research_content_summary"` | The name of the research content summary template which will be used to generate a summary of research content. |
| `paragraph_sep` | `str` | `"// - - -"` | The separator used to separate paragraphs. |
| `article_wrapper` | `str` | `"// =-=-=-=-=-=-=-=-=-="` | The wrapper used to wrap an article. |
| `extract_essence_template` | `str` | `"built-in/extract_essence"` | The name of the extract essence template which will be used to extract the essence of a text. |
| `article_metadata_requirement_template` | `str` | `"built-in/article_metadata_requirement"` | The name of the template used to propose the article's own plan. |
| `article_plan_requirement_template` | `str` | `"built-in/article_plan_requirement"` | The name of the template used to plan the children of one article node. |
| `subsection_requirement_template` | `str` | `"built-in/subsection_requirement"` | The name of the template used to write the prose of one subsection. |

Access at runtime: `from fabricatio_typst.config import typst_config`.

## License

MIT — see [LICENSE](../../LICENSE)

